This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

## 2020-12-09

## Channels

- # adventofcode (197)
- # announcements (25)
- # aws (1)
- # babashka (21)
- # beginners (138)
- # calva (21)
- # cider (5)
- # clara (1)
- # clj-kondo (35)
- # clojure (97)
- # clojure-australia (4)
- # clojure-dev (37)
- # clojure-europe (100)
- # clojure-nl (2)
- # clojure-spec (7)
- # clojure-uk (36)
- # clojurescript (11)
- # conjure (15)
- # crux (93)
- # cursive (20)
- # datomic (12)
- # emacs (10)
- # events (2)
- # fulcro (83)
- # graalvm (14)
- # jobs (1)
- # jobs-discuss (27)
- # kaocha (75)
- # lambdaisland (21)
- # off-topic (27)
- # pedestal (5)
- # reitit (2)
- # reveal (20)
- # rewrite-clj (24)
- # sql (9)
- # tools-deps (37)

Recording for day 9 https://youtu.be/7gp4MZdCDQc used a nested loop/recur for part 2, I may try to clean that up a bit later today 🙂

After some heavy cleanup, I made a version which is using only the for loop. https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_9.clj#L19-L48 Edit: not totally, there is still a reduce inside.

I made this `group-by`

because usually the part which is in the val after the group-by is often the target of further computation.

Another problem I want to address is `comp`

on functions. The way I think about the operations to apply is the reverse of what I need to write.

```
(defn comp-> [& args]
(apply comp (reverse args)))
#_ ((comp str inc) 17) ; => "18"
#_ ((comp-> inc str) 17) ; => "18"
```

Feedback welcome.@vincent.cantin I recommend taking a look at https://github.com/cgrand/xforms - there are lots of goodies in there that help build stuff like this but it's all transducer-based

I used it in a lot of places in my solutions so far https://github.com/imrekoszo/advent-2020/

It is a good library. With this tree-seq transducer, you may have used it at one more place too. https://github.com/cgrand/xforms/issues/20

on the shiny bag day

Side note: The functions I past in the channel are targeted at saving typing time. They are not necessarily the right choice for quality code.

Until now, performance was not the issue in all the puzzles, so lazy collections are still in the game.

what's the best way to do a cartesian product but without the order?

```
(for [x (range 3) y (range 3)] [x y])
=> ([0 0] [0 1] [0 2] [1 0] [1 1] [1 2] [2 0] [2 1] [2 2])
```

yeah I mean having [0 1] but not [1 0] for example

so imagining a square, taking the diagonal and the lower or upper half

Cause that did bug me with day 1 where you kinda need elements taken for the combinations of indices. Not being able to find an existing implementation, I wrote a transducer for it but its performance is shite when compared to the for-based approach: https://github.com/imrekoszo/advent-2020/blob/master/src/imrekoszo/advent2020/day1_alternatives.clj#L102

I used `(for [i (range size) j (range i size)] ...)`

to get a triangle of indices (where size if the count of the collection)

@andrea.crotti There is more than one way to do it, but as mentioned above that’s combinations vs permutations. Another way is in the for macro to make sure that one index is > than another, e.g. 1(for [i xs j xs :when (> j i))1

as @markw mentions:

```
(for [x (range 5)
y (range 5)
:when (< x y)]
[x y])
;; => ([0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3] [2 4] [3 4])
```

Or change `<`

to `<=`

, I would imagine...

Using the when clause will make the for comprehension iterate over all 5*5 indices though (perhaps a small cost compared to the work overall...)

if you want efficient generation i would use combinatorics and tack on the diagonals explicitly

It just won't generate an entry for the failing conditions.

cool nice

As I mentioned above, I did it using the two argument version of range to get the triangular shape of indices.

Missed the fact that you started the second loop at `i`

rather than `i+1`

which would have made it effectively the same as combinations

In my actual for sequence I do have `:let`

and `:when`

for other purposes, just not the range/index checking.

I feel somewhat stupid about my day 1, part 2 implementation where I just added another index instead of doing something else.

```
(time (do (doall (for [x (range 1000) y (range 1000) :when (<= x y)] [x y])) nil))
"Elapsed time: 40.609524 msecs"
=> nil
(time (do (doall (for [x (range 1000) y (range x 1000)] [x y])) nil))
"Elapsed time: 27.957203 msecs"
```

Depends on what your goals are for this puzzle thing. And there are a bunch of conflicting ones there.

```
(time (do (doall (for [x (range 1000) y (range 1000) :when (<= x y)] [x y])) nil))
"Elapsed time: 65.1356 msecs"
(time (do (doall (for [x (range 1000) y (range x 1000)] [x y])) nil))
"Elapsed time: 53.8159 msecs"
```

Never mind my duplicate experiment. I misread yours completely and thought it did not include the x offset for y... Time to fetch my glasses.

I'm using loom for problem 7 https://github.com/aysylu/loom and it worked out nicely for the first part of the problem

I also added the number of bags contained as the weight of each edge, so I thought it would be easy to do part b of the exercise

but I can't find anything useful to do that

Thanks for the heads-up on loom.. I might need to look at that for some non-aoc stuff.

in theory I just want to be able to **sum** all the paths that I generate with a DFS search for example (multiplying the weights)

it's pretty much just

```
(->> "shiny gold"
(la/bf-traverse (get-graph))
count
;; removing the node itself
dec)
```

once you have the graphbut yeah getting the actual weights to do something seems to be another matter

there is a loom conj presentation https://www.youtube.com/watch?v=wEEutxTYQQU

yeah I think I saw that some time ago, but well I kind of know how I could do it I guess. I need to find in the whole dfs which are the terminal nodes, for them generate all the paths, then get the weights, multiply them and sum it all together

would be nice if there was an easier way though

hehe yeah that would work I guess

was trying to avoid that since that's all I'm doing apparently

Day 7 was some ugly for comprehension over recursive calls for me.

mm dammit I think I'm close

```
(defn n-bags-inside [gr starting]
(let [edges (lg/out-edges gr starting)]
(if (empty? edges)
1
(apply +
(for [e edges]
(* (lg/weight gr e)
(n-bags-inside gr (second e))))))))
```

at least it works for this simple graph
```
;; desired = 16
(def sample-g
(lg/weighted-digraph
[:a :b 2]
[:a :d 10]
[:b :c 3]))
```

but aoc doesn't agree with me

mm weird my result is exactly (actual-result / 2 + 1) using the example from the instructions

but of course if I (dec (* 2 current)) it still doesn't work 😄

so probably just a coincidence

I think the problem is maybe the graph generated because the algorithm I think it's correct, bah I'll see tomorrow

@andrea.crotti tws used https://github.com/tschady/advent-of-code/blob/master/src/aoc/2020/d07.clj if you want to peek. Mine is in the related https://github.com/RedPenguin101/aoc2020/blob/main/day7.clj

that's quite neat thanks

I have been revisiting some prior years problems I gave up on… https://adventofcode.com/2018/day/20 is really stumping me. Is it possible to parse something like `ENWWW(NEEE|SSE(EE|N))`

using recursive descent into the following paths? Basically each `|`

is an optional fork in the path, which starts from the point in each prior group formed by `(`

. The instructions give some more detail, but the above should yield these three paths:
• ENWWWNEEE
• ENWWWSSEEE
• ENWWWSSEN
I feel like this should be simple yet I’ve been stuck on it for an embarrassingly long amount of time. I recently abandoned the recursive approach dealing with each symbol in-turn for a token-by-token approach, which is getting be closer but bleh.

Cheating to use instaparse?