diff --git a/2022/python/day13.py b/2022/python/day13.py index 2a6df81..5a59149 100644 --- a/2022/python/day13.py +++ b/2022/python/day13.py @@ -1,128 +1,106 @@ import matrix import shared import itertools -import sys -import os - - -def blockPrint(): - sys.stdout = open(os.devnull, 'w') - - -# Restore -def enablePrint(): - sys.stdout = sys.__stdout__ - - -class BREAK(Exception): - pass - +import functools def part1(rows): groups = [list(v) for k, v in itertools.groupby(rows, key=lambda x: not x) if not k] - NEED = list(range(len(groups))) indexes = [] for idx, (left, right) in enumerate(groups): left = eval(left) right = eval(right) - if idx not in NEED: - blockPrint() - print(f"== Pair {idx+1} ==") - passes = check_group(left, right, idx, 0) - if idx not in NEED: - enablePrint() - if passes is True: - print(f"{idx+1} {matrix.colors.GREEN}{passes}{matrix.colors.ENDC}") + # print(f"== Pair {idx+1} ==") + passes = check_group(left, right) + if passes: indexes.append(idx+1) - elif passes is False: - print(f"{idx+1} {matrix.colors.RED}{passes}{matrix.colors.ENDC}") - else: - print(f"{idx+1} {matrix.colors.BLUE}{passes}{matrix.colors.ENDC}") - print('-'*40) + # if passes is True: + # print(f"{idx+1} {matrix.colors.GREEN}{passes}{matrix.colors.ENDC}") + # elif passes is False: + # print(f"{idx+1} {matrix.colors.RED}{passes}{matrix.colors.ENDC}") + # else: + # print(f"{idx+1} {matrix.colors.BLUE}{passes}{matrix.colors.ENDC}") print(sum(indexes)) -spaces = lambda x: " " * x - - -def check_group(left, right, group, depth=0): - print(f"{spaces(depth)}- Compare {left} vs {right}, depth {depth}") - for idx, _ in enumerate(left): - # print("starting for") - try: - while True: - l = left[idx] - try: - r = right[idx] - except IndexError: - print(" - Right side ran out of items, so inputs are not in the right order") - return False - # print("starting while") - try: - if isinstance(l, int) and isinstance(r, int): - print(f"{spaces(depth)} - Compare {l} vs {r}") - if l == r: - #print(".......BREAK") - raise BREAK() - if l > r: - print(f"{spaces(depth)} - Right is Smaller, so inputs IN WRONG ORDER, False") - return False - if l < r: - print(f"{spaces(depth)} - Left is Smaller, so inputs IN RIGHT ORDER, True") - return True - except IndexError: - print("INDEX ERROR RIGHT RAN OUT") - return False - - try: - if isinstance(l, list) and isinstance(r, list): - print(f"{spaces(depth)} - Both Lists {l} vs {r}") - check = check_group(l, r, group, depth+1) - if check is None: - print("check is none", depth) - continue - if check is False: - "checked list v list and false" - return False - break - - except IndexError: - print("INDEX ERROR LEFT RAN OUT") - return True - - #print(f"TEST: {repr(l)} vs {repr(r)}") - - if isinstance(l, int) and isinstance(r, list): - left[idx] = [ l, ] - print("convert left to list") - continue - if isinstance(l, list) and isinstance(r, int): - right[idx] = [ r, ] - print(f"convert right {r} to list") - continue - except BREAK: - #print("......broke out of while") - continue +def check_group(left, right): + if isinstance(left, list) and isinstance(right, list): + # if both items are lists, loop over both + for idx in range(min(len(left), len(right))): + check = check_group(left[idx], right[idx]) + # bubble up the int comparisons, or list length comparisons + if check is False: + return False + elif check is True: + return True + # is None, continue on! TALLY HO! + else: + # If the left list runs out of items first, the inputs are in the right order. + if len(left) < len(right): + return True + # If the right list runs out of items first, the inputs are not in the right order. + if len(left) > len(right): + return False + # If the lists are the same length and no comparison makes a decision about the order, continue checking the next part of the input. + return None + elif isinstance(left, int) and isinstance(right, list): + # If exactly one value is an integer, convert the integer to a list which contains + # that integer as its only value, then retry the comparison. + left = [left] + return check_group(left, right) + elif isinstance(left, list) and isinstance(right, int): + # If exactly one value is an integer, convert the integer to a list which contains + # that integer as its only value, then retry the comparison. + right = [right] + return check_group(left, right) else: - print("Left side ran out of items so inputs are in the right order") - return True - - + # both ints now + # If the left integer is lower than the right integer, the inputs are in the right order. + if left < right: + return True + # If the left integer is higher than the right integer, the inputs are not in the right order. + elif left > right: + return False + #Otherwise, the inputs are the same integer; continue checking the next part of the input. + elif left == right: + return None def part2(rows): - print(rows) + rows = [eval(r) for r in rows if r] + rows.append([[2]]) + rows.append([[6]]) + print("---") + + wat = {True: 1,False: -1,} + + def cmp(x, y): + return wat[check_group(x, y)] + + s = sorted(rows, key=functools.cmp_to_key(cmp), reverse=True) + + two = 0 + six = 0 + for idx, r in enumerate(s): + if r == [[2]]: + two = idx+1 + if r == [[6]]: + six = idx+1 + break + + print(two * six) + + def main(): rows = shared.load_rows(13) with shared.elapsed_timer() as elapsed: part1(rows) - print(elapsed()) - # with shared.elapsed_timer() as elapsed: - # part2(rows) - # print(elapsed()) + print("🕒", elapsed()) + with shared.elapsed_timer() as elapsed: + part2(rows) + print("🕒", elapsed()) if __name__ == "__main__":