This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-04
Channels
- # adventofcode (171)
- # beginners (160)
- # boot (13)
- # chestnut (2)
- # cider (6)
- # cljs-dev (15)
- # cljsjs (35)
- # cljsrn (1)
- # clojure (139)
- # clojure-argentina (3)
- # clojure-brasil (1)
- # clojure-greece (31)
- # clojure-italy (5)
- # clojure-russia (5)
- # clojure-spec (18)
- # clojure-uk (11)
- # clojurescript (42)
- # clojurex (6)
- # core-async (12)
- # cursive (14)
- # dirac (13)
- # emacs (13)
- # events (1)
- # fulcro (46)
- # graphql (7)
- # leiningen (10)
- # lumo (3)
- # mount (31)
- # off-topic (20)
- # onyx (30)
- # perun (4)
- # planck (47)
- # re-frame (28)
- # reagent (14)
- # ring (5)
- # shadow-cljs (3)
- # spacemacs (7)
- # specter (13)
- # timbre (3)
- # unrepl (65)
- # yada (8)
my inputs agree with their outputs for the first 23 values but i'm not getting the right answer for part b
i was thinking in terms of rings of the spiral. so i ask which cells are adjacent in the inner ring and then which are adjacent in the same ring
I went for a generic 3x3 scan so I didn't have to worry about details of which cells would or wouldn't be filled
yeah. i compute mine on the fly. and looking at the walk and create method, it looks better
(defn cell-value [n]
(if (= n 1)
1
(let [inner (inner-touching n)
outer (outer-touching n)
touching (distinct (concat inner outer))]
;; so a cell's value is the sum of the values it is touching,
;; either in its own ring or in the inner ring
(apply + (map cell-value touching)))))
and then wrap that in a memoize and map it over a range and drop while lest than what they are looking for
https://github.com/minikomi/advent-of-code/blob/master/src/advent/2017/day3.clj#L9-L14 Once I blagged that out on the repl / with pen & paper, I got it.. but not a solution I'm happy with
day 4: almost a no-brainer š
@val_waeselynck Very nice solution
@fellshard Link to your solution?
https://github.com/minikomi/advent-of-code/blob/master/src/advent/2017/day4.clj I just used distinct & sort
I'd like to practice core.logic, anyone knows a problem from AoC 2016 or 2015 for which it's a nice fit?
@val_waeselynck hmm, I think this problem should be solvable with core.logic: https://blog.michielborkent.nl/blog/2017/10/10/parsing-a-circuit-with-clojure-spec/
@borkdude yeah so mostly a graph computation. Clara-rules or plumatic/graph could be a nice fit for that too.
The variability of answers for the āsimpleā puzzles is really an indicator of the language used, Iād think. I also used distinct
and sort
š https://github.com/orestis/adventofcode/blob/master/clojure/aoc/src/aoc/2017_day4.clj
Is there a better way of counting with transducers? https://github.com/borkdude/aoc2017/blob/master/src/day4.clj#L58
so:
(count
(sequence (map identity)
[1 2 3]))
;; vs
(transduce (map (constantly 1))
+
[1 2 3])
Another idea:
(def xf (comp (filter odd?) (map inc)))
(transduce xf #(inc %) 0 (range 5))
day 4: I first checked for palindromes, but then realized they were not anagrams and then refactoredā¦ and eventually ended up with an inefficient solution š³
This one is nice. He just does it in the browser while having his input open: https://www.reddit.com/r/adventofcode/comments/7hf5xb/2017_day_4_solutions/dqqjrq2/
@borkdude for counts with transducers use net.cgrand.xforms/count to replace the (map (constantly 1))
Refactored: https://github.com/borkdude/aoc2017/commit/3e035c04ba00d520741b20090951ed66b2801ff5
@mfikes can you explain your invariant in your step
function for day 3? In looking for the next location, you tag the locations as visited or not. And you find the first one unvisited after one that is visited in the list of potential squares left, down, right, up. Can you tell me why this works?
@dpsutton I unfortunately donāt have anything close to a proof of why that approach works. It intuitively matches what I would do if I were trying to āspiral counter-clockwise,ā without knowing which ālinear directionā Iām already moving: I would try to choose the ācounter-clockwise-mostā free location. Perhaps a proof by contradiction could be constructed where if you chose any other location, you wouldnāt trace a spiral, but I donāt know if that reasoning is too sketchy. In short, it is a physical intuition that matches the concept of keeping your left hand on the wall and just tracing your path.
sounds good to me. that was very clever. I'm enjoying reading the code. People that are doing the spiral are having to enumerate how to make decisions. The one I've seen used the coordinates and the fact that it is a square to know when to turn. Yours didn't need this big decision tree and is quite clever
It would be very interesting to categorize the kinds of solution ātreesā that people have. I imagine they involve recognizing and using perfect squares, keeping track of a current linear direction and knowing when to turn (by memory, or by counting, or by being at a place where x=y or x=-y), or left-hand on wall. Maybe those are the 3?
For me it was -- did we change layers? go :up
(went over another odd square), is it a "corner"? turn left.. (worked out a formula on the repl to generate a set of corners for current layer) otherwise, continue on in the current direction
Yeah, I suspect a broad class of the solutions have a āstateā in #{:up :left :down :right}
that gets flipped at a corner, and then differences on how you detect a corner.
FWIW, I think my solution is wasteful of memory, but I got lucky that the problem fit in RAM. š
(defn adjacent-locations
"Given a location, produces the eight adjacent locations."
[[x y]]
(map (fn [[dx dy]]
[(+ x dx) (+ y dy)])
[[-1 1] [ 0 1] [ 1 1]
[-1 0] [ 1 0]
[-1 -1] [ 0 -1] [ 1 -1]]))
ahh the formatting messed up but the grid layout and the hole for current location is super nice
@mfikes It felt a bit like cheating in the second part to keep a map around with all the previous ātilesā (as I called them), because that required more memory than needed maybe
my solution feels wasteful in trying to determine which cells in the current ring and inner ring are necessary for computation
and involved bringing edge cases rather than just a notion of "add 'em if you got 'em"
@dpsutton Yes, I like using a āgraphicalā code solution sometimes. Here is another, where you need to parse digits from a file containing their representations. I chose to solve it by putting their representations in the code and then constructing a reverse mapping from those representations to the digits.
(def rendered-digit-lines
"A sequence of 3 lines representing all of the digits in order."
[" _ _ _ _ _ _ _ _ "
"| | | _| _||_||_ |_ ||_||_|"
"|_| ||_ _| | _||_| ||_| _| "])
(defn- lines->digit-representations
"Converts a sequence of 3 lines into a sequence of representations
of the digits on those lines, where each digit representation is
a sequence of character triplets."
[lines]
(apply map list (map #(partition 3 %) lines)))
(def digit-representation->digit
"A map from digit representation to digit."
(zipmap (lines->digit-representations rendered-digit-lines)
(range 10)))
If you look at digit-representation->digit
, youāll see what I mean.With the āholeā in the matrix, I had to be careful not to let my editor reformat the code š
(def numerals-text (str " _ _ _ _ _ _ _ _ \n"
"| | | _| _||_||_ |_ ||_||_|\n"
"|_| ||_ _| | _||_| ||_| _|\n"))
(def numeral-streams (->> numerals-text
str/split-lines
(remove str/blank?)))
(defn chunk3
"Partition a string into 3 character substrings"
[s]
(map #(apply str %) (partition 3 s)))
I think the 2d
syntax from racket takes that kind of thing to the extreme
https://docs.racket-lang.org/2d/index.html
https://github.com/codingdojo-org/codingdojo.org/blob/master/content/kata/BankOCR.md
Wow, the whole Kata looks the same. OK:
User Story 1:
I created a new project using lein new bank-ocr
and this is the core file:
https://gist.github.com/mfikes/f43d382057efa017ebfb
User Story 2:
I created a bank-ocr2, and took the contents of the previous story and simply added a account-number-value?
method to compute the validity of a bank account:
https://gist.github.com/mfikes/17ec1cfcdddfdba2b2f4
User Story 3:
I created a bank-ocr3, took the stuff from User Story 2 and added a account-number-illegible?
and revised the account number printing logic to print ā?ā characters and the additional āILLā and āERRā descriptors
https://gist.github.com/mfikes/3c714859cb3da9384d52
FWIW, Outpace is/was awesome. The issue was mine: I backed out because I didnāt want to jump into full-time pairing without having done any, and not knowing what it was like to actually do it full time.
healthfinch seemed cool as well. they did the full time pair thing as well. which i think i would like if i were working remotely for the comraderie
My Day 4 solutions are up. Wondering if anyone found anything simpler. I debated the aspect of counting the number of times a predicate matches a sequence, but in the end went with the obvious one. Perhaps there will be more interesting variation on how people detect valid passphrases. https://github.com/mfikes/advent-of-cljs/commit/4bff774da3e9760e10fbb6cb1e33d7614a185634
@mfikes pretty much the same for me, with frequencies instead of sort
@mfikes I think thatās as simple/efficient as it gets. It would be even simpler if you would put the two parts in one namespace, because a lot of the logic is re-usable (matter of taste)
Notice that this one is almost the same as part 1, except for this line: https://github.com/borkdude/aoc2017/blob/master/src/day4.clj#L58
I think that for this one, if you happen to remember that there is a core predicate that you can use, the problem is trivial. (Especially compared to Day 3.)
Ahh niceātentamenās use of frequencies
instead of sort
might be faster if the words are long. :thinking_face:
@mfikes With my puzzle input it turned out to be the same (sloppy benchmark of course): https://github.com/borkdude/aoc2017/blob/master/src/day4.clj#L77
Yeah, if s
contains the entire contents of /usr/share/dict/words
, in self-hosted ClojureScript:
cljs.user=> (time (do (sort s) nil))
"Elapsed time: 4993.764097 msecs"
nil
cljs.user=> (time (do (frequencies s) nil))
"Elapsed time: 1341.280391 msecs"
nil
I wish there were a better way to know who, of the people listed at https://github.com/adventofcode-clojurians/adventofcode-clojurians have finished Day 4.
I was looking at this yesterday. Thereās an API that returns JSON. Maybe we could somehow hook it up to the README?
What I really want to do: Survey each solution, trying to pick out novel aspects that never crossed my mind or made better use of core fns.
What Iām interested in, from a learning perspective for example. If you are doing (= (count (distinct xs)) (count xs))
, there is a core predicate that makes this trivial.
In fact, this core predicate, is almost cheatingāit nearly solves Day 4 with one fn.
Two things I learned today: distinct?
and normalize data if you want to compare it on one property (without actually generating solutions which you donāt need).
Yes, maybe projection is the better word: sort
and frequencies
are a projection of anagrams into a smaller search space
Yes, need to dig up one of my math books, the term they use for your āprojectionā is āhashā, when applied to the concept of defining a partition (induced by an equivalence relation)
the math term i'd think applied would be an injection or an embedding. embed the underlying representation into its equivalence class
> In mathematics, a projection is a mapping of a set (or other mathematical structure) into a subset (or sub-structure) https://en.wikipedia.org/wiki/Projection_(mathematics) > In mathematics, an injective function or injection or one-to-one function is a function that preserves distinctness https://en.wikipedia.org/wiki/Injective_function > In mathematics, an embedding (or imbedding[1]) is one instance of some mathematical structure contained within another instance https://en.wikipedia.org/wiki/Embedding It might be taste, but I find projection the most fitting, or hash if youāre programming š
embedding is structural preserving. most examples are the copies of the naturals in the integers, integers in the rationals, rationals in the reals, etc
ah yes, it was nice when I got those classes about countability, etc. https://en.wikipedia.org/wiki/Countable_set
There seems to be no name for a function (which is a projection) that is nor injective, bijective and surjective
With the word projection I think of physics where you see the light being concentrated through a lense.
There are functions that tend to be named with the suffix -by
, which take a function which essentially maps the values prior to doing whatever that function was going to do. Maybe there is a curiously recurring concept there.
Apropos to the AoC problem, distinct-by
is a common one. For example https://github.com/clojure/clojurescript/blob/544c1b77d76d48f234cdb03746ea993158c46aff/src/main/clojure/cljs/util.cljc#L286-L297
we also use distinct-by
in JVM clojure. It would be cool if there was also a distinct-by?
, that would be effectively the solution for part 2 with sort
or frequencies
as a key
(havenāt messed around with cljs compiler config for a while, itās been the same for a while)
here are my solutions: https://github.com/ChrisBlom/advent-of-code/tree/master/src/adventofcode/2017
@chrisblom welcome to the repo, just merged your PR
@chrisblom I think we also met at EuroClojure 2016 if Iām not mistaking
@borkdude The ClojureScript compiler doesnāt use Spec to validate compiler configuration. On the other hand, I believe Figwheel uses this lib https://github.com/bhauman/strictly-specking
What are you guys using for parsing inputs? I find it rather tedious, I wish I could find some pattern-matching lib to speed up the process
I realize parsing has not been much of a problem so far in AoC 2017, but as I'm working through some problems from last year I find them more and more demanding in this regard
usually just str/split etc, but at one point clojure.spec, although I first did it with regexes, which was good enough
I didnāt solve all of last yearās problems. Can you give an example of more complex parsing problems there?
@U0ARQ14BA For problems involving parsing integers, frequently Clojure solutions involve clojure.core/read-string
as opposed to Long/parseLong
. FWIW, Planck now has planck.core/read-string
in master. (For now, Iāve just been using js/parseInt
.)
This guy doesnāt even need an editor: https://www.reddit.com/r/adventofcode/comments/7hf5xb/2017_day_4_solutions/dqqjrq2/
Right š Previously I was even wrapping strings with '[]
and just working on the resulting symbols
@mfikes Thatās what Iāve also done. Wrap in []
, then clojure.edn/read-string and process the rest using clojure.spec š
Hey, since we are working in a language that is so data-centric, it doesnāt feel like cheating to paste the data into the source file.
I meant for problems like this one: https://adventofcode.com/2016/day/23
@val_waeselynck for that input iād use the mentioned []
+ read-string approach and then simply destructuring + case for processing
@val_waeselynck read-string
is your secret weapon https://github.com/bhauman/advent-of-clojure-2016/blob/master/src/advent_of_clojure_2016/day23.clj#L7