import hashlib from common import print_results, readline INPUT = readline(__file__) def find_suffix(prefix, suffix=0): while True: md5 = hashlib.md5(str.encode(INPUT + str(suffix))) if md5.hexdigest().startswith(prefix): return suffix suffix += 1 #### Main part. five = find_suffix('0' * 5) six = find_suffix('0' * 6, five) print_results(five, six)
from common import print_results, readline def find_basement_position(parentheses): floor = 0 for i, p in enumerate(parentheses, start=1): floor += 1 if p == '(' else -1 if floor == -1: return i #### Main part. parentheses = readline(__file__) print_results( parentheses.count('(') - parentheses.count(')'), find_basement_position(parentheses), )
def __init__(self): self.x = 0 self.y = 0 self.visited_locations = {(0, 0)} def update_location(self, direction): dx, dy = self.STR2VEC[direction] self.x += dx self.y += dy self.visited_locations.add((self.x, self.y)) #### Main part. directions = readline(__file__) # Part One santa_only = Runner() for d in directions: santa_only.update_location(d) # Part Two santa = Runner() robo_santa = Runner() for d, e in zip(directions[0::2], directions[1::2]): santa.update_location(d) robo_santa.update_location(e) print_results(len(santa_only.visited_locations), len(santa.visited_locations | robo_santa.visited_locations))
import re from common import print_results, readline ROW_COLUMN_REGEX = re.compile(r'Enter the code at row (\d+), column (\d+)\.') ROW, COLUMN = map(int, ROW_COLUMN_REGEX.search(readline(__file__)).groups()) A_0 = 20151125 FACTOR = 252533 DIVISOR = 33554393 # First, calculate how many steps are necessary. b = ROW + COLUMN - 2 number_steps = b * (b + 1) // 2 + b + 2 - ROW def do_step(a_n): while True: yield a_n a_n = FACTOR * a_n % DIVISOR #### Main part. sequence = do_step(A_0) for _ in range(number_steps - 1): sequence.__next__() print_results(sequence.__next__(), 'Merry Christmas!')
import re from common import print_results, readline sequence = readline(__file__) DIGIT_GROUP = re.compile(r'((\d)\2*)') def play_game(times): global sequence for _ in range(times): res = '' for group, digit in DIGIT_GROUP.findall(sequence): res += '{}{}'.format(len(group), digit) sequence = res return len(sequence) print_results(play_game(40), play_game(10))
return True if index in (-1, self.length) else self.boolean_repr[index] def __setitem__(self, index, value): self.boolean_repr[index] = value class ApparentField: def __init__(self, first_row): self.previous_row = first_row self.number_safe_tiles = self.previous_row.get_number_safe_tiles() def __add_next_row(self): new_row = Row.from_previous(self.previous_row) self.previous_row = new_row self.number_safe_tiles += new_row.get_number_safe_tiles() def add_rows(self, number_rows): for i in range(number_rows): self.__add_next_row() #### Main part. first_row = Row.from_string(readline(__file__)) field = ApparentField(first_row) field.add_rows(NUMBER_ROWS_1) part_1 = field.number_safe_tiles field.add_rows(NUMBER_ROWS_2 - NUMBER_ROWS_1) part_2 = field.number_safe_tiles print_results(part_1, part_2)
from collections import deque, namedtuple from hashlib import md5 from common import print_results, readline INPUT = readline(__file__).encode() Direction = namedtuple('Direction', ['dx', 'dy', 'token']) UP = Direction( 0, -1, b'U') DOWN = Direction( 0, +1, b'D') LEFT = Direction(-1, 0, b'L') RIGHT = Direction(+1, 0, b'R') class Position: def __init__(self, x=0, y=0, tokens=b''): self.x = x self.y = y self.digest = Digest(tokens) def get_possible_directions(self): up, down, left, right = self.digest.md5[:4] directions = [] if self.x != 0 and Position.is_door_open(left): directions.append(LEFT) if self.x != 3 and Position.is_door_open(right): directions.append(RIGHT) if self.y != 0 and Position.is_door_open(up): directions.append(UP) if self.y != 3 and Position.is_door_open(down):
from common import print_results, readline NUMBER_ELVES = int(readline(__file__)) def get_winner_of_game_1(): number_participants = 1 winner = 1 while number_participants < NUMBER_ELVES: number_participants += 1 winner = winner + 2 if winner + 2 <= number_participants else 1 return winner def get_winner_of_game_2(): participants = list(range(1, NUMBER_ELVES + 1)) turn = 0 number_participants = NUMBER_ELVES while number_participants > 1: elf_to_kick = (int(number_participants / 2) + turn) % number_participants del participants[elf_to_kick] number_participants = len(participants) turn = (turn if elf_to_kick < turn else turn + 1) % number_participants return participants[0] #### Main part. print_results(get_winner_of_game_1(), get_winner_of_game_2())
from itertools import product as prod import networkx as nx from common import print_results, readline FAVORITE = 1350 SOURCE = (1, 1) TARGET = tuple(map(int, readline(__file__).split(','))) MAX_EXPANSION = 50 MAX_DISTANCE = 50 class Maze: def __init__(self): self.graph = nx.Graph() self.__set_up_graph() # Find shortest path to each node starting at 'SOURCE'. self.shortest_paths = nx.shortest_path_length(self.graph, source=SOURCE) # Set up a graph where the nodes are the open spaces. Neighboring open # spaces are connected by an edge. def __set_up_graph(self): for i, j in prod(range(0, MAX_EXPANSION), repeat=2): if self.__is_open_space(i, j): for k, l in list(prod([-1, 1], [0])) + list(prod([0], [-1, 1])): if self.__is_open_space(i + k, j + l): self.graph.add_edge((i, j), (i + k, j + l)) def __is_open_space(self, x, y): if x < 0 or y < 0:
from functools import reduce from math import ceil, sqrt from common import print_results, readline INPUT = int(readline(__file__)) def get_factors(n): return set( reduce(list.__add__, ([i, n // i] for i in range(1, ceil(sqrt(n)) + 1) if n % i == 0))) def get_factors_with_limitation(Factors): for factor in Factors: Elves[factor] = Elves[factor] + 1 if factor in Elves else 1 return {factor for factor in Factors if Elves[factor] <= 50} #### Main part. Elves = {} house = 0 house_1 = 0 house_2 = 0 while True: house += 1 Factors = get_factors(house)
import hashlib import re from common import print_results, readline SALT = readline(__file__) REACHABLE_NUMBER = 1000 TO_FIND = 64 TIMES = 2016 + 1 class PossibleKey: REGEX_THREE = re.compile(r'(.)\1{2}') REGEX_FIVE = re.compile(r'(.)\1{4}') def __init__(self, md5): try: self.three_char, = PossibleKey.REGEX_THREE.search(md5).groups() self.five_chars = PossibleKey.REGEX_FIVE.findall(md5) except AttributeError: self.three_char = ' ' self.five_chars = [] @classmethod def generate_key(cls, times): suffix = 0 while True: to_hash = SALT + str(suffix) for _ in range(times): to_hash = hashlib.md5(str.encode(to_hash)).hexdigest() yield cls(to_hash), suffix
from common import print_results, readline INITIAL_STATE = readline(__file__) DISK_LENGTH_1 = 272 DISK_LENGTH_2 = 35651584 class BinaryNumber: def __init__(self, binary_number_string): self.str_repr = binary_number_string def __str__(self): return self.str_repr def __len__(self): return len(self.str_repr) def __neg__(self): return BinaryNumber(self.str_repr[::-1]) def __invert__(self): return BinaryNumber( ''.join('1' if x is '0' else '0' for x in self.str_repr) ) def __iadd__(self, other): self.str_repr += '0' + other.str_repr return self def __getitem__(self, items): return self.str_repr[items]