Skip to content

Instantly share code, notes, and snippets.

@aviwarner
Created October 12, 2017 22:01
Show Gist options
  • Save aviwarner/4ff2dc7e288730cd3e855b5b948cba42 to your computer and use it in GitHub Desktop.
Save aviwarner/4ff2dc7e288730cd3e855b5b948cba42 to your computer and use it in GitHub Desktop.
Ongoing notes and scripting for the Heaviest ball problem
/*
1) First: figure out how I would resolve this classic issue (complication comes with more possible balls)
For 8 balls (classic): Weigh 3 and 3, if both equal, weigh last two. If one pan is heavier, weigh 2 balls from that pan. One will be heavier or they'll be equal, in which case last one is heaviest. Works with up to 9 balls.
For 27 balls: Divide by 3, weigh 9 and 9. If one is heavier, follow 9 ball 2 weighing pattern above. If not, follow 9 ball 2 weighing on the unweighed set of 9.
For 81 balls: same as above. Divide in 3. Do 27 ball process with heaviest group of 27.
For 243: same as above, add one more step (weighing 81 and 81)
For 729: same as above, add one more step (weighing 243 and 243)
That's great EXCEPT, pattern is more complex if there's a number of balls between those ranges.
There's a general pattern here though. This looks like a good candidate for a switch statement.
1 ball: you got it
2 balls: weigh em
3 balls: 3
4 balls: 4-2 / 2 = 1 => 1,1,1,1
5 balls: 5-1 / 2 = 2 => 2,2,1
6 balls: 6 / 2 = 3
7 balls: 7-1 / 2 = 3 => 3,3,1
8 balls: 8-2 / 2 = 3 => 3,3,2
9 balls: 9 / 3 = 3
So any number up to 27 can be completed by breaking it down to the level above
10 > 5 & 5
11 > 5 & 5, 1
12 > 6 & 6
13 > 6 & 6, 1
14 > 7 & 7
15 > 7 & 7, 1
16 > 8 & 8
17 > 8 & 8, 1
18 > 9 & 9
19 > 9 & 9, 1
20 > 9 & 9, 2
21 > 9 & 9, 3
...
var remainder = 0;
var panLeft;
var panRight;
if (balls <= 18) {
if (balls % 2 === 0) {
panLeft = balls/2;
panRight = balls/2;
} else {
panLeft = (balls - 1)/2;
panRight = (balls - 1)/2;
remainder = 1;
}
}
2) Now that the solution is basically worked out. Try and build out 1-9 using a switch statement.
3) I was able to do so on codewars w code:
function findBall(scales) {
switch (scales.getWeight([0,1,2], [3,4,5])) {
case 0:
if (scales.getWeight([6],[7]) === -1) {
return 6;
} else {
return 7;
}
break;
case -1:
var secondWeighing = scales.getWeight([0],[1]);
if (secondWeighing === -1) {
return 0;
} else if (secondWeighing === 1) {
return 1;
} else {
return 2;
}
break;
case 1:
var secondWeighing = scales.getWeight([3],[4]);
if (secondWeighing === -1) {
return 3;
} else if (secondWeighing === 1) {
return 4;
} else {
return 5;
}
break;
}
}
4) Ideally though, I'd want this as a more straightforward function I could call later. Plus, as written, it doesn't really scale 1-9 balls
function idea: determine heaviest of 2 or 3 balls
function heaviestTwoThree(firstBall, lastBall) {
switch(scales.getWeight([firstBall], [firstBall + 1])) {
case 0:
return lastBall;
case -1:
return firstBall;
case 1:
return firstBall + 1;
}
}
5) That *could* simplify. First let's write out a function that resolves for any number of balls between 1-9
function findBall(scales, ball_count) {
switch(ball_count) {
case 0:
return '';
case 1:
return [0];
case 2:
heaviestTwoThree(0,1)
}
}
*/
function findBall(scales, ball_count) {
switch(ball_count) {
case 0:
return '';
case 1:
return 1;
case 2:
case 3:
var w = scales.getWeight([0],[1]);
if (w === -1) {
return 1;
} else if (w === 1) {
return 2;
} else {
return 3;
}
case 4:
case 5:
var w = scales.getWeight([0,1],[2,3]);
if (w === -1) {
if (scales.getWeight([0],[1]) === -1 {
return 1;
} else {
return 2;
}
} else if (w === 1) {
if (scales.getWeight([2],[3]) === -1 {
return 3;
} else {
return 4;
}
} else {
return 5;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment