[-] Chais@sh.itjust.works 0 points 2 days ago* (last edited 2 days ago)

Shoot a ray to the right, if and when it collides, shoot a ray to the right, …
You know, recursion.

[-] Chais@sh.itjust.works 1 points 3 days ago

That's what I meant with the second part of my reply. With a recursion depth of at least 4 it'll detect the option for a loop at the location of the ^.

[-] Chais@sh.itjust.works 1 points 3 days ago

I'm only casting a ray to detect where turning right now would lead. So to stick with your example:

.O..
-^+#
#++.
..#.

If the guard had come from the left and run this little loop I'd detect this location to place an obstacle.
Alternatively, if I switch back to recursive rays, I'd detect this location a little later:

.O..
.^.#
#|..
.|#.
[-] Chais@sh.itjust.works 1 points 5 days ago

Yes. For every step I check if turning would lead me back onto my previous path, either because I'm crossing it or because walking that direction will eventually bring me back onto it, passing the obstacle that cause me to turn.

[-] Chais@sh.itjust.works 1 points 5 days ago* (last edited 5 days ago)

But if you move onto a location+heading that you traversed before, that is a loop.

Which is the express goal of part 2.
Conversely walking in the opposite direction would lead me right past any obstacle that cause me to turn. So it's not particularly useful.

[-] Chais@sh.itjust.works 1 points 5 days ago* (last edited 5 days ago)

It just keeps turning. See 3.2. Worst case is it has to turn twice and walk back where it came.

12
Stuck on day 6, part 2 (sh.itjust.works)
submitted 5 days ago* (last edited 5 days ago) by Chais@sh.itjust.works to c/advent_of_code@programming.dev

I'm not looking for a solution or even code, just a hint. Here's what I currently do:

  1. Add the current position and heading to the recorded path
  2. Check if turning right would lead back onto the recorded path in the same direction we walked it before
  3. Check if the next field is obstructed
    1. If so, turn right
    2. Repeat until no longer blocked
  4. Update current position

This approach works fine for the unit test, but yields a result too low for the puzzle input. I tried adding recursion to the party check, but even 20 levels of recursion didn't sufficiently increase the amount of options found, suggesting I'm missing a mechanism to identify them.

Any clues?

Current state of affairs:

from math import sumprod
from operator import add
from pathlib import Path


def parse_input(input: str) -> list[list[int]]:
    return input.strip().splitlines()


def find_guard(world: list[list[int]]) -> tuple[int]:
    for y, line in enumerate(world):
        x = line.find("^")
        if x > -1:
            return (y, x)
    return (-1, -1)  # No guard


def turn(heading: tuple[int]) -> tuple[int]:
    mat = [(0, 1), (-1, 0)]
    return tuple([sumprod(col, heading) for col in mat])


def step(pos: tuple[int], heading: tuple[int]) -> tuple[int]:
    return tuple(map(add, pos, heading))


def is_blocked(world: list[list[str]], guard: tuple[int], heading: tuple[int]) -> bool:
    pos = step(guard, heading)
    try:
        return world[pos[0]][pos[1]] == "#"
    except IndexError:
        return False


def cast_ray(
    world: list[list[int]], start: tuple[int], heading: tuple[int]
) -> list[tuple[int]]:
    pos = step(start, heading)
    ray = []
    try:
        while world[pos[0]][pos[1]] != "#":
            ray.append(pos)
            pos = step(pos, heading)
    except IndexError:
        # Left the world
        ...
    return ray


def part_one(input: str) -> int:
    world = parse_input(input)
    guard = find_guard(world)
    heading = (-1, 0)
    while (
        guard[0] >= 0
        and guard[0] < len(world)
        and guard[1] >= 0
        and guard[1] < len(world[guard[0]])
    ):
        while is_blocked(world, guard, heading):
            heading = turn(heading)
        world[guard[0]] = f"{world[guard[0]][:guard[1]]}X{world[guard[0]][guard[1]+1:]}"
        guard = tuple(map(add, guard, heading))
    return sum([line.count("X") for line in world])


def part_two(input: str) -> int:
    world = parse_input(input)
    guard = find_guard(world)
    heading = (-1, 0)
    path = {}
    options = 0
    while (
        guard[0] >= 0
        and guard[0] < len(world)
        and guard[1] >= 0
        and guard[1] < len(world[guard[0]])
    ):
        path.setdefault(guard, []).append(heading)
        turned = turn(heading)
        if turned in path.get(guard, []) or turned in [
            d
            for p in set(cast_ray(world, guard, turned)).intersection(set(path.keys()))
            for d in path[p]
        ]:
            # Crossing previous path and turning would cause us to retrace our steps
            # or turning would lead us back into our previous path
            options += 1
        while is_blocked(world, guard, heading):
            heading = turned
        world[guard[0]] = f"{world[guard[0]][:guard[1]]}X{world[guard[0]][guard[1]+1:]}"
        guard = tuple(map(add, guard, heading))
    return options


if __name__ == "__main__":
    input = Path("input").read_text("utf-8")
    print(part_one(input))
    print(part_two(input))
[-] Chais@sh.itjust.works 2 points 5 days ago

"Open source" is still commonly used to mean FOSS. Source available software isn't common enough to have made its way into the broader vocabulary.

[-] Chais@sh.itjust.works 5 points 6 days ago

I just checked my KeePass and turns out I still have the entry in the recycle bin.
It was 5 digits. Admittedly, that was "back in 2012," but still. For shame, Bank Austria!

[-] Chais@sh.itjust.works 2 points 6 days ago* (last edited 6 days ago)

No need for floor, you can just use len(pages) // 2.

[-] Chais@sh.itjust.works 2 points 6 days ago* (last edited 6 days ago)

Python

Also took advantage of cmp_to_key.

from functools import cmp_to_key
from pathlib import Path


def parse_input(input: str) -> tuple[dict[int, list[int]], list[list[int]]]:
    rules, updates = tuple(input.strip().split("\n\n")[:2])
    order = {}
    for entry in rules.splitlines():
        values = entry.split("|")
        order.setdefault(int(values[0]), []).append(int(values[1]))
    updates = [[int(v) for v in u.split(",")] for u in updates.splitlines()]
    return (order, updates)


def is_ordered(update: list[int], order: dict[int, list[int]]) -> bool:
    return update == sorted(
        update, key=cmp_to_key(lambda a, b: 1 if a in order.setdefault(b, []) else -1)
    )


def part_one(input: str) -> int:
    order, updates = parse_input(input)
    return sum([u[len(u) // 2] for u in (u for u in updates if is_ordered(u, order))])


def part_two(input: str) -> int:
    order, updates = parse_input(input)
    return sum(
        [
            sorted(u, key=cmp_to_key(lambda a, b: 1 if a in order[b] else -1))[
                len(u) // 2
            ]
            for u in (u for u in updates if not is_ordered(u, order))
        ]
    )


if __name__ == "__main__":
    input = Path("input").read_text("utf-8")
    print(part_one(input))
    print(part_two(input))
[-] Chais@sh.itjust.works 9 points 6 days ago

Right? Had a bank account once, where the login password could only have up to 8 characters. And only digits.

24
100% Rye sourdough (sh.itjust.works)
submitted 2 months ago by Chais@sh.itjust.works to c/bread@lemmy.ca
54

Fermented with black cardamom and garlic (which I'm just noticing I forgot to put on the label 🤷) and puréed with mango and pear.
Added a little rice vinegar and salt to balance the fruit.
It's a little spicier than Sriracha, but not at all unpleasant. Nicely sweet and spicy. You can taste it with a spoon without regretting it.

13
35

I'm trying to get networkd to connect to a wireguard endpoint, specifically ProtonVPN, in case it matters. I just can't get it to connect. Has anyone had success with that? Specifically without using wg-quick.

18
submitted 10 months ago by Chais@sh.itjust.works to c/pizza@sh.itjust.works
45
WIP Wednesday update (sh.itjust.works)
submitted 10 months ago by Chais@sh.itjust.works to c/knitting@lemmy.world

Update since mid November. Finished the central panel of the cardigan. Started on the edge panel. 24 rows down, 488 to go.

21
submitted 1 year ago by Chais@sh.itjust.works to c/metal@lemmy.world
10
submitted 1 year ago by Chais@sh.itjust.works to c/montreal@lemmy.ca

Looking for someone to take over our lease for a 3 1/2 apartment in Petite-Patrie (H2S) starting February 1st 2024.
Lease goes until 31st of October 2024 with option of renewal.
Monthly rent is $1665 including hot water and parking behind the house (electric bill is extra).

The apartment was completely renovated in 2018 with new isolation, windows and doors. It is on the ground floor, very quiet and in walking distance to metro stations (Fabre and Beaubien), supermarkets, cafés and shops.
The bedroom and office both have built-in storage closets. You have full access to the garden in the back and can use it as you wish. Cats are no problem but you will have to check for other pets.
Appliances are NOT included in the lease and we bought them new in 2018 (Stove, fridge with freezer drawer, dishwasher, washing machine and dryer). All are good quality appliances (Whirlpool, Maytag) that work great and we'd prefer them taken over from us (price is negotiable).
All our furniture is also up for sale.

Please send me a message if interested.

https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/b1/b15abf7d-2828-4e00-ab1a-c3c5639e3260?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/76/760166c5-2421-4693-90fa-63658fff07cc?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/82/826354e8-a2e8-4246-8cb8-d831eeb1ef9f?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/e6/e6110cdd-c164-4e58-a83d-8f980e23ca5e?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/6f/6fb34ec2-cbc8-47da-9859-beaa414f3f6c?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/3e/3ef5d1ab-7c43-4edc-bcc8-afe22b2c4ce8?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/24/24b6ccd4-1159-48a8-a456-e5530561670c?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/7d/7d683809-d303-43fc-a78b-3e3677731aa2?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/9f/9f9c5d9c-fcc3-43f5-9395-350f4ff76015?rule=kijijica-640-webp
https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/6c/6cd0de76-e63b-4a7c-8e75-54b0d0dd6b5e?rule=kijijica-640-webp

8
submitted 1 year ago by Chais@sh.itjust.works to c/metal@lemmy.world

Probably even more relevant than it was back then.

4
Kmac2021 ­– Butterfly (www.youtube.com)
submitted 1 year ago by Chais@sh.itjust.works to c/metal@lemmy.world
5
submitted 1 year ago by Chais@sh.itjust.works to c/metal@lemmy.world
view more: next ›

Chais

joined 2 years ago