Return value from inner closure - swift

Can't find a solution searching for this. Classic problem - want to find if a sum exists for any pair within an Integer array such that [1,2,3,4], 7 is true
My naive solution give the error
Unexpected non-void return value in void function
I guess because I want to return from the inner forEach closure.
func pairs (_ input: [Int], _ sum: Int ) -> Bool {
input.forEach { (number) in
let secondInput = input.filter{$0 != number}
secondInput.forEach{secondNumber in
if ((secondNumber + number) == sum) {
return true
}
}
}
return false
}
How do I return?

P.S Please ignore if you're only looking to get your naive solution working.
How about this? It takes time + space complexity into consideration.
I believe this should work well for a large set or arrays
func pairs (_ input: [Int], _ sum: Int ) -> Bool {
var firstIndex = 0
var lastIndex = input.count - 1
while firstIndex != lastIndex {
let sumCalculated = input[firstIndex] + input[lastIndex]
if sumCalculated == sum {
return true
} else if sumCalculated > sum {
lastIndex = lastIndex - 1
} else if sumCalculated < sum {
firstIndex = firstIndex + 1
}
}
return false
}

forEach only iterates through the given sequence, you can't return values from a forEach closure. contains is better suited for this kind of tasks:
func pairs(_ input: [Int], _ sum: Int ) -> Bool {
return input.contains { number in
let secondInput = input.filter { $0 != number }
return secondInput.contains { secondNumber in
return secondNumber + number == sum
}
}
}
You could also try a more functional solution, that splits the problem in multiple steps:
func pairs(_ input: [Int], _ sum: Int ) -> Bool {
return input
.flatMap { input1 in input.map { input2 in (input1, input2) } } // build all combinations of numbers from the input array
.contains { input1, input2 in input1 != input2 && input1 + input2 == sum } // check if a pair made of two distinct numbers adds up to the sum
}
If you need a solution that handles any kind of inputs (e.g. only unique numbers), then the functional solution can be adapted to this:
func pairs(_ input: [Int], _ sum: Int ) -> Bool {
return input.indices
.flatMap { i1 in input.indices.map { i2 in (i1, i2) } }
.contains { i1, i2 in i1 != i2 && input[i1] + input[i2] == sum }
}

Related

Finding indices of array elements that add up to a target number. What would be a way to optimize my solution?

I'm practicing this problem
Given an array of integers nums and an integer target, return indices
of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
You can return the answer in any order.
and came up with
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var indices = [Int]()
for (firstIndex, firstNum) in nums.enumerated() {
for (secondIndex, secondNum) in nums.enumerated() {
if firstNum + secondNum == target && firstIndex != secondIndex {
indices = [firstIndex, secondIndex]
}
}
}
return indices
}
}
However, it has quadratic time complexity because of the nested for-in loops. What would be a good way to optimize this to run in linear time?
Here's an idea that results in a O(n) time ans space solution.
Have a hashtable that maps elements to their indices.
As you iterate through the input array check whether target - element is in the hashtable already. If so, return the indices of the current element and target - element in the hashtable.
If not, add current element as key and its index as value to the hashtable.
Using #user1984 comment your solution should look like this:
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var indices = [Int]()
var dictionary: [Int: Int] = [:]
for (index, num) in nums.enumerated()
{
let diff = target - num
if let index2 = dictionary[diff] {
return [index2, index]
}
else {
dictionary[num] = index
}
}
return []
}
}
There are several approaches (depending on your requirements and time/space constraints)
final class Solution {
// Time Complexity: O(n * (n - 1) / 2) = O(n^2)
// Auxiliary Space: O(1)
func twoSum1(_ nums: [Int], _ target: Int) -> [Int] {
for firstIndex in nums.indices {
for secondIndex in (firstIndex + 1)..<nums.count {
if nums[firstIndex] + nums[secondIndex] == target {
return [firstIndex, secondIndex]
}
}
}
return []
}
// Time Complexity: O(n log n).
// Auxiliary Space: O(n). Can be O(1) if do in-place sort
func twoSum2(_ nums: [Int], _ target: Int) -> [Int] {
let sorted = nums.sorted()
var left = 0
var right = nums.count - 1
while left < right {
if sorted[left] + sorted[right] == target {
return [left, right]
} else if sorted[left] + sorted[right] < target {
left += 1
} else {
right -= 1
}
}
return []
}
// Time Complexity: O(n). (Amortized)
// Auxiliary Space: O(n).
func twoSum3(_ nums: [Int], _ target: Int) -> [Int] {
var differences = [Int: Int]()
for (index, element) in nums.enumerated() {
let difference = target - element
if let dIndex = differences[difference] {
return [index, dIndex]
}
differences[element] = index
}
return []
}
static func test() {
// Given
let nums = [1, 5, 4, 3, 7, 9, -3]
let target = 7
let solution = Solution()
let expectedResult = [2, 3]
// When
let result1 = solution.twoSum1(nums, target)
let result2 = solution.twoSum2(nums, target)
let result3 = solution.twoSum3(nums, target)
// Then
assert(Set(result1) == Set(expectedResult))
assert(Set(result2) == Set(expectedResult))
assert(Set(result3) == Set(expectedResult))
}
}

Prime factorization with return being a string

I am trying to solve the following coding challenge:
Given a positive number n > 1 find the prime factor decomposition of n. The result will be a string with the following form:
"(p1xxn1)(p2xxn2)...(pkxxnk)"
with the p(i) in increasing order and n(i) empty if n(i) is 1.
Example: n = 86240 should return "(2xx5)(5)(7xx2)(11)"
I believe I have figured out how to find the prime factors of a number... my problem is that I have no idea how to convert them into the form required by the question (i.e., a string where p(i) is in increasing order). I tried to convert an integer array containing the prime factors into some sort of array of tuples containing factors p and n, but I have been struggling fruitlessly for several hours.
Here is what I have so far:
func factors(_ number: Int) -> String {
var changedNumber = number
var numberArr = [Int]()
while changedNumber >= 2 {
for i in 2...changedNumber {
if changedNumber % i == 0 {
numberArr.append(i)
changedNumber /= i
break
}
}
}
}
Any insight or resources would be greatly appreciated.
func factors(_ number: Int) -> String
I think it’s a mistake to make this return the String directly. It violates the separation of responsibilities, and makes this hard to reuse.
Imagine elsewhere in a codebase that uses this function, there might be a function which tries to parse the string result of this back into an array to use it in some other way. It may sound ridiculous, but a large number of the questions we get on here are about people trying to build systems to accept silly input from other systems that they should just change instead!
Here's what I would suggest:
func primeFactorization(of value: Int) -> (factor: Int, exponent: Int) {
...
}
func format(_ primeFactors: [(factor: Int, exponent: Int)]) -> String {
return primeFactors
.map { $0.exponent == 1 ? "(\($0.factor))" : "(\($0.factor)xx\($0.exponent))" }
.joined()
}
So you can then do:
let factorization = primeFactorization(of: 86240)
// Which results in: [
// (factor: 2, exponent: 5),
// (factor: 2, exponent: 1),
// (factor: 7, exponent: 2),
// (factor: 11, exponent: 1),
// ]
// Which you can then format as this one question wants:
format(factorization) // => "(2xx5)(5)(7xx2)(11)"
For extra points, you could generify the first function into an extension on BinaryInteger, which would let you be able to write something like 86240.primeFactorization().
Just make your function group the numbers and then use each sub collection count when creating your string:
func factors(_ number: Int) -> String {
var changedNumber = number
var numberArr: [[Int]] = []
while changedNumber >= 2 {
for i in 2...changedNumber {
if changedNumber.isMultiple(of: i) {
if numberArr.last?.last == i {
numberArr[numberArr.count-1].append(i)
} else {
numberArr.append([i])
}
changedNumber /= i
break
}
}
}
return numberArr.reduce(into: "") {
if let last = $1.last {
if $1.count == 1 {
$0 += "(" + String(last) + ")"
} else {
$0 += "(" + String(last) + "xx\($1.count))"
}
}
}
}
print(factors(86240)) // (2xx5)(5)(7xx2)(11)
There's lots of ways to handle this. Here's one, off the top of my head:
Write an extension to Int that has the following functions
func isPrime() -> Bool
func nextPrime() -> Int.
First check to see if the input number n is prime. If it is, return the result as "(nxxx1)" and you're done.
Define a struct primeFactor:
struct PrimeFactor {
let value: Int
var count: Int
}
Create an array of PrimeFactors.
func primeFactorsString(of value: String) -> String {
var primeFactors = [PrimeFactor]()
var currentPrime = 1
var remainder = value
guard !value.isPrime() else { return "(\(value)xx1)" }
while remainder > 1 {
currentPrime = currentPrime.nextPrime()
if remainder % currentPrime == 0 {
let newPrimeFactor = PrimeFactor(value: currentPrime, count: 1)
remainder /= currentPrime
while remainder % currentPrime == 0 {
newPrimeFactor.count = newPrimeFactor.count + 1
remainder /= currentPrime
}
primeFactors.append(newPrimeFactor)
}
}
// Now loop through your array of primeFactors and build your output string.
return primeFactors.map { "(\($0.value)xx\($0.count))".joined()

CodingBat string_bits problem solved using swit for loop

Question:
Given a string, return a new string made of every other char starting with the first, so "Hello" yields "Hlo".
string_bits('Hello') β†’ 'Hlo'
string_bits('Hi') β†’ 'H'
string_bits('Heeololeo') β†’ 'Hello'
Solution:
func string_bits(userString: String) ->String{
var myString = ""
for(i, v) in userString.enumerated(){
if i % 2 == 0{
myString.append(v)
}
}
return myString
}
Output: Hello
Now my question:
Is there any I can iterate my index any way in swift like object-c, c, or other programming languages does. For instance:
result = ""
# On each iteration, add the substring of the chars 0..i
for i in range(len(str)):
result = result + str[:i+1]
return result
str[:i+1]
Here, I am adding +1 with the current index and getting the index value. How can I do this in swift.
extension Collection {
func everyNthIndex(n: Int) -> UnfoldSequence<Index,Index> {
sequence(state: startIndex) { index in
guard index < endIndex else { return nil }
defer { index = self.index(index, offsetBy: n, limitedBy: endIndex) ?? endIndex }
return index
}
}
}
let alphabet = "abcdefghijklmnopqrstuvwxyz"
for evenIndex in alphabet.everyNthIndex(n: 2) {
print("evenIndex", evenIndex, "char:", alphabet[evenIndex])
}
for oddIndex in alphabet.dropFirst().everyNthIndex(n: 2) {
print("oddIndex", oddIndex, "char:", alphabet[oddIndex])
}
regular approach using while loop:
var index = alphabet.startIndex
while index < alphabet.endIndex {
defer { index = alphabet.index(index, offsetBy: 1) }
print(alphabet[index])
print(index)
}
or enumerating the string indices:
func string_bits(userString: String) -> String {
var myString = ""
for (offset,index) in userString.indices.enumerated() {
if offset.isMultiple(of: 2) {
myString.append(userString[index])
}
}
return myString
}

Check prime number in array

Trying to write a check for Prime numbers in the array. The array is populated randomly. But when processing the array code does not work... What am I doing wrong? Thank you!
update 2
Filling the array correctly. But with the test simple number, something is wrong. Specifically what is wrong can not say, but the point is that the rules of a simple number sorting is not working.
import Foundation
func randomArray(var i:Int,var k:Int, var array: [Int]=[], var newArray: [Int]=[]) ->Int {
for i=0;i<10;i++ {
array.append(Int(arc4random_uniform(10)))
}
for i=0;i<=array.count; i++ {
for k=2; k<array[i]; k++ {
if array[i] != 0 && array[i] != 1 && array[i]%k != 0 {
newArray.append(array[i])
} else {
return 0
}
}
}
return newArray[i]
}
randomArray(0, k: 0)
It's not clear to me what you want to do.
a) If you want to generate an array of length k at random and filter for prime numbers, use the code below. Note that this can give give you an array of length between 0 to k, because they may be no prime in the randomly generated array, or every number generated was a prime:
func isPrime(num: Int) -> Bool {
if num < 2 {
return false
}
for i in 2..<num {
if num % i == 0 {
return false
}
}
return true
}
func randomArray(len: Int) -> [Int] {
var results = [Int]()
for _ in 0..<len {
results.append(Int(arc4random_uniform(10)))
}
return results.filter(isPrime)
}
b) If you want an array of k primes, use this instead:
func randomPrimeArray(len: Int) -> [Int] {
var results = [Int]()
while results.count < len {
let x = Int(arc4random_uniform(10))
if isPrime(x) {
results.append(x)
}
}
return results
}
if you want to filter prime numbers from an array use this code:
let primeNumbers = myArray.filter { number in
if number == 0 {
return false
}
return number % 2 == 0
}

Find digit sum of a number in Swift

Does anyone know how to get the sum of all the digits in a number in Swift?
For example using the number 845 would result in 17
update: Swift 5 or later We can use then new Character property wholeNumberValue:
let string = "845"
let sum = string.compactMap{$0.wholeNumberValue}.reduce(0, +)
print(sum) // 17
let integer = 845
let sumInt = String(integer).compactMap{$0.wholeNumberValue}.reduce(0, +)
print(sumInt) // 17
Here is a solution that uses simple integer arithmetic only:
func digitSum(var n : Int) -> Int {
var sum = 0
while n > 0 {
sum += n % 10 // Add least significant digit ...
n /= 10 // ... and remove it from the number.
}
return sum
}
println(digitSum(845)) // 17
Update for Swift 3/4:
func digitSum(_ n : Int) -> Int {
var n = n
var sum = 0
while n > 0 {
sum += n % 10 // Add least significant digit ...
n /= 10 // ... and remove it from the number.
}
return sum
}
print(digitSum(845)) // 17
Another implementation, just for fun:
func digitSum(_ n : Int) -> Int {
return sequence(state: n) { (n: inout Int) -> Int? in
defer { n /= 10 }
return n > 0 ? n % 10 : nil
}.reduce(0, +)
}
The recursive solution in Swift 3!
func digitSum(of number: Int) -> Int {
if(number < 10) {
return number
} else {
return (number % 10) + digitSum(of: (number/10))
}
}
For the sake of completeness, and for those who would like to see or understand a math-based approach, here's a real-number function based technique ported to Swift.
This is not the most efficient way to tally the digits of an integer in Swift. I don't recommend using it. I would personally use #LeoLDbus map/reduce answer to the question, because it is so cool and illustrates a powerful set of Swift features yet short, or #MartinR integer mod/divide answer, due to its utter simplicity and relative speed of integer arithmetic .
Cocoa and UIKit have the requisite math methods, so you'll probably need to import one of those packages.
func sumDigits(var i : Int) -> Int {
var sum = 0
var nDigits = floor(log10(Double(i))) + 1
for var r = nDigits; r > 0; r-- {
var p = pow(10, r - 1)
var d = floor(Double(i) / p)
sum += Int(d)
i -= Int(d * p)
}
return sum
}
for swift4, try below function:
func sumDigits(num: Int) -> Int {
return String(num).compactMap { Int(String($0)) }.reduce(0, +)
}
Split it into two pieces:
digits
public extension UnsignedInteger {
/// The digits that make up this number.
/// - Parameter radix: The base the result will use.
func digits(radix: Self = 10) -> [Self] {
sequence(state: self) { quotient in
guard quotient > 0
else { return nil }
let division = quotient.quotientAndRemainder(dividingBy: radix)
quotient = division.quotient
return division.remainder
}
.reversed()
}
}
XCTAssertEqual(
(867_5309 as UInt).digits(),
[8,6,7, 5,3,0,9]
)
XCTAssertEqual(
(0x00_F0 as UInt).digits(radix: 0b10),
[1,1,1,1, 0,0,0,0]
)
XCTAssertEqual(
(0xA0_B1_C2_D3_E4_F5 as UInt).digits(radix: 0x10),
[10,0, 11,1, 12,2, 13,3, 14,4, 15,5]
)
XCTAssertEqual(
(0o00707 as UInt).digits(radix: 0o10),
[0b111, 0, 0b111]
)
sum
public extension Sequence where Element: AdditiveArithmetic {
var sum: Element? { reduce(+) }
}
public extension Sequence {
/// The first element of the sequence.
/// - Note: `nil` if the sequence is empty.
var first: Element? {
var iterator = makeIterator()
return iterator.next()
}
/// - Returns: `nil` If the sequence has no elements, instead of an "initial result".
func reduce(
_ getNextPartialResult: (Element, Element) throws -> Element
) rethrows -> Element? {
guard let first = first
else { return nil }
return try dropFirst().reduce(first, getNextPartialResult)
}
}
XCTAssertEqual([1, 2, 3].sum, 6)
XCTAssertEqual([0.5, 1, 1.5].sum, 3)
XCTAssertNil([CGFloat]().sum)