Skip to content

Instantly share code, notes, and snippets.

@LukeChannings
Last active March 20, 2018 14:30
Show Gist options
  • Save LukeChannings/81aea25cdaa0cc4c49feb238f1ad1341 to your computer and use it in GitHub Desktop.
Save LukeChannings/81aea25cdaa0cc4c49feb238f1ad1341 to your computer and use it in GitHub Desktop.
// 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