adventofcode

2024-12-06T16:58:41.003609Z

Firing up the stream.

🙌🏻 1
tschady 2024-12-06T17:15:00.991299Z

Since the AOC creator has asked everyone to not publish input or puzzle text data… For anyone who is accidentally publishing anything, I wrote https://github.com/tschady/advent-of-code/blob/main/ENCRYPT.adoc on: 1. how to encrypt the files on your remote, but have unencrypted files locally. It’s very easy to use, no code involved. 2. purge the secret data from your git history (it uses git-crypt and git-filter-repo from homebrew)

❤️ 1
☝️ 1
1
2
Joe 2024-12-06T17:28:22.224679Z

This is very useful to know in general, thanks. But out of interest what's the motivation for encrypting the input for AOC puzzles? Is it sensitive?

➕ 2
tschady 2024-12-06T17:35:18.118799Z

> Don’t make your inputs public! > > Plea from creator of AOC: > If you’re posting a code repository somewhere, please don’t include parts of Advent of Code like the puzzle text or your inputs. > — Eric Wastl

👌 1
Joe 2024-12-06T18:20:06.885329Z

Ah, didn't know that, thanks

souenzzo 2024-12-06T18:40:58.769949Z

I developed a library that https://github.com/souenzzo/maoc/blob/main/projects/aoc/src/aoc/io.clj the input So it is pretty easy to use it from REPL, without commit the file: https://github.com/souenzzo/maoc/blob/main/projects/aoc2024/src/aoc2024/main.clj#L98

Apple 2024-12-06T18:46:55.666249Z

how does crypt apply to history commits?

Apple 2024-12-06T18:48:31.743989Z

Perhaps a folk of AoC like AoC-gen to come up with solutions that generate the appropriate input.

tschady 2024-12-07T02:21:07.516919Z

@zengxh it doesn’t… only files going forward. That’s why there’s the second part to burn your history.

2024-12-06T05:55:36.907999Z

Day 6 - Solutions

2024-12-07T14:37:17.915559Z

I thought I was smarty smart by just rotating the grid counter clockwise for turning right, but I can’t even solve part 1 lol. Value is too high, test input works 🤷

2024-12-07T14:37:53.243589Z

> Story of our lives indeed

roklenarcic 2024-12-07T14:39:10.557429Z

Why would you rotate the grid? What’s the benefit of that compared to keeping a variable to denote direction of movement?

roklenarcic 2024-12-07T14:39:29.319979Z

It’s certainly much slower and more complex implementation-wise

2024-12-07T14:39:40.321239Z

Ha: I just wanted to do something else I guess

2024-12-07T14:44:08.367889Z

And yes to the implementation being more complex. How I ended up implementing this bright idea. 1. “Move” the guard up to the first obstacle and mark all stepped fields with “X” 2. Now that I have implemented this for up direction I could just rotate the grid and repeat that until I have the guard standing at an edge. 3. sunk cost fallacy combined with false pride

2024-12-07T14:45:31.217869Z

Then I wanted to try a (take-while guard-at-edge (iterate make-move start-grid)) , which also doesn’t make sense at all to call last on that one

2024-12-07T14:45:50.199069Z

(and it was a bug: take-until would be correct. I ended up looping)

roklenarcic 2024-12-07T14:46:22.040059Z

I have (iterate make-move start-grid) and when it goes off the end it starts returning nil

roklenarcic 2024-12-07T14:46:49.661409Z

so then it’s just (take-while some? …

roklenarcic 2024-12-07T14:47:00.543109Z

that gives you whole path

2024-12-07T14:47:11.212129Z

Oh, that makes sense!

roklenarcic 2024-12-07T14:47:42.529609Z

fairly easy to do since get-in 2-d vector on a coordinate that doesn’t exist will give you nil

2024-12-07T14:48:26.279629Z

Yes, already liked that in the XMAS trial

roklenarcic 2024-12-07T14:49:12.207679Z

As for movement, a lot of people tried writing code that always moves the guard by 1 position. That is a bitch to write, since you can get into a situation where guard has an obstacle ahead and to the right so you need to do 2 rotations to make one step (back the way you came).

roklenarcic 2024-12-07T14:49:43.409539Z

Instead I wrote code that either moves the guard 1 square OR rotates the guard’s direction once

roklenarcic 2024-12-07T14:50:16.309879Z

far easier to write and all the difference is that you can be at same position multiple consecutive steps while rotating each step

roklenarcic 2024-12-07T14:50:29.065059Z

which doesn’t affect solution

roklenarcic 2024-12-07T14:51:47.685619Z

Here’s my crap https://gist.github.com/RokLenarcic/87898a07717498f5bc86f3d6f96eca26

🙏 1
2024-12-07T14:53:25.694639Z

Yeah skimming the thread here I thought maybe my solution has the same problem, but I think it’s something else 🤔 Thanks for the solution, will check it out later! Groceries first, my one productive activity on this nice Saturday 😄

Ingy döt Net 2024-12-07T15:54:12.156899Z

Did anyone here get an answer that was too high? Any advice?

Aleks 2024-12-07T16:22:35.024119Z

It might be an off-by-one error.

Ingy döt Net 2024-12-07T16:36:18.539979Z

good idea, but nope 😕

roklenarcic 2024-12-07T16:37:13.043399Z

How do you detect a cycle?

Felipe 2024-12-07T16:45:06.856409Z

I think there might be an edge case in my input that's not there for other people. tried inputting the answer I got from some reddit solutions and I still get wrong answer. hmm

Felipe 2024-12-07T16:47:28.441609Z

> You could be placing an obstacle in the path of the patrol from a point you will never reach normally had that obstacle been there from the start oh wow, maybe that's it?

roklenarcic 2024-12-07T16:48:50.371229Z

No that’s nonsense

bhauman 2024-12-07T16:49:44.689099Z

nonsense eh?

😂 1
roklenarcic 2024-12-07T16:50:26.976359Z

Guard goes along a non-circular path. You can only interrupt that path by a single new obstacle. That’s it

bhauman 2024-12-07T16:50:55.387599Z

that note was from my optimizations not for an original impl 🙂

bhauman 2024-12-07T16:52:28.590129Z

as long as you are starting your detection from the starting point it the above note doesn’t apply

Felipe 2024-12-07T16:53:18.962849Z

that insight lowered my answer and it now matches the reddit output, but that's still wrong? 🤔

roklenarcic 2024-12-07T16:55:17.490249Z

It’s really not that complicated. Do part1. Now, for part 2, try placing an obstacle in each position from part 1 and run the guard from the start for each placement, check if he starts looping. That’s it. Count the loop runs.

Felipe 2024-12-07T16:56:22.983759Z

Felipe 2024-12-07T16:56:25.385379Z

yep, that's what I'm doing.

bhauman 2024-12-07T16:56:43.273219Z

not complicated but tempermental

roklenarcic 2024-12-07T16:58:23.389019Z

This is extremely complicated, you probably have a bug with detecting loops. Just keep a set of visited position+direction pairs.

roklenarcic 2024-12-07T17:03:14.336389Z

Having a result too high is likely if you detect loops by just looking for repeated position instead of repeated position + direction

Felipe 2024-12-07T17:06:27.313959Z

oh my god it was an off by one error

Felipe 2024-12-07T17:06:40.736699Z

was getting 1704 and 1703 worked

Ingy döt Net 2024-12-07T17:07:19.015429Z

lol

Ingy döt Net 2024-12-07T17:09:13.888319Z

> This is extremely complicated, you probably have a bug with detecting loops. Just keep a set of visited position+direction pairs. That's exactly what I do... > Having a result too high is likely if you detect loops by just looking for repeated position instead of repeated position + direction I had that for a minute but that caused the 10x10 example to produce 8 instead of 6 > oh my god it was an off by one error did you find the cause?

Ingy döt Net 2024-12-07T17:10:08.996139Z

I'm going to print loops and look for oddities

bhauman 2024-12-07T17:10:27.326669Z

@felipecortezfi so I read all the loop code for nothing?? 🙂

😆 1
bhauman 2024-12-07T17:12:19.143129Z

@felipecortezfi I think your error was you were adding the position and the direction to loops

bhauman 2024-12-07T17:12:37.871909Z

its each unique position that can cause a loop

bhauman 2024-12-07T17:12:49.083629Z

not position and direction

Felipe 2024-12-07T17:13:13.570199Z

hmm, but I do save the position that caused the loop, no the direction

bhauman 2024-12-07T17:13:28.660419Z

(swap! loops conj (mapv + position (direction->delta direction)))

bhauman 2024-12-07T17:13:42.206169Z

oh yep

bhauman 2024-12-07T17:13:44.344369Z

sorry

bhauman 2024-12-07T17:13:54.664619Z

got my hopes up

Ingy döt Net 2024-12-07T17:15:31.291169Z

It’s really not that complicated. Do part1. Now, for part 2, try placing an obstacle in each position from part 1 and run the guard from the start for each placement, check if he starts looping. That’s it. Count the loop runs.That's what I do. BTW my (too high) result is 2078. Did anyone who got it right get higher than that?

roklenarcic 2024-12-07T17:16:24.313729Z

No I get 1482

Felipe 2024-12-07T17:16:42.042759Z

@ingy you mean lower, right? you don’t want something that’s even farther away from the result :)

Felipe 2024-12-07T17:16:55.608389Z

ah, or you mean globally?

roklenarcic 2024-12-07T17:17:16.411439Z

It’s not position that you need to check for the loop, it’s position and direction @bhauman

Felipe 2024-12-07T17:17:45.832939Z

I did not find the cause. only thing I can think of is the initial position restriction, but I check for that

roklenarcic 2024-12-07T17:18:35.016549Z

Consider this:

....#....
.....#...
.........
.........
....^....
No loop but you’ll travel across same positions twice

roklenarcic 2024-12-07T17:18:51.079619Z

up then down

Ingy döt Net 2024-12-07T17:25:15.302569Z

> you mean lower, right? you don’t want something that’s even farther away from the result I meant is 2078 near the median? I made a change that lowered it to 2032. Might be off by one, but now I have to wait 5 minutes because it was my 4th time. > The new obstruction can't be placed at the guard's starting position Failure to honor that could cause off by one

👍 1
Felipe 2024-12-07T17:30:33.188339Z

yep, that was it. wtf

Felipe 2024-12-07T17:30:39.773459Z

(not= position initial-position) ;; nope (not= front initial-position) ;; yep!

👍 1
bhauman 2024-12-07T17:30:47.021499Z

@felipecortezfi So I’m running your code and it isn’t working for the test case, as it’s returning 5 instead of 6

🙈 1
Felipe 2024-12-07T17:32:06.606649Z

@bhauman it now works for the test case if you make the change I just said

bhauman 2024-12-07T17:32:30.818659Z

OK good!

Felipe 2024-12-07T17:33:51.460369Z

it is weird though. I thought you couldn't put the obstruction at her line of sight / immediately-in-front position, but you can't place the obstruction where she is

Ingy döt Net 2024-12-07T17:37:11.781589Z

I think I know what I'm doing wrong. I'm following my part1 path and testing by putting an obstacle in the next position. but I don't keep track of where I've already tried. So counting way too much.

Ingy döt Net 2024-12-07T17:37:34.200219Z

derp

bhauman 2024-12-07T17:38:28.400649Z

so I’m not seeing your code but I would put an obstacle in each unique position of the originial path and start from the beginning

bhauman 2024-12-07T17:38:42.918139Z

not in front

Ingy döt Net 2024-12-07T17:38:43.178189Z

yep

roklenarcic 2024-12-07T17:38:46.602509Z

You are adding obstacles as you go along?

bhauman 2024-12-07T17:41:23.444729Z

and when I say start from the beginning I mean start path tracing at the beginning

Ingy döt Net 2024-12-07T17:42:15.766879Z

um. yeah. I as I go along (the original path), (say I'm in position "pos") I put an obstacle in position "next" and then starting walking from position "pos" (immediately turning of course). Then I detect if I loop.

bhauman 2024-12-07T17:47:30.577309Z

that’s the hardest way to do it and it causes answers that are way too high

bhauman 2024-12-07T17:48:26.859429Z

you can get the correct answer by starting the guard sweep at start position with an empty visited set

bhauman 2024-12-07T17:50:05.764249Z

the problems come from 1. placing a obstacle that on a path for a second time

bhauman 2024-12-07T17:53:53.032549Z

bc now you are in a state that is not actually reachable, had the obstacle been on the path originally

roklenarcic 2024-12-07T17:54:47.948119Z

Right but if you take visited positions from part1 those would have to be deduplicated already

👍 1
bhauman 2024-12-07T17:54:57.721269Z

also you need to construct the correct visited set for loop detection

Ingy döt Net 2024-12-07T18:02:38.079069Z

Got it. 1812. Did exact same thing but didn't try same spot more than once.

🚀 2
Ingy döt Net 2024-12-07T18:06:57.322559Z

12secs 😕 but... it's day 7!

Ingy döt Net 2024-12-07T18:11:12.826949Z

#yamlscript Part 2

1
Gent Krasniqi 2024-12-07T21:26:11.109519Z

I noped out when reading part2 last night and went to sleep, now catching up. This was really hacky, I kept increasing the threshold to get the right answer on the real dataset 😄, as I'm just looking at consecutive already visited points as the test. (in the end that doesn't really slow it down anyway, it's around 8.7 seconds regardless how safe I play it there)

Sam Ferrell 2024-12-06T08:17:36.037189Z

Sam Ferrell 2024-12-06T08:17:49.714429Z

Supremely stuck on part 2, not sure why. Getting around 2,000 obstacles. Any hints? Edit: Solved!

Aleks 2024-12-06T08:20:57.026079Z

Nothing special today, as usual you might use pmap to boost your solution, my part 2 runs ~6 secs https://github.com/zelark/AoC/blob/master/src/zelark/aoc_2024/day_06.clj UPD: optimized my solution for part 2, now it takes less than a sec

Maravedis 2024-12-06T08:26:46.513539Z

@mail191 I think you're detecting loops as you're moving? Thing is, you could potentially let the loop "behind you", as in you are past the point when you would enter the loop. You need to place the obstacle THEN move the guard. I think. Your approach is hard to read for me.

Ben Sless 2024-12-06T08:56:44.324599Z

Don't have time for p2 yet, but enjoy my brutalist p1

Sam Ferrell 2024-12-06T09:25:48.835179Z

@malaingreclement Thanks for the help! I retooled my solution to filter all the visited nodes by nodes that would result in loops (like your part 2) and that did the trick... answer was about 50 off 😕 but everything takes about 4s

karlis 2024-12-06T09:39:36.367279Z

Bruteforcing my way through Day 6 https://github.com/skazhy/advent/blob/master/src/advent/2024/day6.clj

jramosg 2024-12-06T09:46:48.168689Z

35ms fot part 1 but 39 secs for part 2 😅 https://github.com/jramosg/advent-of-code/blob/master/src/advent_of_code/year_2024/day06.clj

(ns advent-of-code.year-2024.day06
  (:require
   [advent-of-code.util :as util]
   [clojure.set :as set]))

(def obstruction \#)

(def ->new-direction {[-1 0] [0 1]
                      [0 1] [1 0]
                      [1 0] [0 -1]
                      [0 -1] [-1 0]})

(defn- get-pos0 [input-coords]
  ((set/map-invert input-coords) \^))

(defn- input-by-coords []
  (reduce-kv
   (fn [acc row-index row]
     (reduce
      (fn [acc-map [col-index cell]]
        (assoc acc-map [row-index col-index] cell))
      acc
      (map-indexed vector row)))
   {} (util/read-input "2024" "06")))

(defn move-guard [pos0 input-coords]
  (loop [direction [-1 0]
         current-pos pos0
         visited {pos0 #{direction}}]
    (let [new-coords (mapv + current-pos direction)
          in-coord (input-coords new-coords)]
      (cond
        ;;
        (= in-coord obstruction)
        (recur (->new-direction direction)
               current-pos 
               visited)
        ;;
        (not in-coord) (keys visited)
        ;;
        (get-in visited [new-coords direction])
        ::looping
        ;;
        :else
        (recur direction
               new-coords
               (update visited new-coords (fnil conj #{}) direction))))))

(defn part1 []
  (let [input-coords (input-by-coords)
        pos0 (get-pos0 input-coords)]
    (count (move-guard pos0 input-coords))))

(defn part2 []
  (let [input-coords (input-by-coords)
        pos0 (get-pos0 input-coords)]
    (->> (move-guard pos0 input-coords)
         (filter
          (fn [coord]
            (and (not= coord pos0)
                 (= ::looping (move-guard pos0 (assoc input-coords coord obstruction))))))
         count)))

(comment
  (part1)
  ;; => 5162
  (time (part2))
  ;; => 1909
  )

exitsandman 2024-12-06T10:30:20.187059Z

exitsandman 2024-12-06T10:35:12.403069Z

just realized that my "optimization" in s2 doesn't happen at all lol, no wonder it took two minutes. E: and good thing it didn't, it was a bad idea anyway

misha 2024-12-06T11:18:38.608829Z

misha 2024-12-06T11:48:25.323089Z

Aleks 2024-12-06T12:08:48.341339Z

I added a few optimizations to my solution: ;; 16071.819368 msecs (my original solution without pmap) ;; 4646.135041 msecs (cut guard's path) ;; 1954.627387 msecs (take big steps) ;; 927.825388 msecs (with pmap) Need some time to clean it up and push

djanus 2024-12-06T12:12:58.829529Z

It's becoming an Advent of Brute Force for me this year 😄 https://codeberg.org/nathell/aoc2024/src/branch/main/src/aoc2024/day6.clj (I might revisit this later in the day... or not)

Aleks 2024-12-06T12:19:25.674769Z

Pushed the update

vncz 2024-12-06T13:37:16.520359Z

(ns day6
  (:require [clojure.string :as str]))

(defn indexed [items]
  (map-indexed vector items))

(def input
  (into {}
        (for [[y line] (indexed (str/split-lines (slurp "src/input/6.txt")))
              [x c]    (indexed line)]
          [[x y] c])))

(def next-dir
  {\^ [0 -1]
   \> [1 0]
   \< [-1 0]
   \v [0 1]})

(def rotate 
    {\^ \>
    \> \v
    \< \^
    \v \<})

; start dir [4 6]

(def sol1
  (loop [grid input
         [x y] [42 83]
         cnt 0]
    (let [guardian (grid [x y])
          [dx dy] (next-dir guardian)
          next-point [(+ x dx) (+ y dy)]
          next-slot (grid next-point -1)]
      (condp = next-slot
        -1  (inc cnt)
        \. (recur (assoc grid next-point guardian [x y] \X) next-point (inc cnt))
        \X (recur (assoc grid next-point guardian [x y] \X)  next-point cnt)
        \# (recur (assoc grid [x y] (rotate guardian)) [x y] cnt)))))

vncz 2024-12-06T13:38:21.283539Z

I am not too sure what is the best way to look for a place to put a new obstacle. Any tip, without me looking at other people's source code?

vncz 2024-12-06T13:38:58.540349Z

It seems like I could collect all the obstacles positions somehow and from there see if I can come up with a "square" of obstacles somehow

Maravedis 2024-12-06T13:49:42.305739Z

Even if you could, you'd have to then find out if the guard reaches your square, which is really hard imho.

vncz 2024-12-06T13:51:30.456409Z

So just brute force it and try with a wall on whatever place the guard walks in?

Maravedis 2024-12-06T13:55:01.653209Z

That seems to be the most common approach, yeah. Although I'm not saying yours cannot work, I'm just saying it doesn't sound easy.

Maravedis 2024-12-06T13:55:28.121199Z

Advent of Bruteforce is in full swing this year.

Aleks 2024-12-06T14:02:06.867639Z

@vincenz.chianese One of the optimizations I did is i cut the guard's path placing the guard in front of the obstacle, it helped a lot.

vncz 2024-12-06T14:39:50.295909Z

All right, thanks everybody. Brute force it is I guess

tschady 2024-12-06T14:41:50.617379Z

tschady 2024-12-06T14:48:51.194259Z

4s unoptimized. lots of duplicate steps on sep guard runs.

exitsandman 2024-12-06T14:50:35.670769Z

random insights that only occurred to me now: • new obstacles only matter when added on the original path of the guard (truly groundbreaking I know...) • we could compute a "minefield" of all possible loop states by placing the guard in each state right after a collision (there are four per obstacle) and tracing its path for the next four "bumps"; of course this needn't happen in an eager fashion. • Assuming that relatively few loop paths are invalidated when only a single obstacle is added, perhaps there are gains that could be made there.

misha 2024-12-06T15:19:57.673759Z

> next four "bumps" are you assuming loop is always rectangle? it is not

bhauman 2024-12-06T15:49:51.637539Z

Hmmmm part 2 is stumping me I’m doing straight forward loop detection and I tried 2 different implementations and get the same result. https://github.com/bhauman/adv2024/blob/main/src/adv2024/day06/sol.clj They keep saying my part 2 answer is too low. Anyone available for a sanity check here?

Ingy döt Net 2024-12-06T15:50:34.390479Z

#yamlscript Part 1:

vncz 2024-12-06T15:59:33.166199Z

My final solution for both

Maravedis 2024-12-06T16:02:09.259709Z

@bhauman I"m checking it out. Gives a too low answer for my input as well. Although I don't know why yet.

bhauman 2024-12-06T16:02:44.834589Z

Thanks, that’s super helpful, at least I know the code is wrong for sure

Maravedis 2024-12-06T16:04:12.982739Z

Something in your mover function, the fact that when you're in front of a crate, you don't keep [pos new-dir], but only [new-pos new-dir] kinds of tickles me the wrong way, but it shouldn't change anything.

bhauman 2024-12-06T16:04:43.369849Z

so part 1 works

bhauman 2024-12-06T16:05:08.353769Z

it would be hard for part 1 to work if the mover function didn’t work

Maravedis 2024-12-06T16:05:17.403649Z

I know.

bhauman 2024-12-06T16:05:50.741709Z

part 1 works for you as well right?

Maravedis 2024-12-06T16:06:12.932189Z

Yup.

Maravedis 2024-12-06T16:09:56.817799Z

Lmao.

Maravedis 2024-12-06T16:09:58.541529Z

I was right

bhauman 2024-12-06T16:10:05.369639Z

what!!

Maravedis 2024-12-06T16:10:30.317939Z

(let [new-dir (turn-right dir)]
          [new-p new-dir])

; Replace by 
[p (turn-right dir)]

; in mover function
EDIT: edited cuz im a moron.

👍 1
Maravedis 2024-12-06T16:10:56.906489Z

And it runs faster too.

Maravedis 2024-12-06T16:11:20.823859Z

I should listen when something tickles me the wrong way.

bhauman 2024-12-06T16:12:23.161109Z

I was so confused

Maravedis 2024-12-06T16:13:33.529479Z

Tbh, I'm not sure why... It just was the only difference I could spot between your code and everyone else's.

Maravedis 2024-12-06T16:13:41.589329Z

If you find out why I'd be delighted to know.

Maravedis 2024-12-06T16:14:14.409749Z

Because you should just be detecting loops one step later. I'm really confused too tbh x)

bhauman 2024-12-06T16:16:50.878859Z

I know why because I could easily step onto a wall and skip its detection

bhauman 2024-12-06T16:16:56.239759Z

ugh

bhauman 2024-12-06T16:17:12.713219Z

I have to just turn and not turn and move

bhauman 2024-12-06T16:19:30.295629Z

I think I’ve made this same mistake before on AOC

bhauman 2024-12-06T16:19:47.673289Z

don’t AOC when you’re under the weather

☝️ 1
Maravedis 2024-12-06T16:22:24.513569Z

Oh yeah.. ANything like this

...#.
....#
Would trip you up. Very surprised part 1 worked actually

Maravedis 2024-12-06T16:23:14.053779Z

I suppose the parts where it happened werent reached before you add the crate.

bhauman 2024-12-06T16:24:05.294909Z

yeah it makes sense that that would have to occur when you are adding crates and very easy for it not to be there in the original

bhauman 2024-12-06T16:25:18.124089Z

@malaingreclement thanks that saved me some cycles. My assumption that the move function worked really got me.

Maravedis 2024-12-06T16:26:35.939379Z

My pleasure 🙂

bhauman 2024-12-06T16:40:43.531359Z

well I did just think of an algorithmic optimization. Because we are only using on-path position-directions, you can move your start position to just before the obstacle, and you can initialize your seen with the path up to that point. Also pmap cut my execution time by 75%

genmeblog 2024-12-06T16:56:24.511219Z

pmap and brute force on originally visited gives around 6 seconds https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2024/day06.clj

👍 1
Maravedis 2024-12-06T17:33:17.138099Z

Got down to 2 seconds with very ugly code.

Maravedis 2024-12-06T17:38:08.988079Z

Optimized with @bhauman idea of placing the guard just before the obstacle and having the previous path in seen . Don't judge me on readability

Ben Sless 2024-12-06T17:40:03.281839Z

I'd appreciate some spoiler free pointers for part 2 My logic was writing the same traversal, but at each point along my path, check if getting blocked will make me close a loop. I recognize a closed loop by visiting the same location in the same direction.

Maravedis 2024-12-06T17:40:03.403849Z

Also I prefer clojure.core.reducer/fold to pmap , although I can't explain why. I remember reading somewhere it was better-suited to parallelization. Does anyone know if that claim holds any water?

bhauman 2024-12-06T17:40:41.888319Z

@ben.sless I’ll take a look

🙏 1
bhauman 2024-12-06T17:54:44.876699Z

@ben.sless it looks good

bhauman 2024-12-06T17:55:42.991839Z

@ben.sless did you reset your repl bc I got symbol reference error for out-of-bounds?

bhauman 2024-12-06T17:58:13.178549Z

actually all kinds of symbol references are missing mainly having to do with '

bhauman 2024-12-06T18:01:38.034379Z

actually check that out and then repost the code and I’ll run it against my data

Ben Sless 2024-12-06T18:04:11.159579Z

@bhauman out-of-bounds'? and out-of-bounds? ended up having the same impl

Ben Sless 2024-12-06T18:04:53.471939Z

same for blocked?

Maravedis 2024-12-06T18:08:36.890599Z

you omitted visit and find-start.

Ben Sless 2024-12-06T18:11:32.931019Z

(defn visit
  [visited x y]
  (let [v (get visited x #{})]
    (assoc visited x (conj v y))))
(defn find-start
  [lines]
  (->> lines
       (map-indexed (fn [i ^String s]
                      (let [j (.indexOf s "^")]
                        (when (nat-int? j)
                          [i j]))))
       (some identity)))

Sam Ferrell 2024-12-06T18:12:05.805829Z

Here's a thought... Detecting loops by placing obstacles while also figuring out where the patrol goes doesn't work

Ben Sless 2024-12-06T18:12:18.140009Z

Why?

Ben Sless 2024-12-06T18:13:15.774099Z

At each point along the patrol's path, I can ask the question - will placing a block in front of it induce a loop

Sam Ferrell 2024-12-06T18:13:57.810609Z

You could be placing an obstacle in the path of the patrol from a point you will never reach normally had that obstacle been there from the start

👀 1
Ben Sless 2024-12-06T18:14:19.255059Z

With added visualization, my solution looks like it works

Ben Sless 2024-12-06T18:15:52.158649Z

I see, so I would in theory need to check I'm not placing the obstacle on a place the patrol had gone through

Ben Sless 2024-12-06T18:15:55.662889Z

is that sufficient?

Sam Ferrell 2024-12-06T18:17:14.626349Z

Maybe... 🤣 All I know is that I tried solving it the same way the first time and it was broken

Ben Sless 2024-12-06T18:17:37.992709Z

gotcha 😉

Ben Sless 2024-12-06T18:20:57.391549Z

Okay, adding the check

can-place? (not (-> visited (get xb) (get yb)))
looping? (and can-place? (will-close-loop? x y dx dy visited lines render))
Makes my result too low, now

Sam Ferrell 2024-12-06T18:26:41.661289Z

What worked for me was collecting the normal patrol first and then filtering the visited set by those that cause a loop were they turned into obstacles, restarting the patrol from the start each time

Apple 2024-12-06T18:35:09.165559Z

#... ...# ^... ..#. Does this case take 0 for part 2?

Ben Sless 2024-12-06T18:42:29.323659Z

@zengxh is this a general question or addressed to me?

Apple 2024-12-06T18:45:10.162339Z

general question

Maravedis 2024-12-06T18:48:22.486339Z

Checked with my code and it would seem that yes.

Apple 2024-12-06T18:49:28.237589Z

Thx

2024-12-06T21:05:38.178169Z

My solution: https://github.com/ChrisBlom/advent-of-code/blob/master/src/adventofcode/2024/day06.clj#L85-L108 Initially with a naive approach (count all positions on the walked path were placing # results in a loop) this ran in 17 seconds. Then i figured i could reuse the state from the initial walk to speed it up to 3.5s Forking state is where immutability and structural sharing shines!

roklenarcic 2024-12-06T21:42:59.712329Z

Man, my friend did it in Rust and it’s about a 100 times faster. The most disappointing thing is parallelization, it only makes it 2-3 times as fast in Clojure, but in Rust it makes it 10 times as fast. When doing these AoC problems I can never seem to squeeze more than 2-3x speedup by doing things in parallel.

2024-12-06T22:11:15.545359Z

Rust is really fast to begin with. I remember seeing 100x speedups when using opt-level = 3`` when i used it for AoC. I found rust a great language for AoC type problems, but i recall parsing the inputs with it was a bit tedious

2024-12-06T23:13:08.173069Z

I tried to do part 2 two ways, a brute force and a smarter approach. Both work for the test input, both fail for the real input 😞

vncz 2024-12-06T23:26:38.477069Z

Story of our lives

Ingy döt Net 2024-12-06T23:27:09.133429Z

Still trying 😕

2024-12-07T00:40:22.137029Z

Given this test map, would you expect it to find a potential obstacle at [1 5]

0123456789
0 ....#.....
1 ..........
2 ..........
3 .#........
4 ........#.
5 ..........
6 ....^.....
7 #.........
8 ....#..#..
9 ..........
The guard walks up, hits the obstacle at [0 4], then the new obstacle at [1 5] and walks right back down again and loops at the bottom:
0123456789
0 ....#.....
1 ....│#....
2 ....│.....
3 .#..│.....
4 .┌──┼──┐#.
5 .│..│..│..
6 .│..^..│..
7 #└──┘──┘..
8 ....#..#..
9 ..........
?

2024-12-07T00:51:09.765599Z

Finally, yep that was my issue above. I wasn't handling that case. I was rotating right and advancing in one step, so when I was placing potential obstacles in the example above I wouldn't consider [1 5], as when I was on [1 4] I was moving north, never east...

Apple 2024-12-07T00:58:21.602239Z

[1 5] is valid

👍 1
bhauman 2024-12-07T02:12:05.143179Z

@qmstuart I had the same problem

bhauman 2024-12-07T02:44:10.913819Z

adding the algorithmic optimization of starting from just before the introduced obstacle and using the path up to that point as the seen, I got part 2 down to 2.7 seconds on my 10yr old MBP, it’s tricky though, you shouldn’t try evaluate the same position again later in the path as an obstacle https://github.com/bhauman/adv2024/blob/main/src/adv2024/day06/sol.clj

2024-12-06T05:57:41.669039Z

https://gitlab.com/maximoburrito/advent2024/-/blob/main/src/day06/main.clj I misunderstood part1 and wrote the cycle detection first assuming that was required. However, I misunderstood that the guard could leave the map and just had the guard turn right at the edge. I spent about 10-15 minutes debugging that. So part2 was pretty trivial after that, though on the first pass I checked every single point for a cycle. After seeing that was slow, I only checked points that were visited by the guard in part1

👍 3
erdos 2024-12-06T06:07:31.726449Z

For me, cycle detection was just checking if path is long enough. After a given length, it either goes outside of the area or is in a loop. Part 2 is quite slow though :F (30s) https://github.com/erdos/advent-of-code/blob/master/2024/day06.clj

👏 1
👏🏻 1
Zach 2024-12-06T06:34:00.879779Z

I used an infinite list for directions. Just look at the first one to get the current direction and drop it when you want the next 😄

Maravedis 2024-12-06T06:39:19.780199Z

Damn my part2 is so slow x) 24s. Imma try to clean this up.

Andrew Byala 2024-12-06T07:10:37.375469Z

All done, and I got my running time for part 2 down from a minute to 13 seconds, which is good enough for me! • Blog: https://github.com/abyala/advent-2024-clojure/blob/main/docs/day06.md • Source: https://github.com/abyala/advent-2024-clojure/blob/main/src/advent_2024_clojure/day06.clj

👍🏻 1
Maravedis 2024-12-06T07:38:22.344699Z

Got it down to 8 seconds with reducers. Not my cleanest code ever.

hansbugge 2024-12-06T07:50:17.674519Z

Around 6 seconds for part 2: https://github.com/hansbugge/aoc/blob/main/src/hansbugge/year2024/day6.clj Edit: Around 3.6s with some parallelisation.

ghaskins 2024-12-23T16:49:59.155209Z

https://github.com/ghaskins/adventofcode/blob/main/src/aoc/2024/day6.clj

(time (part1))
"Elapsed time: 4.444375 msecs"
=> 4982
(time (part2))
"Elapsed time: 446.586625 msecs"
=> 1663