2017-12-14 - Disk Defragmentation
(original .ipynb)full_length = 256 # lengths = [0,1,2,3...255] def rotate_list(lst, pos, length): sublist = [] wrapped = 0 while length > 0: if pos < len(lst): sublist.append(lst.pop(pos)) length -= 1 else: sublist.append(lst.pop(0)) length -= 1 wrapped += 1 while wrapped > 0: lst.insert(0, sublist.pop(0)) wrapped -= 1 while len(sublist) > 0: lst.insert(pos, sublist.pop(0)) return lst def perform_round(lengths, lst, pos=0, skip=0): for length in lengths: lst = rotate_list(lst, pos, length) pos = (pos + length + skip) % len(lst) skip += 1 return lst, pos, skip def hash_block(block, sparse_hash): idx = block*16 values = sparse_hash[idx:idx+16] hash_block = 0 for value in values: hash_block ^= value hex_hash = hex(hash_block)[2:] if len(hex_hash) == 1: return "0"+hex_hash return hex_hash def knot_hash(input_str): lengths = [ ord(c) for c in input_str ] + [17, 31, 73, 47, 23] current_round = 64 skip = 0 pos = 0 sparse_hash = list(range(0, full_length)) while current_round > 0: current_round -= 1 sparse_hash, pos, skip = perform_round(lengths, sparse_hash, pos, skip) assert 256 == len(sparse_hash) block = 0 dense_hash_lst = [] while block < 16: dense_hash_lst.append(hash_block(block, sparse_hash)) block += 1 return "".join(dense_hash_lst).strip() def part_one(input_str): total_hash = [] for n in range(128): h = knot_hash(f"{input_str}-{n}") total_hash += [c for c in "".join([bin(int(c, 16))[2:].zfill(4) for c in h])] return sum(1 for c in total_hash if c == "1") assert 8108 == part_one("flqrgnkx") print("part one:", part_one("ljoxqyyw"))
part one: 8316
from advent import neighbours4 def part_two(input_str): hash_grid = [] for n in range(128): h = knot_hash(f"{input_str}-{n}") hash_grid.append([c for c in "".join([bin(int(c, 16))[2:].zfill(4) for c in h])]) current_group = 0 visited = set() for r,row in enumerate(hash_grid): for c,col in enumerate(row): if col == "0": visited.add((r,c)) continue if (r,c) in visited: continue queue = [(r,c)] while len(queue) > 0: qr,qc = queue.pop(0) if (qr,qc) in visited: continue visited.add((qr,qc)) if hash_grid[qr][qc] == "0": continue for nr,nc in neighbours4(hash_grid, qr, qc): queue.append((nr,nc)) current_group += 1 return current_group assert 1242 == part_two("flqrgnkx") print("part two:", part_two("ljoxqyyw"))
part two: 1074