Related
I have a Class for storing a tree and want to make it printable.
final class Node<Value> : CustomStringConvertible {
var value : Value
private(set) var children : [Node]
var description: String {
value as! String + children.reduce("") { $0 + "\n" + $1.description }
}
//...
}
With my code, all levels start at the first column of each line. Is it possible to indent the results by level in this way (e.g. by 2 spaces per level)?
1
1.1
1.1.1
1.2
1.2.1
1.2.1.1
1.2.1.2
I know how to solve this with some lines of code. I only want to know if it is possible by using reduce() or something like that to code it in one line.
You can achieve that with a helper method which takes a “level” parameter and calls itself recursively on each child node with an increased level:
private func toString(level: Int) -> String {
String(repeating: " ", count: level) + "\(value)"
+ children.reduce("") { $0 + "\n" + $1.toString(level: level + 2) }
}
var description: String {
self.toString(level: 0)
}
I'm new on this site but I've been struggling for several days about this issue I found. I wrote this code in order to solve a challenge of the site Codewars; the challenge consists in calculate the mean and the variance from some data about some fictional rainfalls (I attach the complete page on the bottom). In order to end this challenge I created a function to convert the data from this useless string into an array of Doubles. The weird thing is that the function if called outside the main one works properly but inside returns an empty array. I have no idea why is happening this. Thank you very much for every effort you'll put trying to explain me this.
This is the first part of the Codewars page that explain the callenge
This is the second one
//
// main.swift
// Prova
//
// Created by Lorenzo Santini on 13/06/18.
// Copyright © 2018 Lorenzo Santini. All rights reserved.
//
import Foundation
func mean(_ d: String,_ town: String) -> Double {
let arrayOfValues = obtainArrayOfMeasures(d, town)
var sum: Double = 0
for element in arrayOfValues {
sum += element
}
return sum / Double(arrayOfValues.count)
}
func variance(_ d: String,_ town: String) -> Double {
let meanValue: Double = mean(d, town)
//Here is the problem: when this function is called instead of returning the array containg all the measures for the selected city it returns an empty array
var arrayOfValues = obtainArrayOfMeasures(d, town)
var sum: Double = 0
for element in arrayOfValues {
sum += pow((element - meanValue), 2)
}
return sum / Double(arrayOfValues.count)
}
func isInt(_ char: Character) -> Bool {
switch char {
case "1","2","3","4","5","6","7","8","9":
return true
default:
return false
}
}
func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double]{
//The first array stores the Data string divided for city
var arrayOfString: [String] = []
//The second array stores the measures of rainfall of the town passed as argument for the function
var arrayOfMeasures: [Double] = []
//Split the d variable containg the data string in separated strings for each town and add it to the arrayOfString array
repeat {
let finalIndex = (data.index(of:"\n")) ?? data.endIndex
arrayOfString.append(String(data[data.startIndex..<finalIndex]))
let finalIndexToRemove = (data.endIndex == finalIndex) ? finalIndex : data.index(finalIndex, offsetBy: 1)
data.removeSubrange(data.startIndex..<finalIndexToRemove)
} while data.count != 0
//Find the string of the town passed as argument
var stringContainingTown: String? = nil
for string in arrayOfString {
if string.contains(town) {stringContainingTown = string; print("true")}
}
if stringContainingTown != nil {
var stringNumber = ""
var index = 0
//Add to arrayOfMeasures the measures of the selected town
for char in stringContainingTown! {
index += 1
if isInt(char) || char == "." {
stringNumber += String(char)
print(stringNumber)
}
if char == "," || index == stringContainingTown!.count {
arrayOfMeasures.append((stringNumber as NSString).doubleValue)
stringNumber = ""
}
}
}
return arrayOfMeasures
}
var data = "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9" + "\n" +
"London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9" + "\n" +
"Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7" + "\n" +
"NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2" + "\n" +
"Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5" + "\n" +
"Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2" + "\n" +
"Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4" + "\n" +
"Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4" + "\n" +
"Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7" + "\n" +
"Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7"
var prova = variance(data, "London")
The problem is that func obtainArrayOfMeasures modifies the global data
variable. When called the second time, data is an empty string.
An indicator for this problem is also that making the global data variable constant
let data = "Rome:..."
causes a compiler error at
data.removeSubrange(data.startIndex..<finalIndexToRemove)
// Cannot use mutating member on immutable value: 'data' is a 'let' constant
An immediate fix would be to operate on a local mutable copy:
func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double]{
var data = d
// ...
}
Note however that the function can be simplified to
func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double] {
let lines = d.components(separatedBy: .newlines)
guard let line = lines.first(where: { $0.hasPrefix(town)}) else {
return [] // No matching line found.
}
let entries = line.components(separatedBy: ",")
let numbers = entries.compactMap { Double($0.filter {".0123456789".contains($0) })}
return numbers
}
without mutating any values. You might also consider to return nil
or abort with fatalError() if no matching entry is found.
My program seems to work fine on Heroku, but after reloading the page 3-4 times, it crashes, and I get the error H13: Connection closed without response.
However, it works perfectly fine and without any error when I run it on my computer.
Here is my code:
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import Vapor
let arrayA: [String] = ["some strings here"]
let arrayB: [String] = ["more strings there"]
let arrayC: [String] = ["and some more here"]
func buildName (from arrayA: [String], and arrayB: [String], and arrayC: [String]) -> String {
#if os(Linux)
let a: Int = Int(random() % (arrayA.count + 1))
let b: Int = Int(random() % (arrayB.count + 1))
let c: Int = Int(random() % (arrayC.count + 1))
#else
let a: Int = Int(arc4random_uniform(UInt32(arrayA.count)))
let b: Int = Int(arc4random_uniform(UInt32(arrayB.count)))
let c: Int = Int(arc4random_uniform(UInt32(arrayC.count)))
#endif
return (arrayA[a] + " " + arrayB[b] + " " + arrayC[c])
}
let defaultHead: String = "<head><meta charset='utf-8'></head>"
//create Droplet object
let drop = Droplet()
// REGISTER Routes and handlers
drop.get { req in
return buildName(from: arrayA, and: arrayB, and: arrayC)
}
// Start the server
drop.run()
What am I doing wrong?
let a: Int = Int(random() % (arrayA.count + 1))
this line generate a number may equal to ArrayA.count.
So, it may produce fatal error: Index out of range.
So, I think this is the mainly reason.
arc4random_uniform does not work on linux.
use this instead:
public static func randomInt(min: Int, max:Int) -> Int {
#if os(Linux)
return Glibc.random() % max
#else
return min + Int(arc4random_uniform(UInt32(max - min + 1)))
#endif
}
I need to generate a random number.
It appears the arc4random function no longer exists as well as the arc4random_uniform function.
The options I have are arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int), and arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).
I can't find any docs on the functions and no comments in the header files give hints.
let randomIntFrom0To10 = Int.random(in: 1..<10)
let randomFloat = Float.random(in: 0..<1)
// if you want to get a random element in an array
let greetings = ["hey", "hi", "hello", "hola"]
greetings.randomElement()
You could try as well:
let diceRoll = Int(arc4random_uniform(UInt32(6)))
I had to add "UInt32" to make it work.
Just call this function and provide minimum and maximum range of number and you will get a random number.
eg.like randomNumber(MIN: 0, MAX: 10) and You will get number between 0 to 9.
func randomNumber(MIN: Int, MAX: Int)-> Int{
return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}
Note:- You will always get output an Integer number.
After some investigation I wrote this:
import Foundation
struct Math {
private static var seeded = false
static func randomFractional() -> CGFloat {
if !Math.seeded {
let time = Int(NSDate().timeIntervalSinceReferenceDate)
srand48(time)
Math.seeded = true
}
return CGFloat(drand48())
}
}
Now you can just do Math.randomFraction() to get random numbers [0..1[ without having to remember seeding first. Hope this helps someone :o)
Update with swift 4.2 :
let randomInt = Int.random(in: 1..<5)
let randomFloat = Float.random(in: 1..<10)
let randomDouble = Double.random(in: 1...100)
let randomCGFloat = CGFloat.random(in: 1...1000)
Another option is to use the xorshift128plus algorithm:
func xorshift128plus(seed0 : UInt64, _ seed1 : UInt64) -> () -> UInt64 {
var state0 : UInt64 = seed0
var state1 : UInt64 = seed1
if state0 == 0 && state1 == 0 {
state0 = 1 // both state variables cannot be 0
}
func rand() -> UInt64 {
var s1 : UInt64 = state0
let s0 : UInt64 = state1
state0 = s0
s1 ^= s1 << 23
s1 ^= s1 >> 17
s1 ^= s0
s1 ^= s0 >> 26
state1 = s1
return UInt64.addWithOverflow(state0, state1).0
}
return rand
}
This algorithm has a period of 2^128 - 1 and passes all the tests of the BigCrush test suite. Note that while this is a high-quality pseudo-random number generator with a long period, it is not a cryptographically secure random number generator.
You could seed it from the current time or any other random source of entropy. For example, if you had a function called urand64() that read a UInt64 from /dev/urandom, you could use it like this:
let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
print(rand())
}
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}
In Swift 3 :
It will generate random number between 0 to limit
let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")
My implementation as an Int extension. Will generate random numbers in range from..<to
public extension Int {
static func random(from: Int, to: Int) -> Int {
guard to > from else {
assertionFailure("Can not generate negative random numbers")
return 0
}
return Int(arc4random_uniform(UInt32(to - from)) + UInt32(from))
}
}
This is how I get a random number between 2 int's!
func randomNumber(MIN: Int, MAX: Int)-> Int{
var list : [Int] = []
for i in MIN...MAX {
list.append(i)
}
return list[Int(arc4random_uniform(UInt32(list.count)))]
}
usage:
print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")
Another option is to use GKMersenneTwisterRandomSource from GameKit. The docs say:
A deterministic pseudo-random source that generates random numbers
based on a mersenne twister algorithm. This is a deterministic random
source suitable for creating reliable gameplay mechanics. It is
slightly slower than an Arc4 source, but more random, in that it has a
longer period until repeating sequences. While deterministic, this is
not a cryptographic random source. It is however suitable for
obfuscation of gameplay data.
import GameKit
let minValue = 0
let maxValue = 100
var randomDistribution: GKRandomDistribution?
let randomSource = GKMersenneTwisterRandomSource()
randomDistribution = GKRandomDistribution(randomSource: randomSource, lowestValue: minValue, highestValue: maxValue)
let number = randomDistribution?.nextInt() ?? 0
print(number)
Example taken from Apple's sample code: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift
I'm late to the party 🤩🎉
Using a function that allows you to change the size of the array and the range selection on the fly is the most versatile method. You can also use map so it's very concise. I use it in all of my performance testing/bench marking.
elements is the number of items in the array
only including numbers from 0...max
func randArr(_ elements: Int, _ max: Int) -> [Int] {
return (0..<elements).map{ _ in Int.random(in: 0...max) }
}
Code Sense / Placeholders look like this.
randArr(elements: Int, max: Int)
10 elements in my array ranging from 0 to 1000.
randArr(10, 1000) // [554, 8, 54, 87, 10, 33, 349, 888, 2, 77]
you can use this in specific rate:
let die = [1, 2, 3, 4, 5, 6]
let firstRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
let secondRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
Lets Code with Swift for the random number or random string :)
let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]
let randomNumber = arc4random_uniform(UInt32(quotes.count))
let quoteString = quotes[Int(randomNumber)]
print(quoteString)
it will give you output randomly.
Don't forget that some numbers will repeat! so you need to do something like....
my totalQuestions was 47.
func getRandomNumbers(totalQuestions:Int) -> NSMutableArray
{
var arrayOfRandomQuestions: [Int] = []
print("arraySizeRequired = 40")
print("totalQuestions = \(totalQuestions)")
//This will output a 40 random numbers between 0 and totalQuestions (47)
while arrayOfRandomQuestions.count < 40
{
let limit: UInt32 = UInt32(totalQuestions)
let theRandomNumber = (Int(arc4random_uniform(limit)))
if arrayOfRandomQuestions.contains(theRandomNumber)
{
print("ping")
}
else
{
//item not found
arrayOfRandomQuestions.append(theRandomNumber)
}
}
print("Random Number set = \(arrayOfRandomQuestions)")
print("arrayOutputCount = \(arrayOfRandomQuestions.count)")
return arrayOfRandomQuestions as! NSMutableArray
}
look, i had the same problem but i insert
the function as a global variable
as
var RNumber = Int(arc4random_uniform(9)+1)
func GetCase(){
your code
}
obviously this is not efficent, so then i just copy and paste the code into the function so it could be reusable, then xcode suggest me to set the var as constant so my code were
func GetCase() {
let RNumber = Int(arc4random_uniform(9)+1)
if categoria == 1 {
}
}
well thats a part of my code so xcode tell me something of inmutable and initialization but, it build the app anyway and that advice simply dissapear
hope it helps
I'm working with Swift, Xcode 6 and SpriteKit,
I want make a game where some sprites fall down from the top of the screen, but each sprite have a defined speed, position and activation time. I have this working code, but I really don't think that it's the most optimised way to do it:
class obstacles: SKSpriteNode
{
var isOnScreen = false
var type: Int = 0
var initTime: Int = 0
}
var obstacle = [obstacles]() // obstacle is an array of SKSpriteNode
// type : initTime : speed : position : xScale : yScale
var level1: [String] = ["0:120:3:0:1:1", "0:130:4:80:2:2","1:140:8:120:6:1","0:150:6:240:2:2"]
override func didMoveToView(view: SKView)
{
initObstacles()
}
func initObstacles()
{
for var x = 0; x < level1.count; x++ // for each obstacle
{
var index = 0
var type = String("")
var initTime = String("")
var speed = String("")
var position = String("")
var xScale = String("")
var yScale = String("")
var lastIndex = obstacle.count
for Character in level1[x] // we read each character one by one
{
if Character == ":" { index++ } // if it's a ":" we change the variable
else
{
switch index
{
case 0:
type += String(Character)
case 1:
initTime += String(Character)
case 2:
speed += String(Character)
case 3:
position += String(Character)
case 4:
xScale += String(Character)
case 5:
yScale += String(Character)
default:
break;
}
}
}
obstacle.append(obstacles(imageNamed: "Rectangle")) // we add an element to the array
obstacle[lastIndex].type = type.toInt()! // we init all the values
obstacle[lastIndex].initTime = initTime.toInt()!
obstacle[lastIndex].speed = CGFloat(speed.toInt()!)
obstacle[lastIndex].size.width = DEFAULT_OBSTACLE_SIZE * CGFloat(xScale.toInt()!)
obstacle[lastIndex].size.height = DEFAULT_OBSTACLE_SIZE * CGFloat(yScale.toInt()!)
obstacle[lastIndex].position = CGPointMake(CGFloat(position.toInt()!) - obstacle[lastIndex].size.width/2, CGRectGetMaxY(frame) + obstacle[lastIndex].size.height/2)
}
}
Do you know how could I manage to do the same thing, but more "clean" ?
I would suggest to create a class or struct that holds all necessary data for an obstacle and additionally change your type from a standard number to an enum, e.g.:
enum ObstacleType {
case Block, Tree, WhatEverObstaclesYouHave...
}
struct Obstacle {
var type: ObstacleType
var initializationTime: NSTimeInterval
var speed: Double
// and similarly for position, your scales and what you may need in future
}
and create them using, e.g.
Obstacle(type: .Block, initializationTime: 0, speed: 12.0, ...)
Advantage (obviously) is that you have no problems anymore parsing your string (there is no string anymore) and can provide all necessary information using the appropriate type directly. And you can easily use an enum for your type, which should be an enum, because your Obstacle is not a 1, but a Block, Tree or whatever.
Your level1 variable could then be defined like this:
var level1 : [Obstacle] = [
Obstacle(type: .Block, initializationTime: 120, speed: 3.0, ...),
Obstacle(type: .Block, initializationTime: 130, speed: 4.0, ...),
Obstacle(type: .Tree, initializationTime: 140, speed: 8.0, ...),
Obstacle(type: .Block, initializationTime: 150, speed: 6.0, ...)
]
To get rid of the labels in the initializer, just define your own initializer. Just add this to your struct:
init(_ type: ObstacleType, _ time: NSTimeInterval, _ speed: Double, ...) {
self.type = type
self.initializationTime = time
self.speed = speed
// other variables...
}
Then you can create every Obstacle like this:
Obstacle(.Block, 120, 3.0, ...)
But now you can not easily tell anymore which number has what meaning from reading the instantiation. I do not recommend this just to type less as autocomplete will present you with most of it.