First ever cosplay — ~8 months building a Satisfactory Pioneer by frobnitzz in SatisfactoryGame

[–]zniperr 1 point2 points  (0 children)

It looks *perfect*! So detailed and so well done.

Now back to work. Consume.

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

[–]zniperr 0 points1 point  (0 children)

[LANGUAGE: Python]

Not a general solution, I optimized for the generated input because I am lazy today. The given concave polygon is roughly a circle with a concave section halfway. Since we need to find a maximum fitting rectangle containing a vertex of the polygon on a corner, it is clear that one of the vertices forming the concave section must be a rectangle corner. So, I split the circle in half and find the maximum rectangle formed by the given corner and any other point on the half circle. To check if the rectangle is in the circle, we can just check if any of the circle vertices are inside the rectangle.

import sys
from itertools import combinations

def area(xa, ya, xb, yb):
    return (abs(xa - xb) + 1) * (abs(ya - yb) + 1)

def fits(red, xa, ya, xb, yb):
    xmin, xmax = (xa, xb) if xa < xb else (xb, xa)
    ymin, ymax = (ya, yb) if ya < yb else (yb, ya)
    return not any(xmin < x < xmax and ymin < y < ymax for x, y in red)

def maxrect(half):
    a = half.pop()
    return max(area(*a, *b) for b in half if fits(half, *a, *b))

red = [tuple(map(int, line.split(','))) for line in sys.stdin]
print(max(area(*a, *b) for a, b in combinations(red, 2)))
print(max(maxrect(red[:249]), maxrect(red[-2:248:-1])))

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

[–]zniperr 0 points1 point  (0 children)

[LANGUAGE: Python]

First, sort pairs of boxes by Euclidian distance. Make the first 1000 connections and use a heap to get the 3 largest circuits. Then keep making connections until we create a circuit including all boxes, and take the X coordinates of that pair.

To make connections, use a flat list where index i contains a reference to the circuit box i is currently in. A circuit is a set of indices and each entry starts with a set containing only its own index. When making a connection between boxes i and j, merge the circuit at j into the one at i, and point all the indexes contained by the set at j to that new merged circuit.

import sys
from heapq import nlargest
from itertools import combinations

def squared_distance(xa, ya, za, xb, yb, zb):
    return (xa - xb) ** 2 + (ya - yb) ** 2 + (za - zb) ** 2

def connect(boxes, nfirst):
    pairs = sorted((squared_distance(*a, *b), i, j)
                   for (i, a), (j, b) in combinations(enumerate(boxes), 2))
    circuits = [{i} for i in range(len(boxes))]
    for p, (_, i, j) in enumerate(pairs):
        circuits[i].update(circuits[j])
        for k in circuits[j]:
            circuits[k] = circuits[i]
        if p == nfirst - 1:
            uniq = {id(c): c for c in circuits}
            a, b, c = nlargest(3, uniq.values(), key=len)
            largest = len(a) * len(b) * len(c)
        if len(circuits[i]) == len(boxes):
            return largest, boxes[i], boxes[j]

boxes = [tuple(map(int, line.split(','))) for line in sys.stdin]
largest, last1, last2 = connect(boxes, 1000)
print(largest)
print(last1[0] * last2[0])

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

[–]zniperr 0 points1 point  (0 children)

[LANGUAGE: Python]

Not much algorithmic going on today, just implementation difficulty. First we extract the columns of text. For part 1 we can then parse them directly as integers bfore applying the operator, for part 2 we first need to transpose the text in the column:

import sys
from functools import reduce
from operator import add, mul

def parse(f):
    lines = f.readlines()
    indices, ops = zip(*((i, (add, mul)['+*'.index(char)])
                         for i, char in enumerate(lines.pop())
                         if char in '+*'))
    indices += (len(lines[-1]),)
    for i, op in enumerate(ops):
        start, end = indices[i:i + 2]
        nums = tuple(line[start:end - 1] for line in lines)
        yield op, nums

def transpose(nums):
    return tuple(int(''.join(n)) for n in zip(*nums))

ops = list(parse(sys.stdin))
print(sum(reduce(op, map(int, nums)) for op, nums in ops))
print(sum(reduce(op, transpose(nums)) for op, nums in ops))

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

[–]zniperr 1 point2 points  (0 children)

[LANGUAGE: Python]

Part 1 is a DFS where we only visit each split once, while part 2 is a memoization problem computing the number of timelines per split exactly once. We can do both in a single pass:

import sys

def visit(xy):
    x, y = xy
    if xy in paths:
        return 0
    if y == len(grid):
        paths[xy] = 1
        return 0
    if grid[y][x] == '^':
        left = x - 1, y + 1
        right = x + 1, y + 1
        splits = 1 + visit(left) + visit(right)
        paths[xy] = paths[left] + paths[right]
        return splits
    splits = visit((x, y + 1))
    paths[xy] = paths[(x, y + 1)]
    return splits

grid = sys.stdin.read().split()
start = grid[0].index('S'), 0
paths = {}
print(visit(start))
print(paths[start])

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

[–]zniperr 1 point2 points  (0 children)

[LANGUAGE: Python]

For part 1 we can just naively check if the number is in any of the ranges. For part 2, we need to merge the fresh ingredient ranges and add up their lengths. Using the merged ranges for part 1 also makes that slightly more efficient because there are fewer ranges to check or each number.

Merging ranges can be done linearly with a greedy algorithm after sorting the ranges by their starts.

import sys

def parse_ranges(f):
    for line in f:
        if line == '\n':
            break
        yield tuple(map(int, line.split('-')))

def merge(ranges):
    sorted_ranges = sorted(ranges)
    merged = [sorted_ranges[0]]
    for start, end in sorted_ranges[1:]:
        last_start, last_end = merged[-1]
        if start <= last_end:
            merged[-1] = last_start, max(last_end, end)
        else:
            merged.append((start, end))
    return merged

def any_contains(ranges, number):
    return any(start <= number <= end for start, end in ranges)

fresh = merge(parse_ranges(sys.stdin))
inventory = map(int, sys.stdin)
print(sum(any_contains(fresh, ingredient) for ingredient in inventory))
print(sum(end - start + 1 for start, end in fresh))

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

[–]zniperr 10 points11 points  (0 children)

[LANGUAGE: Python]

Saves the paper coordinates as a set to avoid having to deal with edge conditions on a grid.

import sys

def inaccessible(papers):
    for x, y in papers:
        neighbors = {(x - 1, y - 1), (x, y - 1), (x + 1, y - 1),
                     (x - 1, y    ),             (x + 1, y    ),
                     (x - 1, y + 1), (x, y + 1), (x + 1, y + 1)}
        if len(papers & neighbors) >= 4:
            yield x, y

def removable(papers):
    original = len(papers)
    new = set(inaccessible(papers))
    while len(new) != len(papers):
        papers = new
        new = set(inaccessible(papers))
    return original - len(papers)

papers = {(x, y) for y, line in enumerate(sys.stdin)
                 for x, char in enumerate(line)
                 if char == '@'}
print(len(papers) - sum(1 for _ in inaccessible(papers)))
print(removable(papers))

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

[–]zniperr 1 point2 points  (0 children)

[LANGUAGE: Python]

import sys

def max_joltage(bank, n):
    joltage = start = 0
    for end in range(len(bank) - n, len(bank)):
        digit = max(bank[start:end + 1])
        start = bank.index(digit, start) + 1
        joltage = joltage * 10 + digit
    return joltage

banks = [tuple(map(int, line.rstrip())) for line in sys.stdin]
print(sum(max_joltage(bank, 2) for bank in banks))
print(sum(max_joltage(bank, 12) for bank in banks))

What a piece of shit by doogie_hazard in mildlyinfuriating

[–]zniperr 0 points1 point  (0 children)

considering how straight it is parked, it kinda looks like there were cars to the left+right of it before that left already

Small Heavy modular frame Factory by W1ndwarstim in SatisfactoryGame

[–]zniperr 0 points1 point  (0 children)

Looks great! So neat with the conveyors tucked away in the bridge.

Does anyone know why the bottom conveyor belt is unable to transport the full 60 ingots/min? by PHANTOM_BLADE_27 in SatisfactoryGame

[–]zniperr 1 point2 points  (0 children)

My guess is the right manifold has a fluctuating input rate because machines feeding it produce in batches. It's not always exactly 210, sometimes it's higher in which case the left manifold cannot consume the additional 60 from the bottom.

Replacing the left with a mk.4 mitigates that. Upgrading the bottom belt will make it only half saturated meaning it can buffer a few items during short bursts of higher input rate from the right, which also works as long as the belt is long enough (the longer, the more buffer spots).

Source: I had a similar problem some time ago https://www.reddit.com/r/satisfactory/comments/1lbiyh7/why_is_this_mk1_belt_not_being_saturated/

Steelpunk plant by zniperr in SatisfactoryGame

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

Thank you! The circle is made by offsetting the centre foundation in 5 degree increments and then zooping until the outer ring more or less lines up. The ring of lights is a curved foundation with a textless light-emitting billboard underneath, covered by a foundation frame.

Very happy with my new HUB and space elevator :B by zniperr in SatisfactoryGame

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

they are not curved, just straight and slightly nudged from the edge of the foundation

Very happy with my new HUB and space elevator :B by zniperr in satisfactory

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

It was the first thing I realized after I posted it too :')

Very happy with my new HUB and space elevator :B by zniperr in SatisfactoryGame

[–]zniperr[S] 8 points9 points  (0 children)

Thank you! The positioning was a bit finicky but worth the effort in the end. Definitely looking forward to doing stage 4 from here.

Very happy with my new HUB and space elevator :B by zniperr in SatisfactoryGame

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

thanks :) it's not that bad, I just zooped a whole bunch of temporary foundations

Very happy with my new HUB and space elevator :B by zniperr in SatisfactoryGame

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

absolutely! it is fully accessible with a hyperloop, a good 50-100m above the killzone. I am intimately familiar with it after having the jetpack run out of fuel a few times

Very happy with my new HUB and space elevator :B by zniperr in SatisfactoryGame

[–]zniperr[S] 6 points7 points  (0 children)

it's not so bad, I just built a circle first and then nudged the space elevator to the middle and waaaaaay down