Last active
March 20, 2018 14:30
-
-
Save LukeChannings/81aea25cdaa0cc4c49feb238f1ad1341 to your computer and use it in GitHub Desktop.
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
// See-Saw problem. | |
// | |
// There are 12 people on an island. | |
// One of these 12 people weighs either more or less than the others. | |
// You have a see-saw, you can balance infinite people on either side, | |
// but can only use it a maximum of 3 times. How do you find the person? | |
// implement a function that returns the height of the odd person. | |
runPuzzle((people, seeSaw) => { | |
let firstGroup, secondGroup | |
firstWeighing: { | |
const groupA = people.slice(0, 4) // first third | |
const groupB = people.slice(4, 8) // second third | |
const groupC = people.slice(8, 12) // last third | |
const heavierGroup = seeSaw(groupA, groupB) | |
firstGroup = ! heavierGroup ? groupC : heavierGroup | |
} | |
secondWeighing: { | |
const groupA = firstGroup.slice(0, 2) // first half | |
const groupB = firstGroup.slice(2, 4) // second half | |
secondGroup = seeSaw(groupA, groupB) | |
} | |
thirdWeighing: { | |
const personA = secondGroup[0] | |
const personB = secondGroup[1] | |
return seeSaw(personA, personB) | |
} | |
}) | |
// puzzle runner, you can ignore this. | |
function runPuzzle(solution) { | |
const { random, floor, round } = Math | |
const NUMBER_OF_PEOPLE = 12 | |
const NUMBER_OF_RUNS = 10000 | |
const randomWeight = () => floor(140 + 40 * random()) | |
const newRunContext = solutionFn => { | |
const normalPersonHeight = randomWeight() | |
const oddPersonHeight = randomWeight() | |
const oddPersonIndex = floor(NUMBER_OF_PEOPLE * random()) | |
const people = Array.from({length: NUMBER_OF_PEOPLE}).map((_, index) => { | |
return index === oddPersonIndex ? oddPersonHeight : normalPersonHeight | |
}) | |
// takes a list of weights for both sides, | |
// tells you which side is *heavier*. | |
const sum = list => [].concat(list).reduce((a, b) => a + b) | |
const seeSaw = (() => { | |
let runTimes = 0 | |
return (leftSide, rightSide) => { | |
if (runTimes >= 3) throw new Error('Can only be run a maximum of 3 times!'); | |
const leftWeight = sum(leftSide) | |
const rightWeight = sum(rightSide) | |
return leftWeight === rightWeight ? null : leftWeight > rightWeight ? leftSide : rightSide | |
} | |
})() | |
let result | |
try { | |
result = solutionFn(people, seeSaw) | |
} catch (err) { | |
return false | |
} | |
return result === oddPersonHeight | |
} | |
const results = Array | |
.from({length: NUMBER_OF_RUNS}) | |
.map(() => newRunContext(solution)) | |
if (results.includes(false)) { | |
const resultAccuracy = `Success rate: ${round((results.reduce((a, b) => +a + +b) / NUMBER_OF_RUNS) * 100)}%` | |
console.log(`YOU HAVE FAILED. ${resultAccuracy} over ${NUMBER_OF_RUNS} runs.`) | |
} else { | |
console.log(`You have a stable solution that survived ${NUMBER_OF_RUNS} runs! Amazing!`) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment