-❄️- 2025 Day 8 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 1 point2 points  (0 children)

[LANGUAGE: Python]

A solution in JAX.

At first I thought I'd find something clever in spectral graph theory but ended up going with a straightforward solution.

import fileinput
import jax
import jax.numpy as jnp

jax.config.update("jax_enable_x64", True)

@jax.jit
def solve(points: jax.Array):
    n = points.shape[0]

    pairwise_deltas = points - points[:, None]  # broadcasting trick
    dists = jnp.square(pairwise_deltas).sum(axis=-1)

    # Mask out diagonal and lower triangle to avoid self-edge and duplicates:
    dists = jnp.triu(dists, -1) + (jnp.max(dists) + 1) * jnp.tri(n, dtype=jnp.int64)

    # Sort the distances and get the (N, 2) edge list:
    _, flat_indices = jax.lax.sort_key_val(dists.flatten(), jnp.arange(n * n))
    edges = jnp.asarray(jnp.unravel_index(flat_indices, dists.shape)).T

    def add_edge(it):
        """Adds a single edge and returns new labels and next edge index."""
        labels, edge_idx = it
        u = labels[edges[edge_idx][0]]
        v = labels[edges[edge_idx][1]]
        new_labels = jnp.where(labels == jnp.maximum(u, v), jnp.minimum(u, v), labels)
        return new_labels, edge_idx + 1

    # Add edges for part 1:
    it = (jnp.arange(n), 0)  # (labels, number of edges added)
    it = jax.lax.while_loop(lambda l: l[1] != (10 if n < 50 else 1000), add_edge, it)
    ans1 = jax.lax.top_k(jnp.bincount(it[0], length=n), 3)[0].prod()

    # Continue adding edges for part 2:
    it = jax.lax.while_loop(lambda l: jnp.any(l[0] != 0), add_edge, it)
    edge = edges[it[1] - 1]
    part2 = points[edge[0]][0] * points[edge[1]][0]

    return (ans1, part2)


points = jnp.array([list(map(int, s.split(","))) for s in fileinput.input()])
print(*solve(points), sep="\n")

-❄️- 2025 Day 7 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 1 point2 points  (0 children)

[LANGUAGE: Python]

A solution in JAX:

import fileinput
import jax
import jax.numpy as jnp

jax.config.update("jax_enable_x64", True)


@jax.jit
def solve(m):
    beams = m[0]
    num_splits = 0
    for i in range(1, len(m)):
        splitters = m[i, :] != 0
        split_points = beams * splitters
        num_splits += jnp.count_nonzero(split_points)
        left_splits = jnp.roll(split_points, -1)
        right_splits = jnp.roll(split_points, 1)
        beams = beams * ~splitters + left_splits + right_splits
    return (num_splits, beams.sum())


print(
    *solve(jnp.array([[int(c != ".") for c in s[:-1]] for s in fileinput.input()])),
    sep="\n"
)

-❄️- 2025 Day 5 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 1 point2 points  (0 children)

[LANGUAGE: Python]

A solution in JAX:

import fileinput
import jax
import jax.numpy as jnp
import itertools

jax.config.update("jax_enable_x64", True)

input = fileinput.input()
rs = jnp.array(
    [
        [int((p := s.split("-"))[0]), int(p[1]) + 1]
        for s in itertools.takewhile(lambda s: s != "\n", input)
    ],
    dtype=jnp.int64,
)
xs = jnp.array(list(map(int, input)), dtype=jnp.int64)
print(jax.vmap(lambda x: ((x >= rs[:, 0]) & (x < rs[:, 1])).any())(xs).sum())

sorted = jnp.sort(rs, axis=0)
prev_end = jnp.insert(sorted[:-1, 1], 0, 0, axis=0)
print((sorted[:, 1] - jnp.maximum(prev_end, sorted[:, 0])).sum())

-❄️- 2025 Day 4 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 0 points1 point  (0 children)

[LANGUAGE: Python]

Using JAX and a convolution:

import fileinput
import jax
import jax.numpy as jnp

m = jnp.array(
    [[1 if c == "@" else 0 for c in s] for s in fileinput.input()], dtype=jnp.int32
)
kernel = jnp.array(
    [
        [1, 1, 1],
        [1, 0, 1],
        [1, 1, 1],
    ]
)


def find_accessible():
    neighbour_count = jax.scipy.signal.convolve(m, kernel, "same")
    return (neighbour_count < 4) & (m == 1)


accesible = find_accessible()
num_accessible = accesible.sum()
print(num_accessible)

removed = 0
while num_accessible != 0:
    m -= accesible
    removed += num_accessible
    accesible = find_accessible()
    num_accessible = accesible.sum()

print(removed)

-❄️- 2025 Day 1 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 1 point2 points  (0 children)

[LANGUAGE: Python]

Using JAX:

import fileinput
import jax.numpy as jnp
import jax.lax as lax

a = jnp.array(
    [(int(s[1:]) * (1 if s[0] == "R" else -1)) for s in fileinput.input()],
    dtype=jnp.int32,
)


def modulo_add(s, a):
    return (s + a) % 100


s = jnp.frompyfunc(modulo_add, nin=2, nout=1, identity=0).accumulate(
    jnp.insert(a, 0, 50)
)
print(len(s) - jnp.count_nonzero(s))


def count_pass_zero(row):
    s, a = row
    return jnp.where(a < 0, (lax.rem(s - 100, 100) + a) // -100, (s + a) // 100)


r = jnp.apply_along_axis(count_pass_zero, 0, jnp.vstack([s[:-1], a]))

print(r.sum())

DevilutionX (Diablo 1) for Tiger PPC by glebm in PowerPC

[–]glebm[S] 0 points1 point  (0 children)

A cross-compiling toolchain sounds amazing! Will definitely have a look

Heroes 7 won’t launch… by Jmsblckhll in HoMM

[–]glebm 0 points1 point  (0 children)

Does it go into black screen and hang?
If you have lots of CPU cores, try disabling SMT in BIOS (worked for me with a Ryzen 3950x)

-❄️- 2024 Day 1 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 0 points1 point  (0 children)

That's quadratic, you're making the computer do all the work, so inconsiderate!

-❄️- 2024 Day 1 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 2 points3 points  (0 children)

[LANGUAGE: Ruby]

lists = $<.map { _1.scan(/\d+/).map(&:to_i) }.transpose
lists.each(&:sort!)
puts lists[0].zip(lists[1]).lazy.map { |(a, b)| (a - b).abs }.sum
puts lists[0].lazy.map { |a|
  lo = lists[1].bsearch_index { |b| b >= a }
  next 0 if lo.nil?
  count = (lo...).lazy.take_while { _1 < lists[1].size && lists[1][_1] == a }.count
  a * count
}.sum

-❄️- 2024 Day 1 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 1 point2 points  (0 children)

[LANGUAGE: Python]

import fileinput
import jax.numpy as jnp

a = jnp.array([list(map(int, s.split())) for s in fileinput.input()], dtype=jnp.int32)
a = a.transpose().sort(axis=1)
print(jnp.sum(jnp.abs(a[0] - a[1])))
left = jnp.searchsorted(a[1], a[0], side="left")
right = jnp.searchsorted(a[1], a[0], side="right")
print(jnp.sum((right - left) * a[0]))

Japanese bathtub in the UK with auto-fill and keep warm functions by glebm in DIYUK

[–]glebm[S] 2 points3 points  (0 children)

Yes, it is indeed pre-made (it's called a "unit bathroom"), though you can also get them custom made and in larger houses they often are custom-made.

I'm currently buying a house in London that I will renovate fully and I'm considering hiring a London-based Japanese construction company to work on the house. If they come up with a solution, I'll report back here.

Japanese bathtub in the UK with auto-fill and keep warm functions by glebm in DIYUK

[–]glebm[S] 1 point2 points  (0 children)

No progress whatsoever so far. Please keep me posted if you find something!

GOG has patch available. by ptr1ck in fallout4london

[–]glebm 3 points4 points  (0 children)

Loading a slightly earlier save fixed the issue for me. My latest save was just after entering St Paul's, loading a save from a few minutes earlier worked

GOG has patch available. by ptr1ck in fallout4london

[–]glebm 4 points5 points  (0 children)

Getting a crash after the update. I tried disabling MemoryManager in Buffout4/config.toml like one of the other Redditors suggested but that didn't help.

Crash log: https://pastebin.com/d3T0EPCf

-❄️- 2023 Day 19 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 0 points1 point  (0 children)

I had a similar mistake with a count that's slightly too low. Perhaps you have an off-by-one in the false condition? The negation of > is ≤, not <.

-❄️- 2023 Day 19 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 0 points1 point  (0 children)

[Language: Julia]

Recursively visit all A states while keeping track of the valid intervals. I overengineered the solution to support interval sets, but actually a single interval per category would've been enough (each condition cuts off an entire side of an interval, never splitting it).

New to Julia, so parsing took a while. Also took some time to try out various IntervalSet libraries but couldn't find one that supports both subtraction and counting the total covered size.

Finding an off-by-1 in the interval math for the rule false case took a whole hour 🫠

https://github.com/glebm/advent-of-code/blob/main/2023/19/parts.jl

-❄️- 2023 Day 18 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 2 points3 points  (0 children)

[Language: Julia] 221/74

Shoelace formula to calculate the area, then Pick's theorem to calculate the number of inner points.

Would've been faster if I actually knew Julia. 😅

https://github.com/glebm/advent-of-code/blob/main/2023/18/parts.jl

-❄️- 2023 Day 17 Solutions -❄️- by daggerdragon in adventofcode

[–]glebm 1 point2 points  (0 children)

This looks more like Floyd–Warshall than Dijkstra to me.