def process_two(data): oxy_lines = data[:] colnum = 0 while len(oxy_lines) > 1: cols = parse_lines_into_cols(oxy_lines) most_common, mc_count = lmap(str, Counter(cols[colnum]).most_common()[0]) least_common, lc_count = lmap(str, Counter(cols[colnum]).most_common()[-1]) if mc_count == lc_count: most_common = "1" oxy_lines = lfilter(lambda x: x[colnum] == most_common, oxy_lines) colnum = colnum + 1 oxy_rating = int(oxy_lines[0], 2) co_lines = data[:] colnum = 0 while len(co_lines) > 1: cols = parse_lines_into_cols(co_lines) most_common, mc_count = lmap(str, Counter(cols[colnum]).most_common()[0]) least_common, lc_count = lmap(str, Counter(cols[colnum]).most_common()[-1]) if mc_count == lc_count: least_common = "0" co_lines = lfilter(lambda x: x[colnum] == least_common, co_lines) colnum = colnum + 1 co_rating = int(co_lines[0], 2) return oxy_rating * co_rating
def get_lows(data): grid = [] gridd = {} for y, row in enumerate(data): for x, char in enumerate(row): grid.append(aoc.Point(x=x, y=y)) gridd[aoc.Point(x=x, y=y)] = (char, None) for pt in gridd: above = gridd.get(aoc.Point(x=pt.x, y=pt.y - 1)) below = gridd.get(aoc.Point(x=pt.x, y=pt.y + 1)) left = gridd.get(aoc.Point(x=pt.x - 1, y=pt.y)) right = gridd.get(aoc.Point(x=pt.x + 1, y=pt.y)) adjs = lcompact([above, below, left, right]) curr = int(gridd[pt][0]) low = True for adj in adjs: if curr >= int(adj[0]): low = False if low: gridd[pt] = (gridd[pt][0], curr + 1) lows = lmap(lambda x: x, lfilter(lambda x: x[1][1] is not None, gridd.items())) return lows
def find_all_paths2(graph, start, end): path = [] paths = [] queue = [(start, end, path)] while queue: start, end, path = queue.pop() path = path + [start] if start == end: paths.append(path) for node in set(graph[start]): if node in ("start", "end"): if node not in path: queue.append((node, end, path)) elif node.islower(): lcnodes = lfilter( lambda x: x not in ("start", "end") and x.islower(), path) if len(lcnodes) == len(set(lcnodes)) and path.count(node) <= 1: queue.append((node, end, path)) elif (len(lcnodes) - 1 == len(set(lcnodes)) and path.count(node) < 1): queue.append((node, end, path)) elif node.isupper(): queue.append((node, end, path)) return paths
def filter_by_func(func: Callable, lines: list[str]) -> str: colnum = 0 while len(lines) > 1: qualified = func([ln[colnum] for ln in lines]) lines = lfilter(lambda x: x[colnum] == qualified, lines) colnum = colnum + 1 assert len(lines) == 1 return lines[0]
def process_two(data): numbers, boards = data for number in numbers: boards = [change_board(number, board) for board in boards] if len(boards) == 1: if check_for_winner(boards[0], number): return check_for_winner(boards[0], number) else: boards = lfilter(lambda b: not check_for_winner(b, number), boards)
def incr_neighbors(grid, center, flashed): neighbors = lmap(lambda x: center + Point(*x), adjacent_transforms(2)) points = lfilter(lambda x: x in grid, neighbors) for pt in points: grid[pt] = grid[pt] + 1 for pt in points: if pt not in flashed and grid[pt] > 9: flashed = flashed + [pt] grid, flashed = incr_neighbors(grid, pt, flashed) return grid, flashed
def rearrange_data(data): # We want to have an ordered bunch of rows, corresponding to each puzzle, # and each row should have the puzzle id and the list of people's times in # the same order as the intiial entries. # We can think about sorting it differently another time. entries = [data["members"][k] for k in data["members"]] ordered = sorted(entries, key=lambda x: -x["local_score"]) names = lmap(lambda n: NAMES.get(n, n), lpluck("name", ordered)) days = lmap(methodcaller("keys"), lpluck("completion_day_level", ordered)) latest_day = max(map(int, lconcat(days))) puzzle_rows = [] def get_timestamp(day, part, entry): times = entry["completion_day_level"] timestamp = (times.get(str(day), {}).get(str(part), {}).get("get_star_ts", 0)) return timestamp for i in range(1, 1 + latest_day): p1_info = [] p2_info = [] for entry in ordered: part_one_ts = get_timestamp(i, 1, entry) p1_info.append(part_one_ts) part_two_ts = get_timestamp(i, 2, entry) p2_info.append(part_two_ts) puzzle_rows.append(p1_info) puzzle_rows.append(p2_info) def check(idx_item): return sum([x[idx_item[0]] for x in puzzle_rows]) > 0 filtered = lfilter(check, enumerate(names)) filtered_cols = lpluck(0, filtered) filtered_names = lpluck(1, filtered) def filter_row(row): cols = lfilter(lambda i_r: i_r[0] in filtered_cols, enumerate(row)) return lpluck(1, cols) filtered_rows = lmap(filter_row, puzzle_rows) def mark_winner(row): winner = min(filter(lambda x: x != 0, row)) return [(item, item == winner) for item in row] with_winners = lmap(mark_winner, filtered_rows) return (filtered_names, with_winners)
def filter_row(row): cols = lfilter(lambda i_r: i_r[0] in filtered_cols, enumerate(row)) return lpluck(1, cols)
def process_two(data): incomplete = lfilter(lambda x: find_errors(x) == 0, data) scores = lmap(complete_line, incomplete) return sorted(scores)[len(scores) // 2]
def decipher_line(line): signals, value = line all_chars = lconcat( map(partial(filter, lambda x: "." not in x), lconcat(NUMS.values()))) segments = {} base = {NUM_SEGS.get(len(d)): d for d in value + signals} known = keyfilter(lambda x: x is not None, base) # If it's in 7 not 1 it's a. segments["a"] = (set(known[7]) - set(known[1])).pop() assert len(segments.keys()) == len(set(segments.values())) # If we have a three-letter--i.e. 7--then whatever six-letter is not a # superset of it is six sixes = set(filter(lambda x: len(x) in (6, ), signals)) for t in sixes: if not set(t) >= set(known[7]): known[6] = t assert len(set(known[7]) - set(known[6])) == 1 segments["c"] = (set(known[7]) - set(known[6])).pop() assert len(segments.keys()) == len(set(segments.values())) # Now we know what c is, f is whatever is in 1 that's not a or c: ac = list(pick(["a", "c"], segments).values()) assert len(set(known[1]) - set(ac)) == 1 segments["f"] = (set(known[1]) - set(ac)).pop() assert len(segments.keys()) == len(set(segments.values())) # Now we know acf, we know that any signal lacking f is 2: twos = lfilter(lambda x: segments["f"] not in x, signals) assert len(twos) == 1 known[2] = twos[0] # Now whatever's in 6 that isn't in 7|2 is b: seven_u_two = set(known[7]).union(set(known[2])) assert len(set(known[6]) - seven_u_two) == 1 segments["b"] = (set(known[6]) - seven_u_two).pop() assert len(segments.keys()) == len(set(segments.values())) # Whatever isn't these in four is d: four_not_bcf = set(known[4]) - set( pick(["b", "c", "f"], segments).values()) assert len(four_not_bcf) == 1 segments["d"] = four_not_bcf.pop() assert len(segments.keys()) == len(set(segments.values())) # eight minus d is zero: known[0] = "".join(sorted(filter(lambda x: x != segments["d"], known[8]))) # nine is whatever six-length signal isn't 0 or 6: nine = [x for x in sixes if x not in known.values()] assert len(nine) == 1 known[9] = nine[0] # whatever is in 2 but not in 9 is e: two_not_nine = set(known[2]) - set(known[9]) assert len(two_not_nine) == 1 segments["e"] = two_not_nine.pop() assert len(segments.keys()) == len(set(segments.values())) # Whatever of the five-length signals contains b is 5: fives = set(filter(lambda x: len(x) in (5, ), signals)) five = [x for x in fives if segments["b"] in x] assert len(five) == 1 known[5] = five[0] # Whatever five-length isn't 2 or 5 is 3: three = [x for x in fives if x not in (known[2], known[5])] assert len(three) == 1 known[3] = three[0] # Whatever's in the signal that isn't in segments values must be g: leftover = set(all_chars) - set(segments.values()) assert len(leftover) == 1 segments["g"] = leftover.pop() assert len(known) == 10 codex = {v: k for k, v in known.items()} digits = "" for num in value: digits = digits + str(codex[num]) return int(digits, 10)
def process_one(data): values = lconcat([line[1] for line in data]) return len(lfilter(lambda d: len(d) in NUM_SEGS, values))
def called_winner(board, called_numbers): numbers = lfilter(lambda n: n not in called_numbers, lconcat(board)) return sum(map(int, numbers)) * int(called_numbers[-1])
def adjacent_transforms(dimensions: int, omit_origin: bool = True) -> List[Tuple]: adj = product([-1, 0, 1], repeat=dimensions) not_origin = lambda x: not all([_ == 0 for _ in x]) return lfilter(not_origin, adj) if omit_origin else adj