Skip to content

Instantly share code, notes, and snippets.

@Xpktro
Last active December 11, 2016 00:29
Show Gist options
  • Save Xpktro/a8abcde788f25fc0b0b944e37d539147 to your computer and use it in GitHub Desktop.
Save Xpktro/a8abcde788f25fc0b0b944e37d539147 to your computer and use it in GitHub Desktop.
Advent of code solutions
import re
instructions = """""".split('\n')
robots = {
# '1': (values, low_to, hi_to)
}
outputs = {
# '0': 0
}
def create_or_set(robot_number, number, low_to, hi_to):
if robot_number not in robots:
robots[robot_number] = ([], None, None)
values, low_to_, hi_to_ = robots[robot_number]
if number:
values.append(int(number))
if low_to:
low_to_ = low_to
if hi_to:
hi_to_ = hi_to
robots[robot_number] = (values, low_to_, hi_to_)
for line in instructions:
type_, values = line.split(' ', 1)
if type_ == 'bot':
robot_number, _, low_to, _, hi_to = re.split(r'( gives low to | and high to )', values)
create_or_set(robot_number, None, low_to, hi_to)
elif type_ == 'value':
value, robot_number = values.split(' goes to bot ')
create_or_set(robot_number, value, None, None)
first_number = 61
second_number = 17
while('0' not in outputs):
for robot_number, robot_values in robots.items():
numbers, low_to, hi_to = robot_values
if len(numbers) < 2:
continue
if first_number in numbers and second_number in numbers:
print('robot: ', robot_number)
first, second = numbers
if first > second:
low, high = second, first
else:
low, high = first, second
where_low, low_to = low_to.split(' ')
if where_low == 'bot':
create_or_set(low_to, low, None, None)
else:
outputs[low_to] = low
where_hi, hi_to = hi_to.split(' ')
if where_hi == 'bot':
create_or_set(hi_to, high, None, None)
else:
outputs[hi_to] = high
del robots[robot_number]
robots[robot_number] = ([], low_to, hi_to)
print(outputs)
print('product', outputs['0'] * outputs['1'] * outputs['2'])
from functools import reduce
instructions = ''
instructions = instructions.split(', ')
def L(vector):
x, y = vector
return (y, -1 * x)
def R(vector):
x, y = vector
return (-1 * y, x)
def scalar_mult(vector, factor):
x, y = vector
return (x * factor, y * factor)
def sum_v(vec1, vec2):
x1, y1 = vec1
x2, y2 = vec2
return (x1 + x2, y1 + y2)
def blocks_away(vector):
x, y = vector
return abs(x) + abs(y)
def process_instruction(current_state, item):
current_position, facing = current_state
rotation, blocks = item[0], int(item[1:])
now_facing = {'L': L, 'R': R}[rotation](facing)
will_move = scalar_mult(now_facing, blocks)
resulting_position = sum_v(current_position, will_move)
return (resulting_position, now_facing)
# reducing using (blcks so far, facing direction) as the state
final_position, final_facing = reduce(process_instruction, instructions, ((0, 0), (1,0)))
print('final_position:', final_position, 'blocks_away:', blocks_away(final_position))
from functools import reduce
instructions = ''
instructions = instructions.split(', ')
def L(vector):
x, y = vector
return (y, -1 * x)
def R(vector):
x, y = vector
return (-1 * y, x)
def scalar_mult(vector, factor):
x, y = vector
return (x * factor, y * factor)
def sum_v(vec1, vec2):
x1, y1 = vec1
x2, y2 = vec2
return (x1 + x2, y1 + y2)
def blocks_away(vector):
x, y = vector
return abs(x) + abs(y)
def process_instruction(current_state, item):
current_position, facing, visited_blocks, visited_twice = current_state
if visited_twice:
return (current_position, facing, visited_blocks, visited_twice)
rotation, blocks = item[0], int(item[1:])
now_facing = {'L': L, 'R': R}[rotation](facing)
def walk(current_state, _):
current_position, _ = current_state
if current_position in visited_blocks:
visited_blocks[current_position] = 2
return (current_position, True)
else:
visited_blocks[current_position] = 1
return (sum_v(current_position, now_facing), False)
resulting_position, visited_twice_ = reduce(walk, range(blocks), (current_position, False))
return (resulting_position, now_facing, visited_blocks, visited_twice_)
# reducing using (current position, facing direction, visited blocks, visited twice) as the state
final_position, _, _, _ = \
reduce(process_instruction, instructions, ((0, 0), (1,0), {}, False))
print('final_position:', final_position, 'blocks_away:', blocks_away(final_position))
from functools import reduce
instructions = """"""
instructions = instructions.split('\n')
def coords_to_digit(coords):
x, y = coords
return (
'123',
'456',
'789',
)[y+1][x+1]
def sum_v(vec1, vec2):
x1, y1 = vec1
x2, y2 = vec2
x = x1 + x2
y = y1 + y2
return (x if -1 <= x <= 1 else x1, y if -1 <= y <= 1 else y1)
def process_digit(last_position, instruction):
# Inverted U/D for coords_to_digit to look nice
directions = {'L': (-1, 0), 'R': (1, 0), 'D': (0, 1), 'U': (0, -1)}
return sum_v(last_position, directions[instruction])
def process_digits(code, intructions):
return code + coords_to_digit(reduce(process_digit, intructions, (0, 0)))
print(reduce(process_digits, instructions, ''))
from functools import reduce
instructions = """"""
instructions = instructions.split('\n')
def coords_to_digit(coords):
x, y = coords
return (
'00100',
'02340',
'56789',
'0ABC0',
'00D00',
)[y+2][x+2]
def sum_v(vec1, vec2):
x1, y1 = vec1
x2, y2 = vec2
x = x1 + x2
y = y1 + y2
result = (x if -2 <= x <= 2 else x1, y if -2 <= y <= 2 else y1)
return result if coords_to_digit(result) != '0' else vec1
def process_digit(last_position, instruction):
directions = {'L': (-1, 0), 'R': (1, 0), 'D': (0, 1), 'U': (0, -1)}
return sum_v(last_position, directions[instruction])
def process_digits(code, intructions):
return code + coords_to_digit(reduce(process_digit, intructions, (-2, 0)))
print(reduce(process_digits, instructions, ''))
from functools import reduce
import re
triangles_str = """"""
triangles_in = triangles_str.split('\n')
triangles_split = [
map(int, re.split(' +', triangle.strip()))
for triangle in triangles_in
]
def validate_triangle(valid_triangles, triangle):
a, b, c = triangle
if a + b > c and \
b + c > a and \
a + c > b:
return valid_triangles + 1
return valid_triangles
print(reduce(validate_triangle, triangles_split, 0))
from functools import reduce
import re
triangles_str = """"""
triangles_in = triangles_str.split('\n')
triangles_split = [
map(int, re.split(' +', triangle.strip()))
for triangle in triangles_in
]
triangles_trasposed = zip(*triangles_split)
def validate_triangle(valid_triangles, triangle):
a, b, c = triangle
if a + b > c and \
b + c > a and \
a + c > b:
return valid_triangles + 1
return valid_triangles
def validate_triangle_column(valid_triangles, column):
triangles = [column[i:i + 3] for i in range(0, len(column), 3)]
return valid_triangles + reduce(validate_triangle, triangles, 0)
print(reduce(validate_triangle_column, triangles_trasposed, 0))
rooms_str = """"""
rooms_split = rooms_str.split('\n')
def parse_room(room):
*letters, id_checksum = room.split('-')
letters_merged = ''.join(letters)
id_, checksum = id_checksum.replace(']', '').split('[')
return (letters_merged, checksum, int(id_))
def check_room(room):
letters, checksum, id_ = room
unique_letters = sorted(set(letters))
pre_checksum = sorted(unique_letters, key=letters.count, reverse=True)
if ''.join(pre_checksum[:len(checksum)]) == checksum:
return id_
else:
return 0
rooms = map(parse_room, rooms_split)
print(sum(map(check_room, rooms)))
import string
rooms_str = """"""
rooms_split = rooms_str.split('\n')
def shift(letter, amount=3, alphabet=string.ascii_lowercase):
return alphabet[(alphabet.index(letter) + amount) % len(alphabet)] \
if letter != ' ' else ' '
def parse_room(room):
*letters, id_checksum = room.split('-')
letters_merged = ''.join(letters)
id_, checksum = id_checksum.replace(']', '').split('[')
return (letters_merged, checksum, int(id_))
def check_room(room):
letters, checksum, id_ = room
unique_letters = sorted(set(letters))
pre_checksum = sorted(unique_letters, key=letters.count, reverse=True)
if ''.join(pre_checksum[:len(checksum)]) == checksum:
if ''.join(map(lambda letter: shift(letter, id_), letters)) == 'northpoleobjectstorage':
print('storage:', id_)
return id_
else:
return 0
rooms = map(parse_room, rooms_split)
sum(map(check_room, rooms))
from hashlib import md5
door_id = ''
def door_password(door_id, password_length):
password_so_far = ''
index = 0
while(len(password_so_far) < password_length):
md5_ = md5('{}{}'.format(door_id, index).encode()).hexdigest()
if md5_.startswith('00000'):
password_so_far += md5_[5]
index += 1
return password_so_far
print(door_password(door_id, 8))
from hashlib import md5
door_id = ''
def door_password(door_id, password_length):
password_so_far = '_' * password_length
index = 0
while('_' in password_so_far):
md5_ = md5('{}{}'.format(door_id, index).encode()).hexdigest()
if md5_.startswith('00000'):
position = int(md5_[5], 16)
if position < password_length and password_so_far[position] == '_':
password_so_far = password_so_far[:position] + md5_[6] + password_so_far[position + 1:]
index += 1
return password_so_far
print(door_password(door_id, 8))
signal = """"""
signal = signal.split('\n')
signal = zip(*signal)
ranking = [sorted(letter, key=letter.count, reverse=True)[0] for letter in signal]
print(''.join(ranking))
signal = """"""
signal = signal.split('\n')
signal = zip(*signal)
ranking = [sorted(letter, key=letter.count, reverse=False)[0] for letter in signal]
print(''.join(ranking))
import re
ips = """""".split('\n')
def rule(text):
match = re.search(r'(\w)(\w)\2\1', text)
if match:
return len(set(match.groups())) == 2
else:
return False
def matchs(line):
parts = re.split(r'[\[\]]', line)
outside = parts[::2]
inside = parts[1::2]
if any(map(rule, outside)) and not any(map(rule, inside)):
return 1
else:
return 0
print(sum(map(matchs, ips)))
import regex as re
ips = """""".split('\n')
def abba(text):
match = re.search(r'(\w)(\w)\2\1', text)
if match:
return len(set(match.groups())) == 2
else:
return False
def bab(aba_groups):
a, b = aba_groups
def bab_(hypernet):
match = re.search(r'{}{}{}'.format(b, a, b), hypernet)
if match:
return True
else:
return False
return bab_
def aba(hypernets):
def aba_(text):
match = list(re.finditer(r'(\w)(\w)\1', text, overlapped=True))
if any(match):
return any(map(lambda m: len(set(m.groups())) == 2 and any(map(bab(m.groups()), hypernets)), match))
else:
return False
return aba_
def matchs(line):
parts = re.split(r'[\[\]]', line)
outside = parts[::2]
inside = parts[1::2]
if any(map(aba(inside), outside)):
return 1
else:
return 0
print(sum(map(matchs, ips)))
instructions = """""".split('\n')
instructions = [instruction.split(' ') for instruction in instructions]
screen = ['.' * 50] * 6
def lit_pixel(screen, x, y):
row = screen[y]
new_row = row[:x] + '#' + row[x+1:]
return screen[:y] + [new_row] + screen[y+1:]
def rect(screen, x, y):
for x_ in range(x):
for y_ in range(y):
screen = lit_pixel(screen, x_, y_)
return screen
def rotate(screen, row, amount, column=False):
if column:
screen = list(zip(*screen))
screen = [''.join(line) for line in screen]
row_ = screen[row][-amount:] + screen[row][:-amount]
screen = screen[:row] + [row_] + screen[row+1:]
if column:
screen = list(zip(*screen))
screen = [''.join(line) for line in screen]
return screen
for instruction in instructions:
operation, *rest = instruction
if operation == 'rect':
x, y = map(int, rest.pop().split('x'))
screen = rect(screen, x, y)
elif operation == 'rotate':
row_column, direction, _, amount = rest
direction = int(direction.split('=')[1])
amount = int(amount)
screen = rotate(screen, direction, amount, row_column == 'column')
for line in screen:
print(line)
print(sum(map(lambda l: l.count("#"), screen)))
compressed_str = ''.replace(' ', '')
decompressed_str = compressed_str[:compressed_str.index('(')]
compressed_str = compressed_str[compressed_str.index('('):]
while(compressed_str):
command = compressed_str[1:compressed_str.index(')')]
compressed_str = compressed_str[compressed_str.index(')')+1:]
amount, repeat = map(int, command.split('x'))
decompressed_str += (compressed_str[:amount] * (repeat))
compressed_str = compressed_str[amount:]
if '(' in compressed_str:
decompressed_str += compressed_str[:compressed_str.index('(')]
compressed_str = compressed_str[compressed_str.index('('):]
else:
decompressed_str += compressed_str
compressed_str = ''
print(len(decompressed_str))
compressed_str = ''.replace(' ', '')
def decompress(text):
if '(' not in text:
return len(text)
initial_chars, rest = text.split('(', 1)
instruction, rest = rest.split(')', 1)
chars, amount = map(int, instruction.split('x'))
return len(initial_chars) + decompress(rest[:chars]) * amount + decompress(rest[chars:])
print(decompress(compressed_str))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment