#!/usr/bin/env python3 from functools import reduce import datetime import os, re, sys import math import curses import numpy as np from time import sleep choice = 'e ne nw w sw se'.split() def tpl(l): anyew = re.compile(r'[ns]?[ew]') return anyew.findall(l) def uniq(d): north = d['ne'] + d['nw'] - d['se'] - d['sw'] east = 2 * (d['e'] - d['w']) + d['ne'] + d['se'] - d['nw'] - d['sw'] return '%d/%d' % (north, east) def path2dic(l): return {k: sum(k == p for p in l) for k in choice} def flip(d, t): if t in d: d[t] = not d[t] else: d[t] = True def dprint(*args): sep = False for arg in args: if sep: print('--------') sep = True for a, b in arg.items(): print('%10s: %s' % (a, b)) print() def diccoord(x, y, w=80, h=24): e = x - (w // 2) n = (h // 2) - y if n % 2 == 0: e -= (e % 2) else: e -= ((e+1) % 2) return '%d/%d' % (n, e) def mprint(d, lin, col): print(curses.tigetstr('clear').decode()) for y in range(lin): for x in range(col): c = '.' try: c = '#' if d[diccoord(x, y, w=col, h=lin)] else ' ' except: pass sys.stdout.write(c) print() def surrounding(tile): neigh = ((0, 2), (1, 1), (1, -1), (0, -2), (-1, -1), (-1, 1)) n, e = (int(x) for x in tile.split('/')) return ['%d/%d' % (n+u, e+v) for u, v in neigh] def tick(d): toflip = {} are_black = list(filter(lambda x: d[x], d.keys())) for t in are_black: sur = surrounding(t) """ Any black tile with zero or more than 2 black tiles immediately adjacent to it is flipped to white. """ tobe_white = sum(1 for s in sur if s in are_black) in (0, 3, 4, 5, 6) if tobe_white: toflip[t] = False # "white" """ Any white tile with exactly 2 black tiles immediately adjacent to it is flipped to black. """ for s in sur: # must be one of these, ducy? if s in are_black or s in toflip: # black, or already handled continue sursur = surrounding(s) tobe_black = sum(1 for ss in sursur if ss in are_black) == 2 # >= 1 if tobe_black: toflip[s] = True # Add remaining black tiles for t in are_black: if t not in toflip: toflip[t] = True return toflip curses.setupterm() size = os.get_terminal_size() w, h = size.columns, size.lines w -= 2 # wtf? h -= 2 # wtf? print(w, h) sleep(1) fn = sys.argv[1] if len(sys.argv) > 1 else 'input%s' % 24 with open(fn) as f: lines = [l.strip() for l in f.readlines()] t = [tpl(l) for l in lines] flipdic = {} for p in t: flip(flipdic, uniq(path2dic(p))) #print(path2dic(p), uniq(path2dic(p)), '\n') mprint(flipdic, h, w) dprint(flipdic) print(sum(flipdic.values())) # 24a sleep(1) for i in range(100): flipdic = tick(flipdic) mprint(flipdic, h, w) print('Day %d:' % i, sum(flipdic.values())) sleep(1) print(sum(flipdic.values())) # 24b