def process_one(data): # About 40m to complete the first one. # data = splitstriplines(testdata) connections = [_.split("-") for _ in data] nodes = set(lconcat(connections)) graph = nx.Graph() graph.add_nodes_from(nodes) for edge in connections: graph.add_edge(*edge) paths = find_all_paths(graph, "start", "end") return len(paths)
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 winner(board, number): numbers = lconcat(board) numbers = [n for n in numbers if not n.startswith("x")] total = sum(map(int, numbers)) return total * int(number)
def detect_overlap(lines): llines = lmap(list, lines) counted = Counter(lconcat(llines)) overone = {k: v for k, v in counted.items() if v >= 2} return len(overone)
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 detect_overlap(lines): counted = Counter(lconcat(lines)) return len([v for k, v in counted.items() if v >= 2])