(Itโs technically a solution, but I doubt most can read awk.)
I cannot read and understand it
You want me to explain them?
day-2 is pretty straightforward
you mean the awk syntax. No need to
Too late
# For lines that start with "u", subtract the second token (i.e. the number)
# from variable "d".
/^u/ {d-=$2}
# For lines that start with "d", add the second token (i.e. the number)
# to variable "d".
/^d/ {d+=$2}
# For lines that start with "f", add the second token (i.e. the number)
# to variable "h".
/^f/ {h+=$2}
# At the end, print the product of "d" and "h"
END {print d*h}๐ข again too late
its like someone saw regex and thought, that should be an entire programming language in of itself.
I can't tell yet if I love it or hate it
Oh awk is actually awesome.
I use it less than I used to, but you can really do a lot of work w/ it if you want.
Wellโฆ circumstantially.
People at my work when they saw some CLojure were like "NOPE!, NOT HAPPENING"
I can't imagine if I showed something I'd written in AWK or APL
Hell, they even said no chance to F#
also I also not. Can read clojure a little bit and some ruby
I've basically realised they aren't willing to entertain trying to learn something unless the syntax basically looks like C
Wild to me how close-minded some people are.
Like, if I see something I donโt like, I just say, โYeah I donโt really like that or want to spend my time on that.โ But to respond, โNOOO. THATโS TERRIBLE. ARE YOU KIDDING?โ is nuts.
im afraid a lot of people are closed minded. Even if I look at the dicussion take a vaccin or not. Looks like there are 2 sides and both said there are right and will not listen to the other side
Yeah just a general lacking of curiosity/willingness to be ignorant.
Willingness to be ignorant is actually a sort of superpower imo.
or believing a source on facebook more then a expert
To be fair, they do seem to be happy to hack away on just completely awful code, mainly because I don't think they know any better.
See. The real problem is that usually when people are โjust hacking away on completely awful codeโ very little (or nothing) is actually getting done.
like a program we had internally that downloaded a zip file, and extracted it to disc and ran an exse in the folder was 1000+ lines of code.
WAUW
1000 lines???
yes, thats not a typo, it was over 1000 lines of code
idk, Iโll give a benefit of doubt
things that actually run forever are often more complicated than one might assume
error checking/recovery can occupy a lot of space
that is right
I think you win. ๐
@tws How does this work? https://github.com/tschady/advent-of-code/blob/8bc31afea74cfd522ac3c0bcf79321f059ca9352/src/aoc/2021/d01.clj#L9-L10
Youโre supposed to sum the partition. Youโve clearly seen some math trick that I donโt see.
if you have
A B C D E F
and you partition it by 3 and a step of 1 you get
(A B C) (B C D) (C D E) etc
so only 1 is actually different
so you can jsut take diff of 1st item and 3rd item
i'm guessing thats what his offset of dropping 3 is doing ?
The picture in the problem showed me. The B and C lined up, don't need to add them.
clever
clever
I like your style.
very clever :)
thanks2
yeah, math!
this is how I build my empire
sick
@borkdude never fails
parse-long is getting so much usage already. You can tell who saw the 1.11.0-alpha3 update post and who didn't. Haha
I am waiting for usage of clojure.java.math. I've just grepped my last year solution and there are only 3 cases of Math
I did not see that post. Is there a important change then ?
Here is list of changes https://clojure.org/releases/devchangelog
And here is a highlights of changes https://clojure.org/news/2021/11/24/deref
aha, that is why that post. parse-long is new ๐
i take my AOC way too seriously to use anything alpha.
I added the new parse-long, parse-boolean, etc functions from clojure 1.11 in #babashka 0.6.8 in case anyone wants to play with that for AoC :)
hehe
For today's solution it would have been nice if parse-long supported the radix argument
(cc @alexmiller)
I just used -I and let bb to the parsing ๐
haha awesome!
https://gist.github.com/ordnungswidrig/21224314590b871456cd4ccb2633ca8e
Do you think we could ask a parse-binary in the next Clojure release?
.. kidding
Interesting observation that doesn't mean anything (though there's probably some small degree of correlation with something). A quick scan down the list of current members of the Clojurians private leaderboard (code in this channel's description if you've not joined) shows that there are a fair number of supporters of AoC, all in the top third.
thanks for the reminder!
Certainly not my intent, but ๐
this year I'll do these about 12 hours after the puzzles get unveiled, since I'm doing them with a friend in the EST timezone and there's less of a chance that the problems will bug me into work hours ๐
๐งต Day 2 answers thread: post your answers here
@tws thanks! Iโm interspersing the code with markdown line-comments like ;; # Header, like one does with [Clerk](https://github.com/nextjournal/clerk), and then I have a little [script](https://github.com/samharad/samharad.github.io/blob/master/src/script/aoc.clj) for transforming the namespace into a markdown file. Then [Jekyll](https://jekyllrb.com/) takes it from there.
My first implementation was similar to alekszelark, this one is already refactored https://github.com/nbardiuk/adventofcode/blob/master/2021/src/day02.clj
I also went with a vector instead of a map because I think the argument destructuring makes it quite clear anyway
(defn answer [[distance depth]]
(* distance depth))
(answer
(reduce
(fn [[distance depth] [direction step]]
(case direction
:forward [(+ distance step) depth]
:down [distance (+ depth step)]
:up [distance (- depth step)]))
[0 0]
input))
(answer
(reduce
(fn [[distance depth aim] [direction step]]
(case direction
:forward [(+ distance step) (+ depth (* aim step)) aim]
:down [distance depth (+ aim step)]
:up [distance depth (- aim step)]))
[0 0 0]
input))part-2 aim is identical to part-1 depth, so the same reduction works for both
(defn parse [s]
(->> s (re-seq #"\w+") (map read-string) (partition 2)))
;; This covers parts 1 and 2: for part-1 treat aim as depth and ignore dep
(defn dive [commands]
(reduce (fn [[hor aim dep] [op x]]
(case op
forward [(+ hor x) aim (+ (* aim x) dep)]
down [hor (+ aim x) dep]
up [hor (- aim x) dep]))
[0 0 0]
commands))
(defn part-1 []
(let [[hor dep _] (->> "input/2021/02" slurp parse dive)]
(* hor dep)))
(defn part-2 []
(let [[hor _ dep] (->> "input/2021/02" slurp parse dive)]
(* hor dep)))(defn parse-input [input]
(map (fn [line]
(let [[direction amount] (string/split line #" ")]
[(keyword direction)
(Integer/parseInt amount)]))
(string/split-lines input)))
(def input (parse-input (slurp "aoc-day-2.txt")))
(defn part-one [commands]
(loop [commands commands
horizontal-position 0
vertical-position 0]
(if-let [[direction amount] (first commands)]
(case direction
:forward (recur (rest commands)
(+ horizontal-position amount)
vertical-position)
:up (recur (rest commands)
horizontal-position
(- vertical-position amount))
:down (recur (rest commands)
horizontal-position
(+ vertical-position amount)))
(* horizontal-position vertical-position))))
(defn part-two [commands]
(loop [commands commands
aim 0
horizontal-position 0
depth 0]
(if-let [[direction amount] (first commands)]
(case direction
:forward (recur (rest commands)
aim
(+ horizontal-position amount)
(+ depth (* amount aim)))
:up (recur (rest commands)
(- aim amount)
horizontal-position
depth)
:down (recur (rest commands)
(+ aim amount)
horizontal-position
depth))
(* horizontal-position depth))))https://gist.github.com/borkdude/b5cf0e9d2d8ab7c678d88e27a3357b33#file-aoc21_02-clj
(defn parser [l]
(let [[dir v] (str/split l #" ")]
{:dir dir
:v (Integer/parseInt v)}))
; part 1
(->> (f/read-all-lines-and-parse puzzle-input parser)
(reduce (fn [[x y] {:keys [dir v]}]
(condp = dir
"forward" [(+ x v) y]
"up" [x (- y v)]
"down" [x (+ y v)])) [0 0])
(reduce * 1))
; part 2
(->> (f/read-all-lines-and-parse puzzle-input parser)
(reduce (fn [[x y aim] {:keys [dir v]}]
(condp = dir
"forward" [(+ x v) (+ y (* aim v)) aim]
"up" [x y (- aim v)]
"down" [x y (+ aim v)])) [0 0 0])
(take 2)
(reduce * 1))
https://github.com/RedPenguin101/aoc2021/blob/main/clojure/src/aoc2021/day02.clj
(defn parse [line]
(let [x (Long/parseLong (re-find #"\d+" line))]
(case (first line)
\f [x 0]
\u [0 (- x)]
\d [0 x])))
(->> input
(map parse)
(apply map +)
(apply *))
;; => 2073315
(defn proc [[x y aim] [p d-aim]]
[(+ x p)
(+ y (* p aim))
(+ aim d-aim)])
(->> input
(map parse)
(reduce proc [0 0 0])
(take 2)
(apply *))
;; => 1840311528What do you think about parsing the file like this:
(->> "path"
slurp
(format "{%s}")
read-string)As I understand it, its probably fine for Advent of Code, but you wouldn't want to read untrusted input with (read-string) in real world stuff as it can execute code.
ah right! it's right there in the docs ๐คฆโโ๏ธ
As I understand clojure.edn/read-string is safer alternative and works for AoC fine since input is just data, no function definitions, etc.
Iโm just pasting the input data directly into my code i.e. (def input '(..data here..)) ๐
https://github.com/tschady/advent-of-code/blob/main/src/aoc/2021/d02.clj same as @c.oakley108
https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2021/day02.clj
btw. thanks @borkdude, I learned that case works on symbols without quoting...
https://github.com/potetm/advent-of-code/blob/master/src/advent_2021/day_2.clj
Interesting to see everyoneโs slight variations on the exact same thing ๐
@allaboutthatmace1789 Did one novel thing in that he resolved to a direction tuple (e.g. [-1 0]) in the first step, which eliminated later switches.
Also good to see how much mine looks like @borkdudeโs. Apparently Iโm not too far off the beaten path ๐
heres my solution https://github.com/theianjones/aoc_2021/blob/master/src/theianjones/aoc-2021/d02/answer.clj
same as everyone else's https://github.com/FelipeCortez/advent-of-code/blob/master/2021/02.clj
How do people decide wether to use case , condor condp ?
case - closed value dispatch
cond - conditional logic dispatch
condp - never
haven't profiled it, but I imagine case is always faster so I use it when I can, cond when case isn't enough, condp when cond isn't enough condp when it's cleaner than cond
I considered making the most hacky version for 2 day by rewriting the input to s-expressions, (forward 2), etc and then making functions for forward, etc so I could just run the program. ;)
I literally have no idea what condp is good for.
I never use condp, it's dead to me ;)
same
@borkdude same! (wrt the lispy rewriting)
Iโve seen people who make messes use it. But thatโs it.
@borkdude That sounds like the best kind of over-engineering tbh.
;-)
I recently finished https://beautifulracket.com/ and it seems like Racket really encourages this
read strings, turn them into s-exps somehow, write your DSL logic
A little late to the party https://gist.github.com/galuque/b7d60d2f2ac4c9b4658b4d21f02b12df
Did it last night, but here it is (not at all clean or clojurey, but im still learning!) https://github.com/kwpav/advent-of-code-2021/blob/master/src/advent_of_code_2021/day02.clj
https://github.com/bsless/clj-aoc-2021/blob/master/src/bsless/clj_aoc_2021/day2.clj ๐
I couldn't resist reimplementing part 1 after @borkdude mentioned it...
@coyotesqrl awesome ;)
Note that this wonโt work in Clojure. โญ for the one who tells me why.
I still donโt have proper assoc/`update` and destructuring so it looks a bit weird ๐คท
they are literals, not evaluated
so in clojure you're basically matching against (quote forward)
(case 'foo
foo 1) ;;=> 1https://github.com/Chase-Lambert/aoc-clojure/blob/main/src/aoc/2021/day_02.clj Oh man, some of the answers here are great. I could not figure out how to use reduce for part-2 because I kept thinking I needed a 2 arity function but I have to track 3 things so I had to resort to my usual ugly loop/recur method
This Python solution for Day 2 seems so clean to me: https://www.reddit.com/r/adventofcode/comments/r6zd93/2021_day_2_solutions/hmwbtbe/
They made the connection that aim for part 2 could just be your depth for part 1.
I refactored mine to create a "mover" function which knows how to move forward, down, and up for both parts, and then plugged the mover into a common solver function that uses reduce. Curious about anyone's thoughts. https://github.com/abyala/advent-2021-clojure/blob/main/src/advent_2021_clojure/day02.clj
Another sexpr oriented solution is to just compile the instructions:
(reduce comp (map (fn [[d n]] (fn [sub] (move sub d n))) moves))
If you compile it, you just get function(s). Why does it matter when you do it?
My solution for day2. Maybe too much abstraction ๐ค ๐
(def puzzle-input
(->> (str/split (input "day2.txt") #"\n")
(mapv (fn [instruction]
(let [[direction steps] (str/split instruction #" ")]
[(keyword direction) (read-string steps)])))))
(def instruction-map
{:forward [(fn [{:keys [x] :as current-position} steps]
(assoc current-position :x (+ x steps)))]
:down [(fn [{:keys [y] :as current-position} steps]
(assoc current-position :y (+ y steps)))]
:up [(fn [{:keys [y] :as current-position} steps]
(assoc current-position :y (- y steps)))]})
(def instruction-map-z
{:forward [(fn [{:keys [x] :as current-position} steps]
(assoc current-position :x (+ x steps)))
(fn [{:keys [y z] :as current-position} steps]
(assoc current-position :y (+ y (* z steps))))]
:down [(fn [{:keys [z] :as current-position} steps]
(assoc current-position :z (+ z steps)))]
:up [(fn [{:keys [z] :as current-position} steps]
(assoc current-position :z (- z steps)))]})
(defn move-sub [instruction-map input]
(reduce (fn [current-position [direction steps]]
(reduce (fn [cp f] (f cp steps))
current-position
(get instruction-map direction)))
{:x 0 :y 0 :z 0}
input))
(defn solution [instruction-map input]
(let [{:keys [x y]} (move-sub instruction-map input)]
(* x y)))
(comment
;; Part 1
(solution instruction-map puzzle-input)
;; Part 2
(solution instruction-map-z puzzle-input))My unoriginal take: https://samadams.dev/2021/12/02/advent-of-code-day-2.html
love the blogging approach ๐
@sam.h.adams which tool do you use to process your source to create that blog? i was looking at marginalia but it didnโt quite fit.
@tws If you're looking for a home-made solution: https://blog.michielborkent.nl/writing-clojure-highlighter.html
Solved with awk for fun
BEGIN {
x=0;
y=0;
a=0
#
t["forward"]=0;
t["up"]=-1;
t["down"]=1;
#
h["forward"]=1;
h["up"]=0;
h["down"]=0;
#
v["forward"]=1;
v["up"]=0;
v["down"]=0;
}
{
a = a + t[$1]*$2
x = x + h[$1]*$2;
y = y + v[$1]*$2*a;
}
END {
print x*y;
}
awkful! :)
minified!
BEGIN {x=0; y=0; a=0 t["f"]=0; t["u"]=-1; t["d"]=1; h["f"]=1; h["u"]=0; h["d"]=0; v["f"]=1; v["u"]=0; v["d"]=0;} {c=substr($1,1,1) a = a + t[c]*$2 x = x + h[c]*$2; y = y + v[c]*$2*a;} END {print x*y;}
Fits in a tweet
do it.
Reminds me of the annoying questions from intro to C, "do it without conditionals"
and now write an awk interpreter that fits in a tweet. so we can combine both tweets using tweet-def?
I think I'll first need to bootstrap it with tweet-def itself as a dep, then just chain it, but that's cheating
Which reminds me I wanted to solve it with core.logic
Babashka and pointless (threading style)
# part one
pbpaste | bb -I -e '(->> *input* (partition 2) (reduce (fn [[x y] [c v]] (case (keyword (name c)) :forward [(+ x v) y] :down [x (+ y v)] :up [x (- y v)])) [0 0]) (apply *))'
# part two
pbpaste | bb -I -e '(->> *input* (partition 2) (reduce (fn [[x y a] [c v]] (case (keyword (name c)) :forward [(+ x v) (+ y (* a v)) a] :down [x y (+ a v)] :up [x y (- a v)])) [0 0 0]) butlast (apply *))'Awesome :)
my solution to day2. I'll read your solutions now; I know there are some crazy people who avoided using reduce ๐ https://github.com/euccastro/advent-of-code-2021/blob/main/day2.clj
yeah, I had forgotten about the joys of using re-seq or wrapping the whole input to read it as edn...
I'm real boring https://gist.github.com/corasaurus-hex/389968ca616083ba0feb630330ba1739
https://github.com/benjamin-asdf/advent-of-code-2021/blob/master/src/day2.clj still learning
Little bit late to the game, but here goes, neverthelessโฆ
(ns day2
(:require [clojure.string]))
(comment
; part 1
(->> "input"
slurp
clojure.string/split-lines
(map #(clojure.string/split % #" "))
(map (fn [[command value]] [command (Integer/parseInt value)]))
(reduce (fn [[pos depth] [command value]]
(case command
"forward" [(+ pos value) depth]
"down" [pos (+ depth value)]
"up" [pos (- depth value)]))
[0 0])
(apply *))
;=> 1698735
)
(comment
; part 2
(->> "input"
slurp
clojure.string/split-lines
(map #(clojure.string/split % #" "))
(map (fn [[command value]] [command (Integer/parseInt value)]))
(reduce (fn [[pos depth aim] [command value]]
(case command
"forward" [(+ pos value) (+ depth (* aim value)) aim]
"down" [pos depth (+ aim value)]
"up" [pos depth (- aim value)]))
[0 0 0])
(take 2)
(apply *))
;=> 1594785890
)A bit inelegant, but it got the job done.
Here is mine https://github.com/zelark/AoC-2021/blob/main/src/zelark/aoc_2021/day_02.clj
Some wasted effort using maps, and could be cleaner but it got the job done.
Hereโs mine:
(def input (->> (u/day-input-source 2)
(into [] (map (comp edn/read-string #(str "{:" % "}"))))))
(defn t1
[input]
(let [combined (reduce (fn [acc x] (merge-with + acc x)) input)
{:keys [forward up down]} combined]
(* forward (- down up))))
(defn t2
[input]
(let [f (fn [acc action]
(let [[direction x] (-> action seq first)]
(case direction
:down (update acc :aim + x)
:up (update acc :aim - x)
:forward (-> acc
(update :horiz + x)
(update :depth + (* (:aim acc) x))))))
init (zipmap [:horiz :depth :aim] (repeat 0))
{:keys [horiz depth]} (reduce f init input)]
(* horiz depth)))My solution using recursion: https://github.com/raicotop/advent-of-code-2021/blob/main/src/advent_of_code_2021/day-02.clj