def bags_inside(color, rules, depth = 0): qty = 1 depth_prefix = '....' * depth print('%sLooking for bags inside %s' % (depth_prefix, color)) for inner_color in rules[color]: inner_qty = rules[color][inner_color] print('%s....inner_qty for %s: %d' % (depth_prefix, inner_color, inner_qty)) if inner_qty == 0: continue qty += inner_qty * bags_inside(inner_color, rules, depth + 1) print('%sBags inside %s: %d' % (depth_prefix, color, qty)) return qty state = {'rules': {}} utils.call_for_lines(parse_rules, state) #for k in sorted(state['rules']): # print('%s: %r' % (k, state['rules'][k])) colors = set(state['rules'].keys()) colors.add('shiny gold') print('Colors: %r' % colors) nodes = dict((color, Node()) for color in colors) for outer_color in state['rules']: for inner_color in colors: if get_qty(outer_color, inner_color, state['rules']) > 0: nodes[inner_color].srcs.add(nodes[outer_color]) #print('Nodes: %r' % nodes)
if p[0] == p2[0] and p[1] == p2[1]: return p[0] += p_delta[0] p[1] += p_delta[1] state = { 'field': collections.defaultdict(lambda: collections.defaultdict(lambda: 0)), 'min_x': 0, 'min_y': 0, 'max_x': 0, 'max_y': 0, } utils.call_for_lines(process_line, state) twopoints = 0 for y in range(state['min_y'], state['max_y'] + 1): row = state['field'][y] cells = [] for x in range(state['min_x'], state['max_x'] + 1): if row[x] > 0: if row[x] >= 2: twopoints += 1 cells.append(str(row[x])) else: cells.append('.') print(''.join(cells)) print(twopoints)
def __str__(self): return '({} * {}) => {}'.format(self.x, self.y, self.x*self.y) def execute_command(command, state, _): (direction_s, magnitude_s) = command.split(' ') magnitude = int(magnitude_s) vector = { 'forward': Vector(magnitude, 0), # Day 1 only 'down': Vector(0, magnitude), # Y coordinate is *depth*, so 'down' increases it 'up': Vector(0, -magnitude), }[direction_s] # Day 1 state['position1'].add(vector) if direction_s == 'forward': vector = Vector(magnitude, magnitude*state['aim']) state['position2'].add(vector) #print('day2: Aim of {} added {}, now at {}'.format(state['aim'], vector, state['position2'])) elif direction_s == 'down': state['aim'] += magnitude elif direction_s == 'up': state['aim'] -= magnitude state = {'position1': Vector(), 'position2': Vector(), 'aim': 0} utils.call_for_lines(execute_command, state) print('Day 1 rules: {}'.format(state['position1'])) print('Day 2 rules: {}'.format(state['position2']))
state = { 'depth1': Depth1(), 'depth3_windows': [Depth3Window(), Depth3Window(), Depth3Window()], 'depth3_increase_count': 0, } def saw_depth(line, state, line_idx): depth = int(line) #print('Got depth {}'.format(depth)) state['depth1'].new_depth(depth) for (window_idx, prev_window_idx) in ((0, 2), (1, 0), (2, 1)): depth3_window = state['depth3_windows'][window_idx] depth3_prev = state['depth3_windows'][prev_window_idx] depth3_window.new_depth(depth) if depth3_window.depth3 is not None: window_depth = depth3_window.depth() prev_window_depth = depth3_prev.depth() #print('Depth {} has window={}, prev={}'.format(depth, window_depth, prev_window_depth)) if prev_window_depth is not None and window_depth > prev_window_depth: state['depth3_increase_count'] += 1 utils.call_for_lines(saw_depth, state) print(state['depth1'].depth_increase_count) print(state['depth3_increase_count'])
candidate_set = state['allergen_candidates'][allergen] print('Previous potential sources of allergen %r: %r' % (allergen, candidate_set)) candidate_set.intersection_update(ingredients) print('After incorporating %r: %r' % (ingredients, candidate_set)) else: print('Potential sources of allergen %r: %r' % (allergen, ingredients)) state['allergen_candidates'][allergen] = set(ingredients) state = { 'ingredient_count': collections.defaultdict(lambda: 0), 'allergen_candidates': {} } utils.call_for_lines(ParseFood, state) print('') print('Allergen candidates:') allergens_by_ingredient = collections.defaultdict(set) for allergen in sorted(state['allergen_candidates'].keys()): allergen_candidates = state['allergen_candidates'][allergen] print('%s: %r' % (allergen, allergen_candidates)) for ingredient in allergen_candidates: allergens_by_ingredient[ingredient].add(allergen) print('') while True: unique_candidates = set( list(candidates)[0] for (allergen, candidates) in state['allergen_candidates'].items()
state['wx'] += wp_vector[0] * magnitude state['wy'] += wp_vector[1] * magnitude if rotate: normalized_rotate = rotate % 360 clockwise_rotations = int(normalized_rotate / 90) #print('Rotating %r aka %d (%d turns), starting at (%d, %d' % (line, normalized_rotate, clockwise_rotations, wx, wy)) for _ in range(clockwise_rotations): wx = state['wx'] wy = state['wy'] state['wx'] = wy state['wy'] = -wx print('State after %r: %r' % (line, state)) state = {'x': 0, 'y': 0, 'wx': 10, 'wy': 1} utils.call_for_lines(moveit, state) print('At (%d, %d), %d from origin' % (state['x'], state['y'], abs(state['x']) + abs(state['y']))) """ .....|..... .....|..... .....|.o... .....|..... .....|..... =====*===== .....|..... .....|..... .....|..... .....|..... .....|.....
def find_combinations(deltas): if len(deltas) == 1: return 1 deltas = deltas[:] delta = deltas.pop(0) deltas[0] += delta if deltas[0] > 3: return 1 * find_combinations(deltas) else: return 2 * find_combinations(deltas) state = {'jolts': [0]} utils.call_for_lines(foo, state) jolts = sorted(state['jolts']) jolts.append(jolts[-1] + 3) deltas = [] curr_jolts = 0 for jolt in jolts: deltas.append(jolt - curr_jolts) curr_jolts = jolt #combinations = find_combinations(deltas) print(deltas) # I don't understand the logic here, but through looking at the two examples, it seems that # the answer is to look for runs of 1's in the "deltas" list. # # Number of runs of 4 1's = a
elif c in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'): curr_token.append(c) else: raise Exception('Unknown character %r at pos %d of %r' % (c, i, line)) if stack: raise Exception('Missing close paren in %r' % line) finish_token(curr_token, curr_tokens) val = eval_expr(curr_tokens) print('{0}: {1}'.format(line, val)) state['sum'] += val def eval_expr(tokens): #print('Evaluating %r' % tokens) val = tokens.pop(0) while tokens: token = tokens.pop(0) if token == '+': val += tokens.pop(0) elif token == '*': val *= tokens.pop(0) else: raise Exception('Unexpected token %r' % token) return val state = {'sum': 0} utils.call_for_lines(calculate, state) print('Grand total: %d' % state['sum'])
acc = state['acc'] if ip == len(state['instructions']): print('Program terminating normally with acc=%d.' % acc) sys.exit(0) elif ip > len(state['instructions']) or ip < 0: print('Program terminating abnormally, inslen=%d, ip=%d, acc=%d' % (len(state['instructions']), ip, acc)) sys.exit(1) ins = state['instructions'][ip] visited = state['visited'] if ip in visited and not state['solved_pt1']: print('**PART 1 SOLUTION** -- ip=%d, acc=%d' % (ip, acc)) state['solved_pt1'] = True if acc in visited[ip]: print('Infinite loop: Already visited ip=%d with acc=%d' % (ip, acc)) sys.exit(0) visited[ip].add(acc) ins[0](ins[1], state) new_ip = state['ip'] new_acc = state['acc'] print('Executing %s: ip=%d, acc=%d --> ip=%d, acc=%d' % (ins[2], ip, acc, new_ip, new_acc)) state = {'instructions': [], 'ip': 0, 'acc': 0, 'visited': collections.defaultdict(set), 'solved_pt1': False} utils.call_for_lines(parse_code, state) while True: step(state)
mask_0 = 0 mask_1 = 0 for bit in range(36): mask_char = mask[35 - bit] if mask_char == '0': mask_0 |= 1 << bit elif mask_char == '1': mask_1 |= 1 << bit print('mask_0: {0} ({0:036b})'.format(mask_0)) print('mask_1: {0} ({0:036b})'.format(mask_1)) state['mask_0'] = mask_0 state['mask_1'] = mask_1 def do_line(line, state): if line.startswith('mask'): do_mask(line, state) else: do_write(line, state) state = { 'mask_0': 0, 'mask_1': 0, 'memory': collections.defaultdict(lambda: 0) } utils.call_for_lines(do_line, state) for addr in sorted(state['memory'].keys(), key=int): print('{0}: {1} ({1:036b})'.format(addr, state['memory'][addr])) print(functools.reduce(operator.add, state['memory'].values()))
new_candidates = [] for candidate in candidates: #print('Candidate {} has value {} (?= {})'.format(''.join(candidate), candidate[bit_idx], desired_bit)) if candidate[bit_idx] == desired_bit: new_candidates.append(candidate) candidates = new_candidates bit_idx += 1 #print('Found value: {}'.format(''.join(candidates[0]))) return ''.join(candidates[0]) state = { 'all_numbers': [], 'bit_count': collections.defaultdict(lambda: [0, 0]), } utils.call_for_lines(find_set_bits, state) # Day 1 gamma_rate = [] epsilon_rate = [] for bit in state['bit_count'].values(): if bit[0] > bit[1]: gamma_rate.append('0') epsilon_rate.append('1') else: gamma_rate.append('1') epsilon_rate.append('0') gamma_rate = ''.join(gamma_rate) gamma_num = int(gamma_rate, base=2) epsilon_rate = ''.join(epsilon_rate) epsilon_num = int(epsilon_rate, base=2)