adventofcode

Samuel Ludwig 2023-12-05T16:20:42.145669Z

for those wondering if Hanukkah of Data will make a return this year, I have reason to believe it will, I see saulpw mentioning it in his Discord server

Chase 2023-12-08T03:06:17.941989Z

Thanks for the heads up on this Hanukkah of Data challenge. This was my first time hearing about it and it did start today. It was quite fun and definitely has an AOC vibe https://hanukkah.bluebird.sh/5784/

👍 1
❤️ 1
Chase 2023-12-08T03:07:12.320079Z

the animated ascii text art is quite nice too

2023-12-05T05:46:49.062879Z

Having just read day 5, I must be getting a lot dumber. And I feel bad because I persuaded a whole load of people to try it for the first time this year and I assured them that, even if it got difficult later on, the first week would be relatively doable.

jake 2023-12-05T09:48:54.217489Z

Haha, same here! Day 1 was way harder than I was expecting after having told my friend "don't worry, it will be trivial".

2023-12-05T09:51:40.364519Z

Well I’ve managed part 1 (in Kotlin…) and I think I know how to do part 2 now… but it’s still my view that it is still the first week and I want problems that are easy enough for me to do before work!

oyakushev 2023-12-05T11:28:17.802269Z

2023-12-05T13:22:21.656329Z

Part 1 is actually went faster for me than Day 2 this year lol

2023-12-05T13:22:26.424989Z

Part 2 is evil

Alvydas Vitkauskas 2023-12-05T15:28:52.040769Z

What I like about this kind of puzzles, that they show you how much (in millions and billions) the right thinking and the right algorithm can be better/quicker than just “let’s do it” brute force approach. I always wonder how much we loose in our business code efficiency (and server costs) just because…

hlship 2023-12-06T00:11:08.747569Z

I think up until part 5b it's been pretty easy, except for that one gotcha early one with the number names.

hlship 2023-12-06T00:11:41.560929Z

But 5b seems to require processing billions of values.

hlship 2023-12-06T00:11:45.600039Z

Unless I'm missing something.

hlship 2023-12-06T00:12:59.626849Z

Oh, maybe don't treat the range as a range per-se, but break it down into sub-ranges that match the first formula's ranges.

hlship 2023-12-06T00:19:54.638909Z

So transform the initial seed ranges into a new set of ranges for the first map :seed-to-soil. Each input seed range will convert into 1 or more output seed ranges. The perform the same xform using the :soil-to-fertilizer ranges, all the way down. So basically, you do a lot fewer comparisons.

👍 1
hlship 2023-12-06T00:45:15.549519Z

I think I'm on to something.

dpsutton 2023-12-05T05:53:21.377479Z

yikes. just read it. that's too close to business logic and just tedious. I don't feel bad skipping

2023-12-05T07:00:52.246699Z

Day 5 - Solutions

2023-12-06T13:24:17.060569Z

But yeah, starting at the end and working with ranges until you get to a seed number is basically the approach.

2023-12-06T13:25:25.498139Z

Only fun part of my solutions is that I successfully used tree-seq (maybe for the first time ever).

2023-12-06T13:25:50.018659Z

And it still runs in .5ms after warmup

oyakushev 2023-12-06T13:26:42.760189Z

To me, walking from the beginning was easier.

oyakushev 2023-12-06T13:27:54.393319Z

Actually, I haven't understood yet how working in reverse works:)

2023-12-06T13:27:58.325799Z

Isn't the only way to do that to get lucky?

2023-12-06T13:28:27.022449Z

You can start from anywhere in the beginning and end up anywhere at the end. There's no uniform distribution so even binary searching is out.

2023-12-06T13:28:52.261999Z

Or you just plan to exhaustively search the entire tree?

oyakushev 2023-12-06T13:29:14.073509Z

Don't need any search if you recompute destination ranges step by step.

2023-12-06T13:29:32.350899Z

If that's the case, backwards is the literal same as forwards except you've started in a better spot.

oyakushev 2023-12-06T13:29:43.356399Z

You start with ranges of seed numbers, and given a mapping of seed->soil, you compute soil ranges, and so on

2023-12-06T13:30:13.818009Z

Gotcha. Yeah then backwards is the same except you start with the most likely range (lowest range on the last step)

👍 1
genmeblog 2023-12-06T16:33:14.670839Z

Eventually got it working (part-2). Tricky play with intersection of ranges. Probably can be done simpler, but... https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2023/day05.clj edit: refactored

Ivana 2023-12-06T18:22:45.598089Z

(defn split-interval [[b e] m]
  (let [ps (->> m
                (mapcat (fn [[_ s l]] [s (+ s l)]))
                (filter #(and (< b %) (<= % e)))
                sort
                dedupe
                (mapcat (fn [i] [(- i 1) i])))]
    (partition-all 2 (concat (cons b ps) [e]))))

(defn m-get [m v]
  (if-let [[d s _] (->> m (filter (fn [[_ s l]] (<= s v (+ s l -1)))) first)]
    (+ d (- v s))
    v))

(defn process-intervals [intervals m]
  (let [splitted (reduce (fn [acc iv] (into acc (split-interval iv m))) [] intervals)]
    (map (fn [iv] (map #(m-get m %) iv)) splitted)))

(let [[seeds & path] (->> (str/split input #"\n\n")
                          (map str/split-lines))
      to-vec (fn [s] (read-string (str "[" s "]")))
      seeds (-> seeds first (str/split #"\:" 2) second to-vec)
      path (->> path (map #(->> % rest (mapv to-vec))))
      go (fn [intervals] (reduce process-intervals intervals path))]
  (->> seeds
       (partition-all 2)
       (map (fn [[b l]] [b (+ b l -1)]))
       go
       (map first)
       (apply min)))
5.2: 18 msec

tschady 2023-12-09T16:22:38.987719Z

cleaned it up slightly: https://github.com/tschady/advent-of-code/blob/main/src/aoc/2023/d05.clj

Max 2023-12-12T20:28:06.261129Z

I ended up with two different solutions: I successfully solved pt1 https://github.com/maxrothman/advent-of-code/blob/main/2023/clj2023/src/clj2023/day5.clj#L185 but it was too slow to actually run on the real data. I also did https://github.com/maxrothman/advent-of-code/blob/main/2023/clj2023/src/clj2023/day5.clj#L216 and 2 with interval sets/maps, and my solution for pt2 ended up being a https://github.com/maxrothman/advent-of-code/blob/main/2023/clj2023/src/clj2023/day5.clj#L335

Jakob Durstberger 2023-12-05T11:28:54.416199Z

I don't think my part-2 solution is performing too well..... it has been running for nearly an hour now and still hasn't given me the answer 😄

Arno Jacobs 2023-12-05T11:56:58.871199Z

@jakob.durstberger If it's running for an hour then it will probably run for many more hours. Need a hint?

Jakob Durstberger 2023-12-05T12:21:36.929029Z

I have given up on my current solution. I'll have to think a bit more 😕 No hints yet 😄

Arno Jacobs 2023-12-05T12:27:17.265249Z

@jakob.durstberger 🙂 I'm learning Clojure and (or but) first building my code in Haskell or Swift. The compiled version of the not-so-intelligent brute force solution needed 8+ minutes. (Now working on the efficient version. 😉 )

Jakob Durstberger 2023-12-05T12:27:45.498539Z

Maybe I did something horribly wrong 😅

🤔 1
Jakob Durstberger 2023-12-05T12:43:56.532109Z

Just for my own sanity. With the input on part 2 you end up with billions of seeds, right?

✅ 1
oyakushev 2023-12-05T14:05:55.794639Z

Non-bruteforce solution (similar to @norman's): https://gist.github.com/alexander-yakushev/7f10ec2b18b504533447af0438179507

tschady 2023-12-05T14:05:56.325779Z

unless you go backwards

tschady 2023-12-05T14:06:16.148379Z

my input has a 0 in the last part, can start there

✅ 1
2023-12-05T14:14:39.201739Z

I started with 2.2 billion seeds in 20 groups and ended with 2.2 billion in 92 groups.

Arno Jacobs 2023-12-05T14:18:15.138919Z

@jakob.durstberger @tws And going backwards I didn't need any code.

1
wevrem 2023-12-05T14:26:13.553379Z

time puzzle 1: 4.7ms time puzzle 2: 16.9ms

karlis 2023-12-05T15:43:05.126079Z

Took a while to write down my pen+paper solution for part 2: https://github.com/skazhy/advent/blob/master/src/advent/2023/day5.clj

2023-12-05T20:11:04.615139Z

I won't post my solution here because it's not Clojure (I used - gasp - Kotlin to write it) but I did manage to implement the "clever" solution to part 2 in the end and it runs in 100ms or so. I'm sure it could be made to run faster as well.

Marcel Krcah 2023-12-05T21:10:32.234259Z

new to clojure, I wanted to learn and explore loop-recur; so here's part1 only with some cumbersome but working loop logic https://github.com/mkrcah/advent-of-code/blob/main/src/day_05.clj

Arnaud Geiser 2023-12-05T23:07:04.602179Z

it took me a while, but happy with the solution : https://github.com/arnaudgeiser/advent-of-code/blob/master/2023/clojure/src/advent_of_code/day5.clj

Jörgen Lundberg 2023-12-05T23:20:57.214279Z

Part 2 seemed so simple... 😄 Does the algorithm to solve day 2 have a name?

tschady 2023-12-06T00:21:09.754209Z

My code is shit, so no post for me, but this was fun to use meta data instead of keeping separate collections:

(defn chranges
  [[x y d :as r] [a b :as orig] ]
  (cond
    (:altered (meta orig)) (list orig)            ;; already altered
    (or (< b x) (> a y)) (list orig)              ;; totally outside
    (< a x) (conj (chranges r [x b]) [a (dec x)]) ;; outside L
    (> b y) (conj (chranges r [a y]) [(inc y) b]) ;; outside R
    :else ;; inside, map it and set altered flag
    (list (with-meta [(+ d (- a x)) (+ d (- b x))] {:altered true})))) 

Felipe 2023-12-06T01:53:29.000809Z

solved mine through dataviz. decimated the input ranges, searched for the part that likely had the global minimum, zoomed in and limited the range checking to that region. it worked!

Felipe 2023-12-06T01:53:53.263589Z

Felipe 2023-12-06T01:55:37.008509Z

>

;; this is a bit opaque, but the basic idea is that for each input range,
>   ;; compute the all the ranges it could be after going through the each map
>   ;; the lowest starting point after the final map is the winner...
can't believe that's the way to do it. I thought about that but it just seemed to involved, especially for day 5

Aleks 2023-12-28T16:27:27.223519Z

Rewrote the solution with my namespace to work with ranges. Now I’m satisfied with it completely https://github.com/zelark/AoC/blob/master/src/zelark/aoc_2023/day_05.clj

donaldball 2023-12-07T18:29:41.751189Z

My evaluator for part 2 was irksome to handle all the corners but eventually: https://github.com/dball/aoc2023/blob/main/day5/problem2.bb

alpox 2023-12-08T15:07:48.305269Z

What a rollercoaster. I first thought I wouldn’t manage to make part 2 any performant (< 5 minutes or so). Now I made it run in 10ms 😍

alpox 2023-12-08T15:15:42.187079Z

Sometimes all it takes is the right idea/approach

2023-12-05T07:05:37.704329Z

https://gitlab.com/maximoburrito/advent2023/-/blob/main/src/day05/main.clj I think the solution is pretty solid, but the poor and inconsistent naming and structure makes it a bit opaque. Write once ... read never....

wevrem 2023-12-05T07:11:03.296799Z

I have some repeat logic preparing the input for puzzle 1 and puzzle 2, I usually refactor that sort of thing into a single function, but I’m too tired, I’ll do it tomorrow morning.

Ellis 2023-12-05T07:49:05.148749Z

FYI https://www.reddit.com/r/adventofcode/comments/18an94z/psa_dont_share_your_inputs_even_in_your_github/ Mitigation: git filter-branch --tree-filter 'rm -f resources/inputs/*/day*.txt' HEAD(adjust regex as needed) to remove all the files from all commits If you need them in a build process or automation • Create a private repo with them all in • Add it as a submodule back in the same place • Generate an SSH keypair ssh-keygen -t rsa -b 4096 -C "Fake Deployment Key" -f 'gha_deploy_key' -N '' • Put the contents of gha_deploy_key.pub as a deploy key on the private repo • Put the contents of gha_deploy_key as a secret called SSH_KEY on the aoc repo • Adjust the checkout actions like so https://github.com/elken/aoc/commit/385c29b99ed5a6e567abaf282427bd7e6165a23e

🤯 2
1
genmeblog 2023-12-06T14:02:55.140709Z

I decided to keep inputs in encrypted h2 KV store (JVM). If anyone is interested getter and setter functions are https://github.com/genmeblog/advent-of-code/blob/master/src/common.clj#L8-L33.

maleghast 2023-12-05T08:29:30.591949Z

I had no idea, I always assumed that the input data is / was the same for all participants.

Ellis 2023-12-05T08:30:40.118859Z

Nah there's a (generous) fixed amount, if it was the same for everyone you could just copy the answers 😄

maleghast 2023-12-05T08:32:24.442859Z

Right, but I am (despite previously expressed frustrations) much more interested in solving the puzzles than having all 50 stars or makling the leaderboard, so honestly that never occurred to me until you said it just now...

maleghast 2023-12-05T08:32:53.539129Z

Also, what incentive would anyone have in sharing the answers if there was only 1 canonical input?

Ellis 2023-12-05T08:34:13.017059Z

Some people take gaming the leaderboard very seriously 😄 There's a good amount of people using chatgpt to get super high. > Also, what incentive would anyone have in sharing the answers if there was only 1 canonical input? Same reason anyone lets anyone else cheat or copy off them 😄

maleghast 2023-12-05T08:58:36.965039Z

Yeah, I am sorry it defeats me - there is no up-side to wining by cheating; you always have to live with yoursel fand you know you cheated so it accomplishes nothing.

maleghast 2023-12-05T08:59:12.578259Z

Also, I really hate the idea of people using ChatGPT / Bard to win this - makes a mockery of the effort the organiser puts into it.

carnundotcom 2023-12-05T09:50:16.377949Z

Huh, I also had no idea!

thom 2023-12-05T11:37:19.433799Z

This just appears to be them saying please, is there any legal force behind it? It’s a very silly thing to ask and I’m not going to go and expunge several years of data (which also makes the repos less useful to me and anyone that stumbles on them). Can I feel okay karmically I bought a mug one year? :P

Ellis 2023-12-05T11:38:52.194739Z

Some legal, very little. It's more of a gentlemanly thing to do, because you could technically get the same input as someone else and steal the answers to cheat (yes, there are other ways to cheat)

pez 2023-12-05T11:39:47.856489Z

It has never occurred to me to store my input data locally in a file.

pez 2023-12-05T11:41:34.128219Z

I have this:

(ns pez.aoc-2023.util
  (:require [clj-http.client :as client]
            [clojure.edn :as edn]
            [clojure.string :as string]))

(defn- fetch-input' [day]
  (try
    (let [cookie (slurp ".aoc-session")]
      (:body (client/get
              (str "" day "/input")
              {:cookies {"session" {:value cookie}}})))
    (catch Exception e
      (println "Ho, ho, ho! Did you forget to populate `.aoc-session` with your AOC session cookie?")
      (throw e))))

(def fetch-input
  (memoize fetch-input'))

(comment
  (def day 6)
  (map edn/read-string (string/split-lines "1,2\n2")))

(defn lines [day]
  (-> (fetch-input day)
      (string/split-lines)))

(defn values [day]
  (map edn/read-string
       (lines day)))

pez 2023-12-05T11:41:56.526479Z

The cookie lives for very long.

Ellis 2023-12-05T11:44:03.630789Z

Nice! Iif you're doing anything like that it's also nice to add a user-agent https://www.reddit.com/r/adventofcode/comments/z9dhtd/please_include_your_contact_info_in_the_useragent/

pez 2023-12-05T11:47:36.644429Z

Ah, will add.

✅ 1
Ellis 2023-12-05T11:48:59.354219Z

Not a major deal, but in the future he might add in some user-agent filtering to block automated requests 😄

thom 2023-12-05T11:50:41.034909Z

I’ve always just written my final answers as tests so I can experiment with faster implementations, and I like the builds being reproducible. Going and doing all the auth rigmarole seems a faff and will break at some point. I dunno, I politely decline to stop storing the inputs. I will go buy a T-shirt to assuage my guilt.

pez 2023-12-05T11:52:19.701729Z

Updated fetch function:

(defn- fetch-input' [day]
  (try
    (let [cookie (slurp ".aoc-session")]
      (:body (client/get
              (str "" day "/input")
              {:cookies {"session" {:value cookie}}
               :headers {"User-Agent" "PEZ's AOC dabblings, by  pez@pezius.con"}})))
    (catch Exception e
      (println "Ho, ho, ho! Did you forget to populate `.aoc-session` with your AOC session cookie?")
      (throw e))))

💯 1
Ellis 2023-12-05T11:52:37.137869Z

Yeah I write mine in clerk notebooks that get compiled to a static site so I had to add in the keys step, but honestly it's a 10 second job. No major deal, he's not gonna send the lawyers after us 😄

maleghast 2023-12-05T12:27:37.875569Z

I just use a private Github Repo - I make my solutions public via Gist WITHOUT the inputs.

jkxyz 2023-12-05T13:50:49.518359Z

The benefits of including the inputs in my repo seem to outweigh the benefits of protecting the maybe non-existent copyright of some randomly-generated numbers. Since it's not harmful to share them, I never assumed it would be a problem

pez 2023-12-05T13:53:27.709389Z

The creator of AOC thinks that if enough inputs are sourced, someone else can put up a copy of AOC, and that worries him to no end. Enough reason for me to not contribute to input data being made available.

2023-12-05T14:08:24.248129Z

I'm sympathetic, but I don't think it's reasonable to ask participants to leave a critical piece of data out of their repositories. I no longer add the puzzle text to my repo, for reasons of copyright. I suppose at some point I might try one of the solutions here, but it seems like a lot of extra work for something that both actively makes my aoc experience worse and that I don't believe provides any actual benefit to aoc.

jkxyz 2023-12-05T14:17:57.712559Z

It seems like Eric (the creator) tweeted a while ago that it's "probably fine": https://nitter.net/ericwastl/status/1465805354214830081 Doesn't seem like a strong condemnation. So I will probably just keep the inputs alongside my code. I also can't understand the reasoning that it makes it that much easier to clone the site or why anyone would want to do that. It would be nice to be able to clone the repo in 5 years and be able to run the code on something that explains why I went to all the effort to avoid those heap space errors

pez 2023-12-05T14:23:58.135569Z

“Probably fine” was not about the inputs, but about answer.

jkxyz 2023-12-05T14:24:40.827679Z

You're right, I misread the sentence

pez 2023-12-05T14:26:52.058399Z

TIL about nitter. Very nice!