Skip to content

Instantly share code, notes, and snippets.

@WhiskeyTuesday
Last active March 27, 2022 09:07
Show Gist options
  • Save WhiskeyTuesday/16167b19cc4c13ef9b0c7bfb0c0e7d9e to your computer and use it in GitHub Desktop.
Save WhiskeyTuesday/16167b19cc4c13ef9b0c7bfb0c0e7d9e to your computer and use it in GitHub Desktop.
Impromptu travelling monk kata
/*
Proof that the monk ascending the hill and the monk descending the hill
in the riddle do cross within a meter of each other at some point along
the path to the temple even if they are moving at random speeds.
Technically this doesn't ensure that the trips take equal time to cover
equal distance, but it actually doesn't matter. That part of the question
is a red herring, as is the day usually specified to have been spent on
the mountaintop in between. Because the two journies (or you can think of
it as two diffent monks leaving at the same time) are conducted at the
same average speed the meeting occurs somewhere near the middle of the
distance, if the descending monk was going much faster the two would
meet closer to the bottom, and the opposite is also obviously true
anyway, it's relatively simple if you imagine it as two monks but if
you need to prove it to youself and you understand javascript, here's your
proof I guess.
AUTHOR - @WhiskeyTuesday
LICENCE - WTFPL 3.1 - https://ph.dtf.wtf/u/wtfplv31 for more details.
*/
// create an array where each element represents the distance travelled
// (between 0 and 100 milimeters) in one second (over a 24 hour period)
const ascent = [...Array(24 * 60 * 60)]
.map(() => Math.floor(Math.random() * 100));
// you may understand this easier as a map over ascent where we sum
// all of ascent up to the current index at each element (but this
// is like a billion times faster so I did it this way)
const ascentPositionsAtTimes = [...ascent];
ascentPositionsAtTimes.forEach((distanceCovered, idx) => {
const positionSoFar = idx === 0
? 0
: ascentPositionsAtTimes[idx - 1];
ascentPositionsAtTimes[idx] = positionSoFar + distanceCovered;
return 0;
});
// the same as the ascent (but measured from the top, obviously)
const descent = [...Array(24 * 60 * 60)]
.map(() => Math.floor(Math.random() * 100));
// calculate the total distance travelled
const totalDistance = ascent.reduce((acc, distance) => acc + distance);
// this is the same as on the way up except the absolute position
// with 0 as the bottom and totalDistance as the top is
// calculated by subtracting the distance covered so far from the
// totalDistance we calculated before
const descentPositionsAtTimes = [...descent];
descentPositionsAtTimes.forEach((distanceCovered, idx) => {
const distanceRemaining = idx === 0
? totalDistance
: descentPositionsAtTimes[idx - 1];
descentPositionsAtTimes[idx] = distanceRemaining - distanceCovered;
return 0;
});
// now we iterate through each one second "slice" of time on the
// descent trip and see what the absolute position in mms was
// and what the absolute position in mms of the ascending monk
// was at the same timestamp is and if the two positions are
// within 1 meter of each other's at the same timestamp we
// console log the timestamp (array index) and position of
// each monk
descentPositionsAtTimes.forEach((pos, idx) => {
const within1mBelow = pos > ascentPositionsAtTimes[idx] - 1000;
const within1mAbove = pos < ascentPositionsAtTimes[idx] + 1000;
if (within1mAbove && within1mBelow) {
console.log(idx, ascentPositionsAtTimes[idx], pos);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment