deckard's recent activity

  1. Comment on Which web browser do you use? in ~tech

    deckard
    Link Parent
    It's perfectly performant in my experience. It's a modern, multi-process, blink-derived browser -- I wouldn't really call it lightweight, just configurable and cleanly designed from a UI...

    It's perfectly performant in my experience. It's a modern, multi-process, blink-derived browser -- I wouldn't really call it lightweight, just configurable and cleanly designed from a UI perspective.

    Sidenote: I don't use youtube in any browser, opting for mpv to watch videos instead.

    3 votes
  2. Comment on Which web browser do you use? in ~tech

    deckard
    Link
    These days I mostly use qutebrowser. Like so many “alternative” browsers it’s got chromium’s engine under the hood, but with a level of UI configurability unmatched by any other browser I’ve used....

    These days I mostly use qutebrowser. Like so many “alternative” browsers it’s got chromium’s engine under the hood, but with a level of UI configurability unmatched by any other browser I’ve used. I need those sweet, sweet vi bindings.

    2 votes
  3. Comment on Midweek Movie Free Talk in ~movies

    deckard
    Link
    I watched Glass Onion the other night since it is now on Netflix. Didn't feel as clever or tight as Knives Out, and the final hour kind of dragged in my opinion. Still enjoyable enough due to the...

    I watched Glass Onion the other night since it is now on Netflix. Didn't feel as clever or tight as Knives Out, and the final hour kind of dragged in my opinion. Still enjoyable enough due to the great cast, and I do hope Rian Johnson makes another one of these if he's up to it.

    2 votes
  4. Comment on Year in Review: Movies of 2022 in ~movies

    deckard
    Link Parent
    I totally agree re: Top Gun. Tom Cruise recently has been putting so much effort into high quality, big-screen spectacle despite audiences' shift towards at-home viewing. I'm really excited for...

    I totally agree re: Top Gun. Tom Cruise recently has been putting so much effort into high quality, big-screen spectacle despite audiences' shift towards at-home viewing. I'm really excited for the next Mission: Impossible movie.

    1 vote
  5. Comment on Year in Review: Movies of 2022 in ~movies

    deckard
    Link
    Only including new-to-me watches, otherwise the re-watches of my favorites would dominate the list. I didn't get to see a ton of new releases this year, but I usually hit those in the following...

    Only including new-to-me watches, otherwise the re-watches of my favorites would dominate the list.
    I didn't get to see a ton of new releases this year, but I usually hit those in the following year's January before the Oscars. Here are a few favorites I first saw this year:

    • Prince of Darkness (Carpenter, 1987) -- Caught this on Criterion Channel during October. Kind of a perfect horror film.
    • Braindead (Jackson, 1992) -- Hilarious and super gory, and totally unlike LoTR!
    • Bringing Out the Dead (Scorsese, 1999) -- Cage + Schrader + Scorsese, it's like this was made in a lab just for me.
    • Ambulance (Bay, 2022) -- Somehow a Michael Bay movie is my favorite of 2022? Wild.
    • Drive My Car (Hamaguchi, 2021) -- This got me reading some of Murakami's writing and it's fantastic, especially the short story collection from which this story was adapted.
    2 votes
  6. Comment on Day 13: Distress Signal in ~comp.advent_of_code

    deckard
    Link Parent
    I think the best way to adapt my comparison function would be to return one of {1, 0, -1} instead of {True, None, False}, and then wrap it in functools.cmp_to_key. I saw this in someone else's...

    I think the best way to adapt my comparison function would be to return one of {1, 0, -1} instead of {True, None, False}, and then wrap it in functools.cmp_to_key. I saw this in someone else's solution, but I didn't know about cmp_to_key before so it didn't occur to me when solving.

    1 vote
  7. Comment on Day 13: Distress Signal in ~comp.advent_of_code

    deckard
    Link
    My Python solutions. A somewhat easier problem is welcome on a Monday night! Part 1 #!/usr/bin/env pypy3 import ast import sys def ordered(l, r): if isinstance(l, int) and isinstance(r, int):...

    My Python solutions. A somewhat easier problem is welcome on a Monday night!

    Part 1
    #!/usr/bin/env pypy3
    
    import ast
    import sys
    
    def ordered(l, r):
        if isinstance(l, int) and isinstance(r, int):
            return l < r or (False if l > r else None)
        elif isinstance(l, list) and isinstance(r, list):
            for ll, rr in zip(l, r):
                if (result := ordered(ll, rr)) is not None:
                    return result
            return len(l) < len(r) or (False if len(r) < len(l) else None)
        else:
            return ordered([l], r) if isinstance(l, int) else ordered(l, [r])
    
    def main():
        pairs = [map(ast.literal_eval, section.split('\n')[:2])
                 for section in sys.stdin.read().split('\n\n')]
        total = sum(pairs.index(p) + 1 for p in pairs if ordered(*p))
        print(total)
    
    if __name__ == '__main__':
        main()
    

    Initially I wanted to use Python's sorted() built-in, which optionally takes a key function (though key must take one argument instead of two). Instead I just rolled my own bubble sort. 🤷

    Part 2
    #!/usr/bin/env pypy3
    
    import ast
    import math
    import sys
    
    DIVIDER_PACKETS = [[[2]], [[6]]]
    
    def ordered(l, r):
        if isinstance(l, int) and isinstance(r, int):
            return l < r or (False if l > r else None)
        elif isinstance(l, list) and isinstance(r, list):
            for ll, rr in zip(l, r):
                if (result := ordered(ll, rr)) is not None:
                    return result
            return len(l) < len(r) or (False if len(r) < len(l) else None)
        else:
            return ordered([l], r) if isinstance(l, int) else ordered(l, [r])
    
    def sort_packets(packets):
        n = len(packets)
        for i in range(n - 1):
            for j in range(n - i - 1):
                if not ordered(packets[j], packets[j + 1]):
                    packets[j], packets[j + 1] = packets[j + 1], packets[j]
    
    def main():
        packets = [ast.literal_eval(line.strip()) for line in sys.stdin
                   if line != '\n'] + DIVIDER_PACKETS
        sort_packets(packets)
        key = math.prod(packets.index(p) + 1 for p in DIVIDER_PACKETS)
        print(key)
    
    if __name__ == '__main__':
        main()
    
    4 votes
  8. Comment on Day 9: Rope Bridge in ~comp.advent_of_code

    deckard
    Link
    My Python solution, using complex numbers (which are helpfully one of the language's basic numeric types). Another great problem from Eric! Part 1 #!/usr/bin/env pypy3 import sys NUMKNOTS = 2...

    My Python solution, using complex numbers (which are helpfully one of the language's basic numeric types). Another great problem from Eric!

    Part 1
    #!/usr/bin/env pypy3
    
    import sys
    
    NUMKNOTS = 2
    DIRECTIONS = {
        'R': 1,
        'L': -1,
        'U': 1j,
        'D': -1j,
    }
    
    def update(z1, z2):
        dz = z1 - z2
        if abs(dz) < 2: # ceil(sqrt(2))
            return 0
        return complex(*(part / abs(part) if part else 0
                         for part in (dz.real, dz.imag)))
    
    def main():
        knots = [0 + 0j] * NUMKNOTS
        visited = {knots[-1]}
        for line in sys.stdin:
            direction, magnitude = line.split()
            for _ in range(int(magnitude)):
                knots[0] += DIRECTIONS[direction]
                for i in range(1, NUMKNOTS):
                    knots[i] += update(knots[i - 1], knots[i])
                visited.add(knots[-1])
    
        print(len(visited))
    
    if __name__ == '__main__':
        main()
    
    Because I refactored my solution to a general n-knot case, the only change in the code for Part 2 is the `NUMKNOTS` constant.
    Part 2
    #!/usr/bin/env pypy3
    
    import sys
    
    NUMKNOTS = 10
    DIRECTIONS = {
        'R': 1,
        'L': -1,
        'U': 1j,
        'D': -1j,
    }
    
    def update(z1, z2):
        dz = z1 - z2
        if abs(dz) < 2: # ceil(sqrt(2))
            return 0
        return complex(*(part / abs(part) if part else 0
                         for part in (dz.real, dz.imag)))
    
    def main():
        knots = [0 + 0j] * NUMKNOTS
        visited = {knots[-1]}
        for line in sys.stdin:
            direction, magnitude = line.split()
            for _ in range(int(magnitude)):
                knots[0] += DIRECTIONS[direction]
                for i in range(1, NUMKNOTS):
                    knots[i] += update(knots[i - 1], knots[i])
                visited.add(knots[-1])
    
        print(len(visited))
    
    if __name__ == '__main__':
        main()
    
    4 votes
  9. Comment on Day 8: Treetop Tree House in ~comp.advent_of_code

    deckard
    Link Parent
    For every tree in the forest, I make a list of the trees above it, below it, to the left, and to the right. For part 1 I check if the tree of interest is taller than the tallest tree in at least...

    For every tree in the forest, I make a list of the trees above it, below it, to the left, and to the right. For part 1 I check if the tree of interest is taller than the tallest tree in at least one of those four lists. If it is, add it to a tally of "visible" trees. For part 2 I count how far into each of those four lists I have to go before the tree of interest is no longer sufficiently tall. Multiply the four directional counts to get a score and check if it is the largest such score we've seen.

    I say it's not optimal because it probably does a lot of redundant computation. There is no caching of e.g. how many trees of a certain height exist in a particular direction. The visibility of a tree and and adjacent neighbor are going to be somewhat similar, but I ignore this and calculate each's visibility from scratch.

    2 votes
  10. Comment on Day 8: Treetop Tree House in ~comp.advent_of_code

    deckard
    Link
    My Python solutions, which are surely not optimal but they do the trick. Between yesterday and today, the problems are starting to get fun! Part 1 #!/usr/bin/env pypy3 import sys up = lambda f, r,...

    My Python solutions, which are surely not optimal but they do the
    trick. Between yesterday and today, the problems are starting to get fun!

    Part 1
    #!/usr/bin/env pypy3
    
    import sys
    
    up = lambda f, r, c: [f[r_][c] for r_ in range(r)][::-1]
    dn = lambda f, r, c: [f[r_][c] for r_ in range(r + 1, len(f))]
    lt = lambda f, r, c: [f[r][c_] for c_ in range(c)][::-1]
    rt = lambda f, r, c: [f[r][c_] for c_ in range(c + 1, len(f[r]))]
    
    def main():
        forest = [[int(tree) for tree in line.strip()] for line in sys.stdin]
        total = 0
        for r in range(len(forest)):
            for c in range(len(forest[0])):
                total += any(forest[r][c] > max(d(forest, r, c), default=-1)
                             for d in (up, dn, lt, rt))
    
        print(total)
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import functools
    import operator
    import sys
    
    up = lambda f, r, c: [f[r_][c] for r_ in range(r)][::-1]
    dn = lambda f, r, c: [f[r_][c] for r_ in range(r + 1, len(f))]
    lt = lambda f, r, c: [f[r][c_] for c_ in range(c)][::-1]
    rt = lambda f, r, c: [f[r][c_] for c_ in range(c + 1, len(f[r]))]
    
    def view(tree, direction):
        distance = 0
        for neighbor in direction:
            distance += 1
            if neighbor >= tree:
                break
        return distance
    
    def main():
        forest = [[int(tree) for tree in line.strip()] for line in sys.stdin]
        max_score = 0
        for r in range(len(forest)):
            for c in range(len(forest[0])):
                views = (view(forest[r][c], d(forest, r, c))
                         for d in (up, dn, lt, rt))
                max_score = max(functools.reduce(operator.mul, views, 1),
                                max_score)
    
        print(max_score)
    
    if __name__ == '__main__':
        main()
    
    3 votes
  11. Comment on Day 7: No Space Left On Device in ~comp.advent_of_code

    deckard
    Link
    Here is my Python solution. A hacky use of the os.path module came in handy. Part 1 #!/usr/bin/env pypy3 import os.path import re import sys SIZE_BOUND = 100000 def main(): dirsizes = {} cwd = '/'...

    Here is my Python solution. A hacky use of the os.path module
    came in handy.

    Part 1
    #!/usr/bin/env pypy3
    
    import os.path
    import re
    import sys
    
    SIZE_BOUND = 100000
    
    def main():
        dirsizes = {}
        cwd = '/'
        for line in sys.stdin:
            if m := re.match(r'^\$ cd \.\.$', line):
                cwd, _ = os.path.split(cwd)
            elif m := re.match(r'^\$ cd (\S+)$', line):
                cwd = os.path.join(cwd, m.group(1))
                dirsizes[cwd] = 0
            elif m := re.match(r'^([0-9]+) (\S+)$', line):
                size = int(m.group(1))
                for d in filter(cwd.startswith, dirsizes):
                    dirsizes[d] += size
    
        print(sum(v for v in dirsizes.values() if v <= SIZE_BOUND))
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import os.path
    import re
    import sys
    
    SIZE_DISK = 70000000
    SIZE_NEED = 30000000
    
    def main():
        dirsizes = {}
        cwd = '/'
        for line in sys.stdin:
            if m := re.match(r'^\$ cd \.\.$', line):
                cwd, _ = os.path.split(cwd)
            elif m := re.match(r'^\$ cd (\S+)$', line):
                cwd = os.path.join(cwd, m.group(1))
                dirsizes[cwd] = 0
            elif m := re.match(r'^([0-9]+) (\S+)$', line):
                size = int(m.group(1))
                for d in filter(cwd.startswith, dirsizes):
                    dirsizes[d] += size
    
        size_to_delete = SIZE_NEED - (SIZE_DISK - dirsizes['/'])
        print(min(v for v in dirsizes.values() if v >= size_to_delete))
    
    if __name__ == '__main__':
        main()
    
    6 votes
  12. Comment on Day 6: Tuning Trouble in ~comp.advent_of_code

    deckard
    (edited )
    Link
    My Python solutions, which are identical other than the WINSIZ constant. Surprised there were so many test cases given, since this one is rather straightforward. Part 1 #!/usr/bin/env pypy3 import...

    My Python solutions, which are identical other than the WINSIZ constant.
    Surprised there were so many test cases given, since this one is rather
    straightforward.

    Part 1
    #!/usr/bin/env pypy3
    
    import sys
    
    WINSIZ = 4
    
    def main():
        data = sys.stdin.read().strip()
        nchars = next(i + WINSIZ for i in range(len(data) - WINSIZ)
                      if len(set(data[i:i + WINSIZ])) == WINSIZ)
        print(nchars)
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import sys
    
    WINSIZ = 14
    
    def main():
        data = sys.stdin.read().strip()
        nchars = next(i + WINSIZ for i in range(len(data) - WINSIZ)
                      if len(set(data[i:i + WINSIZ])) == WINSIZ)
        print(nchars)
    
    if __name__ == '__main__':
        main()
    
    6 votes
  13. Comment on Day 5: Supply Stacks in ~comp.advent_of_code

    deckard
    Link
    Here's my Python solution -- my first this year that uses a defaultdict and uses regex for the input parsing. Part 1 #!/usr/bin/env pypy3 from collections import defaultdict import re import...

    Here's my Python solution -- my first this year that uses a defaultdict
    and uses regex for the input parsing.

    Part 1
    #!/usr/bin/env pypy3
    
    from collections import defaultdict
    import re
    import string
    import sys
    
    def build_stacks(lines):
        stacks = defaultdict(list)
        for line in lines.split('\n')[:-1]:
            for col, char in enumerate(line):
                if char in string.ascii_uppercase:
                    stacks[(col - 1) // 4].insert(0, char)
    
        return stacks
    
    def move_crates(moves, stacks):
        for move in moves.split('\n')[:-1]:
            m = re.match(r'^move ([0-9]+) from ([0-9]+) to ([0-9]+)$', move.strip())
            amount, stack_from, stack_to = map(int, m.groups())
            for _ in range(amount):
                crate = stacks[stack_from - 1].pop()
                stacks[stack_to - 1].append(crate)
    
    def main():
        stack_lines, move_lines = sys.stdin.read().split('\n\n')
        stacks = build_stacks(stack_lines)
        move_crates(move_lines, stacks)
        msg = ''.join(stacks[i][-1] for i in sorted(stacks.keys()))
        print(msg)
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    from collections import defaultdict
    import re
    import string
    import sys
    
    def build_stacks(lines):
        stacks = defaultdict(list)
        for line in lines.split('\n')[:-1]:
            for col, char in enumerate(line):
                if char in string.ascii_uppercase:
                    stacks[(col - 1) // 4].insert(0, char)
    
        return stacks
    
    def move_crates(moves, stacks):
        for move in moves.split('\n')[:-1]:
            m = re.match(r'^move ([0-9]+) from ([0-9]+) to ([0-9]+)$', move.strip())
            amount, stack_from, stack_to = map(int, m.groups())
            crates = [stacks[stack_from - 1].pop() for _ in range(amount)][::-1]
            stacks[stack_to - 1] += crates
    
    def main():
        stack_lines, move_lines = sys.stdin.read().split('\n\n')
        stacks = build_stacks(stack_lines)
        move_crates(move_lines, stacks)
        msg = ''.join(stacks[i][-1] for i in sorted(stacks.keys()))
        print(msg)
    
    if __name__ == '__main__':
        main()
    
    4 votes
  14. Comment on Day 4: Camp Cleanup in ~comp.advent_of_code

    deckard
    Link
    My Python solutions. Just like yesterday, sets are perfect here. Part 1 #!/usr/bin/env pypy3 import sys def main(): pairs = ([set(range(a, b + 1)) for a, b in c] for c in (([*map(int,...

    My Python solutions. Just like yesterday, sets are perfect here.

    Part 1
    #!/usr/bin/env pypy3
    
    import sys
    
    def main():
        pairs = ([set(range(a, b + 1)) for a, b in c] for c in
                 (([*map(int, d.split('-'))] for d in line.strip().split(','))
                  for line in sys.stdin))
        overlaps = (a.issubset(b) or b.issubset(a) for a, b in pairs)
        print(sum(overlaps))
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import sys
    
    def main():
        pairs = ([set(range(a, b + 1)) for a, b in c] for c in
                 (([*map(int, d.split('-'))] for d in line.strip().split(','))
                  for line in sys.stdin))
        overlaps = (a & b != set() for a, b in pairs)
        print(sum(overlaps))
    
    if __name__ == '__main__':
        main()
    
    8 votes
  15. Comment on Is anyone here in or familiar with NYC? Going on a trip and have zero idea what to do as a non-tourist... in ~hobbies

    deckard
    Link Parent
    The top of 30 Rock (GE building / Comcast building) has a great view of the city too.

    The top of 30 Rock (GE building / Comcast building) has a great view of the city too.

    1 vote
  16. Comment on Day 3: Rucksack Reorganization in ~comp.advent_of_code

    deckard
    Link Parent
    My first instinct was to use ord() and subtract ascii values, but this worked out cleaner I think.

    My first instinct was to use ord() and subtract ascii values, but this worked out cleaner I think.

    4 votes
  17. Comment on Day 3: Rucksack Reorganization in ~comp.advent_of_code

    deckard
    Link
    As you can tell, I love Python generators! Part 1 #!/usr/bin/env pypy3 import string import sys def main(): rucksacks = ((set(r[:(len(r) - 1) // 2]), set(r[(len(r) - 1) // 2:-1])) for r in...

    As you can tell, I love Python generators!

    Part 1
    #!/usr/bin/env pypy3
    
    import string
    import sys
    
    def main():
        rucksacks = ((set(r[:(len(r) - 1) // 2]), set(r[(len(r) - 1) // 2:-1]))
                     for r in sys.stdin)
        priorities = (string.ascii_letters.index(next(iter(set.intersection(*r)))) + 1
                      for r in rucksacks)
        print(sum(priorities))
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import string
    import sys
    
    def group_sacks(rucksacks, size):
        for i in range(0, len(rucksacks), size):
            yield rucksacks[i:i + size]
    
    def main():
        groups = group_sacks([set(r[:-1]) for r in sys.stdin], 3)
        priorities = (string.ascii_letters.index(next(iter(set.intersection(*r)))) + 1
                      for r in groups)
        print(sum(priorities))
    
    if __name__ == '__main__':
        main()
    
    7 votes
  18. Comment on Day 2: Rock Paper Scissors in ~comp.advent_of_code

    deckard
    (edited )
    Link
    My Python solution, taking advantage of modular arithmetic. Part 1 #!/usr/bin/env pypy3 import sys def main(): score = 0 for line in sys.stdin: rnd = line.split() opp = ord(rnd[0]) - ord('A') #...

    My Python solution, taking advantage of modular arithmetic.

    Part 1
    #!/usr/bin/env pypy3
    
    import sys
    
    def main():
        score = 0
        for line in sys.stdin:
            rnd = line.split()
            opp = ord(rnd[0]) - ord('A')    # ascii
            me = ord(rnd[1]) - ord('X')     # haxx!
            score += me + 1 + ((me - opp + 1) % 3) * 3
    
        print(score)
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import sys
    
    def main():
        score = 0
        for line in sys.stdin:
            rnd = line.split()
            opp = ord(rnd[0]) - ord('A')                    # ascii
            me = (ord(rnd[1]) - ord('X') - 1 + opp) % 3     # haxx!
            score += me + 1 + ((me - opp + 1) % 3) * 3
    
        print(score)
    
    if __name__ == '__main__':
        main()
    
    7 votes
  19. Comment on Day 1: Calorie Counting in ~comp.advent_of_code

    deckard
    Link
    I'm using Python again this year, but going for a better balance of concision and readability. Last year I code golfed my solutions, rendering them totally unreadable to present me. I might also...

    I'm using Python again this year, but going for a better balance of concision and readability. Last year I code golfed my solutions, rendering them totally unreadable to present me. I might also attempt a handful of the days in either Haskell or a Scheme, but we'll see if that pans out.

    Part 1
    #!/usr/bin/env pypy3
    
    import sys
    
    def main():
        elves = [map(int, elf.split('\n')) for elf in sys.stdin.read()[:-1].split('\n\n')]
        print(max(map(sum, elves)))
    
    if __name__ == '__main__':
        main()
    
    Part 2
    #!/usr/bin/env pypy3
    
    import sys
    
    def main():
        elves = [map(int, elf.split('\n')) for elf in sys.stdin.read()[:-1].split('\n\n')]
        print(sum(sorted(map(sum, elves))[-3:]))
    
    if __name__ == '__main__':
        main()
    
    4 votes
  20. Comment on 2023 Independent Spirit Award nominations in ~movies

    deckard
    Link
    I always love the Indie Spirits -- way more deserving films than those typically celebrated at the Oscars, and a much more relaxed atmosphere. Wonder who will host this year. Aubrey Plaza and...

    I always love the Indie Spirits -- way more deserving films than those typically celebrated at the Oscars, and a much more relaxed atmosphere. Wonder who will host this year. Aubrey Plaza and Mulaney/Kroll were some of my favorites.

    1 vote