Skip to content

Instantly share code, notes, and snippets.

@diath
Last active December 3, 2017 14:16
Show Gist options
  • Save diath/3fe59a0fee86e2daa8c40ed3783055fc to your computer and use it in GitHub Desktop.
Save diath/3fe59a0fee86e2daa8c40ed3783055fc to your computer and use it in GitHub Desktop.
Advent of Code, 2016, Python
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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