Created
December 5, 2018 18:18
-
-
Save mrnkr/9d84139b4f09a4156d48429dd66eb155 to your computer and use it in GitHub Desktop.
Backtracking/Dynamic Programming exercise - Find out the minimum number of throws needed to know which floor to throw a marker from in order to know whether it breaks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
func max(a: Int, b: Int) -> Int { | |
return a > b ? a : b | |
} | |
// Assume this one works just fine, since I copied it | |
func pedritoBt(markers: Int, floors: Int) -> Int { | |
if floors <= 1 { | |
return floors | |
} else if markers == 1 { | |
return floors | |
} else { | |
var min = 999999 | |
for i in 1...floors { | |
let breaks = pedritoBt(markers: markers - 1, floors: i - 1) | |
let doesntBreak = pedritoBt(markers: markers, floors: floors - i) | |
let maxCant = 1 + max(breaks, doesntBreak) | |
if min > maxCant { | |
min = maxCant | |
} | |
} | |
return min | |
} | |
} | |
// Will fail 4 times in the first 100 data sets | |
func pedritoDynamic(markers: Int, floors: Int) -> Int { | |
var res: [[Int]] = Array.init(repeating: Array.init(repeating: 0, count: floors + 1), count: markers + 1) | |
for m in 1...markers { | |
for f in 1...floors { | |
if m == 1 && f > 0 { | |
res[m][f] = f | |
} else if m > 1 && f > 0 { | |
res[m][f] = 1 + res[m-1][Int(floor(Double(f/2)))] | |
} else { | |
res[m][f] = 0 | |
} | |
} | |
} | |
return res[markers][floors] | |
} | |
// Will not fail | |
func pedritoDynamicByDani(markers: Int, floors: Int) -> Int { | |
var res: [[Int]] = Array.init(repeating: Array.init(repeating: 0, count: floors + 1), count: markers + 1) | |
for m in 1...markers { | |
for f in 1...floors { | |
if m == 1 && f > 0 { | |
res[m][f] = f | |
} else if m > 1 && f > 0 { | |
var min = 999999 | |
for i in 1...f { | |
let breaks = res[m-1][i-1] | |
let doesntBreak = res[m][f-i] | |
let maxCant = 1 + max(breaks, doesntBreak) | |
if min > maxCant { | |
min = maxCant | |
} | |
} | |
res[m][f] = min | |
} else { | |
res[m][f] = 0 | |
} | |
} | |
} | |
return res[markers][floors] | |
} | |
var errors = 0 | |
// Compare the backtracking solution with the Dynamic programming solution | |
// Backtracking works like a charm | |
for m in 1...10 { | |
for f in 1...10 { | |
let bt = pedritoBt(markers: m, floors: f) | |
let dyna = pedritoDynamicByDani(markers: m, floors: f) | |
if bt != dyna { | |
errors = errors + 1 | |
} | |
} | |
} | |
print("Errors: \(errors)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment