Quest 13: Unlocking the Mountain
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
Link to participate: https://everybody.codes/


Python
A much simpler problem compared to earlier ones
# generator to yield dial values in the required order # yields (value: str, is_reverse: bool) def yield_dial_vals(coll: list): n = len(coll) for i in range(0, n, 2): yield coll[i], False right_start = n - 2 if n % 2 == 1 else n - 1 for i in range(right_start, -1, -2): yield coll[i], True def part1(data: str): nums = data.splitlines() n = len(nums) # total number of values on the dial # + 1 for the '1' value total_vals = n + 1 # effective rotation after full cycles effective_rot = 2025 % total_vals # if full cycles, return '1' if effective_rot == 0: return 1 # adjust for 0-indexing the remaining dial values effective_rot -= 1 # skip numbers on the dial until we reach the final value val_gen = yield_dial_vals(nums) for _ in range(effective_rot): next(val_gen) # return the final value return int(next(val_gen)[0]) assert (t := part1("""72 58 47 61 67""")) == 67, f"Expected: 67, Actual: {t}" def part2(data: str, rotations = 20252025): ranges = data.splitlines() # count values on the dial other than '1' n = 0 for val, _ in yield_dial_vals(ranges): a, b = map(int, val.split("-")) n += b - a + 1 # total number of values on the dial # + 1 for the '1' value total_vals = n + 1 # effective rotation after full cycles effective_rot = rotations % total_vals # if full cycles, return '1' if effective_rot == 0: return 1 # adjust for 0-indexing the remaining dial values effective_rot -= 1 # iterate through ranges until we reach the one the dial lands on for val, is_reverse in yield_dial_vals(ranges): # get range bound and size a, b = map(int, val.split("-")) r = b - a + 1 # check if the dial lands within this range if effective_rot < r: # it does! # return the appropriate value in the range based on direction if is_reverse: return b - effective_rot else: return a + effective_rot # consume the rotations for skipping this range effective_rot -= r assert False, "Should have found the target range" assert part2("""10-15 12-13 20-21 19-23 30-37""") == 30 # part 3 is just part 2 with a larger number of rotations from functools import partial part3 = partial(part2, rotations = 202520252025)I just noticed that you’re probably the first person I’ve seen to include tests.
Yeah, it’s an easy way to make sure everything is working correctly when I refactor or optimize. I used to keep samples in their own text files before but EC samples are small enough to include directly.