From a1e2e9d03ba34c7e9f74cebea34258dce5bdac00 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 5 Mar 2019 22:38:53 -0500 Subject: [PATCH] Updates code to Swift 4.2 --- Genetic/gen.playground/Contents.swift | 192 +++++++++++--------------- 1 file changed, 84 insertions(+), 108 deletions(-) diff --git a/Genetic/gen.playground/Contents.swift b/Genetic/gen.playground/Contents.swift index 79a398ceb..d76342f56 100644 --- a/Genetic/gen.playground/Contents.swift +++ b/Genetic/gen.playground/Contents.swift @@ -1,14 +1,12 @@ -//: Playground - noun: a place where people can play -import Foundation extension String { - var unicodeArray: [UInt8] { - return [UInt8](self.utf8) - } + + var unicodeArray: [UInt8] { + return [UInt8](self.utf8) + } } - let lex: [UInt8] = " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".unicodeArray // This is the end goal and what we will be using to rate fitness. In the real world this will not exist @@ -17,132 +15,110 @@ let OPTIMAL:[UInt8] = "Hello, World".unicodeArray // The length of the string in our population. Organisms need to be similar let DNA_SIZE = OPTIMAL.count -// size of each generation +// Size of each generation let POP_SIZE = 50 -// max number of generations, script will stop when it reach 5000 if the optimal value is not found +// Max number of generations, script will stop when it reaches 5000 if the optimal value is not found let GENERATIONS = 5000 // The chance in which a random nucleotide can mutate (1/n) let MUTATION_CHANCE = 100 -func randomChar(from lexicon: [UInt8]) -> UInt8 { - let len = UInt32(lexicon.count-1) - let rand = Int(arc4random_uniform(len)) - return lexicon[rand] -} - func randomPopulation(from lexicon: [UInt8], populationSize: Int, dnaSize: Int) -> [[UInt8]] { - - var pop = [[UInt8]]() - - (0.. Int { - var fitness = 0 - (0...dna.count-1).forEach { c in - fitness += abs(Int(dna[c]) - Int(optimal[c])) - } - return fitness +func calculateFitness(dna: [UInt8], optimal: [UInt8]) -> Int { + var fitness = 0 + for index in dna.indices { + fitness += abs(Int(dna[index]) - Int(optimal[index])) + } + return fitness } -func weightedChoice(items:[(dna:[UInt8], weight:Double)]) -> (dna:[UInt8], weight:Double) { - - let total = items.reduce(0.0) { return $0 + $1.weight} - - var n = Double(arc4random_uniform(UInt32(total * 1000000.0))) / 1000000.0 - - for item in items { - if n < item.weight { - return item - } - n = n - item.weight +func weightedChoice(items: [(dna: [UInt8], weight: Double)]) -> (dna: [UInt8], weight: Double) { + + let total = items.reduce(0) { $0 + $1.weight } + var n = Double.random(in: 0..<(total * 1000000)) / 1000000.0 + + for item in items { + if n < item.weight { + return item } - return items[1] + n = n - item.weight + } + return items[1] } -func mutate(lexicon: [UInt8], dna:[UInt8], mutationChance:Int) -> [UInt8] { - var outputDna = dna - - (0.. [UInt8] { + var outputDna = dna + (0.. [UInt8] { - let pos = Int(arc4random_uniform(UInt32(dnaSize-1))) - - let dna1Index1 = dna1.index(dna1.startIndex, offsetBy: pos) - let dna2Index1 = dna2.index(dna2.startIndex, offsetBy: pos) - - return [UInt8](dna1.prefix(upTo: dna1Index1) + dna2.suffix(from: dna2Index1)) +func crossover(dna1: [UInt8], dna2: [UInt8], dnaSize: Int) -> [UInt8] { + let pos = Int.random(in: 0..