 # 2015 Advent of Code (Python)

By telleropnul, March 31, 2023

Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like. Go check it out: Advent of Code

### 2015 Day 25

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import numpy as np   data = open('input').read().replace('.','').replace(',','').split(' ') row = int(data[-3]) # 3010 col = int(data[-1]) # 3019   # moving to next colum adds 2, 3, 4, ... to the value grid = np.sum(np.arange(2, col + 1)) + 1 # moving to next row adds the column number, +1, +2 ... to the value grid = grid + np.sum(np.arange(col, col+row-1))   code = 20151125 for i in range(grid - 1): code = code * 252533 % 33554393 print(code)```

### 2015 Day 24 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import itertools from math import prod   data = open('input').read().splitlines() data = [int(d) for d in data] goal = int(sum(data) / 4)   quantum = [] # search for sets of 5 presents which sum to goal (none exist) for i in range (1,10): for group in itertools.combinations(data, i): if sum(group) == goal: quantum.append(prod(group)) break #print(quantum) print(min(quantum))```

### 2015 Day 24 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import itertools from math import prod   data = open('input').read().splitlines() data = [int(d) for d in data] goal = int(sum(data) / 3)   quantum = [] for i in range (1,10): for group in itertools.combinations(data, i): if sum(group) == goal: quantum.append(prod(group)) break #print(quantum) print(min(quantum))```

### 2015 Day 23 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 data = open('input').read().splitlines() cmds = [d.replace(',', '').split(' ') for d in data]   def runCmd(cmd, num, vals): if cmd == "hlf": vals[cmd] /= 2 return num+1 elif cmd == "tpl": vals[cmd] *= 3 return num+1 elif cmd == "inc": vals[cmd] += 1 return num+1 elif cmd == "jmp": return num + int(cmd) elif cmd == "jie": if vals[cmd] % 2 == 0: return num + int(cmd) else: return num + 1 elif cmd == "jio": if vals[cmd] == 1: return num + int(cmd) else: return num + 1 print(cmd) return -1   vals = {"a":0, "b":0} run = 1 while run > 0 and run <= len(cmds): run = runCmd(cmds[run-1], run, vals) print(str(vals["b"]))   vals = {"a":1, "b":0} run = 1 while run > 0 and run <= len(cmds): run = runCmd(cmds[run-1], run, vals) print(str(vals["b"]))```

### 2015 Day 22 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 SPELL_COSTS = { 'magic_missle': 53, 'drain': 73, 'shield': 113, 'poison': 173, 'recharge': 229, }     def apply_effects(game): if game['shield_timer']: game['shield_timer'] -= 1 if game['shield_timer'] == 0: game['player_armor'] = 0 if game['poison_timer']: game['boss_hp'] -= 3 game['poison_timer'] -= 1 if game['recharge_timer']: game['player_mana'] += 101 game['recharge_timer'] -= 1     def player_turn(game, spell): if spell == 'magic_missle': game['boss_hp'] -= 4 elif spell == 'drain': game['boss_hp'] -= 2 game['player_hp'] += 2 elif spell == 'shield': game['shield_timer'] = 6 game['player_armor'] += 7 elif spell == 'poison': game['poison_timer'] = 6 elif spell == 'recharge': game['recharge_timer'] = 5 game['player_mana'] -= SPELL_COSTS[spell]     def boss_turn(game): dmg = max(game['boss_dmg'] - game['player_armor'], 1) game['player_hp'] -= dmg     def check_for_endgame(game, min_mana_spent): if game['boss_hp'] <= 0: min_mana_spent = min(game['mana_spent'], min_mana_spent) return 1, min_mana_spent if game['player_hp'] <= 0: return 2, min_mana_spent return 0, min_mana_spent     def find_minimal_mana(game): min_mana_spent = 9999999 games = [game] while len(games): games, min_mana_spent = try_all_games(games, min_mana_spent) return min_mana_spent     def try_all_games(games, min_mana_spent): new_games = [] for game in games:   # PART B # game['player_hp'] = game['player_hp'] - 1 endgame, min_mana_spent = check_for_endgame(game, min_mana_spent) if endgame: continue   # apply player's turn effects apply_effects(game) endgame, min_mana_spent = check_for_endgame(game, min_mana_spent) if endgame: continue   min_mana_spent = try_all_spells(game, min_mana_spent, new_games)   return new_games, min_mana_spent     def try_all_spells(game, min_mana_spent, new_games): castable_spells = [spell for spell, cost in SPELL_COSTS.items() if cost <= game['player_mana']] if game['shield_timer'] and 'shield' in castable_spells: castable_spells.remove('shield') if game['poison_timer'] and 'poison' in castable_spells: castable_spells.remove('poison') if game['recharge_timer'] and 'recharge' in castable_spells: castable_spells.remove('recharge')   for spell in castable_spells:   sub_game = game.copy() sub_game['spells_cast'] = list(sub_game['spells_cast']) + [spell] sub_game['mana_spent'] = sub_game['mana_spent']+SPELL_COSTS[spell]   # players turn player_turn(sub_game, spell) endgame, min_mana_spent = check_for_endgame(sub_game, min_mana_spent) if endgame: continue   # end early is too much mana spent if sub_game['mana_spent'] > min_mana_spent: continue   # boss's turn apply_effects(sub_game) endgame, min_mana_spent = check_for_endgame(sub_game, min_mana_spent) if endgame: continue   boss_turn(sub_game) endgame, min_mana_spent = check_for_endgame(sub_game, min_mana_spent) if endgame: continue   new_games.append(sub_game) return min_mana_spent   lines = open('input').read().splitlines() lines = [ l.split(' ') for l in lines]   BOSS_HIT_POINTS = int(lines) # 58 BOSS_DAMAGE = int(lines) # 9   initial_game = { 'player_hp': 50, 'player_mana': 500, 'player_armor': 0,   'boss_hp': BOSS_HIT_POINTS, 'boss_dmg': BOSS_DAMAGE,   'shield_timer': 0, 'poison_timer': 0, 'recharge_timer': 0,   'spells_cast': [], 'mana_spent': 0, } print(find_minimal_mana(initial_game.copy()))```

### 2015 Day 21 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 from collections import namedtuple   lines = open('input').read().splitlines() lines = [ l.split(' ') for l in lines]   BOSS_HIT_POINTS = lines # 104 BOSS_DAMAGE = lines # 8 BOSS_ARMOR = lines  # 1   Item = namedtuple('Item', ['name', 'cost', 'dmg', 'armor'])   WEAPONS = [ Item('Dagger', 8, 4, 0), Item('Shortsword', 10, 5, 0), Item('Warhammer', 25, 6, 0), Item('Longsword', 40, 7, 0), Item('Greataxe', 74, 8, 0), ] ARMOR = [ Item('Nothing', 0, 0, 0), Item('Leather', 13, 0, 1), Item('Chainmail', 31, 0, 2), Item('Splintmail', 53, 0, 3), Item('Bandedmail', 75, 0, 4), Item('Platemail', 102, 0, 5), ]   RINGS = [ Item('Nothing 1', 0, 0, 0), Item('Nothing 2', 0, 0, 0), Item('Damage +1', 25, 1, 0), Item('Damage +2', 50, 2, 0), Item('Damage +3', 100, 3, 0), Item('Defense +1', 20, 0, 1), Item('Defense +2', 40, 0, 2), Item('Defense +3', 80, 0, 3), ]     def does_player_win(player_hit, player_dmg, player_armor, boss_hit, boss_dmg, boss_armor):   boss_loss_per_turn = player_dmg - boss_armor if boss_loss_per_turn < 1: boss_loss_per_turn = 1 player_loss_per_turn = boss_dmg - player_armor if player_loss_per_turn < 1: player_loss_per_turn = 1   # the player goes first and gets n+1 turns n, remain = divmod(boss_hit, boss_loss_per_turn) if remain == 0: n -= 1 if player_loss_per_turn * (n) >= player_hit: return False return True     min_cost = 999 max_cost = 0 for weapon in WEAPONS: for armor in ARMOR: for ring1 in RINGS: for ring2 in RINGS:   # cannot own two of the same ring if ring1.name == ring2.name: continue   player_hit = 100 player_dmg = weapon.dmg + ring1.dmg + ring2.dmg player_armor = armor.armor + ring1.armor + ring2.armor cost = weapon.cost + armor.cost + ring1.cost + ring2.cost   if does_player_win(player_hit, player_dmg, player_armor, BOSS_HIT_POINTS, BOSS_DAMAGE, BOSS_ARMOR): # part a, lowest cost items to win min_cost = min(cost, min_cost) else: # part b, highest cost items and still lose max_cost = max(cost, max_cost) print(min_cost) print(max_cost)```

### 2015 Day 20 Part 02

```1 2 3 4 5 6 7 import numpy as np goal = int(open('input').read()) BIG_NUM = 1000000 houses = np.zeros(BIG_NUM) for elf in range(1, BIG_NUM): houses[elf:(elf+1)*50:elf] += 11 * elf print(np.nonzero(houses >= goal))```

### 2015 Day 20 Part 01

```1 2 3 4 5 6 7 import numpy as np goal = int(open('input').read()) BIG_NUM = 1000000 houses = np.zeros(BIG_NUM) for elf in range(1, BIG_NUM): houses[elf::elf] += 10 * elf print(np.nonzero(houses >= goal))```

### 2015 Day 19 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import re   lines = open('input').read().splitlines() medicine = lines.pop()   # LHS, RHS sorted with largest LHS first replacements = [(l.split()[-1], l.split()) for l in lines if '=>' in l] replacements.sort(key=lambda x: len(x)) # sort by string length replacements = replacements[::-1] # reverse   # largest replacements on medicine first, counting steps total = 0 while medicine != 'e': for lhs, rhs in replacements: if lhs in medicine: medicine = medicine.replace(lhs, rhs, 1) total += 1 break print(total)```

### 2015 Day 19 Part 01 v2

```1 2 3 4 5 6 7 8 9 10 11 12 13 import re   lines= open('input').read().splitlines() molecule = lines.pop() lines.pop()   possibilities = set() for l in lines: match, _, replace = l.split(' ') indices = [m.start() for m in re.finditer(match, molecule)] lm = len(match) possibilities.update( [molecule[:i] + replace + molecule[i+lm:] for i in indices] ) print(len(possibilities))```

### 2015 Day 19 Part 01 v1

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 lines = open('input').read().splitlines() molecule = lines.pop() lines.pop()   changes = {} for l in lines: match, _, replace = l.split(' ') if match not in changes: changes[match] = [replace] else: changes[match].append(replace) print(changes)   possibilities = set() for i in range(len(molecule)): if i < len(molecule)-1 and molecule[i+1].islower(): if molecule[i:i+2] in changes: for x in changes[molecule[i:i+2]]: possibilities.add(molecule[:i] + x + molecule[i+2:]) else: if molecule[i] in changes: for x in changes[molecule[i]]: possibilities.add(molecule[:i] + x + molecule[i+1:]) print(len(possibilities))```

### 2015 Day 18 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 # Game of life # https://playgameoflife.com   lines = open('input').read().splitlines()   # Turning all of the corners on lines = "#" + lines[1:-1] + "#" lines[-1] = "#" + lines[-1][1:-1] + "#"   # Running one round def round(grid): next = [] for i in range(len(grid)): temp = "" for j in range(len(grid[i])): count = 0 up = i > 0 down = i < len(grid)-1 left = j > 0 right = j < len(grid[i])-1 if up: if left: if grid[i-1][j-1] == "#": count += 1 if grid[i-1][j] == "#": count += 1 if right: if grid[i-1][j+1] == "#": count += 1 if right: if grid[i][j+1] == "#": count += 1 if left: if grid[i][j-1] == "#": count += 1 if down: if left: if grid[i+1][j-1] == "#": count += 1 if grid[i+1][j] == "#": count += 1 if right: if grid[i+1][j+1] == "#": count += 1 if grid[i][j] == "." and count == 3: temp += "#" elif grid[i][j] == "#" and (count == 2 or count == 3): temp += "#" else: temp += "." next.append(temp) # Turning the corners on next = "#" + next[1:-1] + "#" next[-1] = "#" + next[-1][1:-1] + "#" return next   # Running for 100 rounds for i in range(100): lines = round(lines)   # Getting the final count num = 0 for i in lines: for j in i: if j == "#": num += 1   print(num)```

### 2015 Day 18 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 # Game of life # https://playgameoflife.com   lines = open('input').read().splitlines()   # Running one round def round(grid): next = [] for i in range(len(grid)): temp = "" for j in range(len(grid[i])): count = 0 up = i > 0 down = i < len(grid)-1 left = j > 0 right = j < len(grid[i])-1 if up: if left: if grid[i-1][j-1] == "#": count += 1 if grid[i-1][j] == "#": count += 1 if right: if grid[i-1][j+1] == "#": count += 1 if right: if grid[i][j+1] == "#": count += 1 if left: if grid[i][j-1] == "#": count += 1 if down: if left: if grid[i+1][j-1] == "#": count += 1 if grid[i+1][j] == "#": count += 1 if right: if grid[i+1][j+1] == "#": count += 1 if grid[i][j] == "." and count == 3: temp += "#" elif grid[i][j] == "#" and (count == 2 or count == 3): temp += "#" else: temp += "." next.append(temp) return next   # Running for 100 rounds for i in range(100): lines = round(lines)   # Getting the final count num = 0 for i in lines: for j in i: if j == "#": num += 1   # Printing out the final result print("After 100 rounds,", num, "lights are on.")```

### 2015 Day 17 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import itertools   data = open('input').read().splitlines()   sizes = [] for d in data: sizes.append (int(d)) #print(sizes)   num = 0 min = 999 for i in range(len(sizes)): # range(0,20) for subset in itertools.combinations(sizes, i): if sum(subset) == 150: if len(subset) == min: num += 1 continue elif len(subset) < min: num = 1 min = len(subset) print(num)```

### 2015 Day 17 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 import itertools   data = open('input').read().splitlines()   sizes = [] for d in data: sizes.append (int(d)) #print(sizes)   num = 0 for i in range(len(sizes)): # range(0,20) for subset in itertools.combinations(sizes, i): if sum(subset) == 150: num += 1 print(num)```

### 2015 Day 16 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 data = open('input').read().splitlines()   ticker = { 'children': 3, 'cats': 7, 'samoyeds': 2, 'pomeranians': 3, 'akitas': 0, 'vizslas': 0, 'goldfish': 5, 'trees': 3, 'cars': 2, 'perfumes': 1}   sues = [] for d in data: vals = d.replace(":", "").replace(",", "").split(" ") sues.append ( {"number":vals, vals:int(vals), vals:int(vals), vals:int(vals)} ) #print(sues) for sue in sues: match = True checks = list(sue.keys()) checks.pop(0) for i in checks: if i in ["cats", "trees"]: if sue[i] <= ticker[i]: match = False ; break elif i in ["pomeranians", "goldfish"]: if sue[i] >= ticker[i]: match = False ; break elif sue[i] != ticker[i]: match = False ; break if match == True: print(sue)```

### 2015 Day 16 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 data = open('input').read().splitlines()   ticker = { 'children': 3, 'cats': 7, 'samoyeds': 2, 'pomeranians': 3, 'akitas': 0, 'vizslas': 0, 'goldfish': 5, 'trees': 3, 'cars': 2, 'perfumes': 1}   sues = [] for d in data: vals = d.replace(":", "").replace(",", "").split(" ") sues.append ( {"number":vals, vals:int(vals), vals:int(vals), vals:int(vals)} ) #print(sues) for sue in sues: match = True checks = list(sue.keys()) checks.pop(0) for i in checks: if sue[i] != ticker[i]: match = False break if match == True: print(sue)```

### 2015 Day 15 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 data = open('input').read().splitlines()   info = [] for d in data: _, _, cap, _, dur, _, flv, _, tex, _, cal = d.replace(",", "").split(" ") info.append ( [int(cap), int(dur),int(flv), int(tex), int(cal)] ) #print(info)   # The break statement is used to terminate the loop immediately # The continue statement is used to skip the current iteration of the loop scores = [] for i in range(100): for j in range(100): if j + i > 100: break for k in range(100): if j + k + i > 100: break for l in range(100): if j + k + l + i > 100: break elif j + k + l + i != 100: continue # 500 calory requirement (part 2) #if info*i + info*j + info*k + info*l != 500: continue # Getting the scores cap = info*i + info*j + info*k + info*l dur = info*i + info*j + info*k + info*l flv = info*i + info*j + info*k + info*l tex = info*i + info*j + info*k + info*l if cap < 1 or dur < 1 or flv < 1 or tex < 1: break scores.append(cap*dur*flv*tex)   # Finding the highest score and returning it scores.sort() print(scores[-1])```

### 2015 Day 14 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 data = open('input').read().splitlines()   barn = {} for d in data: deer, _, _, speed, _, _, duration, _, _, _, _, _, _, rest, _ = d.split() barn[deer]= (int(speed), int(duration), int(rest)) #print (barn)   def dist(barn,total_time): dist = {} for deer, nums in barn.items(): speed, duration, rest = nums lap_time = duration + rest run_time, rem_time = divmod (total_time, lap_time) run_distance = speed * (run_time * duration) if rem_time > duration: run_distance += speed * duration else: run_distance += speed * rem_time dist[deer] = run_distance return dist   #total_time = 2503 #print(dist(barn,total_time)) #print(max(dist(barn, total_time).values()))   points = {} for reindeer in barn: points[reindeer] = 0 for time in range(1, 2504): dists = dist(barn, time) max_dist = max(dists.values()) for reindeer in barn: if dists[reindeer] == max_dist: points[reindeer] += 1 print(max(points[reindeer] for reindeer in barn))```

### 2015 Day 14 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 data = open('input').read().splitlines()   barn = {} for d in data: deer, _, _, speed, _, _, duration, _, _, _, _, _, _, rest, _ = d.split() barn[deer] = (int(speed), int(duration), int(rest)) #print (barn)   total_time = 2503 dist = {}   for deer, nums in barn.items(): speed, duration, rest = nums lap_time = duration + rest   run_time = total_time // lap_time rem_time = total_time % lap_time   run_distance = speed * (run_time * duration)   if rem_time > duration: run_distance += speed * duration else: run_distance += speed * rem_time   dist[deer] = run_distance   #print(dist) print(max(dist.values()))```

### 2015 Day 13 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import itertools   happiness = {} people = set()   data = open('input').read().splitlines() data = [d.split(' ') for d in data]   for d in data: #d = d.split() person1 = d direction = d amount = int(d) person2 = d[:-1] #print(person1, direction, amount, person2) people.add(person1) people.add(person2) if direction == 'lose': happiness[person1+person2] = -amount else: assert direction == 'gain' happiness[person1+person2] = amount #print(people) #print(happiness)     def find_maximum_happiness(people, happiness): maximum_happiness = 0 for arrangement in itertools.permutations(people): happiness_gained = 0 for person1, person2 in zip(arrangement[:-1], arrangement[1:]): happiness_gained += happiness[person1 + person2] happiness_gained += happiness[person2 + person1] # add happiness for first and last pair person1 = arrangement person2 = arrangement[-1] happiness_gained += happiness[person1 + person2] happiness_gained += happiness[person2 + person1] maximum_happiness = max(maximum_happiness, happiness_gained) #print(arrangement, happiness_gained) return maximum_happiness   print(find_maximum_happiness(people, happiness))   # part b for person in people: happiness['Self' + person] = 0 happiness[person + 'Self'] = 0 people.add('Self') print(find_maximum_happiness(people, happiness))```

### 2015 Day 12 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import json   def sum_of_item(item, skip_red=False):   if isinstance(item, list): return sum([sum_of_item(i, skip_red) for i in item])   if isinstance(item, dict): if skip_red and 'red' in item.values(): return 0 return sum([sum_of_item(i, skip_red) for i in item.values()])   if isinstance(item, str): return 0   if isinstance(item, int): return item   with open('input') as f: abacus = json.load(f) print(sum_of_item(abacus)) print(sum_of_item(abacus, skip_red=True))```

### 2015 Day 12 Part 01

```1 2 3 4 5 6 7 8 9 10 11 data = open("input").read() nums = [] curr = '' for d in data: if d in "-1234567890": curr += d else: if len(curr) > 0: nums.append(int(curr)) curr = '' print(sum(nums))```

### 2015 Day 11 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 data = open("input").read() data = "hxbxwxba" alphas = "abcdefghjkmnpqrstuvwxyz"   def is_valid(pwd):   # i, o, l shouldn't be in the password forbidden = 'iol' for letter in forbidden: if letter in pwd: return False   # increasing consecutive three letters condition_1 = False for i in range(len(pwd) - 2): a, b, c = pwd[i], pwd[i + 1], pwd[i + 2] if (alphas.index(b) - alphas.index(a)) == 1 and (alphas.index(c) - alphas.index(b)) == 1: condition_1 = True break   if not condition_1: return False   # Non overlapping pairs total_pairs = 0 last_pair_ind = 1 for i in range(len(pwd) - 1): a, b = pwd[i], pwd[i + 1] if a == b: if i == last_pair_ind: continue else: total_pairs += 1 last_pair_ind = i + 1   if total_pairs < 2: return False   return True   def next_password(pwd): if pwd == '': return '' elif pwd[-1] == 'z': return next_password(pwd[:-1]) + 'a' else: return pwd[:-1] + alphas[alphas.index(pwd[-1]) + 1]     while not is_valid(data): data = next_password(data)   print(f"Part 1: {data}")   data = next_password(data)   while not is_valid(data): data = next_password(data)   print(f"Part 2: {data}")```

### 2015 Day 10 Part 01 + 02

```1 2 3 4 5 6 7 8 9 from itertools import groupby s = open("input").read() for i in range(40): s = ''.join([str(len(list(g)))+k for k, g in groupby(s)]) print(len(s)) # Part Two, 10 additional application for i in range(10): s = ''.join([str(len(list(g)))+k for k, g in groupby(s)]) print(len(s))```

### 2015 Day 09 Part 01 + 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import itertools   data = open("input").read().splitlines() data = [d.split(' ') for d in data]   path = {} locations = []   for d in data: city1 = d city2 = d distance = int(d)   path[city1 + city2] = distance path[city2 + city1] = distance   locations.append(city1) locations.append(city2)   locations = set(locations) # find unique locations   #print(locations) #print(path)   # find shortest and longest route shortest = 999999 longest = 0 for route in itertools.permutations(locations): route_length = 0 for city1, city2 in zip(route[:-1], route[1:]): route_length += path[city1 + city2] if route_length < shortest: shortest = route_length if route_length > longest: longest = route_length #print(route, route_length)   print("Shortest route length:", shortest) print("Longest route length:", longest)```

### 2015 Day 08 Part 02

```1 2 3 4 5 6 7 8 data = open("input").read().splitlines() code_total = 0 encode_total = 0 for d in data: code_total += len(d) encode_line = '"' + d.replace('\\', '\\\\').replace('\"', '\\\"').replace('"', '\"') + '"' encode_total += len(encode_line) print(encode_total - code_total)```

### 2015 Day 08 Part 01

```1 2 3 4 5 6 7 data = open("input").read().splitlines() code_total = 0 mem_total = 0 for d in data: code_total += len(d) mem_total += len(eval(d)) print(code_total - mem_total)```

### 2015 Day 07 Part 02

```1 2 3 4 5 6 7 ... tmp = solve('a') for d in data: signal, wire = d.split(' -> ') wires[wire] = signal wires['b']= tmp print(solve('a'))```

### 2015 Day 07 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 data = [ '123 -> x', '456 -> y', 'x AND y -> d', 'x OR y -> e', 'x LSHIFT 2 -> f', 'y RSHIFT 2 -> g', 'NOT x -> h', 'NOT y -> i' ]   data = open("input").read().splitlines()   wires={}   AND = ' AND ' OR = ' OR ' LSHIFT = ' LSHIFT ' RSHIFT = ' RSHIFT ' NOT = 'NOT'   for d in data: signal, wire = d.split(' -> ') wires[wire] = signal #print(wires)   def solve(wire): if wire.isnumeric(): return int(wire)   signal = wires[wire]   if type(signal) == int or signal.isnumeric(): wires[wire] = int(signal)   else: if AND in signal: a, b = signal.split(AND) wires[wire] = solve(a) & solve(b)   elif OR in signal: a, b = signal.split(OR) wires[wire] = solve(a) | solve(b)   elif LSHIFT in signal: a, b = signal.split(LSHIFT) wires[wire] = solve(a) << int(b)   elif RSHIFT in signal: a, b = signal.split(RSHIFT) wires[wire] = solve(a) >> int(b)   elif NOT in signal: _, a = signal.split() wires[wire] = ~(solve(a)) ''' Tilde (~n) operator is the bitwise negation operator: it takes the number n as binary number and “flips” all bits e.g. 0 to 1 and 1 to 0 to obtain the complement binary number. '''   else: wires[wire] = solve(signal)   return wires[wire]   ''' print(solve('d')) print(solve('e')) print(solve('f')) print(solve('g')) print(solve('h')) print(solve('x')) print(solve('y')) ''' print(solve('a'))```

### 2015 Day 06 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import numpy as np data = open("input").read().splitlines() data = [d.split(' ') for d in data] grid = np.zeros((1000, 1000), 'int32') for d in data: # Turn on/off if d == 'turn': x1, y1 = d.split(',') x2, y2 = d.split(',') x1, x2, y1, y2 = int(x1), int(x2), int(y1), int(y2) if d == 'on': grid[x1:x2+1, y1:y2+1] += 1 else: assert d == 'off' grid[x1:x2+1, y1:y2+1] -= 1 grid[grid < 0] = 0 # Toggle else: assert d == 'toggle' x1, y1 = d.split(',') x2, y2 = d.split(',') x1, x2, y1, y2 = int(x1), int(x2), int(y1), int(y2) grid[x1:x2+1, y1:y2+1] += 2 print(np.sum(grid))```

### 2015 Day 06 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import numpy as np data = open("input").read().splitlines() data = [d.split(' ') for d in data] grid = np.zeros((1000, 1000), 'int32') for d in data: # Turn on/off if d == 'turn': x1, y1 = d.split(',') x2, y2 = d.split(',') x1, x2, y1, y2 = int(x1), int(x2), int(y1), int(y2) if d == 'on': grid[x1:x2+1, y1:y2+1] = 1 else: assert d == 'off' grid[x1:x2+1, y1:y2+1] = 0 # Toggle else: assert d == 'toggle' x1, y1 = d.split(',') x2, y2 = d.split(',') x1, x2, y1, y2 = int(x1), int(x2), int(y1), int(y2) grid[x1:x2+1, y1:y2+1] = np.logical_not(grid[x1:x2+1, y1:y2+1]) print(np.sum(grid))```

### 2015 Day 05 Part 02

```1 2 3 from re import search data = open("input").read().splitlines() print(sum(1 for d in data if search(r"(..).*\1", d) and search(r"(.).\1", d)))```

### 2015 Day 05 Part 01

```1 2 3 from re import search data = open("input").read().splitlines() print(sum(1 for d in data if search("([aeiou].*){3}", d) and search(r"(.)\1", d) and not search("ab|cd|pq|xy", d)))```

### 2015 Day 04 Part 02

```1 2 3 4 5 6 7 8 9 10 import hashlib data = open("input").read().strip() num = 0 while True: str2hash = data + str(num) result = hashlib.md5(str2hash.encode()) if result.hexdigest()[0:6] == "000000": break num+=1 print(num)```

### 2015 Day 04 Part 01

```1 2 3 4 5 6 7 8 9 10 import hashlib data = open("input").read().strip() num = 0 while True: str2hash = data + str(num) result = hashlib.md5(str2hash.encode()) if result.hexdigest()[0:5] == "00000": break num+=1 print(num)```

### 2015 Day 03 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import numpy as np data = open("input").read().strip() step = { '^': (0, 1), 'v': (0, -1), '>': (1, 0), '<': (-1, 0), } grid = np.zeros((1000, 1000), dtype='int32') santa_x = 500 santa_y = 500 robot_x = 500 robot_y = 500 grid[santa_x, santa_y] += 1 grid[robot_x, robot_y] += 1 for i, direction in enumerate(data): delta_x, delta_y = step[direction] if (i % 2) == 0: santa_x += delta_x santa_y += delta_y grid[santa_x, santa_y] += 1 else: robot_x += delta_x robot_y += delta_y grid[robot_x, robot_y] += 1 print("At least one present:", len(np.nonzero(grid)))```

### 2015 Day 03 Part 01

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import numpy as np data = open("input").read().strip() step = { '^': (0, 1), 'v': (0, -1), '>': (1, 0), '<': (-1, 0), } grid = np.zeros((1000, 1000), dtype='int32') x = 500 y = 500 grid[x, y] = 1 for direction in data: delta_x, delta_y = step[direction] x += delta_x y += delta_y grid[x, y] += 1 print("At least one present:", len(np.nonzero(grid)))```

### 2015 Day 02 Part 02

```1 2 3 4 5 6 7 8 data = open("input").read().splitlines() data = [d.split('x') for d in data] data = [list(map(int, d)) for d in data] ribbon = 0 for d in data: d = sorted(d) ribbon += 2*d + 2*d + d*d*d print (ribbon)```

### 2015 Day 02 Part 01

```1 2 3 4 5 6 7 8 data = open("input").read().splitlines() data = [d.split('x') for d in data] data = [list(map(int, d)) for d in data] paper = 0 for d in data: sides = [ d*d, d*d, d*d ] paper += 2*sides + 2*sides + 2*sides + min(sides) print (paper)```

### 2015 Day 01 Part 02

```1 2 3 4 5 6 7 8 9 10 11 12 data = open("input").read() floor = 0 pos = 1 for d in data: if d == "(": floor+=1 elif d == ")": floor-=1 if floor < 0: break pos += 1 print (pos)```

### 2015 Day 01 Part 01

```1 2 3 4 5 6 7 8 data = open("input").read() floor = 0 for d in data: if d == "(": floor+=1 elif d == ")": floor-=1 print (floor)```