├── .gitignore ├── Makefile ├── README.md ├── day01.py ├── day02.py ├── day03.py ├── day04.py ├── day05.py ├── day06.cpp ├── day06.py ├── day07.cpp ├── day08.hs ├── day08.py ├── day09.cpp ├── day10.py ├── day11.cpp ├── day12.cpp ├── day13.py ├── day14a.cpp ├── day14b.cpp ├── day15.py ├── day16.py ├── day17.py ├── day18.cpp ├── day18.py ├── day19.cpp ├── day19.py ├── day20.py ├── day21.py ├── day22.cpp ├── day22.py ├── fetch-input.sh ├── template.cpp ├── template.py └── util.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | misc/ 2 | .sessionkey 3 | .*.swp 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CPPFLAGS=-std=c++11 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | My solutions for [Advent of Code 2018](https://adventofcode.com/2018). 2 | 3 | These solutions prioritize typing speed above just about everything else, and 4 | contain a number of regrettable design decisions. Please don't judge too 5 | harshly! 6 | -------------------------------------------------------------------------------- /day01.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools 4 | 5 | deltas = [int(line.strip()) for line in sys.stdin] 6 | 7 | print "sum:", sum(deltas) 8 | 9 | current = 0 10 | freqs = set([current]) 11 | for delta in itertools.cycle(deltas): 12 | current += delta 13 | if current in freqs: 14 | print "duplicate:", current 15 | break 16 | freqs.add(current) 17 | -------------------------------------------------------------------------------- /day02.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | def diff(a,b): 6 | n = 0 7 | for c1, c2 in zip(a,b): 8 | if c1 != c2: 9 | n += 1 10 | return n 11 | 12 | words = [] 13 | 14 | a = b = 0 15 | for line in sys.stdin: 16 | line = line.strip() 17 | words.append(line) 18 | c = collections.Counter(line) 19 | c2 = set(c.values()) 20 | if 2 in c2: 21 | a += 1 22 | if 3 in c2: 23 | b += 1 24 | print a, b, a*b 25 | 26 | for a in words: 27 | for b in words: 28 | if diff(a,b) == 1: 29 | print ''.join(c1 for c1,c2 in zip(a,b) if c1==c2) 30 | -------------------------------------------------------------------------------- /day03.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | 6 | grid = [[0]*1000 for i in xrange(1000)] 7 | claims = [] 8 | 9 | for line in sys.stdin: 10 | line = line.strip() 11 | a, rest = line.split('@') 12 | b, c = rest.split(':') 13 | 14 | left, top = [int(x.strip()) for x in b.split(',')] 15 | width, height = [int(x.strip()) for x in c.split('x')] 16 | 17 | for i in xrange(top, top+height): 18 | for j in xrange(left, left+width): 19 | grid[i][j] += 1 20 | claims.append((a, left, top, left+width-1, top+height-1)) 21 | 22 | n = 0 23 | for row in grid: 24 | for col in row: 25 | if col > 1: 26 | n += 1 27 | print n 28 | 29 | 30 | for a, ax1, ay1, ax2, ay2 in claims: 31 | overlaps = False 32 | for b, bx1, by1, bx2, by2 in claims: 33 | if a == b: continue 34 | if not ((ax1 > bx2) or (bx1 > ax2) or (ay1 > by2) or (by1 > ay2)): 35 | overlaps = True 36 | break 37 | if overlaps: break 38 | if not overlaps: 39 | print a 40 | 41 | -------------------------------------------------------------------------------- /day04.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | mins = collections.defaultdict(lambda: [0]*60) 6 | 7 | lines = [] 8 | current_id = None 9 | for line in sys.stdin: 10 | line = line.strip() 11 | lines.append(line) 12 | 13 | lines.sort() 14 | for line in lines: 15 | if 'begins shift' in line: 16 | a, b = line.split('#') 17 | c = b.split(' ') 18 | current_id = int(c[0]) 19 | 20 | else: 21 | t = int(line[15:17]) 22 | if 'falls asleep' in line: 23 | sleep = t 24 | elif 'wakes up' in line: 25 | wake = t 26 | print current_id, "sleeping", sleep, wake 27 | for i in xrange(sleep, wake): 28 | mins[current_id][i] += 1 29 | 30 | guard_id = max(mins, key = lambda x: sum(mins[x])) 31 | counts = mins[guard_id] 32 | minute = max(xrange(len(counts)), key = lambda x: counts[x]) 33 | print guard_id, minute, guard_id*minute 34 | 35 | a = max([(mins[guard_id][i], guard_id, i) for guard_id in mins for i in xrange(60)]) 36 | print a 37 | print a[1]*a[2] 38 | -------------------------------------------------------------------------------- /day05.py: -------------------------------------------------------------------------------- 1 | def eval(x): 2 | s = [] 3 | for c in x: 4 | if s and ((c.isupper() and c.lower() == s[-1]) or (c.islower() and c.upper() == s[-1])): 5 | s.pop() 6 | else: 7 | s.append(c) 8 | return ''.join(s) 9 | 10 | x = raw_input() 11 | print len(eval(x)) 12 | print min(len(eval(x.replace(c,'').replace(c.upper(),''))) for c in set(x.lower())) 13 | -------------------------------------------------------------------------------- /day06.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | typedef util::point point; 6 | 7 | int main() { 8 | const regex pattern("([0-9]+), ([0-9]+)"); 9 | 10 | vector points; 11 | 12 | int minx = 999999, maxx = -999999, miny = 999999, maxy = -999999; 13 | 14 | for (string l : util::lines(cin)) { 15 | smatch m = util::rmatch(l, pattern); 16 | point p = {stoi(m[1]), stoi(m[2])}; 17 | 18 | minx = min(minx, p.x); 19 | maxx = max(maxx, p.x); 20 | miny = min(miny, p.y); 21 | maxy = max(maxy, p.y); 22 | 23 | points.push_back(p); 24 | } 25 | cout << minx << "," << maxx << "," << miny << "," << maxy << endl; 26 | 27 | unordered_map counts; 28 | unordered_set infinite; 29 | 30 | for (int x = minx; x <= maxx; x++) { 31 | for (int y = miny; y <= maxy; y++) { 32 | int mindist = 999999; 33 | int idx = -1; 34 | for (int i = 0; i < points.size(); i++) { 35 | int d = abs(x-points[i].x)+abs(y-points[i].y); 36 | if (d < mindist) { 37 | mindist = d; 38 | idx = i; 39 | } else if (d == mindist) { 40 | idx = -1; 41 | } 42 | } 43 | if (idx == -1) continue; 44 | 45 | if (x == minx || x == maxx || y == miny || y == maxy) { 46 | infinite.insert(idx); 47 | } 48 | counts[idx]++; 49 | } 50 | } 51 | 52 | int max_value = -1; 53 | for (auto& it : counts) { 54 | if (infinite.count(it.first) == 0) { 55 | max_value = max(max_value, it.second); 56 | } 57 | } 58 | cout << "part 1: " << max_value << endl; 59 | 60 | int safe_count = 0; 61 | for (int x = minx; x <= maxx; x++) { 62 | for (int y = miny; y <= maxy; y++) { 63 | ll d = 0; 64 | for (point& p : points) { 65 | d += abs(x-p.x)+abs(y-p.y); 66 | } 67 | if (d < 10000) { 68 | safe_count++; 69 | } 70 | } 71 | } 72 | cout << "part 2: " << safe_count << endl; 73 | } 74 | -------------------------------------------------------------------------------- /day06.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | points = [] 6 | for line in sys.stdin: 7 | line = line.strip() 8 | x, y = map(int, line.split(', ')) 9 | points.append((x,y)) 10 | 11 | minx = min(p[0] for p in points)-10 12 | miny = min(p[1] for p in points)-10 13 | maxx = max(p[0] for p in points)+10 14 | maxy = max(p[1] for p in points)+10 15 | 16 | counts = collections.defaultdict(int) 17 | infinite = set() 18 | 19 | for x in xrange(minx, maxx+1): 20 | for y in xrange(miny, maxy+1): 21 | mindist = 999999999 22 | idx = None 23 | for i, (x2, y2) in enumerate(points): 24 | d = abs(x2-x)+abs(y2-y) 25 | if d < mindist: 26 | mindist = d 27 | idx = i 28 | elif d == mindist: 29 | idx = None 30 | if x == minx or x == maxx or y == miny or y == maxy: 31 | infinite.add(idx) 32 | if idx is not None: 33 | counts[idx]+=1 34 | 35 | max_value, max_idx = max((counts[i], i) for i in counts if i not in infinite) 36 | print max_value 37 | 38 | safe_count=0 39 | for i in xrange(minx, maxx): 40 | for j in xrange(miny, maxy): 41 | d = 0 42 | for i2, j2 in points: 43 | d += abs(i-i2)+abs(j-j2) 44 | if d < 10000: 45 | safe_count += 1 46 | print safe_count 47 | -------------------------------------------------------------------------------- /day07.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | vector> edges; 8 | 9 | for (string l : util::lines(cin)) { 10 | int a = l[5] - 'A'; 11 | int b = l[36] - 'A'; 12 | edges.push_back({a,b}); 13 | cout << edges.back().first << "," << edges.back().second << endl; 14 | } 15 | 16 | { 17 | vector counts(26); 18 | vector done(26); 19 | for (auto& a : edges) { 20 | counts[a.second]++; 21 | } 22 | cout << counts << endl; 23 | 24 | while (true) { 25 | int next = -1; 26 | for (int i = 0; i < 26; i++) { 27 | if (!done[i] && counts[i] == 0) { 28 | next = i; 29 | break; 30 | } 31 | } 32 | if (next == -1) break; 33 | 34 | done[next] = true; 35 | cout << (char) (next + 'A'); 36 | for (auto& a : edges) { 37 | if (a.first == next) { 38 | counts[a.second]--; 39 | } 40 | } 41 | } 42 | cout << endl; 43 | } 44 | 45 | { 46 | vector counts(26); 47 | vector done(26); 48 | for (auto& a : edges) { 49 | counts[a.second]++; 50 | } 51 | cout << counts << endl; 52 | 53 | int t = 0; 54 | priority_queue, vector>, std::greater>> q; 55 | int active = 0; 56 | 57 | while (true) { 58 | bool added = false; 59 | cerr << "t=" << t << endl; 60 | if (q.size() < 5) { 61 | int next = -1; 62 | for (int i = 0; i < 26; i++) { 63 | if (!done[i] && counts[i] == 0) { 64 | next = i; 65 | break; 66 | } 67 | } 68 | cerr << " start next=" << ((char) (next+'A')) << endl; 69 | if (next != -1) { 70 | q.push({(t+next+61)*100+next, next}); 71 | done[next] = true; 72 | added = true; 73 | } 74 | } 75 | if (!added) { 76 | if (q.size() > 0) { 77 | pair p = q.top(); 78 | q.pop(); 79 | t = p.first/100; 80 | cerr << " done " << ((char) (p.second+'A')) << endl; 81 | 82 | for (auto& a : edges) { 83 | if (a.first == p.second) { 84 | counts[a.second]--; 85 | } 86 | } 87 | } else { 88 | break; 89 | } 90 | } 91 | 92 | } 93 | cout << t << endl; 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /day08.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Control.Monad.State 3 | import Data.List 4 | 5 | data Node = Node { metadata :: [Int], children :: [Node] } 6 | deriving Show 7 | 8 | type Parser = State [Int] 9 | 10 | getNext :: Parser Int 11 | getNext = state (\(x:xs) -> (x, xs)) 12 | 13 | parseTree :: Parser Node 14 | parseTree = do 15 | numChildren <- getNext 16 | numMetadata <- getNext 17 | children <- replicateM numChildren parseTree 18 | metadata <- replicateM numMetadata getNext 19 | return (Node metadata children) 20 | 21 | toTree :: [Int] -> Node 22 | toTree = evalState parseTree 23 | 24 | value1 :: Node -> Int 25 | value1 (Node m c) = sum m + sum (map value1 c) 26 | 27 | value2 :: Node -> Int 28 | value2 (Node m []) = sum m 29 | value2 (Node m c) = sum [value2 (c !! i) | i <- m_, i < (length c)] 30 | where m_ = map (subtract 1) m 31 | 32 | easyInput = [2, 3, 0, 3, 10, 11, 12, 1, 1, 0, 1, 99, 2, 1, 1, 2] 33 | 34 | main = do 35 | let tree = toTree easyInput 36 | putStrLn $ "Part 1: " ++ (show (value1 tree)) 37 | putStrLn $ "Part 2: " ++ (show (value2 tree)) 38 | -------------------------------------------------------------------------------- /day08.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | data = [int(x) for x in sys.stdin.read().split()] 6 | 7 | Node = collections.namedtuple('Node', 'metadata children') 8 | 9 | pos = 0 10 | def get(): 11 | global pos 12 | if pos == len(data): 13 | return None 14 | x = data[pos] 15 | pos += 1 16 | return x 17 | 18 | def read_node(): 19 | nc = get() 20 | nm = get() 21 | children = [] 22 | for i in xrange(nc): 23 | children.append(read_node()) 24 | metadata = [] 25 | for i in xrange(nm): 26 | metadata.append(get()) 27 | return Node(metadata, children) 28 | 29 | def sum_m(node): 30 | return sum(node.metadata) + sum(sum_m(n) for n in node.children) 31 | 32 | def value(node): 33 | if node.children: 34 | x = 0 35 | for i in node.metadata: 36 | i -= 1 37 | if 0 <= i < len(node.children): 38 | x += value(node.children[i]) 39 | return x 40 | else: 41 | return sum(node.metadata) 42 | root = read_node() 43 | print sum_m(root) 44 | 45 | print value(root) 46 | -------------------------------------------------------------------------------- /day09.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void fwd(list& l, list::iterator& it) { 8 | it++; 9 | if (it == l.end()) { 10 | it = l.begin(); 11 | } 12 | } 13 | void back(list& l, list::iterator& it) { 14 | if (it == l.begin()) { 15 | it = l.end(); 16 | } 17 | it--; 18 | } 19 | 20 | 21 | int main() { 22 | int players, marbles; 23 | cin >> players >> marbles; 24 | 25 | vector scores(players); 26 | list circle; 27 | circle.push_back(0); 28 | list::iterator ptr = circle.begin(); 29 | 30 | for (int i = 1; i <= marbles; i++) { 31 | //cout << circle << circle[ptr] << endl; 32 | int pl = (i-1+players) % players; 33 | 34 | if (i % 23 != 0) { 35 | for (int j = 0; j < 2; j++) fwd(circle, ptr); 36 | ptr = circle.insert(ptr, i); 37 | } else { 38 | scores[pl] += i; 39 | for (int j = 0; j < 7; j++) back(circle, ptr); 40 | scores[pl] += *ptr; 41 | ptr = circle.erase(ptr); 42 | if (ptr == circle.end()) ptr = circle.begin(); 43 | } 44 | } 45 | cout << *max_element(scores.begin(), scores.end()) << endl; 46 | } 47 | -------------------------------------------------------------------------------- /day10.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | t = int(sys.argv[1]) 6 | 7 | points = [] 8 | for line in sys.stdin: 9 | line = line.strip() 10 | x = int(line[10:16].strip()) 11 | y = int(line[18:24].strip()) 12 | vx = int(line[36:38].strip()) 13 | vy = int(line[40:42].strip()) 14 | points.append((x+t*vx, y+t*vy)) 15 | 16 | x0 = min(p[0] for p in points) 17 | x1 = max(p[0] for p in points)+1 18 | y0 = min(p[1] for p in points) 19 | y1 = max(p[1] for p in points)+1 20 | 21 | rows = [[' ']*(x1-x0) for i in xrange(y0, y1)] 22 | for x,y in points: 23 | rows[y-y0][x-x0] = '#' 24 | 25 | print y1-y0 26 | for row in rows: 27 | print ''.join(row) 28 | -------------------------------------------------------------------------------- /day11.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | const int serial = 9005; 7 | 8 | vector> cells(400, vector(300)); 9 | 10 | for (int x = 0; x < 300; x++) { 11 | for (int y = 0; y < 300; y++) { 12 | int power = (x+10)*y; 13 | power += serial; 14 | power *= (x+10); 15 | power = (power / 100) % 10; 16 | power -= 5; 17 | cells[x][y] = power; 18 | //cout << cells[x][y] << endl; 19 | } 20 | } 21 | 22 | int m = -9999; 23 | int mx = -1, my = -1, ms = -1; 24 | for (int x = 0; x <= 299; x++) { 25 | cout << "X=" << x << endl; 26 | for (int y = 0; y <= 299; y++) { 27 | int total = 0; 28 | for (int size = 1; size <= min(300-x,300-y); size++) { 29 | for (int i = 0; i < size; i++) { 30 | total += cells[x+i][y+size-1]; 31 | } 32 | for (int j = 0; j < size-1; j++) { 33 | total += cells[x+size-1][y+j]; 34 | } 35 | 36 | if (total > m) { 37 | m = total; 38 | mx = x; 39 | my = y; 40 | ms = size; 41 | } 42 | } 43 | } 44 | } 45 | cout << m << " " << mx << " " << my << " " << ms << endl; 46 | } 47 | -------------------------------------------------------------------------------- /day12.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | //for (string l : util::lines(cin)) { 7 | //} 8 | string word, initial; 9 | cin >> word >> word >> initial; 10 | 11 | vector table(32); 12 | for (int i = 0; i < 32; i++) { 13 | string a, b; 14 | cin >> a >> word >> b; 15 | int mask = 0; 16 | for (int i = 0; i < 5; i++) { 17 | if (a[i] == '#') { 18 | mask |= (1< state(100000); 28 | for (int i = 0; i < initial.length(); i++) { 29 | state[50000+i] = initial[i] == '#'; 30 | } 31 | 32 | 33 | int last = 0; 34 | for (int i = 0; i < 50000; i++) { 35 | int a=99999, b=-9999; 36 | 37 | vector next(100000); 38 | for (int j = 0+2; j < 100000-2; j++) { 39 | int mask = 0; 40 | for (int k = 0; k < 5; k++) { 41 | if (state[j-2+k]) mask |= (1<': (0,'-'), '^': (1,'|'), '<': (2,'-'), 'v': (3,'|')}.get(c,None) 32 | if t: 33 | dir, grid[i][j] = t 34 | carts[next_id] = Cart(i, j, dir) 35 | next_id += 1 36 | 37 | occupied = dict(((c.i,c.j),i) for (i,c) in carts.items()) 38 | while len(carts) >= 2: 39 | skip = set() 40 | for id1, cart in sorted(carts.items(), key = lambda (id,c): (c.i,c.j)): 41 | if id1 in skip: 42 | continue 43 | i2 = cart.i + deltai[cart.dir] 44 | j2 = cart.j + deltaj[cart.dir] 45 | del occupied[cart.i,cart.j] 46 | if (i2, j2) in occupied: 47 | id2 = occupied[i2,j2] 48 | del occupied[i2,j2] 49 | skip.add(id1) 50 | skip.add(id2) 51 | print "removing", id1, id2, "at", (j2, i2) 52 | continue 53 | 54 | cart.i = i2 55 | cart.j = j2 56 | occupied[cart.i,cart.j] = id1 57 | 58 | c = grid[i2][j2] 59 | if c == '/': 60 | cart.dir ^= 1 61 | elif c == '\\': 62 | cart.dir = 3-cart.dir 63 | elif c == '+': 64 | cart.dir = (cart.dir + deltadir[cart.state%3] + 4) % 4 65 | cart.state += 1 66 | for id in skip: 67 | del carts[id] 68 | 69 | print "final", [(c.j,c.i) for c in carts.values()] 70 | -------------------------------------------------------------------------------- /day14a.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int target; 7 | cin >> target; 8 | 9 | list board; 10 | board.push_back(3); 11 | board.push_back(7); 12 | list::iterator it1 = board.begin(); 13 | list::iterator it2 = it1; 14 | it2++; 15 | 16 | cout << board << endl; 17 | int n = 2; 18 | vector result; 19 | bool done = false; 20 | 21 | while (!done) { 22 | int a = *it1, b = *it2; 23 | int next = a+b; 24 | vector buf; 25 | if (next == 0) { 26 | buf.push_back(0); 27 | } 28 | while (next > 0) { 29 | buf.push_back(next % 10); 30 | next /= 10; 31 | } 32 | reverse(buf.begin(), buf.end()); 33 | for (auto i : buf) { 34 | //cout << "n=" << n << endl; 35 | if (n >= target + 10) { 36 | done = true; 37 | break; 38 | } 39 | if (n >= target) { 40 | result.push_back(i); 41 | } 42 | board.push_back(i); 43 | n++; 44 | 45 | } 46 | for (int i = 0; i < a+1; i++) { 47 | it1++; 48 | if (it1 == board.end()) it1 = board.begin(); 49 | } 50 | for (int i = 0; i < b+1; i++) { 51 | it2++; 52 | if (it2 == board.end()) it2 = board.begin(); 53 | } 54 | //cout << board << endl; 55 | } 56 | 57 | for (auto i : result) { 58 | cout << i; 59 | } 60 | cout << endl; 61 | } 62 | -------------------------------------------------------------------------------- /day14b.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int target; 7 | cin >> target; 8 | 9 | list board; 10 | board.push_back(3); 11 | board.push_back(7); 12 | list::iterator it1 = board.begin(); 13 | list::iterator it2 = it1; 14 | it2++; 15 | 16 | cout << board << endl; 17 | int n = 2; 18 | int result; 19 | bool done = false; 20 | 21 | while (!done) { 22 | int a = *it1, b = *it2; 23 | int next = a+b; 24 | vector buf; 25 | if (next == 0) { 26 | buf.push_back(0); 27 | } 28 | while (next > 0) { 29 | buf.push_back(next % 10); 30 | next /= 10; 31 | } 32 | reverse(buf.begin(), buf.end()); 33 | for (auto i : buf) { 34 | n++; 35 | result *= 10; 36 | result += i; 37 | result %= 1000000; 38 | if (result == target) { 39 | cout << (n-6) << endl; 40 | return 0; 41 | } 42 | board.push_back(i); 43 | 44 | } 45 | for (int i = 0; i < a+1; i++) { 46 | it1++; 47 | if (it1 == board.end()) it1 = board.begin(); 48 | } 49 | for (int i = 0; i < b+1; i++) { 50 | it2++; 51 | if (it2 == board.end()) it2 = board.begin(); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /day15.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | board = [] 6 | for line in sys.stdin: 7 | line = line.strip() 8 | board.append(list(line)) 9 | 10 | elfpower = 25 11 | 12 | N = len(board) 13 | M = len(board[0]) 14 | 15 | State = collections.namedtuple('State', 'il jl i0 j0 i j') 16 | hp = {} 17 | n = collections.defaultdict(int) 18 | for i in xrange(N): 19 | for j in xrange(M): 20 | if board[i][j] in ('E','G'): 21 | hp[i,j] = 200# if board[i][j] == 'G' else 1390 22 | n[board[i][j]] += 1 23 | 24 | rounds = 0 25 | while True: 26 | print "rounds=", rounds, n 27 | for line in board: 28 | print ''.join(line) 29 | print sorted(hp.items()) 30 | print 31 | 32 | starts = [] 33 | for i in xrange(N): 34 | for j in xrange(M): 35 | if board[i][j] in ('E','G'): 36 | starts.append((i,j)) 37 | 38 | combat_done = False 39 | skip = set([]) 40 | for i,j in starts: 41 | if (i,j) in skip: 42 | continue 43 | print i, j, "moving" 44 | if board[i][j] == '.': 45 | continue 46 | queue = [State(i,j,i,j,i,j)] 47 | visited = set([]) 48 | target = 'E' if board[i][j] == 'G' else 'G' 49 | if n[target] == 0: 50 | combat_done = True 51 | break 52 | 53 | best = None 54 | dist = 0 55 | while queue and not best: 56 | #print queue 57 | next = [] 58 | for state in sorted(queue): 59 | if (state.i,state.j,state.i0,state.j0) in visited: 60 | continue 61 | visited.add((state.i,state.j,state.i0,state.j0)) 62 | if board[state.i][state.j] == target: 63 | best = state 64 | break 65 | for di,dj in [(0,1),(0,-1),(1,0),(-1,0)]: 66 | i2 = state.i+di 67 | j2 = state.j+dj 68 | if 0 <= i2 < N and 0 <= j2 < M and (dist == 0 or board[state.i][state.j] == '.'): 69 | if dist == 0: 70 | next.append(State(state.i, state.j, i2, j2, i2, j2)) 71 | else: 72 | next.append(State(state.i, state.j, state.i0, state.j0, i2, j2)) 73 | if best is not None: 74 | break 75 | queue = next 76 | dist += 1 77 | print "dist", dist, "best", state 78 | if best is None: 79 | continue 80 | 81 | elif dist > 1: 82 | i2, j2 = best.i0, best.j0 83 | print "moving to", i2, j2, "for", state.il, state.jl 84 | board[i2][j2] = board[i][j] 85 | board[i][j] = '.' 86 | hp[i2,j2] = hp[i,j] 87 | del hp[i,j] 88 | i,j = i2,j2 89 | skip.add((i,j)) 90 | 91 | bestcell = None 92 | besthp = (float('inf'),None,None) 93 | for di,dj in [(0,1),(0,-1),(1,0),(-1,0)]: 94 | i2 = i+di 95 | j2 = j+dj 96 | if 0 <= i2 < N and 0 <= j2 < M and board[i2][j2] == target: 97 | if (hp[i2,j2],i2,j2) < besthp: 98 | besthp = (hp[i2,j2],i2,j2) 99 | bestcell = i2,j2 100 | 101 | if bestcell is not None: 102 | print "attacking", bestcell 103 | hp[bestcell] -= 3 if target=='E' else elfpower 104 | if hp[bestcell] <= 0: 105 | del hp[bestcell] 106 | n[board[bestcell[0]][bestcell[1]]] -= 1 107 | board[bestcell[0]][bestcell[1]] = '.' 108 | 109 | print 110 | if combat_done: 111 | break 112 | rounds += 1 113 | """ 114 | if rounds > 50: 115 | break""" 116 | 117 | 118 | print sorted(n.items()) 119 | print rounds, sum(hp.values()), rounds*sum(hp.values()) 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /day16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | lines = [] 6 | 7 | for line in sys.stdin: 8 | line = line.strip('\n') 9 | lines.append(line) 10 | 11 | cases = [] 12 | it = iter(lines) 13 | while True: 14 | a = next(it) 15 | if not a: 16 | break 17 | b = next(it) 18 | c = next(it) 19 | 20 | before = map(int, a.split(':')[1].strip(' []').split(', ')) 21 | op = map(int, b.split()) 22 | after = map(int, c.split(':')[1].strip(' []').split(', ')) 23 | 24 | cases.append((before, op, after)) 25 | 26 | next(it) 27 | 28 | program = [] 29 | while True: 30 | try: 31 | l = next(it) 32 | except StopIteration: 33 | break 34 | if not l: continue 35 | program.append(map(int,l.split())) 36 | print len(program) 37 | 38 | def addr(a, b, c, regs): 39 | regs[c] = regs[a]+regs[b] 40 | 41 | def addi(a, b, c, regs): 42 | regs[c] = regs[a] + b 43 | 44 | def mulr(a,b,c,regs): 45 | regs[c] = regs[a]*regs[b] 46 | def muli(a,b,c,r): 47 | r[c]=r[a]*b 48 | def banr(a,b,c,r): 49 | r[c]=r[a]&r[b] 50 | def bani(a,b,c,r): 51 | r[c]=r[a]&b 52 | def borr(a,b,c,r): 53 | r[c]=r[a]|r[b] 54 | def bori(a,b,c,r): 55 | r[c]=r[a]|b 56 | def setr(a,b,c,r): 57 | r[c]=r[a] 58 | def seti(a,b,c,r): 59 | r[c]=a 60 | def gtir(a,b,c,r): 61 | r[c]=int(a>r[b]) 62 | def gtri(a,b,c,r): 63 | r[c]=int(r[a]>b) 64 | def gtrr(a,b,c,r): 65 | r[c]=int(r[a]>r[b]) 66 | def eqir(a,b,c,r): 67 | r[c]=int(a==r[b]) 68 | def eqri(a,b,c,r): 69 | r[c]=int(r[a]==b) 70 | def eqrr(a,b,c,r): 71 | r[c]=int(r[a]==r[b]) 72 | 73 | ops = [addr,addi,mulr,muli,banr,bani,borr,bori,setr,seti,gtir,gtri,gtrr,eqir,eqri,eqrr] 74 | 75 | threecount = 0 76 | allnames = [f.func_name for f in ops] 77 | options = [set(allnames) for i in xrange(16)] 78 | 79 | tab = [bori, borr, addi, muli, addr, bani, gtri, setr, gtrr, seti, eqir, eqrr, mulr, eqri, gtir, banr] 80 | 81 | for before, op, after in cases: 82 | n = 0 83 | ps = set() 84 | for opfun in ops: 85 | r = list(before) 86 | opfun(op[1], op[2], op[3], r) 87 | if r == after: 88 | n += 1 89 | ps.add(opfun.func_name) 90 | options[op[0]] &= ps 91 | if n >= 3: 92 | threecount += 1 93 | r = list(before) 94 | tab[op[0]](op[1], op[2], op[3], r) 95 | if r != after: 96 | raise Exception() 97 | print threecount 98 | 99 | for i in xrange(16): 100 | print i, options[i] 101 | 102 | r = [0,0,0,0] 103 | for op in program: 104 | tab[op[0]](op[1], op[2], op[3], r) 105 | print r 106 | -------------------------------------------------------------------------------- /day17.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | import re 5 | 6 | pattern = re.compile(r'([xy])=(\d+), [xy]=(\d+)..(\d+)') 7 | 8 | blocks = [] 9 | sys.setrecursionlimit(10000) 10 | 11 | for line in sys.stdin: 12 | line = line.strip() 13 | m = pattern.match(line) 14 | a, b, c = map(int, [m.group(i) for i in (2,3,4)]) 15 | if m.group(1)=='x': 16 | blocks.append((a, b, a, c)) 17 | else: 18 | blocks.append((b, a, c, a)) 19 | 20 | xs = [i[0] for i in blocks]+[i[2] for i in blocks] 21 | ys = [i[1] for i in blocks]+[i[3] for i in blocks] 22 | xmin = min(xs)-1 23 | ymin = min(min(ys), 0) 24 | xmax = max(xs)+1 25 | ymax = max(ys) 26 | 27 | w = xmax-xmin+2 28 | h = ymax-ymin+1 29 | 30 | board = [[' ']*w for i in xrange(h)] 31 | for a,b,c,d in blocks: 32 | for x in xrange(a,c+1): 33 | for y in xrange(b,d+1): 34 | board[y-ymin][x-xmin] = '#' 35 | 36 | def traverse(x,y): 37 | if y >= h or x < 0 or x >= w: 38 | return '|' 39 | if board[y][x] != ' ': 40 | return board[y][x] 41 | c = traverse(x, y+1) 42 | if c == '|': 43 | board[y][x] = '|' 44 | print "(%d,%d) = |" % (x,y) 45 | return '|' 46 | 47 | left_open = False 48 | for x2 in xrange(x-1, -2, -1): 49 | if x2 >= 0 and board[y][x2] == '#': 50 | break 51 | c = traverse(x2, y+1) 52 | if c == '|': 53 | left_open = True 54 | x2-=1 55 | break 56 | right_open = False 57 | for x3 in xrange(x+1, w+1): 58 | if x3 < w and board[y][x3] == '#': 59 | break 60 | c = traverse(x3, y+1) 61 | if c == '|': 62 | right_open = True 63 | x3+=1 64 | break 65 | 66 | if left_open or right_open: 67 | result = '|' 68 | else: 69 | result = '~' 70 | for i in xrange(x2+1, x3): 71 | board[y][i] = result 72 | print "(%d-%d,%d) = %s" % (x2+1, x3, y, result) 73 | return result 74 | 75 | traverse(500-xmin, 0-ymin) 76 | 77 | n = n2 = 0 78 | for i in xrange(min(ys),ymax+1): 79 | for j in xrange(xmin,xmax+1): 80 | c = board[i-ymin][j-xmin] 81 | if c in ('~','|'): 82 | n += 1 83 | if c == '~': 84 | n2 += 1 85 | print ''.join(board[i-ymin]) 86 | print 87 | print n 88 | print n2 89 | -------------------------------------------------------------------------------- /day18.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | vector board; 7 | for (string l : util::lines(cin)) { 8 | board.push_back(l); 9 | } 10 | 11 | const int N = board.size(), M = board[0].length(); 12 | vector next(board); 13 | for (long long iter = 0; iter < 100000L; iter++) { 14 | int tottree=0, totlumber=0; 15 | for (int i = 0; i < N; i++) { 16 | for (int j = 0; j < N; j++) { 17 | int tree=0, lumber=0; 18 | for (int i2 = max(i-1, 0); i2 <= min(i+1, N-1); i2++) { 19 | for (int j2 = max(j-1, 0); j2 <= min(j+1, M-1); j2++) { 20 | char c = board[i2][j2]; 21 | if (c == '|') tree++; 22 | else if (c == '#') lumber++; 23 | } 24 | } 25 | if (board[i][j] == '.') { 26 | next[i][j] = tree >= 3 ? '|' : '.'; 27 | } else if (board[i][j] == '|') { 28 | next[i][j] = lumber >= 3 ? '#' : '|'; 29 | } else { 30 | next[i][j] = (lumber >= 2 && tree >= 1) ? '#' : '.'; 31 | } 32 | if (next[i][j] == '|') tottree++; 33 | else if (next[i][j] == '#') totlumber++; 34 | } 35 | } 36 | if ((iter+1) % 28L == (1000000000L % 28L)) { 37 | cout << (iter+1) << " " << (tottree * totlumber) << endl; 38 | } 39 | swap(board,next); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /day18.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | board = [] 6 | for line in sys.stdin: 7 | line = line.strip() 8 | board.append(list(line)) 9 | 10 | def step(board): 11 | N = len(board) 12 | M = len(board[0]) 13 | result = [[None]*M for i in xrange(N)] 14 | 15 | for i in xrange(N): 16 | for j in xrange(M): 17 | counts = collections.Counter() 18 | for dx in xrange(-1, 2): 19 | for dy in xrange(-1, 2): 20 | if dx == 0 and dy == 0: continue 21 | i2 = i+dx 22 | j2 = j+dy 23 | if 0 <= i2 < N and 0 <= j2 < M: 24 | counts[board[i2][j2]]+=1 25 | if board[i][j] == '.': 26 | result[i][j] = '|' if counts['|'] >= 3 else '.' 27 | elif board[i][j] == '|': 28 | result[i][j] = '#' if counts['#'] >= 3 else '|' 29 | else: 30 | result[i][j] = '#' if (counts['#'] >= 1 and counts['|'] >= 1) else '.' 31 | return result 32 | 33 | for i in xrange(10000): 34 | board = step(board) 35 | """for row in board: 36 | print ''.join(row)""" 37 | 38 | if i % 100 == 0: 39 | counts = collections.Counter() 40 | for row in board: 41 | for c in row: 42 | counts[c]+=1 43 | print i, counts['#']*counts['|'] 44 | 45 | -------------------------------------------------------------------------------- /day19.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | #define addi(a,b,c) (regs[c] = regs[a]+b) 6 | #define seti(a,b,c) (regs[c] = a) 7 | #define mulr(a,b,c) (regs[c] = regs[a]*regs[b]) 8 | #define eqrr(a,b,c) (regs[c] = (regs[a]==regs[b] ? 1 : 0)) 9 | #define addr(a,b,c) (regs[c] = regs[a]+regs[b]) 10 | #define gtrr(a,b,c) (regs[c] = (regs[a]>regs[b] ? 1 : 0)) 11 | #define muli(a,b,c) (regs[c] = regs[a]*b) 12 | #define setr(a,b,c) (regs[c] = regs[a]) 13 | 14 | int main() { 15 | vector regs(6,0); 16 | regs[0] = 1; 17 | int ip=0; 18 | long long inscount = 0; 19 | 20 | while (true) { 21 | regs[2] = ip; 22 | 23 | if (inscount % 10000000 == 0) { 24 | cout << inscount << " " << regs << endl; 25 | } 26 | 27 | switch (ip) { 28 | case 0: addi(2,16,2); break; 29 | case 1: seti(1,0,1); break; 30 | case 2: seti(1,4,3); break; 31 | case 3: mulr(1,3,4); break; 32 | case 4: eqrr(4,5,4); break; 33 | case 5: addr(4,2,2); break; 34 | case 6: addi(2,1,2); break; 35 | case 7: addr(1,0,0); break; 36 | case 8: addi(3,1,3); break; 37 | case 9: gtrr(3,5,4); break; 38 | case 10: addr(2,4,2); break; 39 | case 11: seti(2,5,2); break; 40 | case 12: addi(1,1,1); break; 41 | case 13: gtrr(1,5,4); break; 42 | case 14: addr(4,2,2); break; 43 | case 15: seti(1,1,2); break; 44 | case 16: mulr(2,2,2); break; 45 | case 17: addi(5,2,5); break; 46 | case 18: mulr(5,5,5); break; 47 | case 19: mulr(2,5,5); break; 48 | case 20: muli(5,11,5); break; 49 | case 21: addi(4,5,4); break; 50 | case 22: mulr(4,2,4); break; 51 | case 23: addi(4,9,4); break; 52 | case 24: addr(5,4,5); break; 53 | case 25: addr(2,0,2); break; 54 | case 26: seti(0,0,2); break; 55 | case 27: setr(2,3,4); break; 56 | case 28: mulr(4,2,4); break; 57 | case 29: addr(2,4,4); break; 58 | case 30: mulr(2,4,4); break; 59 | case 31: muli(4,14,4); break; 60 | case 32: mulr(4,2,4); break; 61 | case 33: addr(5,4,5); break; 62 | case 34: seti(0,6,0); break; 63 | case 35: seti(0,3,2); break; 64 | default: cout << regs << endl; return 0; 65 | } 66 | 67 | ip = regs[2]; 68 | ip++; 69 | inscount++; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /day19.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | ipreg = None 6 | prog = [] 7 | for line in sys.stdin: 8 | line = line.strip() 9 | toks = line.split() 10 | if toks[0] == "#ip": 11 | ipreg = int(toks[1]) 12 | else: 13 | prog.append(tuple([toks[0]]+map(int,toks[1:]))) 14 | 15 | def addr(a, b, c, regs): 16 | regs[c] = regs[a]+regs[b] 17 | 18 | def addi(a, b, c, regs): 19 | regs[c] = regs[a] + b 20 | 21 | def mulr(a,b,c,regs): 22 | regs[c] = regs[a]*regs[b] 23 | def muli(a,b,c,r): 24 | r[c]=r[a]*b 25 | def banr(a,b,c,r): 26 | r[c]=r[a]&r[b] 27 | def bani(a,b,c,r): 28 | r[c]=r[a]&b 29 | def borr(a,b,c,r): 30 | r[c]=r[a]|r[b] 31 | def bori(a,b,c,r): 32 | r[c]=r[a]|b 33 | def setr(a,b,c,r): 34 | r[c]=r[a] 35 | def seti(a,b,c,r): 36 | r[c]=a 37 | def gtir(a,b,c,r): 38 | r[c]=int(a>r[b]) 39 | def gtri(a,b,c,r): 40 | r[c]=int(r[a]>b) 41 | def gtrr(a,b,c,r): 42 | r[c]=int(r[a]>r[b]) 43 | def eqir(a,b,c,r): 44 | r[c]=int(a==r[b]) 45 | def eqri(a,b,c,r): 46 | r[c]=int(r[a]==b) 47 | def eqrr(a,b,c,r): 48 | r[c]=int(r[a]==r[b]) 49 | 50 | ops = [addr,addi,mulr,muli,banr,bani,borr,bori,setr,seti,gtir,gtri,gtrr,eqir,eqri,eqrr] 51 | oplookup = dict((op.func_name,op) for op in ops) 52 | 53 | regs = [0]*6 54 | regs[0] = 0 55 | ip = 0 56 | inscount = 0 57 | while True: 58 | regs[ipreg] = ip 59 | if not (0 <= ip < len(prog)): 60 | break 61 | instr = prog[ip] 62 | if inscount % 1 == 0: 63 | print inscount, ip, instr, regs 64 | op = oplookup[instr[0]] 65 | op(*(list(instr[1:])+[regs])) 66 | ip = regs[ipreg] 67 | ip += 1 68 | inscount += 1 69 | 70 | print regs 71 | 72 | -------------------------------------------------------------------------------- /day20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | regex = raw_input() 6 | regex = regex[1:-1] 7 | 8 | i = 0 9 | def peek(): 10 | if i < len(regex): 11 | return regex[i] 12 | else: 13 | return None 14 | 15 | def get(): 16 | global i 17 | c = regex[i] 18 | i += 1 19 | return c 20 | 21 | Sequence = collections.namedtuple('Sequence', 'seq') 22 | Alternative = collections.namedtuple('Alternative', 'alts') 23 | Literal = collections.namedtuple('Literal', 'dir') 24 | 25 | def parse_expr(): 26 | seq = [] 27 | while peek() is not None and peek() in 'NESW(': 28 | if peek() == '(': 29 | seq.append(parse_alt()) 30 | else: 31 | seq.append(Literal(get())) 32 | return Sequence(seq) 33 | 34 | def parse_alt(): 35 | assert get() == '(' 36 | alts = [] 37 | while True: 38 | alts.append(parse_expr()) 39 | c = get() 40 | if c == ')': 41 | break 42 | assert c == '|' 43 | return Alternative(alts) 44 | 45 | class State(object): 46 | def __init__(self): 47 | self.successors = [] 48 | 49 | allstates = [] 50 | def traverse(expr, start): 51 | current = start 52 | for e in expr.seq: 53 | end = State() 54 | if isinstance(e, Alternative): 55 | for a in e.alts: 56 | next = traverse(a, current) 57 | next.successors.append((None,end)) 58 | elif isinstance(e, Literal): 59 | current.successors.append((e.dir,end)) 60 | current = end 61 | return current 62 | 63 | """next_num = 0 64 | visited = set([]) 65 | def number(node): 66 | global next_num 67 | if node in visited: 68 | return 69 | visited.add(node) 70 | for _, next in node.successors: 71 | number(next) 72 | node.index = next_num 73 | next_num += 1""" 74 | 75 | visited = set([]) 76 | edges = collections.defaultdict(set) 77 | 78 | head = State() 79 | traverse(parse_expr(), head) 80 | 81 | stack = [(0,0,head)] 82 | deltas = {'N': (0,1), 'E': (1,0), 'S': (0,-1), 'W': (-1,0)} 83 | 84 | while stack: 85 | current = stack.pop() 86 | if current in visited: 87 | continue 88 | visited.add(current) 89 | 90 | x, y, curstate = current 91 | for dir, nextstate in curstate.successors: 92 | if dir is not None: 93 | dx, dy = deltas[dir] 94 | x2 = x+dx 95 | y2 = y+dy 96 | 97 | edges[x,y].add((x2,y2)) 98 | edges[x2,y2].add((x,y)) 99 | else: 100 | x2 = x 101 | y2 = y 102 | stack.append((x2, y2, nextstate)) 103 | 104 | for k in sorted(edges): 105 | print k, edges[k] 106 | 107 | visited = set([]) 108 | queue = [(0,0)] 109 | dist = 0 110 | far = 0 111 | while queue: 112 | print queue 113 | nextqueue = [] 114 | for cur in queue: 115 | if cur in visited: 116 | continue 117 | visited.add(cur) 118 | if dist >= 1000: 119 | far += 1 120 | for next in edges[cur]: 121 | nextqueue.append(next) 122 | queue = nextqueue 123 | dist += 1 124 | print dist - 2 125 | print far, "out of", len(edges) 126 | -------------------------------------------------------------------------------- /day21.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def succ(v): 4 | A = v | 65536 5 | v = 2176960 6 | while True: 7 | v += (A & 255) 8 | v &= 0xffffff 9 | v *= 65899 10 | v &= 0xffffff 11 | if A < 256: 12 | return v 13 | A /= 256 14 | 15 | #print succ(7156989) 16 | #succs = [succ(i) for i in xrange(0x1000000)] 17 | visited = set() 18 | i = 0 19 | while i not in visited: 20 | print i 21 | visited.add(i) 22 | i = succ(i) 23 | print "repeat:", i 24 | -------------------------------------------------------------------------------- /day22.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | const long long M=20183; 6 | 7 | struct state { 8 | int x, y, tool; 9 | } 10 | 11 | int main() { 12 | long long depth = 10914; 13 | int tx = 9, ty = 739; 14 | 15 | vector> grid(tx+1, vector(ty+1)); 16 | grid[0][0] = 0; 17 | for (long long x = 1; x <= tx; x++) { 18 | grid[x][0] = (x*16807L)%M; 19 | } 20 | for (long long y = 1; y <= ty; y++) { 21 | grid[0][y] = (y*48271L)%M; 22 | } 23 | for (int x = 1; x <= tx; x++) { 24 | for (int y = 1; y <= ty; y++) { 25 | grid[x][y] = ((grid[x-1][y]+depth)*(grid[x][y-1]+depth))%M; 26 | } 27 | } 28 | grid[tx][ty] = 0; 29 | long long sum = 0; 30 | for (int x = 0; x <= tx; x++) { 31 | for (int y = 0; y <= ty; y++) { 32 | sum += ((grid[x][y]+depth)%M)%3; 33 | } 34 | } 35 | cout << sum << endl; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /day22.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | import heapq 5 | 6 | depth = 10914 7 | tx = 9 8 | ty = 739 9 | 10 | grid = [[0]*(20*ty+1) for i in xrange(20*tx+1)] 11 | M=20183 12 | 13 | for y in xrange(20*ty+1): 14 | grid[0][y] = (y*48271)%M 15 | for x in xrange(1, 20*tx+1): 16 | grid[x][0] = (x*16807)%M 17 | for y in xrange(1, 20*ty+1): 18 | grid[x][y] = ((grid[x-1][y]+depth)*(grid[x][y-1]+depth))%M 19 | grid[tx][ty] = 0 20 | 21 | level = [[((e+depth)%M)%3 for e in row] for row in grid] 22 | 23 | for y in xrange(11): 24 | print ''.join(".=|"[level[x][y]] for x in xrange(11)) 25 | 26 | NONE=0 27 | TORCH=1 28 | GEAR=2 29 | q = [(0,(0,0,TORCH))] 30 | visited = set() 31 | 32 | def valid(g,l): 33 | return (l,g) in [(0,GEAR),(0,TORCH),(1,GEAR),(1,NONE),(2,TORCH),(2,NONE)] 34 | 35 | while True: 36 | t, state = heapq.heappop(q) 37 | print t, state 38 | if state in visited: 39 | continue 40 | visited.add(state) 41 | 42 | x,y,g = state 43 | if x == tx and y == ty and g == TORCH: 44 | print "found",t 45 | break 46 | for g2 in [NONE,TORCH,GEAR]: 47 | if g2 != g and valid(g2,level[x][y]): 48 | heapq.heappush(q, (t+7, (x,y,g2))) 49 | for dx,dy in [(0,1),(0,-1),(-1,0),(1,0)]: 50 | x2 = x + dx 51 | y2 = y + dy 52 | if x2 < 0 or y2 < 0 or x2 >= 20*tx or y2 >= 20*ty: 53 | continue 54 | if valid(g, level[x2][y2]): 55 | heapq.heappush(q, (t+1, (x2,y2,g))) 56 | #print q 57 | -------------------------------------------------------------------------------- /fetch-input.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source .sessionkey 4 | curl -b session=${sessionkey} https://adventofcode.com/2018/day/$1/input > day${1}.in || exit 5 | cat day${1}.in 6 | -------------------------------------------------------------------------------- /template.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | for (string l : util::lines(cin)) { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /template.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, itertools, collections 4 | 5 | for line in sys.stdin: 6 | line = line.strip() 7 | -------------------------------------------------------------------------------- /util.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace util { 19 | using namespace std; 20 | 21 | class line : public string {}; 22 | 23 | istream& operator>>(istream& is, line &l) { 24 | getline(is, l); 25 | return is; 26 | } 27 | 28 | class istream_lines { 29 | istream& is; 30 | 31 | public: 32 | istream_lines(istream& is) : is(is) { } 33 | 34 | istream_iterator begin() { 35 | return istream_iterator(is); 36 | } 37 | 38 | istream_iterator end() { 39 | return istream_iterator(); 40 | } 41 | }; 42 | 43 | istream_lines lines(istream& is) { 44 | return istream_lines(is); 45 | } 46 | 47 | smatch rmatch(const string& text, const regex& pattern) { 48 | smatch m; 49 | if (!regex_match(text, m, pattern)) { 50 | throw invalid_argument("match failure"); 51 | } 52 | return m; 53 | } 54 | 55 | template 56 | struct point { 57 | T x; 58 | T y; 59 | 60 | point(const T& x, const T& y) : x(x), y(y) { } 61 | point() { } 62 | }; 63 | 64 | template 65 | std::ostream& operator<<(std::ostream& os, const point& p) { 66 | os << "(" << p.x << ", " << p.y << ")"; 67 | return os; 68 | } 69 | 70 | } 71 | 72 | template 73 | std::ostream& operator<<(std::ostream& os, const std::vector& v) { 74 | os << "["; 75 | for (int i = 0; i < v.size(); i++) { 76 | if (i > 0) { 77 | os << ", "; 78 | } 79 | os << v[i]; 80 | } 81 | os << "]"; 82 | return os; 83 | } 84 | 85 | template 86 | std::ostream& operator<<(std::ostream& os, const std::unordered_map& m) { 87 | os << "{"; 88 | bool first = true; 89 | for (auto& it : m) { 90 | if (!first) { 91 | os << ", "; 92 | } else { 93 | first = false; 94 | } 95 | os << it.first << ": " << it.second; 96 | } 97 | os << "}"; 98 | return os; 99 | } 100 | 101 | template 102 | std::ostream& operator<<(std::ostream& os, const std::map& m) { 103 | os << "{"; 104 | bool first = true; 105 | for (auto& it : m) { 106 | if (!first) { 107 | os << ", "; 108 | } else { 109 | first = false; 110 | } 111 | os << it.first << ": " << it.second; 112 | } 113 | os << "}"; 114 | return os; 115 | } 116 | 117 | template 118 | std::ostream& operator<<(std::ostream& os, const std::unordered_set& s) { 119 | os << "{"; 120 | bool first = true; 121 | for (auto& it : s) { 122 | if (!first) { 123 | os << ", "; 124 | } else { 125 | first = false; 126 | } 127 | os << it; 128 | } 129 | os << "}"; 130 | return os; 131 | } 132 | 133 | template 134 | std::ostream& operator<<(std::ostream& os, const std::list& s) { 135 | os << "{"; 136 | bool first = true; 137 | for (auto& it : s) { 138 | if (!first) { 139 | os << ", "; 140 | } else { 141 | first = false; 142 | } 143 | os << it; 144 | } 145 | os << "}"; 146 | return os; 147 | } 148 | template 149 | std::ostream& operator<<(std::ostream& os, const std::set& s) { 150 | os << "{"; 151 | bool first = true; 152 | for (auto& it : s) { 153 | if (!first) { 154 | os << ", "; 155 | } else { 156 | first = false; 157 | } 158 | os << it; 159 | } 160 | os << "}"; 161 | return os; 162 | } 163 | 164 | typedef long long ll; 165 | typedef unsigned long long ull; 166 | 167 | --------------------------------------------------------------------------------