Swift class containing another class as var - ios

Consider the following code:
class A {
var x = 0;
var y = 0;
init(x vx: int, y vy: int){
x = vx
y = vy
}
}
class B {
var a_array: [A]
init(){
a_array = []
}
func append(_ a:A){
a_array.append(a)
}
func sum_all(){
var sum = 0
for a in a_array {
sum += (a.x + a.y)
}
print("sum all is",sum)
}
}
var a1 = A(1, 2)
var a2 = A(3, 4)
var b = B();
b.append(a1)
b.append(a2)
b.sum_all() //it prints out 10 correctly.
a1.x = 2
b.sum_all() //it still prints out 10
As I want it prints out 11, how can I modify these code?
In C, it can be done by using a pointer reference easily, how can it be done in Swift?
Thanks a lot in advance!

It is actually printing 11 in the line you said it still prints 10.
You can try it out by modifying a bit your code to look more like Swift syntax as this:
import Foundation
class A {
var x = 0
var y = 0
init(_ vx: Int, _ vy: Int){
x = vx
y = vy
}
}
class B {
var a_array: [A]
init(){
a_array = []
}
func append(_ a:A){
a_array.append(a)
}
func sum_all(){
var sum = 0
for a in a_array {
sum += (a.x + a.y)
}
print("sum all is",sum)
}
}
var a1 = A(1, 2)
var a2 = A(3, 4)
var b = B()
b.append(a1)
b.append(a2)
print("first")
b.sum_all() //it prints out 10 correctly.
a1.x = 2
print("last")
b.sum_all() //it actually prints 11.
You can try the snippet by copy pasting it in this playground online http://online.swiftplayground.run/ and run it.
This is the output:
first
sum all is 10
last
sum all is 11

Related

Concatenate Int like String in Swift?

I need Something like
var a = 1
var b = 2
var c = a + b should be 12 (Int) instead of 3.
var a = 12
var b = 34
var c = a + b should be 1234 (Int) instead of 46.
I am not figuring out how can we do this for any number?
One way is to convert two both Int to String, concatenate and covert it again that String to Int, but I don't think it's efficient.
Thank you in advance if you have a solution.
You can do it with simple conversion like below:
var a = 1
var b = 2
var c = Int("\(a)\(b)") // Result 12
var a1 = 12
var b1 = 34
var c1 = Int("\(a1)\(b1)") // Result 1234
var a2 = 122344
var b2 = 9022
var c2 = Int("\(a2)\(b2)") // Result 1223449022
12+34 = 12*10^2 + 34 = 1200+34 = 1234
func logC(val: Double, forBase base: Double) -> Double {
return log(val)/log(base)
}
var a = 10
var b = 0
let x = b == 10 ? 2 : b == 0 ? 1 : ceil(logC(val: Double(b), forBase: 10))
var c = Int(Double(a) * pow(10, x) + Double(b))
print(c)
You can write something like this:
extension Int {
func concatenateDecimalDigits(in other: Int) -> Int {
let scale: Int
switch other {
case 0...9:
scale = 10
case 10...99:
scale = 100
case 100...999:
scale = 1000
case 1000...9999:
scale = 10000
case 10000...99999:
scale = 100000
case 100000...999999:
scale = 1000000
//You need to add more cases if you need...
//...
//...
default:
scale = 0 //ignore invalid values
}
return self * scale + other
}
}
var a = 1
var b = 2
print( a.concatenateDecimalDigits(in: b) ) //->12
a = 12
b = 34
print( a.concatenateDecimalDigits(in: b) ) //->1234
a = 122344
b = 9022
print( a.concatenateDecimalDigits(in: b) ) //->1223449022
You can write some logic to calculate scale without switch, but that does not make much difference.
General solution for any two Int:
You will need to calculate number of digits for calculate multiplier as:
func numberOfDigits(_ num: Int) -> Int {
var count = 0
var number = num
while number > 0 {
number = number / 10
count += 1
}
return count
}
Use it as:
let a = 11
let b = 24
let noOfDigit = numberOfDigits(b)
let multiplier = pow(Double(10), Double(noOfDigit))
let c = a * Int(multiplier) + b
print(c)
And, in one line as:
let c = a * Int(pow(Double(10), Double(numberOfDigits(b)))) + b

How to build a 2D board using Swift?

I want to create a 2D game board (like a chess board) and each square has a value inside (Int = 1). This board has initially 9 squares (3x3).
Then I need a player that starts at the center of the bard and when I move the player to the edge of the board, it expands.
Example: The player reaches the [3,3] square and the board grows to a 4x4 board.
Also, when as the player moves it will change the value inside each square, from 0 to 1.
This is what I have so far
//Variables to get the player position and expand the board
let initialSize = 3
var newValueX = 0
var newValueY = 0
var newPlayerX = 0
var newPlayerY = 0
//Board
var board= [[Int]]()
struct Player {
var X = 0
var Y = 0
}
func expandBoard (){
for k in 0..<9{
for i in 0..<initialSize {
for j in 0..<initialSize {
array[k].append([i,j])
}
}
}
}
func movePlayer(){
var player = Player() //this goes to viewDidLoad
player.X = newPlayerX
player.Y = newPlayerY
}
An example of the pretended output:
Player moved to [0,3] and changed the square value from 1 to 0.
How can I do this correctly?
EDIT:
I have
class Array2D<T> {
var columns = 1//: Int
var rows = 1//: Int
var array: Array<T?>
init(columns: Int, rows: Int) {
self.columns = columns
self.rows = rows
array = Array<T?>(repeating: nil, count:rows * columns)
}
subscript(column: Int, row: Int) -> T? {
get {
return array[(row * columns) + column]
}
set(newValue) {
array[(row * columns) + column] = newValue
}
}
}
func move(PX: Int, PY: Int){
if (board[PX, PY] == true){
moveCount += 1
board[PX, PY] = false
}
if (PX == board.rows.magnitude){
board.rows += 1
}
if (PY == board.columns.magnitude){
board.columns += 1
}
}
And when I run i get "Thread 1: Fatal error: Index out of range" on line (return array[(row * columns) + column]) from the subscript.
Any Idea how can I fix this?
UICollectionView would be another simple choice if you don't want use the SpriteKit.
I would recommend using SpriteKit, which have an element called 'Tile Map' which meets your requirements, here is a tutorial that can help.

Find the 4 closest positions of X and Y on a list

I have the following class :
class IBeacon {
var x = Int()
var y = Int()
var ID = Int()
init(id: Int, x :Int, y: Int) {
self.x = x
self.y = y
self.ID = id
}
}
and in another class I have a beacons list:
var listIBeacon = [IBeacon]()
Problem: I get my coordinate X (Int) and Y (Int) and I would know the 4 closest IBeacon in the list listIBeacon to me.
Add a helper function to compute distances between beacons (we can drop the pesky square root since we are only comparing distances):
extension IBeacon {
func distanceSquared(to beacon: IBeacon) -> Int {
let dx = beacon.x - self.x
let dy = beacon.y - self.y
return dx*dx + dy*dy
}
}
then sort using the distanceSquared function we just implemented:
var listIBeacon = [IBeacon]()
let myBeacon: IBeacon = ...
listIBeacon.sort {
let dist0 = myBeacon.distanceSquared(to: $0)
let dist1 = myBeacon.distanceSquared(to: $1)
return dist0 < dist1
}
finally, filter the closest 4 beacons:
let closestBeacons = Array(listIBeacon.prefix(4))

I want multiple non-random numbers in swift

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
}

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