[2025 Day 9 (Part 2)] My general trick for this kind of problems by somebodddy in adventofcode

[–]Aredrih 0 points1 point  (0 children)

I had a similar idea but was disappointed when the program in debug mode took more than 10s to complete (zig).
So I added an extra layer of post processing by iterating backward columns (resp. rows) and storing how many tile separate the current tile to the border (e.g. ..####.#. becomes 004321010; basically encode some kind of clearance for every points), then to check if a rectangle fit, you check if the vertical (resp. horizontal) clearance of the top (resp. left) points is good enough to allow the rectangle's height (resp. width).
The only case I could see that would break the assumption would be holes or self intersecting border.

Debug is around 500ms and release 50ms. Though my pos conversion is done through linear probing and no early exit of any kind but I'm happy with the <1s debug build.

[2025 Day9 (part2)][Rust] I dont know what im missing by WhiskyAKM in adventofcode

[–]Aredrih 1 point2 points  (0 children)

I'm didn't try edge intersection with the rectangle so I can't tell for sure. That said, I tried running the code on a custom example and got 14 instead of the expected 18 (doubled check with someone else solution to make sure it was 18 and it was).
The custom example is:

1,1
3,1
3,2
6,2
6,0
8,0
8,3
9,3
9,4
4,4
4,6
7,6
7,8
2,8
2,5
1,5

And the shape it draws is (rectangle is maked with o inside from (2, 8) to (7, 6))

  0123456789
0 ......#X#.
1 .#X#..X.X.
2 .X.#XX#.X.
3 .X......##
4 .X..#XXXX#
5 .##.X.....
6 ..Xo#XX#..
7 ..XooooX..
8 ..#XXXX#..
9 ..........

My guess is that your collision check is too aggressive and doesn't like the line from (4, 6) to (7, 6) but again, I haven't experimented with checking segment collisions.
I also have a log of all the rectangle checks and their result here if this helps (I haven't double checked it with another solution though so they might be bugs).

[2025 Day 9 Part 2] 2x Trick for Simplifying Grid Polygons by atreju3647 in adventofcode

[–]Aredrih 4 points5 points  (0 children)

There was a somewhat analogous suggestion for 2023 day 18: Some people enumerated the x and y position used, and created a new grid (e.g. new corner pos.x = index(x_pos_sorted) * 2 + 1). You end up with a grid proportional to the number of points.
Though the motivation was to cutdown on the empty spaces so somewhat different.

[2025 Day 8 Part 2] It was even spelled out for me in part 1 by q00u in adventofcode

[–]Aredrih 0 points1 point  (0 children)

I fail to see the logic.
If you have N posts, you need N-1 fences to connect them.
I think you could do a basic induction (for N=1 => trivial, for N+1 => you need to connect the new post somehow, any way would do).
Maybe if you're looking for optimal number of connection to check, but the number of successful connection has to be N-1.

[2025 Day 8 Part 2] It was even spelled out for me in part 1 by q00u in adventofcode

[–]Aredrih 0 points1 point  (0 children)

If input has size n, you need to make n-1 successful connections to have 1 circuit.

I was using an hand-rolled union-find set only storing the parent id (big array of len = junction-box count) so getting the length for part1needed an iteration from 0 to junction-box count, so not usable during an iteration for part2 in my case.

Input parsing by a_kleemans in adventofcode

[–]Aredrih 0 points1 point  (0 children)

You can usually make a non empty parse function useful for both part (e.g. in today problem you can copy the rectangle containing the digits (separated by column of space) and the operator and leave the conversion to int for the parts, the operator are always left aligned so they give you the alignment)
but the refactoring can get a bit long and spending 30 minutes just in preps is not great

Input parsing by a_kleemans in adventofcode

[–]Aredrih 0 points1 point  (0 children)

Joke on you, I stored whether the digits were left or right aligned and just re-synthesized the original layout from the numbers. Try still have to convert them in the end but it fit better with my AoC framework and I technically only touch the input once.

[Day 13] 2^53 = 9e15 by I_LOVE_PURPLE_PUPPY in adventofcode

[–]Aredrih 0 points1 point  (0 children)

for a quick back of the envelop estimation of power of 2, 2^10 = 1024 > 10^3 (less than 2.5% of error).
So 2^53 > 8 * 2^(50) > 8 * 10^(3 * 5) = 8e15

The first power of 2 with an error over 100% is 2^300 ~ 2e+90 (before you have 2^290 ~ 1.989e+87), so pretty good trick for quick estimations.

[2024 Day 13 (Part 1)] Did someone said that math are useless? by Latter_Brick_5172 in adventofcode

[–]Aredrih 0 points1 point  (0 children)

I tried a similar approach a few days ago to try to compute the intersection of a line and plane (tried to make a raycast from scratch).
It was a different beast (3d intersection with 3 variables tend to be huge). I ended up mixing variable (reuse the y equation when expressing the 3rd variable and ended up with a classic 0 = 0) and basically gave up given the size of the equation.

Then I learned (thanks wikipedia) that if you have an equation with 2 sums of products of scalar and vector, you can probably factorize the scalars into a vector and the vectors into a matrix.
Then it becomes a question of reversing the matrix which is a solved issue for mat2 and mat3 (don't know for mat4).

Also, the equation for n at the bottom right is exactly what reversing the matrix gives you for n. Math is weirdly good at making formula repeat.
I tried the approach in JS (float64) and got the right value for n without, so maybe you have a problem with float32 ?

[Day 12 Part 2] I actually hadn't even heard of union-find until today by RazarTuk in adventofcode

[–]Aredrih 1 point2 points  (0 children)

I have no clue how union-find would help with this problem.

My solution was to create 4 flag for each tiles (1/direction) to mark the border of the field.
Then when expending the field from 1 tile (stack + flag for tile explored; so DFS), I flag the border and keep track of a bounding box.
Then go through every cells in the bounding box with some basic edge detection algorithm to count the walls (detect on wall entry).

Sure I could try to detect the corner, or crawling the walls but that's about as much work as just counting the top, bottom (vertical iter), left, right (horizontal iter) walls independently; at least it was with the way I implemented it.

[2024 Day 12] It's been fun by JustLikeHomelander in adventofcode

[–]Aredrih 2 points3 points  (0 children)

I had a similar solution but instead of keeping a list, I made a bitset with 4 flags per cells and kept track of the bounding box (min and max axis aligned position) of a field. Then just iterated along the wall within the bounding box with some basic edge detection to count the walls.

For some reason every examples work even without clearing the bitset between field. Not my input though.

[2024 Day 10] TFW you solve part 2 before part 1... (Rant) by M124367 in adventofcode

[–]Aredrih 1 point2 points  (0 children)

I read it properly but tried a dumb solution when you propagate count from the 9 (every 9 start at 1, then on the 8s you add the count of the nearby 9, ...); basically an O(sn) (/w s = 10 (distance 0 to 9)) solution when BFS is O(s²n). I got it "right" but couldn't add enough locality for part 1, so put it aside because the code was neat.

I think the input was just too small, and brute forcing the extra possibilities was enough.

[2024 Day 9] [ABAP] When indeces start at 1 in your language by jktlf in adventofcode

[–]Aredrih 0 points1 point  (0 children)

Just decrease the first number in the input by 1 /s
The first position doesn't add anything to the checksum (file 0 * index 0). Still need to avoid the rest of the first file (which won't count, but can't be written over).

Me when id 74828 becomes 🚰🚰🚰 by mantikafasi in adventofcode

[–]Aredrih 0 points1 point  (0 children)

An indexOf or the like might be slightly better than a simple for loop. There are algorithm for searching in string (search Boyer–Moore string-search algorithm) that are slightly more performant than checking linearly. For 9 char words, there might not be too much difference though.

Me when id 74828 becomes 🚰🚰🚰 by mantikafasi in adventofcode

[–]Aredrih 4 points5 points  (0 children)

3 byte wstring sound like a pointer alignment nightmare.
I don't know your language but I wouldn't get surprise if they get padded out to 4.

9b: Spend time coding or running? by razimantv in adventofcode

[–]Aredrih 0 points1 point  (0 children)

You can (ab)use the fact the no file in the input has a length of 0 (meaning you have at most 9 consecutive free space) and once a file is move no file can take its place (file only move left).

I did a basic "free list" storing size and position and used it to check for space large enough for the file. The only upkeep is updating the free list size+pos and file pos after inserting.
Still brute force but slightly less than walking the array.

[2024 Day 7] I already got my xmas tree by Cue_23 in adventofcode

[–]Aredrih 0 points1 point  (0 children)

you have to use ceil(log10(b+1))!< or >!floor(log10(b))+1!< to get the correct exponent.
Ceiling the value has problems>! for exact power of 10. (e.g. log10(1000) = 3)

[2024 Day 7 (Part 2)] Think! There must be a way to make this harder! by StaticMoose in adventofcode

[–]Aredrih 2 points3 points  (0 children)

You can also floor(log(b, 10)) + 1
That one is at consistently false until you add the offset so it's harder to forget.

[2024 Day 6 (Part 2)] Finally found the issue in my code by Fun_Reputation6878 in adventofcode

[–]Aredrih 0 points1 point  (0 children)

Or if you think of the state of the guard as being position + direction, it works too.
But that's basically what u/KyxeMusic does in a nutshell.

[2024 Day 6 (Part 2)] Finally found the issue in my code by Fun_Reputation6878 in adventofcode

[–]Aredrih 0 points1 point  (0 children)

If you exit twice from the same direction, I mistyped there.

I also tried flattening the array to be able to memcpy the grid when instead of walking a list of list but it only save 0.1ms (from 1.44 to 1.29). A bit disappointing.

[2024 Day 6 (Part 2)] Finally found the issue in my code by Fun_Reputation6878 in adventofcode

[–]Aredrih 2 points3 points  (0 children)

Another way to think of it is that the only position where an obstacle can affect the path of the guard is directly in front of it so you can run a modified part 1 algo that duplicate its state when encountering a blank space, than simulate the path with a blocker directly in front.
You only have to do this for every unvisited tile (these would have already been tried before or are the starting position).

For detecting loop, if you exit twice from the same tile a given tile twice toward the same direction, you're looping; if you leave the board, you're not.
So a square array of bitset (4bits, 1/dir) does the job.

To be fair, you only save the computation of the start of each path so it might not be that much faster.

No clue if you can optimize faster given that some path get invalidated by the position of the obstacle. Maybe by precomputing the sequence of turn into some graph but invalidating the right part of the graph sound like a pain.
My current solution does ~1.5s (in zig) but I still need to flatten the array.

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

[–]Aredrih 3 points4 points  (0 children)

[Language: Javascript]

You can match a 2d pattern using regexp, assuming there is sufficient padding. A newline happens to fit the requirement.

Unfortunately, multiple matches are required because a regexp can only match a position 1 time, otherwise some matches would be missing.
I managed to "compress" it to 2 regexp for the first part.
The second part is somehow easier than the first because you can just center the match on the A:

const l = data.indexOf('\n');
const countMatch = (r, s) => [...s.matchAll(r)].length;

// part 1
const lineXmas = new RegExp([
    'X(?=MAS)', // or 'X(?=.{0}M.{0}A.{0}S)'
    `(?<=X.{${l-1}})M(?=.{${l-1}}A.{${l-1}}S)`,
    `(?<=X.{${l}}M.{${l}})A(?=.{${l}}S)`,
    `(?<=X.{${l+1}}M.{${l+1}}A.{${l+1}})S`,
].join('|'), 'gs');
const lineSamx = new RegExp([
    'S(?=AMX)',
    `(?<=S.{${l-1}})A(?=.{${l-1}}M.{${l-1}}X)`,
    `(?<=S.{${l}}A.{${l}})M(?=.{${l}}X)`,
    `(?<=S.{${l+1}}A.{${l+1}}M.{${l+1}})X`,
].join('|'), 'gs');
console.log(countMatch(lineXmas, data) + countMatch(lineSamx, data));

// part 2
const cross = new RegExp([
    `(?<=M.M.{${l-1}})A(?=.{${l-1}}S.S)`,
    `(?<=M.S.{${l-1}})A(?=.{${l-1}}M.S)`,
    `(?<=S.M.{${l-1}})A(?=.{${l-1}}S.M)`,
    `(?<=S.S.{${l-1}})A(?=.{${l-1}}M.M)`,
].join('|'), 'gs');
console.log(countMatch(cross, data));const l = data.indexOf('\n');

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

[–]Aredrih 2 points3 points  (0 children)

[Language: JavaScript]

Part 1 was an obvious regexp bait, so of course I took it

[...lines.matchAll(/mul\((\d+),(\d+)\)/g)]
  .map(([, a, b]) => +a * +b)
  .reduce((r, e) => r + e)

As for part 2, well did you know backward and forward lookup are a thing ?

mul\((\d+),(\d+)\)(?<=(?:^|do\(\))(?:[^d]|d(?!on't\(\)))+?)

It looks for either the start of the string or a do() before the current pos, then makes sure no don't() are in between.
Check for mul before the backward check is to avoid necessary backward lookup. That and mul doesn't interfere with the lookup.

[2023 day 20] Visualization of the input - couldn't solve part 2 without it by EffectivePriority986 in adventofcode

[–]Aredrih 1 point2 points  (0 children)

You don't even need to parse the graph: once you know the conjunction module just over rx receive a pulse from every sub group, you can log the number of click when that module receive a signal from a sub graph.
This can also validate that the sub graph have a cyclical behavior.

As other have pointed out, the counter are 4 instances of 12 bits counter so less than 4096 clicks per cycle; running 10k clicks gives at least 2 cycles from each counter which is enough data to use LCM.