From 39e09dd36e7976d3a960a0a9644e2ef4621dca0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Engl=C3=B6f=20Ytterstr=C3=B6m?= Date: Thu, 5 Dec 2024 01:12:43 +0100 Subject: [PATCH] Solve 2016:19 p1-2 "An Elephant Named Joseph" Learned a lot about the Josephus' Problem today! Solved part 1 by using a dict, but eventually ended up just adding the mathematical shortcut and rewriting both parts to use deque() for performance. Part 2 was tricky, since k (the elf to remove after all presents were stolen from them) is a index that changes over time. No tries for a solution that was performant enough using lists and dicts were succesfull, so by inspiration from the subreddit the final solution code is based on 2 deque() that pops and appends between them. There are 2 part 1 solutions. - A correct implementation of the Josephus' Problem, using deque(). Recursion would have worked as well, but Python do not like recursions. - The mathematical superior version, with a link to the Youtube video were it is introduced. --- 2016-python2/output/day_19.py | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 2016-python2/output/day_19.py diff --git a/2016-python2/output/day_19.py b/2016-python2/output/day_19.py new file mode 100644 index 0000000..2abd264 --- /dev/null +++ b/2016-python2/output/day_19.py @@ -0,0 +1,52 @@ +from collections import deque + + +def solve(data): + elfes = int(data) + p1 = left_adjacent_rule(elfes) + p1b = mathematical_superiority(elfes) + p2 = opposite_side_rule(elfes) + assert p1 == p1b + return p1, p2 + + +def mathematical_superiority(num_elfes): + # Josephus' problem, quick method: + # https://www.youtube.com/watch?v=uCsD3ZGzMgE + b = format(num_elfes, "b") + return int(b[1:] + b[0], 2) + + +def left_adjacent_rule(num_elfes): + # https://en.wikipedia.org/wiki/Josephus_problem + q = deque(list(range(1, num_elfes + 1))) + while len(q) > 1: + q.rotate(-1) + q.popleft() + return q.pop() + + +def opposite_side_rule(num_elfes): + elfes = list(range(1, num_elfes + 1)) + separator = num_elfes // 2 + L, R = deque(elfes[:separator]), deque(elfes[separator:]) + + while L and R: + R.popleft() + l2r = L.popleft() + R.append(l2r) + if len(R) - len(L) != 1: + r2l = R.popleft() + L.append(r2l) + + return R.pop() + + +if __name__ == "__main__": + with open("./input/19.txt", "r") as f: + inp = f.read().strip() + + p1, p2 = solve(inp) + + print(p1) + print(p2)