Quick actions

cmd+k|ctrl+k

Navigation

Languages

aoc2017-day14

Snippet info

Language

Python

Visibility

public

Author

christophe.guillon.perso

Created

2017-12-14T07:03:52Z

Updated

2017-12-14T07:03:52Z

import sys
import re
from functools import reduce
def rrotate(sequence, amount):
    l = list(sequence)
    amount %= len(l)
    return l[-amount:] + l[:-amount]
def lrotate(sequence, amount):
    l = list(sequence)
    amount %= len(l)
    return l[amount:] + l[:amount]
def slice(sequence, position, length):
    sequence = list(sequence)
    assert(length >= 0 and length <= len(sequence))
    position %= len(sequence)
    return lrotate(sequence,position)[:length]
def insert(sequence, toinsert, position, length=None):
    sequence = list(sequence)
    toinsert = list(toinsert)
    size = length if length != None else len(toinsert)
    assert(size >= 0 and size <= len(sequence))
    position %= len(sequence)
    return rrotate(toinsert[:size] + lrotate(sequence,position)[size:], position)
def xorall(sequence):
    return reduce(lambda x,y: x^y, sequence)
def mulall(sequence):
    return reduce(lambda x,y: x*y, sequence)
def sumall(sequence):
    return reduce(lambda x,y: x+y, sequence)
def splitevery(sequence, step):
    l = list(sequence)
    r = []
    num, rest = divmod(len(l), step)
    for e in range(num):
        r.append(slice(l, e*step, step))
    if rest > 0: r.append(slice(l, num*step, rest))
    return r
def splitin(sequence, number):
    l = list(sequence)
    return splitevery(sequence,(len(l)+number-1)//number)
def formatall(sequence, fmt="%s", sep=""):
    return sep.join(map(lambda x: fmt % x, sequence))

#input = "nbysizxe"
input = "flqrgnkx"  # the test

inputs = []
for i in range(128):
    inputs.append("%s-%d" % (input, i))

def getxy(x, y, grid):
    if x < 0 or x > 127: return ("0", "")
    if y < 0 or y > 127: return ("0", "")
    return (grid[y * 128 + x], ("%.3dx%.3d" % (x,y)))

grid = ""
acc = 0
for input in inputs:
    lengths = list(map(ord,input)) + [17, 31, 73, 47, 23]
    l = list(range(256))
    pos = 0
    skip = 0
    for round in range(64):
        for leng in lengths:
            l = insert(l, reversed(slice(l, pos, leng)), pos)
            pos += leng + skip
            skip += 1
    hash = formatall(map(xorall, splitevery(l,16)), "%.2x")
    binfmt = [format(int("%s" % i, 16), "04b") for i in hash]
#    print(binfmt)
#    print(hash)
    acc += sum([i.count("1") for i in binfmt])
    for i in binfmt:
        grid += i

print("acc:", acc)
print("grid:", grid)

succs = {}
acc2 = 0
for x in range(128):
    for y in range(128):
        n = getxy(x, y - 1, grid)
        s = getxy(x, y + 1, grid)
        o = getxy(x-1, y, grid)
        e = getxy(x+1, y, grid)
        c = getxy(x,y, grid)
        if c[0] == "1":
            acc2 += 1
            succs[c[1]] = set()
            for i in [c,n,s,e,o]:
                if i[0] == "1": succs[c[1]].add(i[1])
assert(acc2 == acc)
assert(len(succs.keys()) == acc)

with sys.stdout as f:
#with open("output.txt", "w") as f:
    limit = 0
    for i in sorted(succs.keys()):
        succ = succs[i]
        if len(succ):
            print("%s <-> %s" % (i, succ),file=f)
        # break at first 10 for output in glot.io
        limit += 1
        if limit >= 10: break
INFO