Swift - how to reduce matrix - swift

I have an 3 dimension array (array[x][y][z], x y z can flexible)
var array = [ [[1,1,1],[0,0,0],[1,1,1]],
[[1,0,1],[1,0,1],[1,0,1]],
[[1,1,1],[0,0,0],[1,1,1]]
]
How can I reduce 3D to 2D to : array[z][y]
[3,1,3],[2,0,2],[3,1,3]
I read the instruction here but couldn't figure out how to apply to mine.
Updated :
Here is the logic

Let's start by forming a utility function as an extension on a matrix-style array ("cw" means column-wise):
extension Array where Element == [[Int]] {
func cwsum(_ ix1:Int, _ ix2:Int) -> Int {
return reduce(0) {$0 + $1[ix1][ix2]}
}
}
Then if the array is:
let array = [[[1,1,1],[0,0,0],[1,1,1]],
[[1,0,1],[1,0,1],[1,0,1]],
[[1,1,1],[0,0,0],[1,1,1]]]
... then the answer is:
[[array.cwsum(0,0), array.cwsum(1,0), array.cwsum(2,0)],
[array.cwsum(0,1), array.cwsum(1,1), array.cwsum(2,1)],
[array.cwsum(0,2), array.cwsum(1,2), array.cwsum(2,2)]]
// [[3, 1, 3], [2, 0, 2], [3, 1, 3]]
But wait — I think I see a pattern here! We can rewrite that without hard-coding the indices, as:
var result = [[Int]]()
for j in 0..<3 {
var r1 = [Int]()
for i in 0..<3 {
r1.append(array.cwsum(i,j))
}
result.append(r1)
} // result is now [[3, 1, 3], [2, 0, 2], [3, 1, 3]]
Okay, but where we can loop and append, we can map instead, thus turning i into the map variable:
var result = [[Int]]()
for j in 0..<3 {
result.append((0..<3).map{i in array.cwsum(i,j)})
}
But then we can do that for j as well — and thus it becomes a single line:
result = (0..<3).map{j in (0..<3).map{i in array.cwsum(i,j)}}

Since it sounds like you’re looking for a functional programming one-liner, here’s your answer:
array.indices.map{ j in array.indices.map{ i in array.map{ $0[i][j] }.reduce(0, +) } }
It’s basically the same as this code, which, while much longer, I consider much easier to read and gives me fewer headaches to reason about.
func flatten2(_ array:[[[Int]]]) -> [[Int]]
{
var result:[[Int]] = []
for j in 0..<array.count
{
var row:[Int] = []
for i in 0..<array.count
{
row.append(array.map{ $0[i][j] }.reduce(0, +))
}
result.append(row)
}
return result
}
Keep in mind the one-liner will take over two orders of magnitude longer to compile, since the Swift compiler is not very optimized for functional and closure programming, and so it has to construct enormous overload trees to parse that expression. As I suspect this is a question from a practice exam for a CS final, please, please, make your poor TA’s life easier and use the multi-liner.

Given this
let matrix = [
[[1,1,1],[0,0,0],[1,1,1]],
[[1,0,1],[1,0,1],[1,0,1]],
[[1,1,1],[0,0,0],[1,1,1]]
]
lets calculate these
let all = matrix.joined().enumerated()
let a = all.filter { $0.offset % 3 == 0 }.map { $0.element[0] }.reduce(0, +)
let b = all.filter { $0.offset % 3 == 1 }.map { $0.element[0] }.reduce(0, +)
let c = all.filter { $0.offset % 3 == 2 }.map { $0.element[0] }.reduce(0, +)
let d = all.filter { $0.offset % 3 == 0 }.map { $0.element[1] }.reduce(0, +)
let e = all.filter { $0.offset % 3 == 1 }.map { $0.element[1] }.reduce(0, +)
let f = all.filter { $0.offset % 3 == 2 }.map { $0.element[1] }.reduce(0, +)
let g = all.filter { $0.offset % 3 == 0 }.map { $0.element[2] }.reduce(0, +)
let h = all.filter { $0.offset % 3 == 1 }.map { $0.element[2] }.reduce(0, +)
let i = all.filter { $0.offset % 3 == 2 }.map { $0.element[2] }.reduce(0, +)
and finally lets put the values together
let res = [[a, b, c], [d, e, f], [g, h, i]]

After hours of attempts. This is my output, it's very simple and unrelated to reduce. The inputs of 3d array are flexible x,y,z
let x = array.count
let y = array[0].count
let z = array[0][0].count
var final = Array(repeating: Array(repeating: 0, count: y), count: z)
for i in 0..<z {
for ii in 0..<y {
var sum = 0
for iii in 0..<x {
sum = sum + array[iii][ii][i]
}
final[i][ii] = sum
}
}

Related

My Swift code getting error Can't form range with upperbound < lowerbound

I try to run my code in leetcode site. In XCode this code compiled successful. But in leetcode is error:
Fatal error: Can't form range with upperbound < lowerbound
Description of task:
Given an array nums of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which
gives the sum of zero.
My solution of this task is:
class Solution {
func threeSum(_ nums: [Int]) -> [[Int]] {
var arr: [[Int]] = []
var fIndex = 0
var sIndex = 1
var tIndex = 2
for i in fIndex..<nums.count-2 {
for n in sIndex..<nums.count-1 {
for z in tIndex..<nums.count {
let sum = nums[i] + nums[n] + nums[z]
if sum == 0 {
arr.append([nums[i], nums[n], nums[z]])
}
}
sIndex += 1
tIndex += 1
}
fIndex += 1
}
return arr
}
}
// delete this in leetcode site
let threeNums = [-1, 0, 1, 2, -1, -4]
let sol = Solution()
print(sol.threeSum(threeNums))
Where is the problem in my code?
Assuming all the other parts of your code works, you just need to check if the input array has less than 3 elements before the loops:
class Solution {
func threeSum(_ nums: [Int]) -> [[Int]] {
var arr: [[Int]] = []
var fIndex = 0
var sIndex = 1
var tIndex = 2
if nums.count < 3 { return [] } // if there is less than 3 elements, there can't be any triplets
for i in fIndex..<nums.count-2 {
...
Without the check, your code will fail when, say, nums has only one element, and enums.count - 2 would be -1.

Generating random Int array of random count without repeated vars [duplicate]

This question already has answers here:
Get random elements from array in Swift
(6 answers)
Closed 5 years ago.
Code first generates a random between 0-8, assigning it to var n. Then a 2nd randomNumber Generator func is looped n amount of times to generate n amount of ints between 0 and 10, all having different probabilities of occurring and ultimately put into an array. What I want is for none of those 10 possible numbers to repeat, so once one is chosen it can no longer be chosen by the other n-1 times the func is run. I'm thinking a repeat-while-loop or an if-statement or something involving an index but I don't know exactly how, nor within what brackets. Thanks for any help! Some whisper this is the most challenging and intelligence demanding coding conundrum on earth. Challenge Accepted?
import UIKit
let n = Int(arc4random_uniform(8))
var a:Double = 0.2
var b:Double = 0.3
var c:Double = 0.2
var d:Double = 0.3
var e:Double = 0.2
var f:Double = 0.1
var g:Double = 0.2
var h:Double = 0.4
var i:Double = 0.2
var j:Double = 0.2
var k: [Int] = []
for _ in 0...n {
func randomNumber(probabilities: [Double]) -> Int {
let sum = probabilities.reduce(0, +)
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}}
return (probabilities.count - 1)
}
k.append(randomNumber(probabilities: [a, b, c, d, e, f, g, h, i, j]))
}
print(k)
pseudo Code -
1)generate a number between 1-8
n
2)take empty array
arr[]
3)loop from 0 to n
1) generate a random no
temp
2) check if it is there in arr
> if it is there in arr, generate another
3) when you get a number which is not there in arr, insert it
This is a python code
import random
n = random.randint(1,8)
arr = []
print(n)
for each in range(n):
temp = random.randint(1, 10)
while temp in arr:
temp = random.randint(1, 10)
print(temp)
arr.append(temp)
print(arr)
Check code example here
Swift version of Ankush's answer -
let n = arc4random_uniform(7) + 1
var arr: [UInt32] = []
for _ in 0 ... n {
var temp = arc4random_uniform(9) + 1
while arr.contains(temp) {
temp = arc4random_uniform(9) + 1
}
print(temp)
arr.append(temp)
}
print(arr)
Hope this helps!

In Swift 3, how to calculate the factorial when the result becomes too high?

I have written this function to return the factorial of a given number
func factorial(_ n: Int) -> Int {
if n == 0 {
return 1
}
else {
return n * factorial(n - 1)
}
}
print( factorial(20) ) // 2432902008176640000
Works as it should, as long the given number does not exceed 20, because then the result becomes too high!
How can I circumvent this limit and thus calculate the factorial of higher numbers?
I have searched around and found some bignum libraries for Swift. I'm doing this to learn and be familiar with Swift, therefore I want to figure this out on my own.
Here's an approach that will let you find very large factorials.
Represent large numbers as an array of digits. For instance 987 would be [9, 8, 7]. Multiplying that number by an integer n would require two steps.
Multiply each value in that array by n.
Perform a carry operation to return a result that is again single digits.
For example 987 * 2:
let arr = [9, 8, 7]
let arr2 = arr.map { $0 * 2 }
print(arr2) // [18, 16, 14]
Now, perform the carry operation. Starting at the one's digit, 14 is too big, so keep the 4 and carry the 1. Add the 1 to 16 to get 17.
[18, 17, 4]
Repeat with the ten's place:
[19, 7, 4]
And then with the hundred's place:
[1, 9, 7, 4]
Finally, for printing, you could convert this back to a string:
let arr = [1, 9, 7, 4]
print(arr.map(String.init).joined())
1974
Applying that technique, here is a carryAll function that performs the carry operation, and a factorial that uses it to calculate very large factorials:
func carryAll(_ arr: [Int]) -> [Int] {
var result = [Int]()
var carry = 0
for val in arr.reversed() {
let total = val + carry
let digit = total % 10
carry = total / 10
result.append(digit)
}
while carry > 0 {
let digit = carry % 10
carry = carry / 10
result.append(digit)
}
return result.reversed()
}
func factorial(_ n: Int) -> String {
var result = [1]
for i in 2...n {
result = result.map { $0 * i }
result = carryAll(result)
}
return result.map(String.init).joined()
}
print(factorial(1000))
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
You can use this library:
BigInt
Install it using CocoaPods:
pod 'BigInt'
Then you can use it like this:
import BigInt
func factorial(_ n: Int) -> BigInt {
if n == 0 {
return 1
}
else {
return BigInt(n) * factorial(n - 1)
}
}
print( factorial(50) ) // 30414093201713378043612608166064768844377641568960512000000000000

Swift : how to work with 2D array and Calculate on them

Hi I have problem with swift 2D array and calculate on them like : multiple , sum , subtract ... but I get error like : cannot convert value type
this is my code:
let ar1: [[Int]] = [[1,2], [3, 4], [5, 6], [7, 8]]
let ar2: [[Int]] = [[2,4], [6,8],[10,12],[14,16]]
var ar3: [[Int]] = []
for i in 0...ar1.count-1
{
for j in 0...ar1.count-1
{
ar3.append(ar1[i][j] + ar2 [i][j])
}
}
I have to do it by for loop please help me
ar3 contains elements of type [Int], so consequently ar3.append(…) needs an object of type [Int]. But you're not giving it an [Int], you're giving it an Int (i.e. the result of the expression ar1[i][j] + ar2[i][j]).
If you want to sum ar1 and ar2 into [1+2, 2+4, 3+6, …]:
var ar3 = [Int]()
for i in ar1 {
for j in ar2 {
ar3.append(i + j)
}
}
(or a functional way to do the same: zip(ar1, ar2).flatMap { zip($0, $1).map(+) })
If you want to sum ar1 and ar2 into [[1+2, 2+4], [3+6, 4+8], …]:
var ar3 = [[Int]]()
for i in ar1 {
ar3.append([])
for j in ar2 {
ar3.last!.append(i + j)
}
}
(or a functional way to do the same: zip(ar1, ar2).map { zip($0, $1).map(+) })

List comprehension in Swift

The language guide has revealed no trace of list comprehension. What's the neatest way of accomplishing this in Swift? I'm looking for something similar to:
evens = [ x for x in range(10) if x % 2 == 0]
As of Swift 2.x, there are a few short equivalents to your Python-style list comprehension.
The most straightforward adaptations of Python's formula (which reads something like "apply a transform to a sequence subject to a filter") involve chaining the map and filter methods available to all SequenceTypes, and starting from a Range:
// Python: [ x for x in range(10) if x % 2 == 0 ]
let evens = (0..<10).filter { $0 % 2 == 0 }
// Another example, since the first with 'x for x' doesn't
// use the full ability of a list comprehension:
// Python: [ x*x for x in range(10) if x % 2 == 0 ]
let evenSquared = (0..<10).filter({ $0 % 2 == 0 }).map({ $0 * $0 })
Note that a Range is abstract — it doesn't actually create the whole list of values you ask it for, just a construct that lazily supplies them on demand. (In this sense it's more like Python's xrange.) However, the filter call returns an Array, so you lose the "lazy" aspect there. If you want to keep the collection lazy all the way through, just say so:
// Python: [ x for x in range(10) if x % 2 == 0 ]
let evens = (0..<10).lazy.filter { $0 % 2 == 0 }
// Python: [ x*x for x in range(10) if x % 2 == 0 ]
let evenSquared = (0..<10).lazy.filter({ $0 % 2 == 0 }).map({ $0 * $0 })
Unlike the list comprehension syntax in Python (and similar constructs in some other languages), these operations in Swift follow the same syntax as other operations. That is, it's the same style of syntax to construct, filter, and operate on a range of numbers as it is to filter and operate on an array of objects — you don't have to use function/method syntax for one kind of work and list comprehension syntax for another.
And you can pass other functions in to the filter and map calls, and chain in other handy transforms like sort and reduce:
// func isAwesome(person: Person) -> Bool
// let people: [Person]
let names = people.filter(isAwesome).sort(<).map({ $0.name })
let sum = (0..<10).reduce(0, combine: +)
Depending on what you're going for, though, there may be more concise ways to say what you mean. For example, if you specifically want a list of even integers, you can use stride:
let evenStride = 0.stride(to: 10, by: 2) // or stride(through:by:), to include 10
Like with ranges, this gets you a generator, so you'll want to make an Array from it or iterate through it to see all the values:
let evensArray = Array(evenStride) // [0, 2, 4, 6, 8]
Edit: Heavily revised for Swift 2.x. See the edit history if you want Swift 1.x.
With Swift 5, you can choose one of the seven following Playground sample codes in order to solve your problem.
#1. Using stride(from:to:by:) function
let sequence = stride(from: 0, to: 10, by: 2)
let evens = Array(sequence)
// let evens = sequence.map({ $0 }) // also works
print(evens) // prints [0, 2, 4, 6, 8]
#2. Using Range filter(_:) method
let range = 0 ..< 10
let evens = range.filter({ $0 % 2 == 0 })
print(evens) // prints [0, 2, 4, 6, 8]
#3. Using Range compactMap(_:) method
let range = 0 ..< 10
let evens = range.compactMap({ $0 % 2 == 0 ? $0 : nil })
print(evens) // prints [0, 2, 4, 6, 8]
#4. Using sequence(first:next:) function
let unfoldSequence = sequence(first: 0, next: {
$0 + 2 < 10 ? $0 + 2 : nil
})
let evens = Array(unfoldSequence)
// let evens = unfoldSequence.map({ $0 }) // also works
print(evens) // prints [0, 2, 4, 6, 8]
#5. Using AnySequence init(_:) initializer
let anySequence = AnySequence<Int>({ () -> AnyIterator<Int> in
var value = 0
return AnyIterator<Int> {
defer { value += 2 }
return value < 10 ? value : nil
}
})
let evens = Array(anySequence)
// let evens = anySequence.map({ $0 }) // also works
print(evens) // prints [0, 2, 4, 6, 8]
#6. Using for loop with where clause
var evens = [Int]()
for value in 0 ..< 10 where value % 2 == 0 {
evens.append(value)
}
print(evens) // prints [0, 2, 4, 6, 8]
#7. Using for loop with if condition
var evens = [Int]()
for value in 0 ..< 10 {
if value % 2 == 0 {
evens.append(value)
}
}
print(evens) // prints [0, 2, 4, 6, 8]
Generally, a list comprehension in Python can be written in the form:
[f(x) for x in xs if g(x)]
Which is the same as
map(f, filter(g, xs))
Therefore, in Swift you can write it as
listComprehension<Y>(xs: [X], f: X -> Y, g: X -> Bool) = map(filter(xs, g), f)
For example:
map(filter(0..<10, { $0 % 2 == 0 }), { $0 })
As of Swift 2 you can do something like this:
var evens = [Int]()
for x in 1..<10 where x % 2 == 0 {
evens.append(x)
}
// or directly filtering Range due to default implementations in protocols (now a method)
let evens = (0..<10).filter{ $0 % 2 == 0 }
Got to admit, I am surprised nobody mentioned flatmap, since I think it's the closest thing Swift has to list (or set or dict) comprehension.
var evens = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].flatMap({num -> Int? in
if num % 2 == 0 {return num} else {return nil}
})
Flatmap takes a closure, and you can either return individual values (in which case it will return an array with all of the non-nil values and discard the nils) or return array segments (in which case it will catenate all of your segments together and return that.)
Flatmap seems mostly (always?) to be unable to infer return values. Certainly, in this case it can't, so I specify it as -> Int? so that I can return nils, and thus discard the odd elements.
You can nest flatmaps if you like. And I find them much more intuitive (although obviously also a bit more limited) than the combination of map and filter. For example, the top answer's 'evens squared', using flatmap, becomes,
var esquares = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].flatMap({num -> Int? in
if num % 2 == 0 {return num * num} else {return nil}
})
The syntax isn't quite as one-line not-quite-the-same-as-everything-else as python's is. I'm not sure if I like that less (because for the simple cases in python it's very short and still very readable) or more (because complex cases can get wildly out of control, and experienced python programmers often think that they're perfectly readable and maintainable when a beginner at the same company can take half an hour to puzzle out what it was intended to do, let alone what it's actually doing.)
Here is the version of flatMap from which you return single items or nil, and here is the version from which you return segments.
It's probably also worth looking over both array.map and array.forEach, because both of them are also quite handy.
One aspect of list comprehension that hasn't been mentioned in this thread is the fact that you can apply it to multiple lists' Cartesian product. Example in Python:
[x + y for x in range(1,6) for y in range(3, 6) if x % 2 == 0]
… or Haskell:
[x+y | x <- [1..5], y <- [3..5], x `mod` 2 == 0]
In Swift, the 2-list equivalent logic is
list0
.map { e0 in
list1.map { e1 in
(e0, e1)
}
}
.joined()
.filter(f)
.map(g)
And we'd have to increase the nesting level as the number of lists in input increases.
I recently made a small library to solve this problem (if you consider it a problem). Following my first example, with the library we get
Array(1...5, 3...5, where: { n, _ in n % 2 == 0}) { $0 + $1 }
The rationale (and more about list comprehension in general) is explained in an blog post.
One way would be :
var evens: Int[]()
for x in 0..<10 {
if x%2 == 0 {evens += x} // or evens.append(x)
}
Range operators
Arrays
Here's an extension to the Array types that combines filter and map into one method:
extension Array {
func filterMap(_ closure: (Element) -> Element?) -> [Element] {
var newArray: [Element] = []
for item in self {
if let result = closure(item) {
newArray.append(result)
}
}
return newArray
}
}
It's similar to map except you can return nil to indicate that you don't want the element to be added to the new array. For example:
let items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let newItems = items.filterMap { item in
if item < 5 {
return item * 2
}
return nil
}
This could also be written more concisely as follows:
let newItems = items.filterMap { $0 < 5 ? $0 * 2 : nil }
In both of these examples, if the element is less than 5, then it is multiplied by two and added to the new array. If the closure returns nil, then the element is not added. Therefore, newIems is [2, 4, 6, 8].
Here's the Python equivalent:
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
newItems = [n * 2 for n in items if n < 5]