Browse Source

Day 19

master
Chris Smith 7 years ago
parent
commit
0bc768123a
1 changed files with 84 additions and 0 deletions
  1. 84
    0
      19.py

+ 84
- 0
19.py View File

@@ -0,0 +1,84 @@
1
+#!/usr/bin/python3
2
+
3
+"""Solution for day 19 of Advent of Code 2016.
4
+
5
+There are two different solutions presented here. The "manually" methods simulate the present-thieving step by step
6
+to get the results. I used these to figure out the patterns to both part 1 and part 2 and thus write simple, super
7
+quick formulae to get the answer.
8
+
9
+For part 1, the results look something like this:
10
+
11
+  Number of Elves |  Winning Elf
12
+  1               |  0
13
+  2               |  0
14
+  3               |  2
15
+  4               |  0
16
+  5               |  2
17
+  6               |  4
18
+  7               |  6
19
+  8               |  0
20
+
21
+So if the number of elves is a power of two, then the first elf wins. Otherwise, the winning elf is the one with a
22
+number double the difference between the last power of two and the number of elves.
23
+
24
+For part 2, the results are more complicated (as you'd expect!):
25
+
26
+  Number of Elves |  Winning Elf
27
+  1               |  0
28
+  2               |  0
29
+  3               |  2
30
+  4               |  0
31
+  5               |  1
32
+  6               |  2
33
+  7               |  4
34
+  8               |  6
35
+  9               |  8
36
+  10              |  0
37
+  11              |  1
38
+  12              |  2
39
+  13              |  3
40
+  ...             |  ...
41
+  18              |  8
42
+  19              |  10
43
+  20              |  12
44
+  ...             |  ...
45
+  28              |  0
46
+
47
+The points where elf 0 wins (and the sequence resets) now follow the pattern 3^n+1 (instead of 2^n from part 1).
48
+Between those points, the winning elf increases by 1 for the first 3^n elves, then by 2 thereafter.
49
+"""
50
+
51
+import math
52
+
53
+seed = 3004953
54
+
55
+print('Part one: %s' % (1 + 2 * int(seed - 2 ** math.floor(math.log(seed, 2)))))
56
+
57
+lp = 3 ** int(math.floor(0.0001 + math.log(seed - 1, 3)))  # Add a small amount to avoid floating point errors
58
+print('Part two: %s' % ((seed - lp) * (1 + max(0, (seed - 2 * lp) / (lp + 1)))))
59
+
60
+
61
+def run_part1_manually(n):
62
+    elves = {}
63
+    for i in range(n):
64
+        elves[i] = i + 1 if i < n - 1 else 0
65
+    current = 0
66
+    while len(elves) > 1:
67
+        neighbour = elves[current]
68
+        elves[current] = elves[neighbour]
69
+        del elves[neighbour]
70
+        current = elves[current]
71
+    return elves.keys()[0]
72
+
73
+
74
+def run_part2_manually(n):
75
+    elves = range(n)
76
+    current = 0
77
+    while len(elves) > 1:
78
+        target = (current + int(math.floor(len(elves) / 2))) % len(elves)
79
+        del elves[target]
80
+        if target > current:
81
+            current = (current + 1) % len(elves)
82
+        else:
83
+            current %= len(elves)
84
+    return elves[0]

Loading…
Cancel
Save