This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-12-18
Channels
- # adventofcode (40)
- # aleph (8)
- # announcements (2)
- # beginners (27)
- # calva (3)
- # cider (3)
- # clj-kondo (21)
- # cljsrn (9)
- # clojure (122)
- # clojure-europe (38)
- # clojure-france (93)
- # clojure-nl (2)
- # clojure-spec (1)
- # clojure-uk (32)
- # clojuredesign-podcast (1)
- # clojurescript (12)
- # community-development (11)
- # conjure (14)
- # cursive (11)
- # datalog (7)
- # depstar (21)
- # emacs (31)
- # fulcro (85)
- # google-cloud (1)
- # graalvm (1)
- # graphql (7)
- # jobs-discuss (3)
- # joker (1)
- # kaocha (14)
- # pathom (2)
- # re-frame (1)
- # reagent (1)
- # reitit (6)
- # reveal (50)
- # shadow-cljs (64)
- # spacemacs (8)
- # tools-deps (5)
Morning 🙂
morning
Morning
måning¡
What's a good name for this function?
(defn f [m]
(reduce (fn [A [key val]] (update A val conj key)) {} m))
It's inverting a map, but the new values are a collection of the keys that have a given old value.
I had map-invert-with-collect
or collect-values
map-invert
would sound good to me
have you checked out https://clojure.github.io/clojure/clojure.set-api.html#clojure.set/map-invert though?
oh that doesn't tolarate multi mappings from v->k though
maybe multimap-invert
? just to labour the point
Yeah, map-invert
is a name collision unfortunately 🙂 I like multimap invert, though maybe that implies it inverts a multimap, rather than returns one? Maybe map-invert-to-multi
that sounds just fine fthat sounds just
I find it a bit annoying that there isn't a Clojure function that lets you do things like that (as far as I know?) that doesn't involve you stopping to think about what on earth's going on
Like, the Kotlin equivalent is something like map.entries.groupBy({ it.value }) { it.key }
which I find easy to scan for it being probably correct
Oh wait, no, you're basically just doing (group-by val {:a 10 :b 20 :c 10})
, not what I was thinking 😁
@dominicm conceptually yeah, but the output I want is a bit different
(map-invert-multi {:a 10 :b 20 :c 10})
;; => {10 (:c :a), 20 (:b)}
(group-by val {:a 10 :b 20 :c 10})
;; => {10 [[:a 10] [:c 10]], 20 [[:b 20]]}
@allaboutthatmace1789 how are you consuming this downstream?
In this context, it's part of a quick game of life implementation
(def blinker [[0 0] [0 1] [0 2]])
(defn neighbours [[x y]]
(for [xvar [-1 0 1]
yvar [-1 0 1]
:when (not= xvar yvar 0)]
[(+ x xvar) (+ y yvar)]))
(defn map-invert-multi [m]
(reduce (fn [n [key val]] (update n val conj key)) {} m))
(defn new-active-cells [already-active-cells]
(let [cells-with-n-active-neigbours
(->> already-active-cells
(mapcat neighbours)
frequencies
map-invert-multi)]
(sort (concat (get cells-with-n-active-neigbours 3)
(filter (set already-active-cells) (get cells-with-n-active-neigbours 2))))))
(-> blinker
new-active-cells
new-active-cells)
so after map-invert-multi-ing, I want to concat everything with key 3 and a filtered list of things with key 2.If an active cell has > 3 neighbours it's 'overcrowded' and dies - here's a complete mapping:
C N new C
1 0,1 -> 0 # Lonely
1 4,5,6,7,8 -> 0 # Overcrowded
1 2,3 -> 1 # Lives
0 3 -> 1 # It takes three to give birth!
0 0,1,2,4,5,6,7,8 -> 0 # Barren
But stated another way, any cell with 3 neighbours is alive the next round, any with 2 neighbours is alive in the next round if it's alive nowI guess an interesting way to flip this would be to use frequencies directly?
(reduce-kv (fn [state cnt neighbours] (case cnt (0 1) (lonely …) 3 (give-birth …))) state (frequencies …))
I was trying to write the program to be as close as possible to the description of the rules of the game, hence the
new-active-cells = (concat (get cells-with-n-active-neigbours 3)
(filter (set already-active-cells) (get cells-with-n-active-neigbours 2)))