Fork me on GitHub
#code-reviews
<
2021-12-14
>
noisesmith06:12:10

I can't figure out which of these is clearer

(defn play
  [number boards]
  (mapv (fn [board]
          (mapv (fn [row]
                  (mapv (fn [{:keys [value] :as p}]
                          (if (= value number)
                            (assoc p :marked true)
                            p))
                        row))
                board))
        boards))

(defn play'
  [number boards]
  (letfn [(process-cell [{:keys [value] :as p}]
            (if (= value number)
              (assoc p :marked true)
              p))
          (process-row [row]
            (mapv process-cell row))
          (process-board [board]
            (mapv process-row board))]
    (mapv process-board
          boards)))

phronmophobic06:12:43

I vote play', but play isn't bad either. I do like using specter for this kind of stuff, but I know there's lots of people who prefer not to use specter for various reasons.

noisesmith06:12:53

I could even use post-walk, but the data structure is so uniform that it seems silly

noisesmith06:12:35

I'm not using any code outside clojure.core for this (advent of code)

👍 1
phronmophobic06:12:15

it seems like you're processing a 2d array. another option is to use a map of [x,y] to cell

phronmophobic06:12:29

and then you can just use update-vals

noisesmith06:12:31

yeah, maybe 2d isn't actually ideal here

Fredrik06:12:28

A recursive structure might warrant a recursive function

(defn mapv-dim [dim f coll]
  (if (= 1 dim)
    (mapv f coll)
    (mapv #(map-dim (dec dim) f %) coll)))

(defn play [number boards]
  (mapv-dim 3
          #(cond-> % (= number (:value %)) (assoc :marked true))
          boards))

Fredrik06:12:41

Now you just bump up the dimension when asked to check all boards on all tournaments on all planets in all solar systems

phronmophobic06:12:42

The map has a few advantages: • it's trivial to filter for only occupied cells • an empty board is just {} • expanding, contracting the board isn't too bad but it's not ideal for all uses cases. I'm not doing advent of calendar, so no idea if it makes sense there.

noisesmith06:12:49

it's a set of bingo cards

noisesmith06:12:26

anyway, I would have switched to hash-map indexed by [x,y] pairs if there was even one bug in my play function, but it was good as written the first time it got used lol

noisesmith06:12:01

maybe I'll switch to a hash-map for part two

noisesmith06:12:49

ehh, nope the only change is when to stop iterating, all other rules are unchanged (that is all marking / winning logic stays the same, only difference is we keep going until all boards win which is well outside this scope)

👍 1
noisesmith06:12:32

the kind of thing you can only get away with when coding for fun

(let [next-boards ((rand-nth [play play']) boards n)]

3
bananadance 3
❤️ 1
potetm13:12:03

yet another alternative is to generate points [x y] on the board and map over those instead

Drew Verlee06:12:09

potetem has the right of it. The function is over the index, not the collection. Or something.

Drew Verlee06:12:16

alternatively, flatten the board into a single collection and keep the dimensions as data.

Drew Verlee06:12:15

which is better will have to do with if you ever care about "rows" or not as a single collection.