I want multiple non-random numbers in swift - ios

I am using swift and want to have a number of duplicatable patterns throughout my game.
Ideally I would have some sort of shared class that worked sort of like this (this is sort of pseudo-Swift code):
class RandomNumberUtility {
static var sharedInstance = RandomNumberUtility()
var random1 : Random()
var random2 : Random()
func seedRandom1(seed : Int){
random1 = Random(seed)
}
func seedRandom2(seed : Int){
random2 = Random(seed)
}
func getRandom1() -> Int {
return random1.next(1,10)
}
func getRandom2() -> Int {
return random2.next(1,100)
}
}
Then, to begin the series, anywhere in my program I could go like this:
RandomNumberUtility.sharedInstance.seedNumber1(7)
RandomNumberUtility.sharedInstance.seedNumber2(12)
And then I would know that (for example) the first 4 times I called
RandomNumberUtility.sharedInstance.getRandom1()
I would always get the same values (for example: 6, 1, 2, 6)
This would continue until at some point I seeded the number again, and then I would either get the exact same series back (if I used the same seed), or a different series (if I used a different seed).
And I want to have multiple series of numbers (random1 & random2) at the same time.
I am not sure how to begin to turn this into an actual Swift class.

Here is a possible implementation. It uses the jrand48 pseudo random number generator,
which produces 32-bit numbers.
This PRNG is not as good as arc4random(), but has the advantage
that all its state is stored in a user-supplied array, so that multiple
instances can run independently.
struct RandomNumberGenerator {
// 48 bit internal state for jrand48()
private var state : [UInt16] = [0, 0, 0]
// Return pseudo-random number in the range 0 ... upper_bound-1:
mutating func next(upper_bound: UInt32) -> UInt32 {
// Implementation avoiding the "module bias" problem,
// taken from: http://stackoverflow.com/a/10989061/1187415,
// Swift translation here: http://stackoverflow.com/a/26550169/1187415
let range = UInt32.max - UInt32.max % upper_bound
var rnd : UInt32
do {
rnd = UInt32(truncatingBitPattern: jrand48(&state))
} while rnd >= range
return rnd % upper_bound
}
mutating func seed(newSeed : Int) {
state[0] = UInt16(truncatingBitPattern: newSeed)
state[1] = UInt16(truncatingBitPattern: (newSeed >> 16))
state[2] = UInt16(truncatingBitPattern: (newSeed >> 32))
}
}
Example:
var rnd1 = RandomNumberGenerator()
rnd1.seed(7)
var rnd2 = RandomNumberGenerator()
rnd2.seed(12)
println(rnd1.next(10)) // 2
println(rnd1.next(10)) // 8
println(rnd1.next(10)) // 1
println(rnd2.next(10)) // 6
println(rnd2.next(10)) // 0
println(rnd2.next(10)) // 5
If rnd1 is seeded with the same value as above then it
produces the same numbers again:
rnd1.seed(7)
println(rnd1.next(10)) // 2
println(rnd1.next(10)) // 8
println(rnd1.next(10)) // 1

What you need is a singleton that generates pseudo-random numbers and make sure all your code that need a random number call via this class. The trick is to reset the seed for each run of your code. Here is a simple RandomGenerator class that will do the trick for you (it's optimized for speed which is a good thing when writing games):
import Foundation
// This random number generator comes from: Klimov, A. and Shamir, A.,
// "A New Class of Invertible Mappings", Cryptographic Hardware and Embedded
// Systems 2002, http://dl.acm.org/citation.cfm?id=752741
//
// Very fast, very simple, and passes Diehard and other good statistical
// tests as strongly as cryptographically-secure random number generators (but
// is not itself cryptographically-secure).
class RandomNumberGenerator {
static let sharedInstance = RandomNumberGenerator()
private init(seed: UInt64 = 12347) {
self.seed = seed
}
func nextInt() -> Int {
return next(32)
}
private func isPowerOfTwo(x: Int) -> Bool { return x != 0 && ((x & (x - 1)) == 0) }
func nextInt(max: Int) -> Int {
assert(!(max < 0))
// Fast path if max is a power of 2.
if isPowerOfTwo(max) {
return Int((Int64(max) * Int64(next(31))) >> 31)
}
while (true) {
var rnd = next(31)
var val = rnd % max
if rnd - val + (max - 1) >= 0 {
return val
}
}
}
func nextBool() -> Bool {
return next(1) != 0
}
func nextDouble() -> Double {
return Double((Int64(next(26)) << 27) + Int64(next(27))) /
Double(Int64(1) << 53)
}
func nextInt64() -> Int64 {
let lo = UInt(next(32))
let hi = UInt(next(32))
return Int64(UInt64(lo) | UInt64(hi << 32))
}
func nextBytes(inout buffer: [UInt8]) {
for n in 0..<buffer.count {
buffer[n] = UInt8(next(8))
}
}
var seed: UInt64 {
get {
return _seed
}
set(seed) {
_initialSeed = seed
_seed = seed
}
}
var initialSeed: UInt64 {
return _initialSeed!
}
private func randomNumber() -> UInt32 {
_seed = _seed &+ ((_seed &* _seed) | 5)
return UInt32(_seed >> 32)
}
private func next(bits: Int) -> Int {
assert(bits > 0)
assert(!(bits > 32))
return Int(randomNumber() >> UInt32(32 - bits))
}
private var _initialSeed: UInt64?
private var _seed: UInt64 = 0
}

Related

SpriteKit Swift 4 Error: Type 'Int' has no member 'random'

I am making a jumping game using Swift 4 and I am running into an error with the following code:
func addRandomForegroundOverlay() {
let overlaySprite: SKSpriteNode!
let platformPercentage = 60
if Int.random(min: 1, max: 100) <= platformPercentage {
overlaySprite = platform5Across
} else {
overlaySprite = coinArrow
}
createForegroundOverlay(overlaySprite, flipX: false)
}
The error comes on line 4 and says: Type Int has no member random.
Simplest way would be to use Int(arc4random_uniform(100))
The Int type doesn't provide a random() method.
Since you are making a game, using GameplayKit.GKRandom might be a good fit. Try this instead:
import GameplayKit
...
let randomizer = GKRandomSource.sharedRandom()
let randomInt = 1 + randomizer.nextInt(upperBound: 100) // 1...100
Or, better yet, implement the missing method yourself ;)
extension Int {
static func random(min: Int, max: Int) -> Int {
precondition(min <= max)
let randomizer = GKRandomSource.sharedRandom()
return min + randomizer.nextInt(upperBound: max - min + 1)
}
}
usage:
let randomInt = Int.random(min: 1, max: 100)

How to make a "for" loop on the condition of a number interval Xcode Swift2

Hey I'm trying to figure out how to tally up soccer goals on the condition that the goal was scored in under 45 minutes, but the func has some slight errors with swift 2. Any help? Thanks!
Code:
var barcelonavsRealMadrid1goals : [String : Int] = ["barcelonaGoal1":21,"RealMadridGoal2":23,"barcelonaGoal3":24,"RealMadridGoal4":27]
func Run() {
var goalCount=0
for (goal,numbers) in barcelonavsRealMadrid1goals{
for(var number in numbers) {
if(number < 45)
goalCount++
}
}
You have an extra for..in loop in there that's not needed:
for(var number in numbers) {
It also has an extraneous ( and ) around it
for var number in numbers {
Here is a working version of your code:
var barcelonavsRealMadrid1goals = ["barcelonaGoal1":21,"RealMadridGoal2":23,"barcelonaGoal3":24,"RealMadridGoal4":27]
func run() -> Int { // functions should start with lower case
var goalCount=0
for (_,numbers) in barcelonavsRealMadrid1goals where numbers < 45 {
goalCount++
}
return goalCount
}
let goalCount = run()
And the functional way would be something like:
let goalCount = goals.reduce(0) {
if $0.1.1 < 45 {
return $0.0 + 1
}
return $0.0
}
With explanation:
var goals = [
"barcelonaGoal1" :21,
"RealMadridGoal2":23,
"barcelonaGoal3" :24,
"RealMadridGoal4":27,
"RealMadridGoal5":45]
// For our use reduce takes an initial value of Int
// and a combine function of type
// (Int, (String, Int)) -> Int
//
// Reduce will call the closure once with
// each value in the map and the previous return value
let goalCount = goals.reduce(0, combine: {
(initial:Int, current:(key:String, value:Int)) -> Int in
var currentCount = initial
// print to show input and output of closure
print( "parameters:(\(initial), (\"\(current.key)\", \(current.value)))", terminator:", ")
defer {
print("return:\(currentCount)")
}
// end printing
if current.value < 45 {
++currentCount // add 1 to the running total
return currentCount
}
return currentCount
})
// console output:
// parameters:(0, ("barcelonaGoal1", 21)), return:1
// parameters:(1, ("RealMadridGoal4", 27)), return:2
// parameters:(2, ("RealMadridGoal5", 45)), return:2
// parameters:(2, ("RealMadridGoal2", 23)), return:3
// parameters:(3, ("barcelonaGoal3", 24)), return:4
For solving of you're problem try to use functional programing that is introduced in swift :
var barcelonavsRealMadrid1goals : [String : Int] = ["barcelonaGoal1":95,"RealMadridGoal2":23,"barcelonaGoal3":24,"RealMadridGoal4":27]
var filtered = barcelonavsRealMadrid1goals.filter { (team:String, minute:Int) -> Bool in
var state = false
if (minute > 45)
{
return true
}
return state
}
let totalCount = filtered.count
Try this method.
func Run() {
var goalCount=0
for (_, score) in barcelonavsRealMadrid1goals {
if(score < 45) {
goalCount++
}
}
print(goalCount)
}

Calculate all permutations of a string in Swift

For the string "ABC" the code snippet below calculates 5 of the 6 total permutations. My strategy was to insert each character at each index possible index. But the function never gets "CBA" as a possible permutation. What am I missing?
var permutationArray:[String] = [];
let string: String = "ABC"
func permute(input: String) -> Array<String>
{
var permutations: Array<String> = []
/* Convert the input string into characters */
var inputArray: Array<String>
inputArray = input.characters.map { String($0) }
print(inputArray)
/* For each character in the input string... */
for var i = 0; i < inputArray.count; i++
{
/* Insert it at every index */
let characterInArray: String = inputArray[i]
var inputArrayCopy: Array<String> = []
for var y = 0; y < inputArray.count; y++
{
inputArrayCopy = inputArray
inputArrayCopy.removeAtIndex(i)
inputArrayCopy.insert(characterInArray, atIndex:y)
let joiner = ""
let permutation = inputArrayCopy.joinWithSeparator(joiner)
if !permutations.contains(permutation) {
permutations.insert(permutation, atIndex: 0)
}
}
}
return permutations
}
var permutations = permute(string)
print(permutations)
While Stefan and Matt make a good point about using Heap's algorithm, I think you have an important question about why your code doesn't work and how you would debug that.
In this case, the algorithm is simply incorrect, and the best way to discover that is with pencil and paper IMO. What you are doing is picking each element, removing it from the array, and then injecting it into each possible location. Your code does what you have asked it to do. But it's not possible to get to "CBA" that way. You're only moving one element at a time, but "CBA" has two elements out of order. If you expanded to ABCD, you'd find many more missing permutations (it only generates 10 of the 24).
While Heap's algorithm is nicely efficient, the deeper point is that it walks through the entire array and swaps every possible pair, rather than just moving a single element through the array. Any algorithm you choose must have that property.
And just to throw my hat into the ring, I'd expand on Matt's implementation this way:
// Takes any collection of T and returns an array of permutations
func permute<C: Collection>(items: C) -> [[C.Iterator.Element]] {
var scratch = Array(items) // This is a scratch space for Heap's algorithm
var result: [[C.Iterator.Element]] = [] // This will accumulate our result
// Heap's algorithm
func heap(_ n: Int) {
if n == 1 {
result.append(scratch)
return
}
for i in 0..<n-1 {
heap(n-1)
let j = (n%2 == 1) ? 0 : i
scratch.swapAt(j, n-1)
}
heap(n-1)
}
// Let's get started
heap(scratch.count)
// And return the result we built up
return result
}
// We could make an overload for permute() that handles strings if we wanted
// But it's often good to be very explicit with strings, and make it clear
// that we're permuting Characters rather than something else.
let string = "ABCD"
let perms = permute(string.characters) // Get the character permutations
let permStrings = perms.map() { String($0) } // Turn them back into strings
print(permStrings) // output if you like
Here's an expression of Heap's (Sedgewick's?) algorithm in Swift. It is efficient because the array is passed by reference instead of being passed by value (though of course this means you must be prepared to have the array tampered with). Swapping is efficiently expressed through the use of the built-in swapAt(_:_:) function:
func permutations(_ n:Int, _ a: inout Array<Character>) {
if n == 1 {print(a); return}
for i in 0..<n-1 {
permutations(n-1,&a)
a.swapAt(n-1, (n%2 == 1) ? 0 : i)
}
permutations(n-1,&a)
}
Let's try it:
var arr = Array("ABC".characters)
permutations(arr.count,&arr)
Output:
["A", "B", "C"]
["B", "A", "C"]
["C", "A", "B"]
["A", "C", "B"]
["B", "C", "A"]
["C", "B", "A"]
If what you wanted to do with each permutation was not merely to print it, replace print(a) with something else. For example, you could append each permutation to an array, combine the array of characters into a string, whatever.
A very straightforward approach as also suggested in Swift coding challenges.
func permutation(string: String, current: String = "") {
let length = string.characters.count
let strArray = Array(string.characters)
if (length == 0) {
// there's nothing left to re-arrange; print the result
print(current)
print("******")
} else {
print(current)
// loop through every character
for i in 0 ..< length {
// get the letters before me
let left = String(strArray[0 ..< i])
// get the letters after me
let right = String(strArray[i+1 ..< length])
// put those two together and carry on
permutation(string: left + right, current: current +
String(strArray[i]))
}
}
}
Apple today released an Algorithms package available at:
https://github.com/apple/swift-algorithms
This package includes a permutations function that works like so:
let string = "abc"
string.permutations()
/*
["a", "b", "c"]
["a", "c", "b"]
["b", "a", "c"]
["b", "c", "a"]
["c", "a", "b"]
["c", "b", "a"]
*/
func generate(n: Int, var a: [String]){
if n == 1 {
print(a.joinWithSeparator(""))
} else {
for var i = 0; i < n - 1; i++ {
generate(n - 1, a: a)
if n % 2 == 0 {
let temp = a[i]
a[i] = a[n-1]
a[n-1] = temp
}
else {
let temp = a[0]
a[0] = a[n-1]
a[n-1] = temp
}
}
generate(n - 1, a: a)
}
}
func testExample() {
var str = "123456"
var strArray = str.characters.map { String($0) }
generate(str.characters.count, a: strArray)
}
Don't reinvent the wheel. Here's a simple port of Heap's algorithm.
Here is my solution.
import Foundation
class Permutator {
class func permutation(_ str: String) -> Set<String> {
var set = Set<String>()
permutation(str, prefix: "", set: &set)
return set
}
private class func permutation(_ str: String, prefix: String, set: inout Set<String>) {
if str.characters.count == 0 {
set.insert(prefix)
}
for i in str.characters.indices {
let left = str.substring(to: i)
let right = str.substring(from: str.index(after: i))
let rem = left + right
permutation(rem, prefix: prefix + String(str[i]), set: &set)
}
}
}
let startTime = Date()
let permutation = Permutator.permutation("abcdefgh")
print("\(permutation) \n")
print("COMBINAISON: \(permutation.count)")
print("TIME: \(String(format: "%.3f", Date().timeIntervalSince(startTime)))s")
You can copy/paste it in a file and execute it with the command line swift binary.
For a permutation of 7 all unique characters, this algorithm take around 0,06 second to execute.
I was searching to solve the same problem, but I wanted a solution that worked with Generic data type, so I wrote one by looking at a scala code (http://vkostyukov.ru/posts/combinatorial-algorithms-in-scala/)
https://gist.github.com/psksvp/8fb5c6fbfd6a2207e95638db95f55ae1
/**
translate from Scala by psksvp#gmail.com
http://vkostyukov.ru/posts/combinatorial-algorithms-in-scala/
*/
extension Array
{
func combinations(_ n: Int) -> [[Element]]
{
guard self.count > 0 else {return [[Element]]()}
guard n <= self.count else {return [[Element]]()}
if 1 == n
{
return self.map {[$0]}
}
else
{
let head = self.first! // at this point head should be valid
let tail = Array(self.dropFirst())
let car = tail.combinations(n - 1).map {[head] + $0} // build first comb
let cdr = tail.combinations(n) // do the rest
return car + cdr
}
}
func variations(_ n:Int) -> [[Element]]
{
func mixone(_ i: Int, _ x: Element, _ ll: [Element]) -> [Element]
{
return Array( ll[0 ..< i] + ([x] + ll[i ..< ll.count]) )
}
func foldone(_ x: Element, _ ll: [Element]) -> [[Element]]
{
let r:[[Element]] = (1 ... ll.count).reduce([[x] + ll])
{
a, i in
[mixone(i, x, ll)] + a
}
return r
}
func mixmany(_ x: Element, _ ll: [[Element]]) -> [[Element]]
{
guard ll.count > 0 else {return [[Element]]()}
let head = ll.first!
let tail = Array<Array<Element>>(ll.dropFirst())
return foldone(x, head) + mixmany(x, tail)
}
guard self.count > 0 else {return [[Element]]()}
guard n <= self.count else {return [[Element]]()}
if 1 == n
{
return self.map {[$0]}
}
else
{
let head = self.first! // at this point head should be valid
let tail = Array(self.dropFirst())
return mixmany(head, tail.variations(n - 1)) + tail.variations(n)
}
}
var permutations: [[Element]]
{
variations(self.count)
}
}
print([1, 2, 3, 4].combinations(2))
print([1, 2, 3, 4].variations(2))
print([1, 2, 3, 4].permutations)
print(Array("ABCD").permutations)
100% working tested
func permute(strInput:String,l:Int,r:Int){
var inputCharacter = Array(strInput)
if ( l==r){
print(strInput)
}else{
for var i in l..<r{
// Swapping done
inputCharacter.swapAt(l, i);
// Recursion called
permute(strInput: String(inputCharacter), l: l+1, r: r);
//backtrack
inputCharacter.swapAt(l, i);
}
}
}
This way you can call method:
permute(strInput: "ABC", l: 0, r: 3)
Output:
ABC
ACB
BAC
BCA
CBA
CAB
You can use the functions of this framework to calculate permutations and combinations both with repetition and without repetition. You can investigate the source code and compare with your own.
https://github.com/amirrezaeghtedari/AECounting
This library calculates the results based on lexicographic order. For example the result of permutation 3 items out of 5 items are same as below:
let result = Permutation.permute(n: 5, r: 3)
//result
//[
// [1, 2, 3],
// [1, 2, 4],
// [1, 2, 5],
// ...,
// 5, 4, 3]
//].
You can easily assign your problem items to 1 to n numbers in the result array.
In case of your problem, you should call:
let result = Permutation.permute(n: 3, r: 3)
For those looking to calculate all permutations of an array:
func permutations<T>(_ arr: [T]) -> [[T]] {
if arr.count < 2 {
return [arr]
}
var ret: [[T]] = []
let rest = Array(arr[1...])
for p in permutations(rest) {
for i in 0...p.count {
ret.append(Array(p[0..<i]) + [arr[0]] + Array(p[i...]))
}
}
return ret
}
🚨 Update: just use array.permuations() as noted by #Caleb

How to make computer generate predefined set of numbers in Swift?

I want to make the computer generate predefined set of numbers one-by-one. How is it possible in Swift? Is it possible using arrays?
For example: I want to generate [1,2,3,4] in that same order one-by-one. By generate I mean to show up like how random numbers show up when you type in arcrandom_uniform().
Example:
var randomNumber = [1,2,3,4,5]
var guessInt = guess.text.toInt()
Then when I type ..
if Int(randomNumber) == guessInt {
//conditions
}
The error shows as : Cannot assgn to the result of ths expresson
Sometimes I get the error as Int' is not convertible to '[Int]' swift
The code won't work! Help ?
Here's the code for #David Skrundz :
` #IBAction func guessButton(sender: AnyObject) {
var randomNumber = [1,2,3,4,7,8,9,5]
var guessInt = guess.text.toInt()
func generator() -> () -> Int {
var currentIndex = 0
let array = Array(1...5)
func generate() -> Int {
let value = array[currentIndex++]
if currentIndex >= array.count {
currentIndex = 0
}
return value
}
return generate
}
let gen = generator()
gen() // Returns 1
gen() // Returns 2
gen() // Returns 3
gen() // Returns 4
gen() // Returns 1
let answer = gen()
if answer == guessInt {
resultLabel.text = "Bingoo..! "}
else {
resultLabel.text = "Oh such a bad guesser! It was a \(answer)"
}
println(answer)
}
`
Any idea how to fix this code the problem mentioned below ! ? Please !
You may want the range operator:
for index in 1...5 {
println("\(index)")
}
If you want to generate the next element in a repeating sequence, you could use
func generator() -> () -> Int {
var currentIndex = 0
let array = Array(1...4)
func generate() -> Int {
let value = array[currentIndex++]
if currentIndex >= array.count {
currentIndex = 0
}
return value
}
return generate
}
And to use it:
let gen = generator()
gen() // Returns 1
gen() // Returns 2
gen() // Returns 3
gen() // Returns 4
gen() // Returns 1

swift performance issue: local array vs global array

I found a strange performance issue when playing with array in swift.
In the following two demo codes, I try to do a random copy for an array.
The only difference between these two codes is the position of the array definition.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var array: [Int] = [] /* HERE */
var n: Int = 10000
var timer = NSDate()
for i in 0 ..< n {
array.append(i)
}
println("append \(n) elements \(NSDate().timeIntervalSinceDate(timer))")
for i in 0 ..< n {
var p: Int = Int(arc4random_uniform(UInt32(array.count - i))) + i
array[i] = array[p]
}
println("permutation \(array.count) elements \(NSDate().timeIntervalSinceDate(timer))")
}
}
// append 10000 elements 0.0597179532051086
// permutation 10000 elements 0.108937978744507
But when I move the definition of array outside the function (inside the class), then some strange things happened.
import UIKit
class ViewController: UIViewController {
var array: [Int] = [] /* HERE */
override func viewDidLoad() {
super.viewDidLoad()
var n: Int = 10000
var timer = NSDate()
for i in 0 ..< n {
array.append(i)
}
println("append \(n) elements \(NSDate().timeIntervalSinceDate(timer))")
for i in 0 ..< n {
var p: Int = Int(arc4random_uniform(UInt32(array.count - i))) + i
array[i] = array[p]
}
println("permutation \(array.count) elements \(NSDate().timeIntervalSinceDate(timer))")
}
}
// append 10000 elements 0.0645599961280823
// permutation 10000 elements 4.61092203855515
I am a newbie to swift. But I guess I am familiar with other programming language such C++, Java, Python. And this behaviour is REALLY REALLY strange for me. Am I miss anything?
Thanks so much for your help. :>
BTW, my XCode version is 6.1 6A1052D, and the simulator is iPad. I use Debug mode to test my code. But even in Release mode, the second code is still much slower than the first one. So Sad. ;<
Interestingly, the results change dramatically if you replace:
for i in 0 ..< n {
let p = Int(arc4random_uniform(UInt32(array.count - i))) + i
array[i] = array[p]
}
with
for i in 0 ..< n {
let p = Int(arc4random_uniform(UInt32(array.count - i))) + i
let tmp = array[p]
array[i] = tmp
}

Resources