#Day 7
1 messages · Page 1 of 1 (latest)
I think this is the first day so far where ive been happy with my original solution and wont need to rewrite it
I LOVED today
Ran 2025 day 7:
Part 1: _ (in 958 µs)
Part 2: _ (in 1.234 ms)
was going to keep track of all the timelines, but remembered that I should never do more work than needed, and that all I need is the count of timelines
did some working out by hand to figure out the pattern (really helped simplify it in my head) and modified my part 1 solution just a little bit
same, was really fun
seems like your solution is pretty similar to mine
pretty much
I like how you've used set operations to update the beam positions
seems smarter than my nested fold
did you write your solution for the general case with n initial beams?
kinda by accident just cause it ended up being easier yeah lol
yeah, it also does seem like a possible part 2 when you're on part 1
why do you sized_chunk on line 13? just to ignore the last line? is that because you saw the last line is empty (unlikely) or because your utils.lines adds an extra empty line or something like that?
its because every second line is empty
so this
list.sized_chunk(2)
|> list.map(fn(lines) {
let assert [first, _] = lines
...
})
only processes every even line
OH it's not window
yeah
It took me sooo long
its not strictly necessary, since both parts will work with empty sets
but it just avoids unnecessary operations
yeah, about 30 minutes for each part for me too
but i did some working out by hand
i came up with the idea for my solution on a whim and just hoped that it would work
im glad i was right
overall enjoying the problems this year much more than i usually do
if we can get through all of them without any maze solving i would be happy
they've been nice so far, but I was thinking they seem a bit easier than the last time I did AoC
yeah theyre definitely a bit easier, but I like the more moderate difficulty
it means i dont have to dedicate 2+ hours each day to aoc
that could be either because
- eric is still calibrating for a 12-day AoC
- the last time I did AoC was 2 years ago and (I hope) I'm a much better programmer now
I really like the solution I came up with though I'll have to clean it up later
I've picked keysmash names in a rush
fn asd(rows, start, splitters) { ... }
fn a(rays, splitters) { ... }
What's asd and a? I hope the me that wakes up in two hours will remember
thankfully aoc starts at 4pm here in aus
ouch, this was painful. I was being "clever" when I wrote one of my dict.upserts and it took a long time to find out. -_-
i should stop using u32
just use u64 or u128 i can do it
decided to use rust for this one when i was still trying to bruteforce it
and i had the right answer but u32
part 1 and dumb bruteforce https://tangled.org/aylac.top/advent_of_code/blob/main/2025/7/gleam/src/main.gleam
part 2 https://tangled.org/aylac.top/advent_of_code/blob/main/2025/7/rust/src/main.rs
Good morning just woke up again
I had a dream where you came up with a gleam solution that took 5ns
good morning, same!
Doing a jak was fun, wasn’t it??
oh my god. I literally just woke up from a dream in which you live in New York.
it took me a while to fall back asleep, but yeah, i live for aoc 💀
I need someone to write an Aoc enemies to lovers fanfiction now
if you're curious: you moved there when you were in kindergarten
hahahahaaa
Blessed be Set and Dict
Me at problem 2:
"Surely I can just brute force computing individual beams, right?"
In the end I used a Dict(Int, Int) to track how many beams each location had at any given time, which I believe is almost identical to what i did in problem 1 which was to use a Set(Int) since I believe that's just a Dict(Int, Nil)
And then the final amount of beams is how many times a beam was split
I totally was too optimistic here. turned my alarm off, then fell asleep and I just woke up 💀
I made it stupid fast
part 1: 0.107ms ±0.2
part 2: 0.110ms ±0.2
I feel so smug about this
daaamn
The cool thing is this doesn't have to parse anything, it just goes over the entire string once and it's done
I'm a parse denier now, fuck parsing
yeah, i realised that a bit, I think. I was doing a fold within a fold with the same acc, and I thought that looked like the same as just folding over the string
I think this is my favourite day so far
what I really found surprising was the huge difference in orders of magnitude between the answers
almost 10 billion times
I have a very nice and clean recursive solution for part 2, made a lot more ugly by the fact that I need to do all sorts of weird actor-message-sending stuff to get a mutable memoization cache 😐
today was p fun
at first for part 2 I tried replacing a set by a list, but that would have needed a list of 25 trillion elements so that wasn't feasible
so I just made it into a dict that kept the count
yeah, it's always best to avoid doing work you don't strictly need to do
type Splitters =
Set(Int)
fn part1(input: #(Int, List(Splitters))) -> Nil {
let #(start, splitters) = input
let #(result, _) = {
use #(count, beams), row <- list.fold(splitters, #(
0,
set.from_list([start]),
))
let #(splits, beams) = splitter_pass(row, beams)
#(count + splits, beams)
}
result
|> int.to_string()
|> string.append("Part 1: ", _)
|> io.println()
}
fn part2(input: #(Int, List(Splitters))) -> Nil {
let #(start, splitters) = input
let result =
{
use beams, row <- list.fold(splitters, dict.from_list([#(start, 1)]))
splitter_quantum_pass(row, beams)
}
|> dict.fold(0, fn(acc, _, n) { acc + n })
result
|> int.to_string()
|> string.append("Part 2: ", _)
|> io.println()
}
fn splitter_pass(s: Splitters, beams: Set(Int)) -> #(Int, Set(Int)) {
use #(count, next), beam <- set.fold(beams, #(0, set.new()))
case set.contains(s, beam) {
True -> #(count + 1, next |> set.insert(beam - 1) |> set.insert(beam + 1))
False -> #(count, set.insert(next, beam))
}
}
fn splitter_quantum_pass(s: Splitters, beams: Dict(Int, Int)) -> Dict(Int, Int) {
use next, beam, beam_count <- dict.fold(beams, dict.new())
let inc = fn(x) {
case x {
Some(x) -> x + beam_count
None -> beam_count
}
}
case set.contains(s, beam) {
True -> next |> dict.upsert(beam - 1, inc) |> dict.upsert(beam + 1, inc)
False -> next |> dict.upsert(beam, inc)
}
}
Can someone explain to me what part1 is actually asking for?
like
am i counting every time i encounter a splitter?
Part 2 is not as complicated as it first appears
today was fun!
pub fn pt_1(input: #(Int, List(List(Int)))) {
let #(starting_pos, splitters) = input
let acc = #(set.new() |> set.insert(starting_pos), 0)
let acc =
list.fold(splitters, acc, fn(acc, row) {
list.fold(row, acc, fn(acc, position) {
let #(beams, count) = acc
case set.contains(acc.0, position) {
True -> {
let beams =
beams
|> set.delete(position)
|> set.insert(position - 1)
|> set.insert(position + 1)
let count = count + 1
#(beams, count)
}
False -> acc
}
})
})
acc.1
}
pub fn pt_2(input: #(Int, List(List(Int)))) {
let #(starting_pos, splitters) = input
let acc = dict.new() |> dict.insert(starting_pos, 1)
let acc =
list.fold(splitters, acc, fn(acc, row) {
list.fold(row, acc, fn(acc, position) {
let prev = acc |> dict.get(position) |> result.unwrap(0)
acc
|> dict.delete(position)
|> dict.upsert(position - 1, fn(value) {
value |> option.unwrap(0) |> int.add(prev)
})
|> dict.upsert(position + 1, fn(value) {
value |> option.unwrap(0) |> int.add(prev)
})
})
})
acc |> dict.values |> int.sum
}
Ran 2025 day 7:
Part 1: ✅ met expected value: 1537 (in 645 µs)
Part 2: ✅ met expected value: 18818811755665 (in 516 µs)
Oh that's better:
fn count_timelines(
remaining_layers: List(set.Set(Int)),
location: Int,
cache_handle,
) -> Int {
let cache_key = #(list.length(remaining_layers), location)
use <- memoize(cache_handle, cache_key)
case remaining_layers {
[] -> 1
[current_layer, ..rest] -> {
let split_this_layer = set.contains(current_layer, location)
let answer = case split_this_layer {
False -> count_timelines(rest, location, cache_handle)
True ->
count_timelines(rest, location - 1, cache_handle)
+ count_timelines(rest, location + 1, cache_handle)
}
actor.send(cache_handle, Set(cache_key, answer))
answer
}
}
}
Using a self-written memoize function that uses an actor to keep the memo table
:P
neat
everyones got such different approaches 
here's mine
https://tangled.org/nuv.sh/advent_of_code/blob/main/src/aoc_2025/day_7.gleam
my clever solution for part2 is still not fast enough
nvm i just forgot to add to the dict
Ended up with same iteration logic than p1 but with a dict to store the timelines counts
Yeah that's pretty much what I did
same, part 2 to part 1 was just going from set to dict
Switching my cache to an ETS table dropped the timing to 5 ms from ~25
Ran 2025 day 7:
Part 1: _ (in 9.523 ms)
Part 2: _ (in 6.144 ms)
way more timelines than I expected
https://github.com/AlexStory/glaoc/blob/main/src/aoc_2025/day_7.gleam
those functions probably need broken out too
Numberphile recently released a video which is relevant ||https://www.youtube.com/watch?v=JXUOMsFBDXQ||
Learn this caching trick for faster code from Dr Mike Pound -- Check out Brilliant's courses and start for free at https://brilliant.org/computerphile/ (episode sponsor) -- More links in full description below ↓↓↓
Computerphile is supported by Jane Street. Learn more about them (and exciting career opportunities) at: https://jane-st.co/com...
Tbh the search+cache/memoization solutions seem like way more work to implement than the linear solution
yeah, i saw a bunch of people doing the memoization + tree search on the subreddit and it seemed much less intuitive than counting beam overlaps
Yep. I considered memoisation but set -> dict was a much easier transition than rewriting the entire solution
Someone I know made this super clean version of the dict/hashmap solution in ruby
splits = 0
counters = Hash.new 0
ARGF.each_line(chomp: true) do |line|
line.chars.each_with_index do |char, col|
if char == ?^
splits += 1 if counters[col] > 0
counters[col - 1] += counters[col]
counters[col + 1] += counters[col]
counters[col] = 0
elsif char == ?S
counters[col] = 1
end
end
end
puts splits
puts counters.values.sum
In tempted to convert it to gleam to simplify my solution even further
I just used a list and went over the whole string
Ooh that is nice
that's so good. it is very close to what you've done already though
Yeah it's the same general algorithm, just stripped down to the bare minimum
I also like the way it incorporates the pt 1 solution into the logic for pt 2
It's not that much effort. 1 for bottom row, laser next row, split next row left and right, done
Indeed. Seeing reactions I though part 2 would be long and slow, but I am under 1ms for both solutions on first try 
Ran 2025 day 7:
Part 1: _ (in 355 µs)
Part 2: _ (in 609 µs)
https://git.alpaga.dev/miniprojects/advent_of_code_gleam/src/branch/develop/src/aoc_2025/day_7.gleam
https://github.com/ollien/advent-of-code-2025/blob/main/src/day7.gleam
classic DP problem?
I don't like how I had to separate part 1 and 2 tho
You can do it without memoisation
i basically slapped memoization around the naive solution
I overcomplicated it a bit before i got to that solution, tough :P
Oh there's a nice visual that explains how Jak's solution works, assuming I understand it right
https://www.reddit.com/r/adventofcode/comments/1pgnmou/2025_day_7_lets_visualize/
That's pretty cool. A bit too clever for me. Grug brain over here
@fair herald if you don't mind me asking, if I understand your solution right you have beam_positions which counts the number of times a beam crosses a position
https://whitespace.moe/lily/gleam_aoc/src/branch/main/src/aoc_2025/day_7.gleam#L60
Why do you subtract one here?
Oh wait, because the splitter collision can't count for anything
Oh good, I managed to clean up my solution without changing approach. Much easier now
Now I feel a little silly, I did that for part 1 but just didn't think to do it for part 2. Just dove straight into memoisation
That's subtracting one from the indexes/keys in the dict, not the values
You take the dict elements where it hits splitters, and duplicate those elements to the left (-1 to index) and right (+1 to index) of the splitter
Then just merge those left and right shifted dicts with the dict of elements that didn't hit anything, adding together anything on the same index
Part 1:_ (in 79.839 ms)
Part 2: _ (in 59.271 ms)
Went with a naive solution that had a cache slapped on it using ETS 🤡 (updated: tiny bit faster)
Ahhh ok. Must have misread it. Thanks!
I have really been enjoying looking at everyone’s solutions. I think I did what a lot of people did, keeping counts of timelines leading to a beam as I fold rows down to the bottom of the manifold. My solution is here: https://github.com/devries/advent_of_code_2025/blob/main/src/day07/solution.gleam
I also like watching @versed aurora on twitch, but never get to see it live because I don’t want spoilers until I’ve done the problem.
Finally getting back to continuing AoC - Here's my Day 7 https://github.com/TigerWalts/AoC-2025/blob/main/src/day7.gleam
I also kept track of timelines to reach each position so part 2 was just summing the timelines on the last row
I'm finding this one very tough, my solutions keeps rounding back to arrays, and there are no arrays...
Dicts and Sets that have indices as the keys are very useful for these kinds of problems
I've taken a quick peek at yours and other people solution, I'll try that today with a fresh mind
Oh, you can do it with arrays graph theory and adjacency matrices https://www.youtube.com/watch?v=_otitFBNjhQ