Last active
December 3, 2017 14:16
-
-
Save diath/3fe59a0fee86e2daa8c40ed3783055fc to your computer and use it in GitHub Desktop.
Advent of Code, 2016, Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_VALUE = re.compile(r'value (\d+) goes to bot (\d+)') | |
RE_GIVES = re.compile(r'bot (\d+) gives low to (bot|output) (\d+) and high to (bot|output) (\d+)') | |
CHIP_VAL_A = 61 | |
CHIP_VAL_B = 17 | |
def main(): | |
data = [] | |
with open('D10.txt') as f: | |
data = f.read().strip().split('\n') | |
bins = {} | |
bots = {} | |
done = False | |
while not done and data: | |
for line in data[:]: | |
match = RE_VALUE.match(line) | |
if match: | |
value, id = map(int, match.group(1, 2)) | |
bot = bots.get(id, None) | |
if bot: | |
bot.append(value) | |
bot.sort() | |
else: | |
bots[id] = [value] | |
data.remove(line) | |
continue | |
match = RE_GIVES.match(line) | |
if match: | |
id, low_dst, low_id, high_dst, high_id = match.group(1, 2, 3, 4, 5) | |
id, low_id, high_id = map(int, [id, low_id, high_id]) | |
bot = bots.get(id) | |
if not bot: | |
continue | |
if len(bot) < 2: | |
continue | |
high = bot.pop() | |
low = bot.pop() | |
if high == CHIP_VAL_A and low == CHIP_VAL_B: | |
print('Result({})'.format(id)) | |
done = True | |
break | |
if low_dst == 'output': | |
bins[low_id] = [low] | |
elif low_dst == 'bot': | |
_bot = bots.get(low_id) | |
if _bot: | |
_bot.append(low) | |
_bot.sort() | |
else: | |
bots[low_id] = [low] | |
if high_dst == 'output': | |
bins[high_id] = [high] | |
elif high_dst == 'bot': | |
_bot = bots.get(high_id) | |
if _bot: | |
_bot.append(high) | |
_bot.sort() | |
else: | |
bots[high_id] = [high] | |
data.remove(line) | |
continue | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_VALUE = re.compile(r'value (\d+) goes to bot (\d+)') | |
RE_GIVES = re.compile(r'bot (\d+) gives low to (bot|output) (\d+) and high to (bot|output) (\d+)') | |
def main(): | |
data = [] | |
with open('D10.txt') as f: | |
data = f.read().strip().split('\n') | |
bins = {} | |
bots = {} | |
while data: | |
b1, b2, b3 = bins.get(0, None), bins.get(1, None), bins.get(2, None) | |
if b1 and b2 and b3: | |
print('Result({})'.format(b1[0] * b2[0] * b3[0])) | |
break | |
for line in data[:]: | |
match = RE_VALUE.match(line) | |
if match: | |
value, id = map(int, match.group(1, 2)) | |
bot = bots.get(id, None) | |
if bot: | |
bot.append(value) | |
bot.sort() | |
else: | |
bots[id] = [value] | |
data.remove(line) | |
continue | |
match = RE_GIVES.match(line) | |
if match: | |
id, low_dst, low_id, high_dst, high_id = match.group(1, 2, 3, 4, 5) | |
id, low_id, high_id = map(int, [id, low_id, high_id]) | |
bot = bots.get(id) | |
if not bot: | |
continue | |
if len(bot) < 2: | |
continue | |
high = bot.pop() | |
low = bot.pop() | |
if low_dst == 'output': | |
bins[low_id] = [low] | |
elif low_dst == 'bot': | |
_bot = bots.get(low_id) | |
if _bot: | |
_bot.append(low) | |
_bot.sort() | |
else: | |
bots[low_id] = [low] | |
if high_dst == 'output': | |
bins[high_id] = [high] | |
elif high_dst == 'bot': | |
_bot = bots.get(high_id) | |
if _bot: | |
_bot.append(high) | |
_bot.sort() | |
else: | |
bots[high_id] = [high] | |
data.remove(line) | |
continue | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
def main(): | |
data = [] | |
with open('D12.txt') as f: | |
data = f.read().strip().split('\n') | |
def cpy(pc, regs, src, dst): | |
if src in ['a', 'b', 'c', 'd']: | |
regs[dst] = regs[src] | |
else: | |
regs[dst] = int(src) | |
return pc + 1 | |
def inc(pc, regs, reg): | |
regs[reg] += 1 | |
return pc + 1 | |
def dec(pc, regs, reg): | |
regs[reg] -= 1 | |
return pc + 1 | |
def jnz(pc, regs, reg, offset): | |
try: | |
n = int(reg) | |
if n != 0: | |
return pc + int(offset) | |
else: | |
return pc + 1 | |
except: | |
if regs[reg] != 0: | |
return pc + int(offset) | |
else: | |
return pc + 1 | |
lut = {'cpy': cpy, 'inc': inc, 'dec': dec, 'jnz': jnz} | |
regs = {'a': 0, 'b': 0, 'c': 0, 'd': 0} | |
pc = 0 | |
while pc < len(data): | |
info = data[pc].split(' ') | |
pc = lut.get(info[0], None)(pc, regs, *info[1:]) | |
print(regs) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
def main(): | |
data = [] | |
with open('D12.txt') as f: | |
data = f.read().strip().split('\n') | |
def cpy(pc, regs, src, dst): | |
if src in ['a', 'b', 'c', 'd']: | |
regs[dst] = regs[src] | |
else: | |
regs[dst] = int(src) | |
return pc + 1 | |
def inc(pc, regs, reg): | |
regs[reg] += 1 | |
return pc + 1 | |
def dec(pc, regs, reg): | |
regs[reg] -= 1 | |
return pc + 1 | |
def jnz(pc, regs, reg, offset): | |
try: | |
n = int(reg) | |
if n != 0: | |
return pc + int(offset) | |
else: | |
return pc + 1 | |
except: | |
if regs[reg] != 0: | |
return pc + int(offset) | |
else: | |
return pc + 1 | |
lut = {'cpy': cpy, 'inc': inc, 'dec': dec, 'jnz': jnz} | |
regs = {'a': 0, 'b': 0, 'c': 1, 'd': 0} | |
pc = 0 | |
while pc < len(data): | |
info = data[pc].split(' ') | |
pc = lut.get(info[0], None)(pc, regs, *info[1:]) | |
print(regs) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
fav = 1364 | |
dst = [31, 39] | |
def is_wall(x, y): | |
num = x * x + 3 * x + 2 * x * y + y + y * y + fav | |
return bin(num).count('1') % 2 == 1 | |
class Node(object): | |
def __init__(self, x, y): | |
self.x = x | |
self.y = y | |
def equals(self, other): | |
return self.x == other.x and self.y == other.y | |
class Nodes(object): | |
def __init__(self): | |
self.nodes = [] | |
def add(self, node): | |
self.nodes.append(node) | |
def contains(self, node): | |
return any([node.equals(cmp) for cmp in self.nodes]) | |
def walk(current, reached): | |
ret = Nodes() | |
for node in current.nodes: | |
(x, y, ) = node.x, node.y | |
new_node = Node(x - 1, y) | |
if x > 0 and not is_wall(x - 1, y) and not reached.contains(new_node): | |
reached.add(new_node) | |
ret.add(new_node) | |
new_node = Node(x, y - 1) | |
if y > 0 and not is_wall(x, y - 1) and not reached.contains(new_node): | |
reached.add(new_node) | |
ret.add(new_node) | |
new_node = Node(x + 1, y) | |
if not is_wall(x + 1, y) and not reached.contains(new_node): | |
reached.add(new_node) | |
ret.add(new_node) | |
new_node = Node(x, y + 1) | |
if not is_wall(x, y + 1) and not reached.contains(new_node): | |
reached.add(new_node) | |
ret.add(new_node) | |
return ret | |
steps = 0 | |
reachedCount = 0 | |
current = Nodes() | |
reached = Nodes() | |
current.add(Node(1, 1)) | |
target = Node(dst[0], dst[1]) | |
while not current.contains(target): | |
steps += 1 | |
current = walk(current, reached) | |
if steps == 50: | |
reachedCount = len(reached.nodes) | |
print('Part 1: {}'.format(steps)) | |
print('Part 2: {}'.format(reachedCount)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from hashlib import md5 | |
def main(): | |
salt = 'zpqevtbw' | |
index = 0 | |
def get_hash(index): | |
hash = md5('{}{}'.format(salt, index).encode()) | |
return hash.hexdigest().lower() | |
def check_hash(size, value, tc=None): | |
for (index, ch) in enumerate(value): | |
if value[index - (size - 1):index + 1] == (tc if tc else ch) * size: | |
return tc if tc else ch | |
return None | |
keys = [] | |
while len(keys) < 64: | |
temp = get_hash(index) | |
ch = check_hash(3, temp) | |
if not ch: | |
index += 1 | |
continue | |
for n in range(1, 1001): | |
temp2 = get_hash(index + n) | |
if check_hash(5, temp2, ch): | |
keys.append(temp2) | |
break | |
index += 1 | |
print('Result({})'.format(index - 1)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from hashlib import md5 | |
def main(): | |
salt = 'zpqevtbw' | |
index = 0 | |
def get_hash(index): | |
hash = md5('{}{}'.format(salt, index).encode()) | |
return hash.hexdigest().lower() | |
def get_stretched_hash(index): | |
hash = get_hash(index) | |
for n in range(2016): | |
hash = md5(hash.encode().lower()).hexdigest() | |
return hash | |
def check_hash(size, value, tc=None): | |
for (index, ch) in enumerate(value): | |
if value[index - (size - 1):index + 1] == (tc if tc else ch) * size: | |
return tc if tc else ch | |
return None | |
keys = [] | |
cache = [get_stretched_hash(n) for n in range(1001)] | |
while len(keys) < 64: | |
stretched = cache.pop(0) | |
ch = check_hash(3, stretched) | |
if not ch: | |
index += 1 | |
cache.append(get_stretched_hash(index + len(cache))) | |
continue | |
for entry in cache: | |
if check_hash(5, entry, ch): | |
keys.append(stretched) | |
break | |
index += 1 | |
cache.append(get_stretched_hash(index + len(cache))) | |
print('Part 2: {}'.format(index - 1)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_DISC = re.compile(r'Disc #(\d+) has (\d+) positions; at time=(\d+), it is at position (\d+).') | |
def main(): | |
data = [] | |
with open('D15.txt') as f: | |
data = f.read().strip().split('\n') | |
class Disc(object): | |
def __init__(self, id, positions, position): | |
self.id = id | |
self.positions = positions | |
self.position = position | |
def __repr__(self): | |
return '<Disc.{}.{}.{}>'.format(self.id, self.positions, self.position) | |
def get_state_at(self, time): | |
return (self.position + time) % self.positions | |
def done(discs, time): | |
return all([disc.get_state_at(time + index + 1) == 0 for (index, disc) in enumerate(discs)]) | |
discs = [Disc(*map(int, RE_DISC.match(line).group(1, 2, 4))) for line in data] | |
time = 0 | |
while not done(discs, time): | |
time += 1 | |
print('Result({})'.format(time)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_DISC = re.compile(r'Disc #(\d+) has (\d+) positions; at time=(\d+), it is at position (\d+).') | |
def main(): | |
data = [] | |
with open('D15.txt') as f: | |
data = f.read().strip().split('\n') | |
class Disc(object): | |
def __init__(self, id, positions, position): | |
self.id = id | |
self.positions = positions | |
self.position = position | |
def __repr__(self): | |
return '<Disc.{}.{}.{}>'.format(self.id, self.positions, self.position) | |
def get_state_at(self, time): | |
return (self.position + time) % self.positions | |
def done(discs, time): | |
return all([disc.get_state_at(time + index + 1) == 0 for (index, disc) in enumerate(discs)]) | |
discs = [Disc(*map(int, RE_DISC.match(line).group(1, 2, 4))) for line in data] | |
discs.append(Disc(7, 11, 0)) | |
time = 0 | |
while not done(discs, time): | |
time += 1 | |
print('Result({})'.format(time)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
data = '11011110011011101' | |
size = 35651584 | |
def dragon_curve(data): | |
return '{}0{}'.format( | |
data, | |
''.join(['0' if ch == '1' else '1' for ch in data[::-1]]) | |
) | |
def get_checksum(data, size): | |
checksum = '' | |
for n in range(0, size, 2): | |
chunk = data[n:n+2] | |
if chunk[0] == chunk[1]: | |
checksum += '1' | |
else: | |
checksum += '0' | |
return get_checksum(checksum, len(checksum)) if len(checksum) % 2 == 0 else checksum | |
while len(data) < size: | |
data = dragon_curve(data) | |
print('Result({})'.format(get_checksum(data, size))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
rows = 400000 | |
data = [] | |
with open('D18.txt') as f: | |
data = list(f.read().strip()) | |
def build_row(prev): | |
row = [] | |
size = len(prev) | |
for n in range(size): | |
left = prev[n - 1] if n > 0 else '.' | |
center = prev[n] | |
right = prev[n + 1] if n < (size - 1) else '.' | |
is_trap = False | |
if left == '^' and center == '^' and right == '.': | |
is_trap = True | |
elif center == '^' and right == '^' and left == '.': | |
is_trap = True | |
elif left == '.' and center == '.' and right == '^': | |
is_trap = True | |
elif left == '^' and center == '.' and right == '.': | |
is_trap = True | |
row.append('^' if is_trap else '.') | |
return row | |
board = data[:] | |
count = board.count('.') | |
for n in range(rows - 1): | |
board = build_row(board) | |
count += board.count('.') | |
print('Result({})'.format(count)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
input = 3005290 | |
elves = [1 for _ in range(input)] | |
while not any([elf == input for elf in elves]): | |
for index in range(input): | |
if elves[index] == 0: | |
continue | |
index2 = 0 if index == (input - 1) else index + 1 | |
while True: | |
if elves[index2] == 0: | |
index2 = (index2 + 1) % input | |
else: | |
break | |
elves[index] += elves[index2] | |
elves[index2] = 0 | |
print('Result({})'.format(elves.index(input) + 1)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NORTH = 1 | |
EAST = 2 | |
SOUTH = 3 | |
WEST = 4 | |
def main(): | |
data = [] | |
with open('D1.txt') as f: | |
data = f.read().strip('\n').replace(' ', '').split(',') | |
x, y = 0, 0 | |
dir = NORTH | |
def rotate(d, r): | |
if r == 'L': | |
return d - 1 if d > NORTH else WEST | |
elif r == 'R': | |
return d + 1 if d < WEST else NORTH | |
def move(p, d, n): | |
if d == NORTH: | |
p[1] += n | |
elif d == SOUTH: | |
p[1] -= n | |
elif d == EAST: | |
p[0] += n | |
elif d == WEST: | |
p[0] -= n | |
return p[0], p[1] | |
for info in data: | |
dir, steps = rotate(dir, info[:1]), int(info[1:]) | |
x, y = move([x, y], dir, steps) | |
print('Dir({}), Steps({})'.format(dir, steps)) | |
print('Dest({}, {})'.format(x, y)) | |
print('Result({})'.format(abs(x) + abs(y))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NORTH = 1 | |
EAST = 2 | |
SOUTH = 3 | |
WEST = 4 | |
def main(): | |
data = [] | |
with open('D1.txt') as f: | |
data = f.read().strip('\n').replace(' ', '').split(',') | |
x, y = 0, 0 | |
dir = NORTH | |
visited = {} | |
def rotate(d, r): | |
if r == 'L': | |
return d - 1 if d > NORTH else WEST | |
elif r == 'R': | |
return d + 1 if d < WEST else NORTH | |
def move(p, d, n): | |
if d == NORTH: | |
p[1] += n | |
elif d == SOUTH: | |
p[1] -= n | |
elif d == EAST: | |
p[0] += n | |
elif d == WEST: | |
p[0] -= n | |
return p[0], p[1] | |
for info in data: | |
dir, steps = rotate(dir, info[:1]), int(info[1:]) | |
print('Dir({}), Steps({})'.format(dir, steps)) | |
for _ in range(steps): | |
x, y = move([x, y], dir, 1) | |
index = '{}_{}'.format(x, y) | |
if visited.get(index, None): | |
print('Dest({}, {})'.format(x, y)) | |
print('Result({})'.format(abs(x) + abs(y))) | |
return | |
visited[index] = True | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
data = [] | |
with open('D20.txt') as f: | |
data = f.read().strip().split('\n') | |
blacklist = [list(map(int, line.split('-'))) for line in data] | |
blacklist.sort(key=lambda v: (v[0], v[1])) | |
ip, valid, idx = 0, [], 0 | |
while ip <= 4294967295: | |
(min, max, ) = blacklist[idx] | |
if ip < min: | |
valid.append(ip) | |
ip += 1 | |
else: | |
if ip > max: | |
idx += 1 | |
else: | |
ip = max + 1 | |
print('Part 1: {}'.format(valid[0])) | |
print('Part 2: {}'.format(len(valid))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import itertools | |
RE_SWAP_POS = re.compile(r'swap position (\d+) with position (\d+)') | |
RE_SWAP_LET = re.compile(r'swap letter ([a-z]+) with letter ([a-z]+)') | |
RE_ROT_DIR = re.compile(r'rotate (left|right) (\d+) step(?s)') | |
RE_ROT_POS = re.compile(r'rotate based on position of letter ([a-z]+)') | |
RE_REV_POS = re.compile(r'reverse positions (\d+) through (\d+)') | |
RE_MOV_POS = re.compile(r'move position (\d+) to position (\d+)') | |
def main(): | |
input1 = list('abcdefgh') | |
input2 = list('fbgdceah') | |
data = [] | |
with open('D21.txt') as f: | |
data = f.read().strip().split('\n') | |
def solve(data, input): | |
for line in data: | |
match = RE_SWAP_POS.match(line) | |
if match: | |
(a, b, ) = list(map(int, match.group(1, 2))) | |
input[a], input[b] = input[b], input[a] | |
continue | |
match = RE_SWAP_LET.match(line) | |
if match: | |
(a, b, ) = match.group(1, 2) | |
(ap, bp, ) = input.index(a), input.index(b) | |
input[ap], input[bp] = input[bp], input[ap] | |
continue | |
match = RE_ROT_DIR.match(line) | |
if match: | |
(dir, steps, ) = match.group(1), int(match.group(2)) | |
if dir == 'right': | |
steps = -steps | |
input = input[steps:] + input[:steps] | |
continue | |
match = RE_ROT_POS.match(line) | |
if match: | |
let = match.group(1) | |
pos = input.index(let) | |
rot = pos + 1 | |
if pos > 3: | |
rot += 1 | |
for n in range(rot): | |
input = input[-1:] + input[:-1] | |
continue | |
match = RE_REV_POS.match(line) | |
if match: | |
(a, b, ) = list(map(int, match.group(1, 2))) | |
rev = input[a:b+1][::-1] | |
input = input[:a] + rev + input[b+1:] | |
continue | |
match = RE_MOV_POS.match(line) | |
if match: | |
(a, b, ) = list(map(int, match.group(1, 2))) | |
let = input.pop(a) | |
input.insert(b, let) | |
continue | |
return input | |
p1 = solve(data, input1) | |
p2 = [] | |
for mut in itertools.permutations(input1): | |
if solve(data, list(mut)) == input2: | |
p2 = list(mut) | |
break | |
print('Part 1: {}'.format(''.join(p1))) | |
print('Part 2: {}'.format(''.join(p2))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from getch import getch | |
RE_NODE = re.compile(r'/dev/grid/node-x(\d+)-y(\d+)(?: +)(\d+)T(?: +)(\d+)T(?: +)(\d+)T(?: +)(\d+)%') | |
KEY_ESC = 27 | |
KEY_SPECIAL = 224 | |
KEY_DOWN = 80 | |
KEY_UP = 72 | |
KEY_RIGHT = 77 | |
KEY_LEFT = 75 | |
def main(): | |
data = [] | |
with open('D22.txt') as f: | |
data = f.read().strip().split('\n') | |
class Node(object): | |
def __init__(self, x, y, size, used, avail, percent): | |
self.x = x | |
self.y = y | |
self.size = size | |
self.used = used | |
self.avail = avail | |
self.percent = percent | |
def __repr__(self): | |
return '<Node@({}, {})>'.format(self.x, self.y) | |
def canMove(self, other): | |
return other.avail > self.used | |
def move(self, other): | |
if other.avail < self.used: | |
return False | |
other.used += self.used | |
other.avail -= self.used | |
self.used = 0 | |
self.avail = self.size | |
return True | |
nodes = [] | |
for line in data: | |
match = RE_NODE.match(line) | |
if match: | |
nodes.append(Node(*map(int, match.group(1, 2, 3, 4, 5, 6)))) | |
viable = 0 | |
for node in nodes: | |
for inner in nodes: | |
if node == inner: | |
continue | |
if node.used != 0 and node.canMove(inner): | |
viable += 1 | |
print('Part 1: {}'.format(viable)) | |
width = max([node.x for node in nodes]) | |
height = max([node.y for node in nodes]) | |
min_size = min([node.size for node in nodes]) | |
grid = [[None] * width for _ in range(height)] | |
for node in nodes: | |
(x, y, ch, ) = node.x - 1, node.y - 1, '.' | |
if (x, y, ) == (0, 0, ): | |
ch = 'S' | |
elif (x, y, ) == (width - 1, 0, ): | |
ch = 'G' | |
elif node.used == 0: | |
print(x, y) | |
ch = '_' | |
elif node.size > 500: | |
ch = '#' | |
grid[y][x] = ch | |
(cx, cy, steps, ) = (width - 2, height - 1, 0, ) | |
while True: | |
print('===========') | |
print('\n'.join([''.join(row) for row in grid])) | |
print('Steps: {}'.format(steps)) | |
key = ord(getch()) | |
if key == KEY_ESC: | |
break | |
elif key == KEY_SPECIAL: | |
key = ord(getch()) | |
if key == KEY_DOWN: | |
grid[cy][cx] = grid[cy + 1][cx] | |
grid[cy + 1][cx] = '_' | |
cy += 1 | |
elif key == KEY_UP: | |
grid[cy][cx] = grid[cy - 1][cx] | |
grid[cy - 1][cx] = '_' | |
cy -= 1 | |
elif key == KEY_RIGHT: | |
grid[cy][cx] = grid[cy][cx + 1] | |
grid[cy][cx + 1] = '_' | |
cx += 1 | |
elif key == KEY_LEFT: | |
grid[cy][cx] = grid[cy][cx - 1] | |
grid[cy][cx - 1] = '_' | |
cx -= 1 | |
steps += 1 | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
def main(): | |
data = [] | |
with open('D23.txt') as f: | |
data = f.read().strip().split('\n') | |
def cpy(tape, pc, regs, src, dst): | |
try: | |
if src in ['a', 'b', 'c', 'd']: | |
regs[dst] = regs[src] | |
else: | |
regs[dst] = int(src) | |
except KeyError: | |
pass | |
return pc + 1 | |
def inc(tape, pc, regs, reg): | |
try: | |
regs[reg] += 1 | |
except KeyError: | |
pass | |
return pc + 1 | |
def dec(tape, pc, regs, reg): | |
try: | |
regs[reg] -= 1 | |
except KeyError: | |
pass | |
return pc + 1 | |
def jnz(tape, pc, regs, reg, offset): | |
value = 0 | |
offset_ = 1 | |
try: | |
value = int(reg) | |
except ValueError: | |
value = regs[reg] | |
if value != 0: | |
try: | |
offset_ = int(offset) | |
except ValueError: | |
offset_ = regs[offset] | |
return pc + offset_ | |
def tgl(tape, pc, regs, reg): | |
value = regs[reg] | |
position = pc + value | |
if position < 0 or position > len(tape) - 1: | |
return pc + 1 | |
info = tape[position].split(' ') | |
if info[0] in ['dec', 'tgl']: | |
tape[position] = 'inc {}'.format(info[1]) | |
elif info[0] == 'inc': | |
tape[position] = 'dec {}'.format(info[1]) | |
elif info[0] == 'jnz': | |
tape[position] = 'cpy {} {}'.format(info[1], info[2]) | |
elif info[0] == 'cpy': | |
tape[position] = 'jnz {} {}'.format(info[1], info[2]) | |
return pc + 1 | |
lut = {'cpy': cpy, 'inc': inc, 'dec': dec, 'jnz': jnz, 'tgl': tgl} | |
def solve(tape, regs): | |
pc = 0 | |
while pc < len(tape): | |
info = tape[pc].split(' ') | |
pc = lut.get(info[0], None)(tape, pc, regs, *info[1:]) | |
return regs | |
print('Part 1: {}'.format(solve(data[:], {'a': 7, 'b': 0, 'c': 0, 'd': 0}).get('a', 0))) | |
print('Part 2: {}'.format(solve(data[:], {'a': 12, 'b': 0, 'c': 0, 'd': 0}).get('a', 0))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
KEYPAD = [ | |
[1, 2, 3], | |
[4, 5, 6], | |
[7, 8, 9], | |
] | |
def main(): | |
data = [] | |
with open('D2.txt') as f: | |
data = f.read().strip().split('\n') | |
x, y = 1, 1 | |
code = [] | |
def move(p, d): | |
if d == 'L' and p[0] > 0: | |
p[0] -= 1 | |
elif d == 'R' and p[0] < 2: | |
p[0] += 1 | |
elif d == 'U' and p[1] > 0: | |
p[1] -= 1 | |
elif d == 'D' and p[1] < 2: | |
p[1] += 1 | |
return p[0], p[1] | |
for line in data: | |
for dir in line: | |
x, y = move([x, y], dir) | |
code.append(str(KEYPAD[y][x])) | |
print('Code({})'.format(''.join(code))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
KEYPAD = [ | |
[None, None, 1, None, None], | |
[None, 2, 3, 4, None, None], | |
[5, 6, 7, 8, 9], | |
[None, 'A', 'B', 'C', None], | |
[None, None, 'D', None, None], | |
] | |
def main(): | |
data = [] | |
with open('D2.txt') as f: | |
data = f.read().strip().split('\n') | |
x, y = 0, 2 | |
code = [] | |
def move(p, d): | |
x, y = p[0], p[1] | |
if d == 'L': | |
if y == 0 or y == 4: | |
pass | |
elif y == 1 or y == 3: | |
if x > 1: | |
x -= 1 | |
elif y == 2: | |
if x > 0: | |
x -= 1 | |
elif d == 'R': | |
if y == 0 or y == 4: | |
pass | |
elif y == 1 or y == 3: | |
if x < 3: | |
x += 1 | |
elif y == 2: | |
if x < 4: | |
x += 1 | |
elif d == 'U': | |
if x == 0 or x == 4: | |
pass | |
elif x == 1 or x == 3: | |
if y > 1: | |
y -= 1 | |
elif x == 2: | |
if y > 0: | |
y -= 1 | |
elif d == 'D': | |
if x == 0 or x == 4: | |
pass | |
elif x == 1 or x == 3: | |
if y < 3: | |
y += 1 | |
elif x == 2: | |
if y < 4: | |
y += 1 | |
return x, y | |
for line in data: | |
for dir in line: | |
x, y = move([x, y], dir) | |
code.append(str(KEYPAD[y][x])) | |
print('Code({})'.format(''.join(code))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
data = [] | |
with open('D3.txt') as f: | |
data = f.read().strip().split('\n') | |
def is_valid_triangle(*args): | |
a, b, c = args[0], args[1], args[2] | |
return a + b > c and b + c > a and a + c > b | |
valid = [is_valid_triangle(*map(int, line.split())) for line in data].count(True) | |
print('Result({})'.format(valid)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
data = [] | |
with open('D3.txt') as f: | |
data = f.read().strip().split('\n') | |
def is_valid_triangle(*args): | |
a, b, c = args[0], args[1], args[2] | |
return a + b > c and b + c > a and a + c > b | |
triangles = [] | |
offset = 0 | |
total = len(data) | |
while offset < total: | |
a1, a2, a3 = map(int, data[offset + 0].split()) | |
b1, b2, b3 = map(int, data[offset + 1].split()) | |
c1, c2, c3 = map(int, data[offset + 2].split()) | |
triangles.append([a1, b1, c1]) | |
triangles.append([a2, b2, c2]) | |
triangles.append([a3, b3, c3]) | |
offset += 3 | |
valid = [is_valid_triangle(*triangle) for triangle in triangles].count(True) | |
print('Result({})'.format(valid)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from collections import Counter | |
def main(): | |
data = [] | |
with open('D4.txt') as f: | |
data = f.read().strip().split('\n') | |
def is_real_room(line): | |
match = re.match(r'([a-z\-]+)-(\d+)\[([a-z]+)\]', line) | |
room, id, checksum = match.group(1, 2, 3) | |
data = [] | |
freq = Counter(room.replace('-', '')) | |
for (letter, count, ) in freq.items(): | |
data.append([letter, count]) | |
data.sort(key=lambda v: (-v[1], v[0], )) | |
return int(id) if ''.join([v[0] for v in data[:5]]) == checksum else 0 | |
print('Result({})'.format(sum([is_real_room(line) for line in data]))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from collections import Counter | |
def main(): | |
data = [] | |
with open('D4.txt') as f: | |
data = f.read().strip().split('\n') | |
def get_room_info(line): | |
match = re.match(r'([a-z\-]+)-(\d+)\[([a-z]+)\]', line) | |
room, id, checksum = match.group(1, 2, 3) | |
data = [] | |
freq = Counter(room.replace('-', '')) | |
for (letter, count, ) in freq.items(): | |
data.append([letter, count]) | |
data.sort(key=lambda v: (-v[1], v[0], )) | |
if ''.join([v[0] for v in data[:5]]) != checksum: | |
return (-1, '', ) | |
result = [chr((ord(letter) - ord('a') + int(id)) % 26 + ord('a')) if letter != '-' else ' ' for letter in room] | |
return (id, ''.join(result), ) | |
valid = list(filter( | |
lambda v: v[1].find('north') != -1, | |
list(filter(lambda v: v[0] != -1, [get_room_info(line) for line in data])) | |
)) | |
print('\n'.join(['#{} - {}'.format(entry[0], entry[1]) for entry in valid])) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from hashlib import md5 | |
def main(): | |
input = 'abbhdwsy' | |
output = '' | |
index = 0 | |
while len(output) < 8: | |
hash = md5('{}{}'.format(input, index).encode()).hexdigest() | |
if hash.startswith('00000'): | |
output += hash[5] | |
index += 1 | |
print(output) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from hashlib import md5 | |
def main(): | |
input = 'abbhdwsy' | |
output = [None] * 8 | |
index = 0 | |
while not all(output): | |
hash = md5('{}{}'.format(input, index).encode()).hexdigest() | |
index += 1 | |
if hash.startswith('00000'): | |
pos = hash[5] | |
# 0-7 range | |
if ord(pos) < 48 or ord(pos) > 55: | |
continue | |
if output[int(pos)] is not None: | |
continue | |
output[int(pos)] = hash[6] | |
print(''.join(output)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import Counter | |
def main(): | |
data = [] | |
with open('D6.txt') as f: | |
data = f.read().strip().split('\n') | |
print(''.join([Counter(line).most_common()[0][0] for line in zip(*data)])) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import Counter | |
def main(): | |
data = [] | |
with open('D6.txt') as f: | |
data = f.read().strip().split('\n') | |
print(''.join([Counter(line).most_common()[-1][0] for line in zip(*data)])) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
def main(): | |
data = [] | |
with open('D7.txt') as f: | |
data = f.read().strip().split('\n') | |
def get_chunks(line): | |
chunks_outer = [] | |
chunks_inner = [] | |
str_outer = '' | |
str_inner = '' | |
inner = False | |
for ch in line: | |
if ch == '[': | |
inner = True | |
chunks_outer.append(str_outer) | |
str_outer = '' | |
elif ch == ']': | |
inner = False | |
chunks_inner.append(str_inner) | |
str_inner = '' | |
else: | |
if inner: | |
str_inner += ch | |
else: | |
str_outer += ch | |
if str_outer: | |
chunks_outer.append(str_outer) | |
return chunks_outer, chunks_inner | |
def check_chunk(chunk): | |
for n in range(len(chunk) - 4 + 1): | |
a, b = chunk[n:n+2], chunk[n+2:n+2+2][::-1] | |
if a == b and a[0] != a[1]: | |
return True | |
return False | |
def supports_tls(outer, inner): | |
inner_any = any([check_chunk(chunk) for chunk in inner]) | |
outer_any = any([check_chunk(chunk) for chunk in outer]) | |
return 1 if (not inner_any and outer_any) else 0 | |
result = sum([supports_tls(*get_chunks(line)) for line in data]) | |
print('Result({})'.format(result)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
def main(): | |
data = [] | |
with open('D7.txt') as f: | |
data = f.read().strip().split('\n') | |
def get_chunks(line): | |
chunks_outer = [] | |
chunks_inner = [] | |
str_outer = '' | |
str_inner = '' | |
inner = False | |
for ch in line: | |
if ch == '[': | |
inner = True | |
chunks_outer.append(str_outer) | |
str_outer = '' | |
elif ch == ']': | |
inner = False | |
chunks_inner.append(str_inner) | |
str_inner = '' | |
else: | |
if inner: | |
str_inner += ch | |
else: | |
str_outer += ch | |
if str_outer: | |
chunks_outer.append(str_outer) | |
return chunks_outer, chunks_inner | |
def partition_chunk(chunk): | |
parts = [] | |
for n in range(len(chunk) - 3 + 1): | |
part = chunk[n:n+3] | |
if part[0] == part[2] and part[0] != part[1]: | |
parts.append(part) | |
return parts | |
def supports_ssl(outer, inner): | |
outer = sum([partition_chunk(chunk) for chunk in outer], []) | |
inner = sum([partition_chunk(chunk) for chunk in inner], []) | |
inner = ['{}{}{}'.format(chunk[1], chunk[0], chunk[1]) for chunk in inner] | |
return 1 if len([o for o in outer if o in inner]) else 0 | |
result = sum([supports_ssl(*get_chunks(line)) for line in data]) | |
print('Result({})'.format(result)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_RECT = re.compile(r'rect (\d+)x(\d+)') | |
RE_ROT_COL = re.compile(r'rotate column x=(\d+) by (\d+)') | |
RE_ROT_ROW = re.compile(r'rotate row y=(\d+) by (\d+)') | |
def main(): | |
data = [] | |
with open('D8.txt') as f: | |
data = f.read().strip().split('\n') | |
board = [['.' for _ in range(50)] for _ in range(6)] | |
for line in data: | |
if line.startswith('rect '): | |
w, h = RE_RECT.match(line).group(1, 2) | |
for x in range(int(w)): | |
for y in range(int(h)): | |
board[y][x] = '#' | |
elif line.startswith('rotate column '): | |
x, r = RE_ROT_COL.match(line).group(1, 2) | |
column = [board[n][int(x)] for n in range(6)] | |
for _ in range(int(r)): | |
column.insert(0, column.pop()) | |
for (index, cell) in enumerate(column): | |
board[index][int(x)] = cell | |
elif line.startswith('rotate row '): | |
y, r = RE_ROT_ROW.match(line).group(1, 2) | |
for _ in range(int(r)): | |
board[int(y)].insert(0, board[int(y)].pop()) | |
valid = len(list(filter(lambda v: v != '.', sum(board, [])))) | |
print('Result({})'.format(valid)) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_RECT = re.compile(r'rect (\d+)x(\d+)') | |
RE_ROT_COL = re.compile(r'rotate column x=(\d+) by (\d+)') | |
RE_ROT_ROW = re.compile(r'rotate row y=(\d+) by (\d+)') | |
def main(): | |
data = [] | |
with open('D8.txt') as f: | |
data = f.read().strip().split('\n') | |
board = [['.' for _ in range(50)] for _ in range(6)] | |
for line in data: | |
if line.startswith('rect '): | |
w, h = RE_RECT.match(line).group(1, 2) | |
for x in range(int(w)): | |
for y in range(int(h)): | |
board[y][x] = '#' | |
elif line.startswith('rotate column '): | |
x, r = RE_ROT_COL.match(line).group(1, 2) | |
column = [board[n][int(x)] for n in range(6)] | |
for _ in range(int(r)): | |
column.insert(0, column.pop()) | |
for (index, cell) in enumerate(column): | |
board[index][int(x)] = cell | |
elif line.startswith('rotate row '): | |
y, r = RE_ROT_ROW.match(line).group(1, 2) | |
for _ in range(int(r)): | |
board[int(y)].insert(0, board[int(y)].pop()) | |
print('\n'.join([''.join(row) for row in board])) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
RE_MARKER = re.compile(r'\((\d+)x(\d+)\)') | |
def main(): | |
data = [] | |
with open('D9.txt') as f: | |
data = f.read().strip().split('\n') | |
def decompress(line): | |
result = 0 | |
pos = 0 | |
while pos < len(line): | |
match = RE_MARKER.search(line, pos) | |
if not match: | |
result += len(line[pos:]) | |
break | |
chars, times = map(int, match.group(1, 2)) | |
result += chars * times | |
pos += match.end() - match.start() | |
pos += chars | |
return str(result) | |
print('\n'.join([decompress(line) for line in data])) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment