I'll check it out, I think this was posted on a thread in reddit I had made.
Hallo fellow adventers
o/
well, day3 upped the ante a little i see
yeah this is a tricky one
my inputs agree with their outputs for the first 23 values but i'm not getting the right answer for part b
Misread the value they're looking for?
turns out what i thought was a special case for one number was in fact general
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
Ahh
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
and the code i saw uses the coordinates to know when to turn,, etc. it looks nice
i've never seen the with-tests
macro either. that's pretty nice
but i do like the way mine came together
(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)))))
but lots of edge cases in the outer touching functoin
can you link me your day3.clj?
and then wrap that in a memoize and map it over a range and drop while lest than what they are looking for
totally brute forced day3
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
yeah, day4 was a piece of cake 😄
Yeh. Hurrah for quick set conversion
@fellshard Link to your solution?
https://github.com/armstnp/advent-of-code-2017/blob/master/day-4.clj
I dumped the entire input in, heh. 😫
hahaha
cool 🙂
https://github.com/minikomi/advent-of-code/blob/master/src/advent/2017/day4.clj I just used distinct & sort
I had this too at first #(= (count %) (count (set %))
== (apply distinct? ...)
I haven't used distinct
much, that's one to add to the toolkit!
Yeah, I’ve seen sort a couple of times now. I feel so dumb
First thing to think when looking for anagrams is a lex-sort : )
Not when making them, so much
Yeah, checking whether they exist vs. creating them
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
ooh, thought of a better way to do day3-part1
Is there a better way of counting with transducers? https://github.com/borkdude/aoc2017/blob/master/src/day4.clj#L58
maybe use (into [] ,,,)
with count instead of transduce with highlighted line?
yeah, or (count (sequence xform input))
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))
doesn’t compile
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))
@thegeez something like this?
(first (eduction x/count
[1 2 3]))
(not yet familiar with this lib)
o no, this is better: (x/count (map identity) [1 2 3])
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. 🙂
also your potential candidates function is written really well
(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
That second category doesn’t require O(n^2) memory, I’d guess
@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.Ah, now I see it in your solution @mfikes, nicely done 🙂
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)))
spaces in between are not usually formatted right?
i did the same thing
Is the digits example from last year?
Cursive will ignore the spaces and just mess it all up 🙂
it's a kata about ocr
https://github.com/codingdojo-org/codingdojo.org/blob/master/content/kata/BankOCR.md
No the digits example is from a pre-screen interview I did
ha same
Damn. You are right! 🙂
did you get the gig?
Yes, but I didn’t take it
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
yup. was it a health care company you interviewed with?
No, it was Outpace
ah. i had the same thing with healthfinch
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.
I think the 2d
syntax from racket takes that kind of thing to the extreme
https://docs.racket-lang.org/2d/index.html
ascii art as syntax
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 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)
Yeah, that’s a recurring pattern with the part 1 / part 2 aspect.
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 might take tha approach of putting common bits in a shared core ns.
Yes, for me the addition of sort
was the difference.
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.
@mfikes The leaderboard!
👍
https://adventofcode.com/2017/leaderboard/private/view/217019
I was looking at this yesterday. There’s an API that returns JSON. Maybe we could somehow hook it up to the README?
It would be a bonus puzzle 😉
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.
^ yeah. be nice to see a curated list of different interesting aspects
That would be a manual effort I guess but worth doing!
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.
Yes, or (set xs)
is what I was doing
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).
By “normalize data,” are you thinking of the sort
in day 4 part 2?
Yes, maybe projection is the better word: sort
and frequencies
are a projection of anagrams into a smaller search space
Maybe there are other projections possible
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
A -> equivalence classes over A
> 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 seems to be about groups, category theory etc.
embedding is structural preserving. most examples are the copies of the naturals in the integers, integers in the rationals, rationals in the reals, etc
so since this would throw away structure it's not the right usage
(or add structure)
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
@mfikes Looking at that link, wondering what they use Levenshtein for
It is used to find compiler configuration keys that are slightly off
and then it gives a suggestion: “did you mean…” or does it blindly accept it
awesome
(This was an attempt to validate configuration, prior to Spec’s release.)
Levenshtein + spec could still be cool 🙂
as a layer on top maybe, or does the user now get a raw spec error message?
(haven’t messed around with cljs compiler config for a while, it’s been the same for a while)
@mfikes pretty much the same for me, with frequencies instead of sort
i like the advent of code repo, i've already picked some nice tricks
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
ah yes, we were on the same bus & had coffee
@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 instaparse for complex things, otherwise clojure core & string function
usually just str/split etc, but at one point clojure.spec, although I first did it with regexes, which was good enough
I’m solving in cljs, planck so .split
. tbh I used it today for the first time
todays puzzle is hilariously straightforward
I didn’t solve all of last year’s problems. Can you give an example of more complex parsing problems there?
@nooga 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
.)
It was distinctly easy 😜
oh, I just wrap numeric tables with [] in emacs and paste them into the repl
too lazy to create files
and applying map will sort the second part ;D
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.
Some people do this to avoid the IO monad 😉
I meant for problems like this one: https://adventofcode.com/2016/day/23
I’d totally quote that
@val_waeselynck for that input i’d use the mentioned []
+ read-string approach and then simply destructuring + case for processing
My solutions for day 3 and doy 4 are posted...
now to check everyone else's