def run2(): cout_a, cout_b = deque(), deque() a = execute(Input(18), cout_a, pid=0) b = execute(Input(18), cout_b, pid=1) next(a) next(b) a_count = b_count = 0 loop = 0 while cout_a or cout_b: # print((cout_a, cout_b)) try: a.send(cout_b.popleft()) b_count += 1 except IndexError as e: pass try: b.send(cout_a.popleft()) a_count += 1 except IndexError as e: pass # print((cout_a, cout_b)) loop += 1 if not loop % 10000: print(loop, len(cout_a), len(cout_b)) return a_count, b_count
next_floor = state.floor[e] | set(obj) if not valid_floor(prev_floor) or not valid_floor(next_floor): continue floors = list(state.floor) floors[state.elevator] = prev_floor floors[e] = next_floor yield State(e, tuple(floors)) def valid_floor(floor): chips = [x[0] for x in floor if x[1].startswith('micro')] gens = [x[0] for x in floor if x[1].startswith('gen')] if gens: if chips: if any(c not in gens for c in chips): return False return True def sum_dist_from_top(state): total = 0 for value, floor in enumerate(reversed(state.floor)): total += value*len(floor) return total if __name__ == '__main__': start = initalize(Input(11)) pprint(start) path = astar_search(start, h_func=sum_dist_from_top, moves_func=get_moves) pprint(path) print(len(path)-1, ' steps needed.')
parts.append(remainder) break parts.append(expanded) string = remainder return ''.join(parts) def decompress2(string): matcher = re.compile(r'\((\d+)x(\d+)\)').match length = 0 i = 0 while i < len(string): m = matcher(string, i) if m: i = m.end() num_chars, repetitions = [int(x) for x in m.groups()] length += repetitions * decompress2(string[i:i + num_chars]) i += num_chars else: i += 1 length += 1 return length if __name__ == '__main__': # assert decompress('A(2x2)BCD(2x2)EFG') == 'ABCBCDEFEFG' # assert decompress('(6x1)(1x3)A') == '(1x3)A' print(decompress2('X(8x2)(3x3)ABCY')) print(decompress2(Input(9).read().strip()))
send(*bot.send_high, high) bot.values.clear() def send(to_type, to_id, value): if to_type == 'bot': bot = BOTS[to_id] bot.values.add(value) if len(bot.values) > 2: raise ValueError("bot {} is full and cannot receive".format(to_id)) if 61 in bot.values and 17 in bot.values: print('ANSWER FOUND: BOT {} compairs 61 and 17'.format(to_id)) elif to_type == 'output': try: OUTPUTS[to_id].add(value) except KeyError: OUTPUTS[to_id] = {value} return if __name__ == '__main__': load_instructions(Input(10)) simulate() to_mult = [] for i in range(3): i = str(i) pprint(OUTPUTS[i]) to_mult.append(OUTPUTS[i].pop()) a, b, c = to_mult print(a * b * c)
grid = list(map(list, (r for r in transpose(grid)))) grid = rotate_row(column, offset, grid) return list(map(list, (r for r in transpose(grid)))) def interpret_instruction(line, grid): if line.startswith('rect'): func = make_rect elif 'column' in line: func = rotate_column else: func = rotate_row args = map(int, re.findall('\d+', line)) return func(*args, grid) def print_grid(grid): for row in grid: print(''.join(row)) print() if __name__ == '__main__': grid = make_grid(6, 50) print_grid(grid) for line in Input(8): grid = interpret_instruction(line, grid) print_grid(grid) print(sum(c == ON for row in grid for c in row))
try: current_sq = grid[pos] except KeyError: current_sq = 'c' if current_sq == 'c': current_dir = (current_dir - 1) % 4 grid[pos] = 'w' elif current_sq == 'w': grid[pos] = 'i' elif current_sq == 'i': current_dir = (current_dir + 1) % 4 grid[pos] = 'f' elif current_sq == 'f': current_dir = (current_dir + 2) % 4 del grid[pos] yield current_sq dr, dc = dirs[current_dir] r, c = pos pos = (r + dr, c + dc) if __name__ == '__main__': grid, center = make_grid(Input(22)) flips = 0 g = burst(center, grid) for _ in range(10000000): flips += next(g) == 'w' print(flips)
from common import Input import re data = Input(9).read() data = re.sub(r'!.', '', data) level = 0 score = 0 garbage_count = 0 not_garbage = True i = 0 while i < len(data): c = data[i] if c == '<' and not_garbage: not_garbage = False garbage_count -= 1 if c == '>': not_garbage = True if c == '{': level += 1 * not_garbage score += level * not_garbage if c == '}': level += (-1 * not_garbage) garbage_count += not not_garbage i += 1 print(score, garbage_count)
from common import Input, transpose, cat from collections import Counter if __name__ == '__main__': data = Input(6).read().split() t_data = [col for col in transpose(data)] couters = [Counter(m) for m in t_data] frequenc_items = [m.most_common(1)[0][0] for m in couters] print(cat(frequenc_items))
def seq_3(seq): for i in range(len(seq) - 2): yield seq[i:i + 3] def is_aba(seq_of_3): return seq_of_3[0] == seq_of_3[2] != seq_of_3[1] def inverted(aba): a, b, _ = aba return ''.join((b, a, b)) def is_ssl(address): sections = re.split(r'\[|\]', address) outs = {s for sec in sections[::2] for s in seq_3(sec) if is_aba(s)} ins = {s for sec in sections[1::2] for s in seq_3(sec) if is_aba(s)} return any(inverted(seq) in ins for seq in outs) if __name__ == '__main__': assert is_tls('abba[mnop]qrst') assert not is_tls('aaaa[qwer]tyui') assert not is_tls('abcd[bddb]xyyx') assert is_tls('ioxxoj[asdfgh]zxcvbn') print(sum(is_tls(a) for a in Input(7).read().split())) print(sum(is_ssl(a) for a in Input(7).read().split()))
from common import Input s = Input(1).read().strip() numbers = [] for i, n in enumerate(s): if s[i - 1] == n: numbers.append(n) print(sum(int(x) for x in numbers)) numbers = [] for i, n in enumerate(s): opposite = (i + len(s) // 2) % len(s) if s[opposite] == n: numbers.append(n) print(sum(int(x) for x in numbers))
if not pos: pos = (0, maze[0].index('|')) if not delta: delta = (1, 0) steps = 1 x, y = pos dx, dy = delta letters = [] while maze[x][y] != '+': x += dx y += dy if maze[x][y] == ' ': return ''.join(letters), steps if maze[x][y] not in '+-|': letters.append(maze[x][y]) steps += 1 other_dir = DELTAS - {(-dx, -dy)} for dx, dy in other_dir: if maze[x + dx][y + dy] != ' ': x += dx y += dy let, s = follow_path(maze, (x, y), (dx, dy)) return ''.join(letters) + let, steps + s if __name__ == '__main__': maze = make_maze(Input(19)) print(follow_path(maze))
inst = 'jnz' # print(instructions[index], ' at ', index, ' changed to ', [inst, args]) instructions[index] = [inst, args] def out(x): yield resolve(x) instruction_set = { 'cpy': cpy, 'inc': inc, 'dec': dec, 'jnz': jnz, 'tgl': tgl, 'out': out, } a = 0 while True: register = { 'a': a, 'b': 0, 'c': 0, 'd': 0, 'i': 0, } if verify(execute(register, instruction_set, Input(25)), register): print('DONE: ', a) break a += 1
return int(re.findall('\d+', room)[0]) def decrypt_name(line): name = line.rsplit('-', 1)[0] ID = get_id(line) offset = ID % 26 mapping = { chr(i + ord('a')): chr(ord('a') + (i + offset) % 26) for i in range(0, 27) } mapping['-'] = ' ' trans = str.maketrans(mapping) name = name.translate(trans) return line, name if __name__ == '__main__': assert is_real('aaaaa-bbb-z-y-x-123[abxyz]') assert is_real('a-b-c-d-e-f-g-h-987[abcde]') assert is_real('not-a-real-room-404[oarel]') assert not is_real('totally-real-room-200[decoy]') print(sum(get_id(l) for l in Input(4) if is_real(l.strip()))) print(decrypt_name('qzmt-zixmtkozy-ivhz-343')) for line, name in (decrypt_name(line) for line in Input(4)): if 'north' in name: print(line, name)
if __name__ == '__main__': def cpy(x, y): register[y] = resolve(x) def inc(x): register[x] += 1 def dec(x): register[x] -= 1 def jnz(x, y): register['i'] += resolve(y) - 1 if resolve(x) != 0 else 0 instruction_set = { 'cpy': cpy, 'inc': inc, 'dec': dec, 'jnz': jnz, } register = { 'a': 0, 'b': 0, 'c': 1, 'd': 0, 'i': 0, } register = execute(register, instruction_set, Input(12)) print(register)
if c not in '#.': poi.append(c) return grid, start, poi def moves_func(grid, state): location, visited = state for p in neighbors4(location): v = grid[p] if v == '#': continue if v == '.': yield (p, visited) else: yield (p, visited | {v}) def heur(poi, start, state): location, visited = state return (len(poi) - len(visited)) + (location != start) if __name__ == '__main__': grid, start_point, goals = parse_grid(Input(24)) start = (start_point, frozenset('0')) moves = partial(moves_func, grid) h = partial(heur, goals, start_point) p = astar_search(start, h_func=h, moves_func=moves) # print(p) print(len(p) - 1)
from my_utils.iteration import transpose from common import Input import re if __name__ == '__main__': t = [[101, 301, 501], [102, 302, 502], [103, 303, 503], [201, 401, 601], [202, 402, 602], [203, 403, 603]] tris = re.findall('\d+', Input(3).read()) tris = [tris[s+offset:s+9:3] for s in range(0,len(tris),9) for offset in range(3)] tris = [sorted(map(lambda i: int(i), tri)) for tri in tris] possible = (sum(tri[:2]) > tri[2] for tri in tris) print(sum(possible))
return self.__class__(x, y, z) def __abs__(self): x = abs(self.x) y = abs(self.y) z = abs(self.z) return self.__class__(x, y, z) def __repr__(self): return "HexPoint({s.x}, {s.y}, {s.z})".format(s=self) def hex_distance(a, b=(0, 0, 0)): if not isinstance(a, HexPoint): a = HexPoint(*a) if not isinstance(b, HexPoint): b = HexPoint(*b) d = abs(a - b) return (d.x + d.y + d.z) // 2 if __name__ == '__main__': pos = HexPoint(0, 0, 0) furthest = 0 for d in Input(11).read().strip().split(','): pos += DIR[d] furthest = max((hex_distance(pos), furthest)) print(pos) print(hex_distance(pos)) print("Furthest:", furthest)
....... """.split() def translate(instructions, keypad): x, y = 3, 1 d_map = { # south and north are switched because of row, col difference 'U': 'S', 'D': 'N', 'L': 'W', 'R': 'E', } code = [] for line in instructions: for d in line.strip(): nx, ny = point_from_movement((x, y), d_map[d]) try: if keypad[ny][nx] != '.': x, y = nx, ny except IndexError: print(ny, nx) raise code.append(keypad[y][x]) return cat(code) if __name__ == '__main__': print(translate(Input(2), pad2))
#G.#.G# #G..#.# #...E.# #######\ """.split('\n')) == 35 * 793 == 27755 assert simulate_fight("""\ ####### #.E...# #.#..G# #.###.# #E#G#G# #...#G# #######\ """.split('\n')) == 54 * 536 == 28944 assert simulate_fight("""\ ######### #G......# #.E.#...# #..##..G# #...##..# #...#...# #.G...G.# #.....G.# #########\ """.split('\n')) == 20 * 937 == 18740 print("Part 1:", simulate_fight(Input(15))) print( "Part 2 (minimise the necessary amount of damage for no elven casualties):", simulate_fight(Input(15), intervention=True))
from common import Input from my_utils.graphs import dijkstra_all_paths import re graph = {} for line in Input(12): node, *connections = re.findall(r'\d+', line) graph[node] = connections moves = lambda x: graph[x] paths = dijkstra_all_paths('0', moves).parents print(len(paths)) remaining_nodes = set(graph) - set(paths) groups = [paths] while remaining_nodes: group = set(dijkstra_all_paths(remaining_nodes.pop(), moves).parents) remaining_nodes -= group groups.append(group) print(len(groups))
if not remaining: return (0, 0, tuple()) mx = (0, 0, tuple()) for comp in (p for p in remaining if num in p): l, s, b = search(comp[comp[0] == num], remaining - {comp}) b = b + (comp, ) l = len(b) s = sum(map(sum, b)) mx = max((mx, (l, s, b))) return mx def get_most_valuable_bridge(components): mx = (0, 0, []) for c in (x for x in components if 0 in x): l, s, b = search(c[1], components - {c}) b = b + (c, ) l = len(b) s = sum(map(sum, b)) mx = max((mx, (l, s, b))) return mx[0], mx[1], mx[2][::-1] if __name__ == '__main__': components = parse(Input(24)) l, s, b = get_most_valuable_bridge(components) print('Longest Bridge:', b) print('LENGTH:', len(b), 'components') print('STRENGTH:', s)
particles -= set(g) def parse_input(inp): particles = set() for i, line in enumerate(inp): parts = re.findall(r'<(.+?)>', line) parts = [np.array(list(map(int, p.split(',')))) for p in parts] particles.add(Particle(*parts, id=i)) return particles def nearest_origin_long_term(particles, prune=True): ticks = tick_till_moving_away(particles, prune) print('simulated', ticks, 'ticks') def key_func(p): # all manhattan >= |vec| so unnecessary """key is a tuple because velocity away from origin will always tump position, and acceleration will always trump both for greater t""" return magnitude(p.acc), abs(-p.pos @ p.vel), magnitude(p.pos) return min(particles, key=key_func) if __name__ == '__main__': particles = parse_input(Input(20)) p = nearest_origin_long_term(particles, prune=True) print(p) print('Particle #', p.id, sep='') print(len(particles))
weight_count = lambda x: weights_list.count(x) odd_weight, correct_weight, *_ = sorted(weights_list, key=weight_count) diff = odd_weight - correct_weight odd_child = [w for w in weights if weights[w] == odd_weight][0] message = 'Tree is unbalanced: "{}" weighs {}, but should weigh {}.' message = message.format(odd_child.name, odd_child.weight, odd_child.weight - diff) raise UnbalancedTree(message) if __name__ == '__main__': parent = {} weight = {} for line in Input(7): m = re.match(r'^(\w+) \((\d+)\)(?: -> (.*))?$', line) name, w, children = m.groups() weight[name] = int(w) if name not in parent: parent[name] = None if not children: continue for c in children.split(', '): parent[c] = name base = [n for n in parent if parent[n] is None][0] print('Base Program:', base) tree = build_tree(base, parent, weight) try: w = weigh_balanced_tree(tree)
from common import Input data = [int(x) for x in Input(5)] i = 0 counter = 0 try: while i > -1: if data[i] < 3: data[i] += 1 i += data[i] - 1 else: data[i] -= 1 i += data[i] + 1 counter += 1 except IndexError: print(counter)
if verbose: print(' after: ', data) return data if __name__ == '__main__': data = 'abcde' instructions = """swap position 4 with position 0 swap letter d with letter b reverse positions 0 through 4 rotate left 1 step move position 1 to position 4 move position 3 to position 0 rotate based on position of letter b rotate based on position of letter d""".splitlines() instructions = compile_instructions(instructions) ans = execute(data, instructions) print(ans) assert ans == 'decab' instructions = compile_instructions(Input(21)) data = 'abcdefgh' data = execute(data, instructions) print(data) for p in itertools.permutations('fbgdceah'): if execute(p, instructions, verbose=False) == 'fbgdceah': print(''.join(p)) break
continue if avail >= used: pairs[x, y].add((i, j)) return grid, pairs def moves_func(grid, state): empty, target = state transfers = [(x, y) for x, y in neighbors4(empty) if (x, y) in grid] for n in transfers: if grid[empty][SIZE] > grid[n][USED]: yield (n, empty if n == target else target) def heur_func(state): _, target = state return cityblock_distance(target) if __name__ == '__main__': grid, pairs = parse(Input(22)) print(sum(len(s) for s in pairs.values())) empty = [n for n in grid if grid[n][USED] == 0][0] moves_func = functools.partial(moves_func, grid) maxx = max(n[0] for n in grid) start = (empty, (maxx, 0)) path = astar_search(start, heur_func, moves_func=moves_func) print(path) print(len(path) - 1)
elif cmd.startswith('rotate row'): screen[A, :] = rotate(screen[A,:], B) elif cmd.startswith('rotate col'): screen[:,A] = rotate(screen[:, A], B) def rotate(items, n): return np.append(items[-n:], items[:-n]) def Screen(): return np.zeros((6, 50), dtype = np.int) def run(commands, screen): for cmd in commands: interpret(cmd,screen) return screen screen = run(Input(8), Screen()) print(np.sum(screen)) for row in screen: # print(cat(' @'[pixel] for pixel in row)) # print([' @'[pixel] for pixel in row]) # print([[pixel] for pixel in row]) print(cat( ' @' if pixel == 1 else ' ' for pixel in row)) # a = np.zeros((6,6), dtype=int) # b = [1,2, 3] # c = [' @'[m] for m in b] # print(c)
def distribute_cycle(mem): blocks = len(mem) while True: i = max(range(blocks), key=lambda x: mem[x]) items = mem[i] mem[i] = 0 while items: i = (i + 1) % blocks mem[i] += 1 items -= 1 yield tuple(mem) if __name__ == '__main__': mem = [int(x) for x in Input(6).read().split()] states = {tuple(mem)} for c, state in enumerate(distribute_cycle(mem), 1): if state in states: print(c) break states.add(state) goal = tuple(mem) for c, state in enumerate(distribute_cycle(mem), 1): if state == goal: print(c) break
yield False continue scanner = get_scanner_pos(width, step + start_step) print(step, step + start_step, scanner) if verbose else 0 if scanner == 0: yield True else: yield False def get_scanner_pos(width, step): period = width + width - 2 if step % period == 0: return 0 else: return -1 def find_min_delay(layers): for i in count(): if not any(severity_gen(layers, i)): return i if __name__ == '__main__': layers = dict(tuple(map(int, (line.split(': ')))) for line in Input(13)) test_layers = {0: 3, 1: 2, 4: 4, 6: 4} print(find_min_delay(layers))
import re from common import Input def parse(data): disks = [] for line in data: m = re.search(r'#(\d) has (\d+) .* position (\d+)', line) num, positions, initial = m.groups() disks.append(tuple(int(x) for x in (num, initial, positions))) return disks def get_time(disks): t = 0 while True: if all((t + d_num + initial) % positions == 0 for d_num, initial, positions in disks): break t += 1 return t if __name__ == '__main__': disks = parse(Input(15)) print(get_time(disks))