• 19 Posts
  • 121 Comments
Joined 2 years ago
cake
Cake day: June 18th, 2023

help-circle
  • Python

    (Part 1) omg I can’t believe this actually worked first try!

    with open('input') as data:
        parts = data.read().rstrip().split("\n\n")
        ordering_rules = parts[0].split("\n")
        updates = parts[1].split("\n")
    
    correct_updates = []
    middle_updates = []
    
    def find_relevant_rules(pg_num: str, rules: list[str]) -> list[str] | None:
        for rule in rules:
            return list(filter(lambda x: x.split("|")[0] == pg_num, rules))
    
    def interpret_rule(rule: str) -> list[str]:
        return rule.split("|")
    
    def interpret_update(update: str) -> list[str]:
        return update.split(",")
    
    def find_middle_update_index(update: list[str]) -> int:
        num_of_elements = len(update)
        return num_of_elements // 2
    
    for update in updates:
        is_correct = True
        for i, page in enumerate(interpret_update(update)):
           rules_to_check = find_relevant_rules(page, ordering_rules) 
           for rule in rules_to_check:
               if rule.split("|")[1] in interpret_update(update)[:i]:
                   is_correct = False
        if is_correct:
            correct_updates.append(update)
    
    for update in correct_updates:
        split_update = update.split(",")
        middle_updates.append(int(split_update[find_middle_update_index(split_update)]))
    print(sum(middle_updates))
    

  • Part 1:

    with open('input') as data:
        lines = [l.strip() for l in data.readlines()]
    # Remove empty line
    class Result():
        def __init__(self):
            self.count = 0
    
    
    def analyze_lines(lines: list[str]):
        ans.count += get_rights(lines)
        ans.count += get_ups(lines)
        ans.count += get_downs(lines)
        ans.count += get_down_rights(lines)
        ans.count += get_down_lefts(lines)
        ans.count += get_up_lefts(lines)
        ans.count += get_up_rights(lines)
        for line in lines:
            ans.count += get_lefts(line)
    
    
    
    
    def get_ups(lines: list[str]) -> int:
        up_count = 0
        for i_l, line in enumerate(lines):
            result = ""
            if i_l < 3:
                continue
            for i_c, char in enumerate(line):
                if char == "X":
                    result = char
                    result += "".join([lines[i_l - n][i_c] for n in range(1, 4)])
                    if result == "XMAS":
                        up_count += 1
                    else:
                        result = ""
        return up_count
    
    
    def get_downs(lines: list[str]) -> int:
        down_count = 0
        for i_l, l in enumerate(lines):
            result = ""
            for i_c, c in enumerate(l):
                if c == "X":
                    result += c
                    try:
                        result += "".join([lines[i_l + n][i_c] for n in range(1, 4)])
                    except IndexError:
                        result = ""
                        continue
                    finally:
                        if result == "XMAS":
                            down_count += 1
                        result = ""
        return down_count
    
    
            
    def get_lefts(line: str) -> int:
        left_count = 0
        for i, char in enumerate(line):
            if i < 3:
                continue
            elif char == "X" and line[i-1] == "M" and line[i-2] == "A" and line[i-3] == "S":
                left_count += 1
        return left_count
    
    
    def get_rights(lines: list[str]) -> int:
        right_counts = 0
        for l in lines:
            right_counts += l.count("XMAS")
        return right_counts
    
    def get_down_rights(lines: list[str]) -> int:
        down_right_count = 0
        for i_l, l in enumerate(lines):
            result = ""
            for i_c, c in enumerate(l):
                if c == "X":
                    result += c
                    try:
                        result += "".join(
                                [lines[i_l + n][i_c + n] for n in range(1,4)]
                                )
                    except IndexError:
                        result = ""
                        continue
                    finally:
                        if result == "XMAS":
                            down_right_count += 1
                        result = ""
        return down_right_count
    
    def get_down_lefts(lines: list[str]) -> int:
        down_left_count = 0
        for i_l, l in enumerate(lines):
            result = ""
            for i_c, c in enumerate(l):
                if i_c < 3:
                    continue
                if c == "X":
                    result += c
                    try:
                        result += "".join(
                                [lines[i_l + n][i_c - n] for n in range(1,4)]
                                )
                    except IndexError:
                        result = ""
                        continue
                    finally:
                        if result == "XMAS":
                            down_left_count += 1
                        result = ""
        return down_left_count
    
    def get_up_rights(lines: list[str]) -> int:
        up_right_count = 0
        for i_l, l in enumerate(lines):
            result = ""
            if i_l < 3:
                continue
            for i_c, c in enumerate(l):
                if c == "X":
                    result += c
                    try:
                        result += "".join(
                                [lines[i_l - n][i_c + n] for n in range(1,4)]
                                )
                    except IndexError:
                        result = ""
                        continue
                    finally:
                        if result == "XMAS":
                            up_right_count += 1
                        result = ""
        return up_right_count
    
    
    def get_up_lefts(lines: list[str]) -> int:
        up_left_count = 0
        for i_l, l in enumerate(lines):
            result = ""
            if i_l < 3:
                continue
            for i_c, c in enumerate(l):
                if i_c < 3:
                    continue
                if c == "X":
                    result = c
                    try:
                        result += "".join(
                                [lines[i_l - n][i_c - n] for n in range(1,4)]
                                )
                    except IndexError as e:
                        result = ""
                        continue
                    finally:
                        if result == "XMAS":
                            up_left_count += 1
                        result = ""
        return up_left_count
    
    ans = Result()
    analyze_lines(lines)
    print(ans.count)
    

    Part 2:

    with open('input') as data:
        lines = list(filter(lambda x: x != '', [l.strip() for l in data.readlines()]))
        
    xmases = 0
    for i in range(1, len(lines)):
        for j in range(1, len(lines[i])):
            if lines[i][j] == "A":
                try:
                    up_back = lines[i-1][j-1]
                    down_over = lines[i+1][j+1]
                    up_over = lines[i-1][j+1]
                    down_back = lines[i+1][j-1]
                except IndexError:
                    continue
                else:
                    if {up_back, down_over} == set("MS") and {up_over, down_back} == set("MS"):
                        xmases += 1
    
    print(xmases)
    

    I actually found part two A LOT easier than part 1.





  • I did part 2 live with the python interactive shell. I deleted all the stuff where I was just exploring ideas.

    part 1:

    import re
    
    def multiply_and_add(data: "str") -> int:
        digit_matches = re.findall(r"mul\(\d{0,3},\d{0,3}\)", data)
        result = 0
        for _ in digit_matches:
            first = _.split("(")[1].split(")")[0].split(",")[0]
            second = _.split("(")[1].split(")")[0].split(",")[1]
            result += int(first) * int(second)
    
        return result
    
    with open("input") as file:
        data = file.read()
    
    
    answer = multiply_and_add(data)
    print(answer)
    

    part 2:

    Python 3.11.2 (main, Aug 26 2024, 07:20:54) [GCC 12.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import solution2
    <re.Match object; span=(647, 651), match='do()'>
    >>> from solution2 import *
    >>> split_on_dont = data.split("don't()")
    >>> valid = []
    >>> valid.append(split_on_dont[0])
    >>> for substring in split_on_dont[1:]:
    ...     subsubstrings = substring.split("do()", maxsplit=1)
    ...     for subsubstring in subsubstrings[1:]:
    ...             valid.append(subsubstring)
    ...
    >>> answer = 0
    >>> for _ in valid:
    ...     answer += multiply_and_add(_)
    ...
    >>> answer
    103811193
    

  • this took me so fucking long and in the end i just went for brute force anyway. there are still remnants of some of previous, overly complicated, failed attempts, like the hideous global removed. In the end, I realized I was fucking up by using remove() instead of pop(), it was causing cases with duplicates where the removal of one would yield a safe result to count as unsafe.


  • def is_safe(report: list[int]) -> bool:
        global removed
        acceptable_range = [_ for _ in range(-3,4) if _ != 0]
        diffs = []
        if any([report.count(x) > 2 for x in report]):
            return False
        for i, num in enumerate(report[:-1]):
            cur = num
            next = report[i+1]
            difference = cur - next
            diffs.append(difference)
            if difference not in acceptable_range:
                return False
            if len(diffs) > 1:
                if diffs[-1] * diffs[-2] <= 0:
                    return False
        return True
    
    with open('input') as reports:
        list_of_reports = reports.readlines()[:-1]
    
    
    count = 0
    
    failed_first_pass = []
    failed_twice = []
    
    for reportsub in list_of_reports:
        levels = [int(l) for l in reportsub.split()]
        original = levels.copy()
        if is_safe(levels):
            safe = True
            count += 1
        else:
            failed_first_pass.append(levels)
    
    for report in failed_first_pass:
        print(report)
        working_copy = report.copy()
        for i in range(len(report)):
            safe = False
            working_copy.pop(i)
            print("checking", working_copy)
            if is_safe(working_copy):
                count += 1
                safe = True
                break
            else:
                working_copy = report.copy()
    
    print(count)
    










  • HammerhearttoLinuxThis is why it's not mainstream
    link
    fedilink
    arrow-up
    4
    ·
    3 months ago

    For real. The main reason I switched to linux was because I was getting into progamming, and when I had to troubleshoot something on windows it was like half a dozen arcane solutions which might work, but the linux solution to the same problem was a terminal one liner. Maybe I’d feel differently if I was afraid of the terminal, but that’s one affliction I am blessedly free of.