Random array range 1-4 with each number only printed twice - arrays

I'm trying to learn how to assign a range of numbers 1 to 4 to an array with each number printed twice. I can't figure out how to use the random range to print numbers specific amounts of times.
Not exactly sure if this is even right. I've haven't really working with for loops, but i did learn them. Not even complete because of the roadblock of how to do this.
By the way, also might help to say this is a card matching game I'm making, so thats why i only need to print twice.
/*for index in imageArray
{
imageArray[index] =
}*/

To assign numbers one through four to an array:
let numbers = Array(1...4)
To assign the numbers one through four twice to an array:
let numbers = Array(1...4) + Array(1...4)
To shuffle those numbers:
var shuffledNumbers = numbers.shuffled()
In Swift 4.2 and later, you can use the built-in shuffled method. In earlier versions, you'd have to write your own, e.g. using the Fisher-Yates algorithm:
// see http://stackoverflow.com/a/24029847/1271826
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
if count < 2 { return } // empty and single-element collections don't shuffle
for i in 0 ..< count - 1 {
let j = Int(arc4random_uniform(UInt32(count - i)))
if j != 0 {
let current = index(startIndex, offsetBy: i)
let swapped = index(current, offsetBy: j)
swapAt(current, swapped)
}
}
}
/// Return shuffled collection the elements of `self`.
func shuffled() -> Self {
var results = self
results.shuffle()
return results
}
}

Related

iOS How to Find Minimum Difference Between the values of Array of Floating/Integer Values

I have an array of floating values:
let array:[Double] = [2270.87, 2285.15, 2273.49, 2312.89, 2323.07, 2336.14, 2355.09, 2633.0, 2671.34]
I need and single line logic using swift higher-order functions or array extension to find the minimum difference value from all differences between the values.
I tried but I'm unable to move further:
let array = [2270.87, 2285.15, 2273.49, 2312.89, 2323.07, 2336.14, 2355.09, 2633.0, 2671.34]
let minDiff = array.map( { *All differences between array of values* } ).reduce(0, min)
Actually I am showing these values in a graph. So I want the minimum absolute fluctuation between the values. in the above example like 2323.07 and 2336.14 have minimum fluctuation 10.18.
You can zip two arrays where second one doesn't have first element. Then you can get abs value of subtraction value with index x + 1 from that with index x, and using map() you can get the minimum value from all of those absolute values.
zip(array, array.dropFirst()).map { abs($1 - $0) }.min() // 10.180000000000291
If you want to find the minimum absolute difference between two consecutive elements of your array, you can use below extension, which maps over the indices of the array, to access 2 consecutive elements at a time.
dropLast is important to ensure that we stop iteration before the last element (since we calculate the diff between the penultimate and last element before reaching the last index).
extension Array where Element: Comparable, Element: SignedNumeric {
func minConsecutiveDiff() -> Element? {
indices.dropLast().map { abs(self[$0] - self[$0+1])}.min()
}
}
let array:[Double] = [2270.87, 2285.15, 2273.49, 2312.89, 2323.07, 2336.14, 2355.09, 2633.0, 2671.34]
array.minConsecutiveDiff() // 10.18
If you were interested in the diff between any two elements of the array, not just consecutive ones, you could get that by first sorting the Array and then calculating the diff between the consecutive elements of the sorted array as #MartinR pointed out in comments.
extension Array where Element: Comparable, Element: SignedNumeric {
func minDiff() -> Element? {
sorted().minConsecutiveDiff()
}
}
Here is one way using forEach
var min: Double = array.max()!
var previous: Double?
array.forEach {
if let prev = previous, min > abs($0 - prev) {
min = abs($0 - prev)
}
previous = $0
}
another option is to use reduce(into:) with a tuple
let min = array.reduce(into: (Double, Double)(array.first!, 0)) {
if abs($1 - $0.1) < $0.0 {
$0.0 = abs($1 - $0.1)
}
$0.1 = $1
}.0
which both gives 10.18 as the smallest difference.

Swift algorithm to enumerate a multilinear map, using multiples indexes:[Int]

A multilinear map M has its elements stored in a one-dimension array of length N, with a Shape S defined by S:[Int] = [p,q,r,...] so that q*p*r*... = N. The Shape is of variable size, not known at compile time.
The issue I'm trying to solve is a generic approach to accessing the map's elements using an array of integers, which individual values are coordinates in the Shape S, ex: M[1,3,2], M[2,3,3,3] etc... This is a problem different from a simple enumeration of the map's elements.
One method is to use M[i,j,k] and implement a subscript method. Unfortunately, this approach hardcodes the map's shape, and the algorithm is no longer generic.
Say there's a utility function that returns an element index from a tuple derived from the map's Shape, so that:
func index(_ indexes:[Int]) -> Int {....}
func elementAt(indexes:[Int]) -> Element {
return elements_of_the_map[self.index(indexes)]
}
M.elementAt(indexes:[i,j,k]) or M.elementAt(indexes:[i,j,k,l,m]) always work. So the problem at this point is to build the array [i,j,k,...]
Question: Is there an algorithm to efficiently enumerate those indexes? Nested loops won't work since the number of loops isn't known at compile time, and recursive function seem to add a lot of complexity (in particular keeping track of previous indexes).
I'm thinking about an algorithm 'a la' base-x counting, that is adding one unit to the top right index, and moving leftwards one unit if the count exceeds the number of elements by the map's Shape.
Same idea, but less code:
func addOneUnit(shape: [Int], indexes: [Int]) -> [Int]? {
var next = indexes
for i in shape.indices.reversed() {
next[i] += 1
if next[i] < shape[i] {
return next
}
next[i] = 0
}
return nil
}
Here's the code, it's primitive, but should work. The idea is to increment, right-to-left, to move say to [1,2,2] from [1,2,1] with the shape constraint [2,3,3].
func add_one_unit(shape:[Int],indexes:[Int]) -> [Int]? {
//Addition is right to left, so we have to reverse the arrays. Shape Arrays are usually very small, so it's fast.
let uu = Array(indexes.reversed()); //Array to add one index to.
let shape_reversed = Array(shape.dimensions.reversed()); //Shape array.
var vv:[Int] = [];
var move_next:Bool = true;
for i in 0..<uu.count {
if move_next {
if uu[i] < shape_reversed[i] - 1 { //Shape constraint is OK.
vv.append(uu[i] + 1)
move_next = false;
} else {
vv.append(0) //Shape constraint is reached.
move_next = true;//we'll flip the next index.
}
} else {
vv.append(uu[i]) //Nothing to change.
}
}
return ( vv.reduce(true, { $0&&($1 == 0) }) ) ? nil : Array(vv.reversed()); //Returns nil once we reached the Zero Vector.
}
Which gives
add_one_unit(shape:[2,3,3],indexes:[0,0,0]) -> [0,0,1]
add_one_unit(shape:[2,3,3],indexes:[1,2,2]) -> [0,0,0]/nil
Once this is done, this function can be used to enumerate a multilinear map of any shape (a mapping of [i,j,k,...] to a unique index such as matrix to index mapping is necessary and depends on your implementation), or slice a map starting from any particular vector.

Adding non-repeating random numbers to an array [duplicate]

This question already has answers here:
How do I shuffle an array in Swift?
(25 answers)
Closed 5 years ago.
Hi I am trying to create an array from non-repeating random numbers.
I wrote below code numberOfAnimals which is 10 currently shows how many numbers will be in the array. When I run this in playground I get
"[6, 5, 1, 4, 7, 0]\n" as output of print statement so in total 6 numbers instead of 10. To avoid it I am decreasing value of i in if statement in case random number exists in the array already, in this case for loop needs an additional loop to reach 10 but still it does not work.
Can you please check where is the mistake or give me another code suggestion that can work ?
import UIKit
var array = [Int]()
var max : Int = 10
var numberOfAnimals : Int = 10
for var i in 0..<numberOfAnimals {
let randomNumber : Int = Int(arc4random_uniform(UInt32(max)))
if array.contains(randomNumber) {
i = i - 1
} else {
array.append(randomNumber)
}
}
print(array)
Why not have a while loop that continues until you have ten numbers in your array.
while array.count < 10 {
...
if !array.contains(randomNumber) {
array.append(randomNumber)
}
}
If you repeat your loop until every number has been hit, the worst case runtime of your algorithm is infinite. As far is I understand your problem, you have an array with fixed size and fixed elements, which you want to be shuffled, so why not do this? I found a nice algorithm in another thread:
extension MutableCollection {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
let i = index(firstUnshuffled, offsetBy: d)
swapAt(firstUnshuffled, i)
}
}
}
let numberOfAnimals = [1,2,3,4,5,6,7,8,9,10]
array.shuffle()
print(array)
I'd suggest a slight modification of #Joakim Danielson 's answer if you can afford the extra space and implement a set - if an array isn't of vital importance you may want to consider a set for your implementation as well, just $0.02
var array = [Int]()
var seen = Set<Int>()
let max = 10
while array.count < max {
let number = Int(arc4random_uniform(UInt32(max)))
if seen.contains(number) {
continue
}
array.append(number)
seen.insert(number)
}
print(array)

Type Int does not conform to protocol sequence

I have the following code in Swift 3:
var numbers = [1,2,1]
for number in numbers.count - 1 { // error
if numbers[number] < numbers[number + 1] {
print(number)
}
}
I am checking if the value on the index [number] is always higher than the value on the index [number + 1]. I am getting an error:
Type Int does not conform to protocol sequence
Any idea?
It may be swift.
You can use this iteration.
for number in 0..<(numbers.count-1)
The error is because Int is not a Sequence. You can create a range as already suggested, which does conform to a sequence and will allow iteration using for in.
One way to make Int conform to a sequence is:
extension Int: Sequence {
public func makeIterator() -> CountableRange<Int>.Iterator {
return (0..<self).makeIterator()
}
}
Which would then allow using it as a sequence with for in.
for i in 5 {
print(i)
}
but I wouldn't recommend doing this. It's only to demonstrate the power of protocols but would probably be confusing in an actual codebase.
From you example, it looks like you are trying to compare consecutive elements of the collection. A custom iterator can do just that while keeping the code fairly readable:
public struct ConsecutiveSequence<T: IteratorProtocol>: IteratorProtocol, Sequence {
private var base: T
private var index: Int
private var previous: T.Element?
init(_ base: T) {
self.base = base
self.index = 0
}
public typealias Element = (T.Element, T.Element)
public mutating func next() -> Element? {
guard let first = previous ?? base.next(), let second = base.next() else {
return nil
}
previous = second
return (first, second)
}
}
extension Sequence {
public func makeConsecutiveIterator() -> ConsecutiveSequence<Self.Iterator> {
return ConsecutiveSequence(self.makeIterator())
}
}
which can be used as:
for (x, y) in [1,2,3,4].makeConsecutiveIterator() {
if (x < y) {
print(x)
}
}
In the above example, the iterator will go over the following pairs:
(1, 2)
(2, 3)
(3, 4)
This maybe a little late but you could have done:
for number in numbers { }
instead of:
for number in numbers.count - 1 { }
For a for loop to work a sequence (range) is needed. A sequence consists of a stating a value, an ending value and everything in between. This means that a for loop can be told to loop through a range with ether
for number in 0...numbers.count-1 { } `or` for number in numbers { }
Both example give the nesasery sequences. Where as:
for number in numbers.count - 1 { }
Only gives one value that could either be the starting or the ending value, making it impossible to work out how many time the for loop will have to run.
For more information see Apple's swift control flow documnetation
This error can also come about if you try to enumerate an array instead of the enumerated array. For example:
for (index, element) in [0, 3, 4] {
}
Should be:
for (index, element) in [0, 3, 4].enumerated() {
}
So first you need to understand what is sequence..
A type that provides sequential, iterated access to its elements.
A sequence is a list of values that you can step through one at a time. The most common way to iterate over the elements of a sequence is to use a for-in loop:
let oneTwoThree = 1...3. // Sequence
for loop actually means
For number in Sequences {}
So you need to use
for number in 0..<(numbers.count-1) {}
The error is because number is not an index, but the element of the array on each iteration. You can modify your code like this:
var numbers = [1,2,1,0,3]
for number in 0..<numbers.count - 1 {
if numbers[number] < numbers[number + 1] {
print(numbers[number])
}
}
Or there is a trick using the sort method, but that's kind of a hack (and yes, the subindexes are right, but look like inverted; you can try this directly on a Playground):
var numbers = [1,2,1,0,3]
numbers.sort {
if $0.1 < $0.0 {
print ($0.1)
}
return false
}
For me, this error occurred when I tried writing a for loop, not for an array but a single element of the array.
For example:
let array = [1,2,3,4]
let item = array[0]
for its in item
{
print(its)
}
This gives an error like: Type Int does not conform to protocol 'sequence'
So, if you get this error in for loop, please check whether you are looping an array or not.

Swift - speed and efficiency of higher order functions (reduce)

Quick question please about the efficiency of higher order swift functions with large input data. During a recent test I had a question about finding 'equlibirum indexes' in arrays- i.e. the index of an array where the sum of all elements below the index equals the sum of all elements above the index
An equilibrium index of this array is any integer P such that 0 ≤ P <
N and the sum of elements of lower indices is equal to the sum of
elements of higher indices, i.e.
A[0] + A[1] + ... + A[P−1] = A[P+1] + ... + A[N−2] + A[N−1].
The challenge was to write a short function which computed the first (or any) index which was considered 'equilibirum'.
I put together a simple snippet which scored highly but failed some of the 'performance' tests which used large input data (array sizes around 100,000).
Here's the code
public func solution(inout A : [Int]) -> Int {
var index = 0;
for _ in A {
let sumBefore = A[0...index].reduce(0) { $0 + $1 }
let sumAfter = A[index...A.count-1].reduce(0) { $0 + $1 }
if (sumBefore == sumAfter) { return index; }
index += 1;
}
return -1;
}
Would anyone please be able to explain why the code performs so poorly with large sets of data, or any recommended alternatives?
Here, for example is a description of a failing perfomance test:
Large performance test, O(n^2) solutions should fail.
✘ TIMEOUT ERROR
running time: >6.00 sec., time limit: 0.22 sec.
It looks like the challenge is failing because your solution is O(n^2).
Your for loop, along with 2 sequential reduces inside, make your solution ~ O(2*n^2) since reduce goes through all the elements again.
A simpler solution is to first compute the whole sum, and then iterate through the elements once, subtracting each value from the whole sum, one by one, thus having access to the left and right sums, for comparison.
Using Swift 3.0, Xcode 8:
func findEquilibriumIndex(in array: [Int]) -> Int? {
var leftSum = 0
var rightSum = array.reduce(0, combine: +)
for (index, value) in array.enumerated() {
rightSum -= value
if leftSum == rightSum {
return index
}
leftSum += value
}
return nil
}
let sampleArray = [-7, 1, 5, 2, -4, 3, 0]
findEquilibriumIndex(in: sampleArray)
The problem is not that "the built-in functions perform so poorly."
Your solution is slow because in each iteration, N elements are
added (N being the length of the array). It would be more efficient
to compute the total sum once and update the "before sum"
and "after sum" while traversing through the array. This reduces
the complexity from O(N^2) to O(N):
public func solution(A : [Int]) -> Int {
var sumBefore = 0
var sumAfter = A.reduce(0, combine: +)
for (idx, elem) in A.enumerate() {
sumAfter -= elem
if sumBefore == sumAfter {
return idx
}
sumBefore += elem
}
return -1
}
(Swift 2.2, Xcode 7.3.1)
Remarks:
There is no reason to pass the array as inout parameter.
An operator (in this case +) can be passed as a argument to the reduce() function.
enumerate() returns a sequence of array indices together with
the corresponding element, this saves another array access.
Note also that a more "Swifty" design would be to make the return type
an optional Int? which is nil if no solution was found.
The incrementalSums extension
If you define this extension
extension Array where Element : SignedInteger {
var incrementalSums: [Element] {
return Array(reduce([0]) { $0.0 + [$0.0.last! + $0.1] }.dropLast())
}
}
given an array of Int(s) you can build an array where the Int at the n-th position represents the sum of the values from 0 to (n-1) in the original array.
Example
[1, 2, 3, 10, 2].incrementalSums // [0, 1, 3, 6, 16]
The equilibriumIndex function
Now you can build a function like this
func equilibriumIndex(nums: [Int]) -> Int? {
let leftSums = nums.incrementalSums
let rightSums = nums.reversed().incrementalSums.reversed()
return Array(zip(leftSums, rightSums)).index { $0 == $1 }
}
Here is a functional version of the solution in Swift 3
let total = sampleArray.reduce(0,+)
var sum = 0
let index = sampleArray.index{ v in defer {sum += v}; return sum * 2 == total - v }
If I understand correctly the element at the resulting index is excluded from the sum on each side (which I'm not certain the other solutions achieve)

Resources