if 0 <= y + dy < n and 0 <= x + dx < m: q += (x + dx, y + dy), return not grid[y][x] for round in range(1, (steps or 999) + 1): q = [] for x in range(m): for y in range(n): flashes += flash(q, x, y) while q: x, y = q.pop() if grid[y][x]: flashes += flash(q, x, y) if set(x for row in grid for x in row) == {0}: return round return flashes if __name__ == "__main__": change_dir(__file__) test(0, solve(steps=1, file='input-test-1')) test(35, solve(steps=2, file='input-test-1')) test(80, solve(steps=3, file='input-test-1')) test(204, solve(steps=10, file='input-test-1')) test(1656, solve(steps=100, file='input-test-1')) test(1700, solve(steps=100, file='input-real')) test(195, solve(steps=200, file='input-test-1')) test(273, solve(steps=999, file='input-real'))
def solve(part, goal, file): dp = [[] for _ in range(151)] dp[0].append([]) jugs = sorted(load_ints(file)) def backtrack(i, remaining, count=0): if i < 0: if remaining == 0: yield count else: yield from backtrack(i - 1, remaining, count) if remaining >= jugs[i]: yield from backtrack(i - 1, remaining - jugs[i], count + 1) res = list(backtrack(len(jugs) - 1, goal)) if part == 2: res = list(next(groupby(sorted(res)))[1]) return len(res) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(4, solve(part=1, goal=25, file='input-test-1')) test(4372, solve(part=1, goal=150, file='input-real')) test(3, solve(part=2, goal=25, file='input-test-1')) test(4, solve(part=2, goal=150, file='input-real'))
s = data[0][0] C = Counter(zip(s, s[1:])) for _ in range(steps): D = Counter() for (a, b), v in C.items(): c = rules[a, b] D[a, c] += v D[c, b] += v C = D D = Counter((s[0], s[-1])) for (a, b), v in C.items(): D[a] += v D[b] += v mc = D.most_common() return (mc[0][1] - mc[-1][1]) // 2 ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(1588, solve(steps=10, file='input-test-1')) test(2851, solve(steps=10, file='input-real')) test(2188189693529, solve(steps=40, file='input-test-1')) test(10002813279337, solve(steps=40, file='input-real'))
parens = '([{<)]}>' def get_score(s): stack = [] for c in s.strip(): if c in parens[:4]: stack += c, elif c != parens[parens.index(stack.pop()) + 4]: return (points[parens.index(c)], 0) score = 0 while stack: score = score * 5 + points[parens.index(stack.pop())] return (0, score) def solve(part, file): data = load(file) res = filter(None, (get_score(line)[part-1] for line in data)) return (sum, median)[part-1](res) if __name__ == "__main__": change_dir(__file__) test(26397, solve(part=1, file='input-test-1')) test(345441, solve(part=1, file='input-real')) # not 320361 test(288957, solve(part=2, file='input-test-1')) test(3235371166, solve(part=2, file='input-real'))
block.split('\n') for block in '\n'.join(lines).split('inp w\n')[1:] ] model = [0] * 14 stack = [] for i, block in enumerate(blocks): if block[3] == 'div z 1': x = int(block[14].split(' ')[-1]) stack.append((i, x)) elif block[3] == 'div z 26': y = int(block[4].split(' ')[-1]) j, x = stack.pop() diff = x + y if diff < 0: i, j, diff = j, i, -diff if part == 1: model[i] = 9 model[j] = 9 - diff else: model[i] = 1 + diff model[j] = 1 return int(''.join(map(str, model))) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(93997999296912, solve(part=1, file='input-real')) test(81111379141811, solve(part=2, file='input-real'))
elif tokens[0] == 'rotate' and tokens[1] == 'based': if part == 1: s = rotate_by_letter(s, tokens[-1]) else: s = rotate_by_letter_inverse(s, tokens[-1]) else: raise Exception('no match', line) return ''.join(s) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test('ebcda', ''.join(swap_pos(list('abcde'), 4, 0))) test('edcba', ''.join(swap_letter(list('ebcda'), 'd', 'b'))) test('abcde', ''.join(reverse(list('edcba'), 0, 4))) test('bcdea', ''.join(rotate_left(list('abcde'), 1))) test('eabcd', ''.join(rotate_right(list('abcde'), 1))) test('bdeac', ''.join(move(list('bcdea'), 1, 4))) test('abdec', ''.join(move(list('bdeac'), 3, 0))) test('ecabd', ''.join(rotate_by_letter(list('abdec'), 'b'))) test('decab', ''.join(rotate_by_letter(list('ecabd'), 'd'))) test('decab', solve(part=1, input='abcde', file='input-test-1')) test('baecdfgh', solve(part=1, input='abcdefgh', file='input-real')) for x in range(8): for y in range(8): test('abcdefgh',
#!/usr/bin/env python3 from collections import Counter from functools import reduce from common.util import load_csv, test, change_dir def solve(days, file): data = [*map(int, load_csv(file)[0])] return sum( reduce( lambda c, _: Counter({x - 1: v for x, v in c.items() if x}) + Counter({ 6: c[0], 8: c[0] }), range(days), Counter(data)).values()) if __name__ == "__main__": change_dir(__file__) test(26, solve(days=18, file='input-test-1')) test(362740, solve(days=80, file='input-real')) test(26984457539, solve(days=256, file='input-test-1')) test(1644874076764, solve(days=256, file='input-real'))
x0, x1 = x1 - q * x0, x0 if x1 < 0: x1 += b0 return x1 def load_discs(file): return [parse_nums(line)[3::-2] for line in load(file)] def solve(part, file): discs = load_discs(file) if part == 2: discs.append([0, 11]) for i in range(len(discs)): x, size = discs[i] discs[i][0] = (x + i + 1) % size return -sub(*chinese_remainder(discs)) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(5, solve(part=1, file='input-test-1')) test(148737, solve(part=1, file='input-real')) test(85, solve(part=2, file='input-test-1')) test(2353212, solve(part=2, file='input-real'))
return {(x + 1, y + 1): enhance_x_y(x, y) for y in range(-1, n + 1) for x in range(-1, n + 1)} def solve(part, file): data = load_blocks(file) algo = [c == '#' for c in data[0][0]] grid = {(x, y): c == '#' for y, line in enumerate(data[1]) for x, c in enumerate(line)} outside = 0 n = len(data[1]) for _ in range((2, 50)[part - 1]): grid = enhance(grid, algo, outside, n) outside = algo[outside * 255] n += 2 return sum(grid.values()) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(35, solve(part=1, file='input-test-1')) test(5249, solve(part=1, file='input-real')) test(3351, solve(part=2, file='input-test-1')) test(15714, solve(part=2, file='input-real'))
"perfumes": 1, } ops_part_2 = {'cats': gt, 'trees': gt, 'pomeranians': lt, 'goldfish': lt} def solve(part, file): data = load(file) sues = {} for line in data: m = re.split(r'[:, ]+', line) sues[int(m[1])] = { item: int(count) for item, count in zip(*[iter(m[2:])] * 2) } ops = (ops_part_2 if part == 2 else {}) for num, info in sues.items(): if all( ops.get(item, eq)(count, my_sue[item]) for item, count in info.items()): yield num ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test([40], list(solve(part=1, file='input-real'))) test([241], list(solve(part=2, file='input-real')))
yield x, *tup def scores(ingredients, calories): ing = list(ingredients.values()) for tup in pick_sum(len(ing), 101): if not calories or calories == sum(i[4] * t for i, t in zip(ing, tup)): yield reduce(mul, (max(0, sum(i[x] * t for i, t in zip(ing, tup))) for x in range(4))) def solve(part, file): ingredients = {} for line in load(file): name, spec = line.split(':') ingredients[name] = Ingredient(*parse_nums(spec)) return max(scores(ingredients, 500 * (part - 1))) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(62842880, solve(part=1, file='input-test-1')) test(18965440, solve(part=1, file='input-real')) test(57600000, solve(part=2, file='input-test-1')) test(15862900, solve(part=2, file='input-real'))
def solve(part, file): cube_input = [(line[:2] == 'on', parse_nums(line)) for line in load(file)] cubes = {} for on, cube in cube_input: if part == 2 or is_within(cube, 50): cube = tuple(cube) for other_cube in list(cubes): if is_overlapping(cube, other_cube): del cubes[other_cube] for piece in cut_cube(other_cube, cube): cubes[piece] = area(piece) if on: cubes[cube] = area(cube) return sum(cubes.values()) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(39, solve(part=1, file='input-test-1')) test(590784, solve(part=1, file='input-test-2')) test(474140, solve(part=1, file='input-test-3')) test(606484, solve(part=1, file='input-real')) test(2758514936282235, solve(part=2, file='input-test-3')) test(1162571910364852, solve(part=2, file='input-real'))
#!/usr/bin/env python3 from common.util import load_tokens, test, change_dir def solve(part, file): data = load_tokens(file) h = d = a = 0 for line in data: dir, x = line[0][0], int(line[1]) if dir == 'f': h += x a += d * x else: d += (1 | -(dir == 'u')) * x return h * [d, a][part == 2] if __name__ == "__main__": change_dir(__file__) test(150, solve(part=1, file='input-test-1')) test(1746616, solve(part=1, file='input-real')) test(900, solve(part=2, file='input-test-1')) test(1741971043, solve(part=2, file='input-real'))
def solve(part, file): rule_block, goal = load_blocks(file) rules = [line.split(' => ') for line in rule_block] goal = goal[0] def expand(s): for a, b in rules: for m in re.finditer(a, s): s2 = list(s) s2[m.start():m.end()] = b yield ''.join(s2) if part == 1: return len(set(expand(goal))) return len(re.findall(r'[A-Z]', goal)) \ - goal.count('Rn') - goal.count('Ar') \ - 2 * goal.count('Y') - 1 ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(4, solve(part=1, file='input-test-1')) test(7, solve(part=1, file='input-test-2')) test(535, solve(part=1, file='input-real')) test(212, solve(part=2, file='input-real'))
#!/usr/bin/env python3 from math import floor, ceil from common.util import load, parse_nums, test, change_dir def compute(data, cost_fn, *possible): return min(sum(cost_fn(abs(x - y)) for x in data) for y in possible) def solve(part, file): data = [*map(parse_nums, load(file))][0] if part == 1: return compute(data, lambda x: x, sorted(data)[len(data) // 2]) else: avg = sum(data) / len(data) return compute(data, lambda x: x * (x + 1) // 2, *{floor(avg), ceil(avg)}) if __name__ == "__main__": change_dir(__file__) test(37, solve(part=1, file='input-test-1')) test(343441, solve(part=1, file='input-real')) test(168, solve(part=2, file='input-test-1')) test(98925151, solve(part=2, file='input-real'))
#!/usr/bin/env python3 from common.util import load, test, change_dir, parse_nums def solve(part, file, lo=0, hi=0): ranges = sorted(parse_nums(line) for line in load(file)) res = 0 for x, y in ranges: if lo + 1 <= x - 1: if part == 1: return lo + 1 res += x - lo - 1 lo = max(lo, y) return res + hi - lo ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(3, solve(part=1, hi=9, file='input-test-1')) test(19449262, solve(part=1, hi=4294967295, file='input-real')) test(2, solve(part=2, hi=9, file='input-test-1')) test(119, solve(part=2, hi=4294967295, file='input-real'))
def solve(part, file): data = load_csv(file)[0] pos = 0 dir = 0 + 1j grid = defaultdict(int) first_revisit = None for step in data: dir *= 1j if step[0] == 'L' else -1j for _ in range(int(step[1:])): pos += dir grid[pos] += 1 if grid[pos] > 1 and first_revisit is None: first_revisit = pos if part == 2: pos = first_revisit return int(abs(pos.real) + abs(pos.imag)) if __name__ == "__main__": change_dir(__file__) test(5, solve(part=1, file='input-test-1')) test(2, solve(part=1, file='input-test-2')) test(12, solve(part=1, file='input-test-3')) test(236, solve(part=1, file='input-real')) test(4, solve(part=2, file='input-test-4')) test(182, solve(part=2, file='input-real'))
for room, fold in zip(rooms, [[3, 3], [1, 2], [0, 1], [2, 0]]): room[:] = [room[0], *fold, room[1]] return tuple(hall), tuples(rooms) def solve(part, file): hall, rooms = load_amphibians(part, file) seen = set() q = [(0, hall, rooms)] while q: weight, hall, rooms = heappop(q) if (hall, rooms) not in seen: seen.add((hall, rooms)) if is_victory(hall, rooms): return weight for w, h, r in possible_moves(hall, rooms, part * 2): heappush(q, (weight + w, h, r)) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(12521, solve(part=1, file='input-test-1')) test(10411, solve(part=1, file='input-real')) test(44169, solve(part=2, file='input-test-1')) test(46721, solve(part=2, file='input-real'))
#!/usr/bin/env python3 from common.util import test, load_ints, change_dir def solve(part, file): data = load_ints(file) return sum(map(int.__lt__, data, data[part * 2 - 1:])) if __name__ == "__main__": change_dir(__file__) test(7, solve(part=1, file='input-test-1')) test(1215, solve(part=1, file='input-real')) test(5, solve(part=2, file='input-test-1')) test(1150, solve(part=2, file='input-real'))
{ keys.NAME: 'id', keys.REGEX: [('Detail/(\d+)', '$1')], keys.SOURCE: '1' }, { keys.NAME: 'title', keys.REGEX: [('<h1>\s*(.*?)</h1>', '$1')], }, { keys.NAME: 'source', keys.REGEX: [('【来源:(.*?)】', '$1')], }, { keys.NAME: 'date', keys.REGEX: [('【时间:(.*?)】', '$1')], }, { keys.NAME: 'content', keys.REGEX: [('<div id="fontzoom">([\s\S]*?)</div>', '$1')], keys.REMOVE_HTML: '1', keys.POST_REPLACES: [('”', ''), ('“', '')] }, ] if __name__ == '__main__': from pathlib import Path rule_name = Path(__file__).name.split('.')[0] r = util.test('http://sg.vegnet.com.cn/News/Detail/1220502', rule_name)
vars[args[0]] += 1 elif instruction == 'tpl': vars[args[0]] *= 3 elif instruction == 'hlf': vars[args[0]] //= 2 elif instruction == 'jmp': idx += int(args[0]) - 1 elif instruction == 'jio': if vars[args[0]] == 1: idx += int(args[1]) - 1 elif instruction == 'jie': if vars[args[0]] % 2 == 0: idx += int(args[1]) - 1 return vars def solve(var, part, file): instructions = load_instructions(file) return sim(instructions, {'a': part - 1, 'b': 0})[var] ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(2, solve('a', part=1, file='input-test-1')) test(184, solve('b', part=1, file='input-real')) test(231, solve('b', part=2, file='input-real'))
if seen[y] > val2: seen[y] = val2 heappush(q, (val2, y)) def solve(part, file): boss_hp, boss_damage = (parse_nums(line)[0] for line in load(file)) start = Fight(mana=500, player_hp=50, boss_hp=boss_hp) def is_goal(fight): return fight.boss_hp <= 0 def expand(fight): for spell, cost in spell_costs.items(): result = fight.copy() if result.round(boss_damage, spell, part == 2) != False: yield cost, result return djyk(start, expand, is_goal) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(953, solve(part=1, file='input-real')) test(1289, solve(part=2, file='input-real'))
def hashgen(input, ignore_invalid=False): seen = set() for i in count(): hash = md5((input + str(i)).encode('utf-8')).hexdigest() if hash[:5] == '00000': if not (ignore_invalid and (not hash[5].isdigit() or hash[5] not in '01234567' or hash[5] in seen)): yield hash[5], hash[6] seen.add(hash[5]) def solve(part, file): input = load(file)[0] g = hashgen(input, part == 2) code = [next(g) for _ in range(8)] if part == 2: code = sorted((x[::-1] for x in code), key=itemgetter(1)) return ''.join(c[0] for c in code) if __name__ == "__main__": change_dir(__file__) test('18f47a30', solve(part=1, file='input-test-1')) test('1a3099aa', solve(part=1, file='input-real')) test('05ace8e3', solve(part=2, file='input-test-1')) test('694190cd', solve(part=2, file='input-real'))
res[x, y] = '#' elif grid[x, y] == '#': res[x, y] = '.#'[count in {2, 3}] else: res[x, y] = '.#'[count == 3] return res def solve(part, steps, file): grid = load_grid_dict(file) max_x = max_y = None if part == 2: max_x = max(x for x, _ in grid) max_y = max(y for _, y in grid) grid[0, 0] = grid[0, max_y] = grid[max_x, 0] = grid[max_x, max_y] = '#' for _ in range(steps): grid = step(grid, max_x, max_y) return sum(x == '#' for x in grid.values()) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(4, solve(part=1, steps=4, file='input-test-1')) test(814, solve(part=1, steps=100, file='input-real')) test(14, solve(part=2, steps=4, file='input-test-1')) test(924, solve(part=2, steps=100, file='input-real')) # not 861
def find_code(row, col): codes = accumulate(repeat(20151125), lambda z, _: (z * 252533) % 33554393) for (x, y), code in zip(diag_count(), codes): if x == col and y == row: return code def solve(file): row, col = parse_nums(load(file)[0]) return find_code(row, col) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) expected = [ [20151125, 18749137, 17289845, 30943339, 10071777, 33511524], [31916031, 21629792, 16929656, 7726640, 15514188, 4041754], [16080970, 8057251, 1601130, 7981243, 11661866, 16474243], [24592653, 32451966, 21345942, 9380097, 10600672, 31527494], [77061, 17552253, 28094349, 6899651, 9250759, 31663883], [33071741, 6796745, 25397450, 24659492, 1534922, 27995004], ] actual = [[find_code(col, row) for row in range(1, 7)] for col in range(1, 7)] test(expected, actual) test(8997277, solve(file='input-real'))
def solve(part, file): data = load(file) total = 0 for line in data: seqs = re.split(r'\[|\]', line) outs, ins = seqs[::2], seqs[1::2] if part == 1: total += not any(map(has_abba, ins)) and any(map(has_abba, outs)) else: total += any(bab in s for bab, s in product(find_babs(outs), ins)) return total if __name__ == "__main__": change_dir(__file__) test(1, solve(part=1, file='input-test-1')) test(0, solve(part=1, file='input-test-2')) test(0, solve(part=1, file='input-test-3')) test(1, solve(part=1, file='input-test-4')) test(110, solve(part=1, file='input-real')) test(1, solve(part=2, file='input-test-5')) test(0, solve(part=2, file='input-test-6')) test(1, solve(part=2, file='input-test-7')) test(1, solve(part=2, file='input-test-8')) test(242, solve(part=2, file='input-real'))
def count_safe(s, n): safe = 0 for _ in range(n): safe += s.count('.') s = step(s) return safe ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test('.^^^^', steps('..^^.', 1)) test('^^..^', steps('..^^.', 2)) test('^^^...^..^', steps('.^^.^.^^^^', 1)) test('^.^^.^.^^.', steps('.^^.^.^^^^', 2)) test('..^^...^^^', steps('.^^.^.^^^^', 3)) test('.^^^^.^^.^', steps('.^^.^.^^^^', 4)) test('^^..^.^^..', steps('.^^.^.^^^^', 5)) test('^^^^..^^^.', steps('.^^.^.^^^^', 6)) test('^..^^^^.^^', steps('.^^.^.^^^^', 7)) test('.^^^..^.^^', steps('.^^.^.^^^^', 8)) test('^^.^^^..^^', steps('.^^.^.^^^^', 9)) test(38, count_safe('.^^.^.^^^^', 10)) input = load_string('input-real')
if num_groups == 1: yield (nums,) else: num_set = set(nums) goal = sum(nums) // num_groups for y in range(1, len(nums)): for combo in sorted(combinations(nums, y), key=lambda x: reduce(mul, x)): if sum(combo) == goal: remaining = sorted(num_set - set(combo)) for other_combos in partition(remaining, num_groups - 1): yield combo, *other_combos def solve(part, file): data = load_ints(file) combos = next(partition(data, 2 + part)) return reduce(mul, combos[0]) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(99, solve(part=1, file='input-test-1')) test(11846773891, solve(part=1, file='input-real')) test(44, solve(part=2, file='input-test-1')) test(80393059, solve(part=2, file='input-real'))
return Item(cost, damage, armor) def solve(part, file): boss = parse_character(load(file)) shop = parse_shop() players = [] for weapon in shop['Weapons']: for armor in chain(shop['Armor'], [None]): for num_rings in range(3): for rings in permutations(shop['Rings'], num_rings): stats = combine(weapon, armor, *rings) player = Character(100, stats.damage, stats.armor) players.append((stats.cost, player)) players.sort() if part == 1: return next(cost for cost, player in players if fight(player, boss)) else: return next(cost for cost, player in reversed(players) if not fight(player, boss)) ### THE REST IS TESTS ### if __name__ == "__main__": change_dir(__file__) test(1, fight(Character(8, 5, 5), Character(12, 7, 2))) test(78, solve(part=1, file='input-real')) test(148, solve(part=2, file='input-real'))
def run_bot(): for b in bots: if len(bots[b]) == 2: (is_out_lo, lo_id), (is_out_hi, hi_id) = splits[b] if (is_out_lo or len(bots[lo_id]) < 2) and (is_out_hi or len(bots[hi_id]) < 2): return b outs = defaultdict(list) while ((b := run_bot()) is not None): lo, hi = sorted(bots[b]) if compares and (lo, hi) == compares: return b bots[b] = [] (is_out_lo, lo_id), (is_out_hi, hi_id) = splits[b] (outs if is_out_lo else bots)[lo_id] += lo, (outs if is_out_hi else bots)[hi_id] += hi, return outs[0][0] * outs[1][0] * outs[2][0] if __name__ == "__main__": change_dir(__file__) test(2, solve(compares=(2, 5), file='input-test-1')) test(56, solve(compares=(17, 61), file='input-real')) test(30, solve(file='input-test-1')) test(7847, solve(file='input-real'))