In Swift programming. I have created a public class called Array3d and is inside Array3d.swift file. My ViewController2.swift create a variable called dog by using the Array3d class and i println(dog). However my console does not show the values of the array of dog but show FYP_Table.Array3D instead.
I have created a 3D Array Called dog and inserted some values into it. Now i want to print it to my debugger output. But does not work.
// Array3d.swift
public class Array3D {
var zs:Int, ys:Int, xs:Int
var matrix: [Float]
init(zs: Int, ys:Int, xs:Int) {
self.zs = zs
self.ys = ys
self.xs = xs
matrix = Array(count:zs*ys*xs, repeatedValue:0)
}
subscript(z:Int, y:Int, x:Int) -> Float {
get {
return matrix[ z * ys * xs + y * xs + x ]
}
set {
matrix[ z * ys * xs + y * xs + x ] = newValue
}
}
//ViewController2.swift
class ViewController2: UITableViewController {
var dog = Array3D(zs: 3, ys: 3, xs: 3)
override func viewDidLoad() {
dog[1,0,0] = 1
dog[0,4,0] = 2
dog[0,0,4] = 3
dog[0,4,4] = 4
for z in 0..<3 {
for y in 0..<3 {
for x in 0..<3 {
println(self.dog)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your class doesn't have a description, so it's just printing out the default representation.
func description() -> String {
return String(format: "Array3D zs:%d ys:%d xs:%d", self.zs, self.ys, self.zs)
}
The proper way to do this is to implement the Printable protocol (see here), which is simply a read-only property named description.
var description : String {
return String(format: "Array3D zs:%d ys:%d xs:%d", zs, ys, zs)
}
Related
I have a custom Rules class.
class Rules: NSCoding {
var x: String?
var y: Double?
override func mapping(map: Map) {
self.x <- map["x"]
self.y <- map["y"]
}
In my viewModel I need to create an object rules and to pass 1 by 1 the elements of two array. The first array is composed by 3 strings, the second array has some Double (more than 3 !!)
This is what I tried so far:
let xValues = ["String1", "String2", "String3"]
let yValues = [1.0, 2.0, 1.5, 2.5, 5.1, 6.0, 8.0]
let rules = zip(xValues, yValues).map {
Rules(x: "\($0.0)", y: $0.1)
}
The problem with this (I guess) is that my rules object has some duplicated string or sometimes more than what I have in my xValues array. (It's possible I am doing something wrong somewhere else ...)
What I need is to pass exactly three strings, and a number of Double which is different, lets say 6 double.
Since zip only returns tuples for those indices where both input arrays have have values, you'll need a method that fills up the smaller array instead, like this:
func zipFill<T, U>(_ arr1: [T], _ arr2: [U]) -> [(T?, U?)] {
let c1 = arr1.count
let c2 = arr2.count
let count = max(c1, c2)
var result = [(T?, U?)]()
for i in 0..<count {
if i < c1 && i < c2 {
result.append((arr1[i], arr2[i]))
} else if i >= c1 {
result.append((nil, arr2[i]))
} else if i >= c2 {
result.append((arr1[i], nil))
}
}
return result
}
let xValues = ["String1", "String2", "String3"]
let yValues = [1.0, 2.0, 1.5, 2.5, 5.1, 6.0, 8.0]
let rules = zipFill(xValues, yValues).map {
Rules(x: $0.0, y: $0.1)
}
print(rules)
// [ {x "String1", y 1}, {x "String2", y 2}, {x "String3", y 1.5},
// {x nil, y 2.5}, {x nil, y 5.1}, {x nil, y 6}, {x nil, y 8} ]
Why don't you just remove duplicates before creating your rules?
Define a generic extension to remove duplicates:
extension RangeReplaceableCollection {
func removingDuplicates<E>(keyPath path: KeyPath<Element, E>) -> Self
where E: Hashable
{
var seen = Set<E>()
seen.reserveCapacity(count)
var new = self
new.removeAll { element -> Bool in
if seen.contains(element[keyPath: path]) {
return true
} else {
seen.insert(element[keyPath: path])
return false
}
}
return new
}
}
Then remove duplicates before zipping:
let xValues = ["String1", "String2", "String3"].removingDuplicates(keyPath: \.self)
let yValues = [1.0, 2.0, 1.5, 2.5, 5.1, 6.0, 8.0].removingDuplicates(keyPath: \.self)
let rules = zip(xValues, yValues).map {
Rules(x: $0.0, y: $0.1)
}
Tidbit: you don't need to use String interpolation for the x argument, because the parameter $0.0 is already a String.
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
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)
}
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
}
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
}