
Advent of Code Solutions - abecedarius
http://nbviewer.jupyter.org/url/norvig.com/ipython/Advent%20of%20Code.ipynb
======
solaxun
I knew he was working on these from seeing the leaderboard, and was reeeeally
hoping he'd share the solutions, so I'm super happy to see this. What about
you, Darius? Did you participate this year? I remember you from CS212 and
would be interested in seeing your solutions as well!

~~~
abecedarius
No, I haven't started this year, though maybe I still will -- it's always
interesting to see the Norvig treatment after having a go yourself.

------
hzhou321
There are 3 assembly code exercise: day 12, 23, and 25. The solutions in the
post just interprets the code as is, which all run quite a while. I tend to
write my code on a much slower computer and I being quite impatient, so I was
forced to abort the program and forced myself to actually read the assembly
code (input). It is actually quite interesting:

Day 12 calculates the fibonacci sequence, day 23 involves a big
multiplication, and day 25 outputs the a number in binary format. If we run
all additions and multiplications with "inc" and "dec", of course it is going
to take forever (on my computer at least). So for me, I was forced to read the
code and recognize the multiplication and algorithm and put in a couple
"shortcut". If my computer is any faster, I might miss the fun.

------
Buge
Interesting that he used a non-ascii character (Ø) as a variable name. Also
ctrl+f in Chrome seems to think this character is the same as o.

~~~
niwri
I wouldn't be surprised if that behaviour was intentional.

~~~
x3n0ph3n3
It's done with case-insensitive matching based on the rules of character
collation [1], but I'm struggling to find a good article on the topic.

1.[https://en.wikipedia.org/wiki/Collation](https://en.wikipedia.org/wiki/Collation)

~~~
Pyppe
Transliteration. See e.g.
[https://en.m.wikipedia.org/wiki/Transliteration](https://en.m.wikipedia.org/wiki/Transliteration)

------
dorianm
I feel like most of his Day 0 functions should be in Python's standard library
(groupby, first, firstrue (e.g.: detect), counttrue (e.g. count with block in
ruby), trace, etc.)

~~~
choppaface
It's funny seeing how Norvig implements some of these functions. I've seen a
few of these used as Google interview questions and Norvig's solutions would
not pass the hiring bar ...

~~~
kutkloon7
Of course. It would be idiotic to expect 'code of advent' solutions to pass as
production code, especially if you take into account the time pressure for
submitting these solutions.

~~~
taeric
I get what you are saying. However, the comparison is to whiteboard interview
questions. If these don't pass your bar... Think long and hard about what this
implies about who you would not hire.

------
Tycho
I love in Day 2 how he represents the keypad in string form, padded with .
characters to simplify the edge detection logic.

~~~
kornish
Also love how he aliases `str.split` to `Keypad` so you can see the intention
of his semantics that much more easily. And the assertion of keypad[2][2], as
a quick reference point for himself. The whole thing is just so eminently
understandable.

------
Dowwie
It's great to have a benchmark from which other work can be compared. Norvig's
submissions are one example for the Python community. Hopefully, other
submissions are raised for the other languages.

------
kutkloon7
I don't understand why solutions to pretty trivial problems are upvoted so
many times. Solutions to the very hardest project Euler problems would be far
more interesting.

~~~
RodericDay
The very hardest PE problems are almost completely mathematical and require
very straightforward code.

There's a few amazing computational ones interspersed, like the Numbermind
one, but in general I didn't find that the further along I went the harder I
worked out my elegant programming skills. It was mostly doing math on paper
and pressing it into code.

~~~
chillee
I agree. In my experience, Project Euler is more computer science for
mathematicians than math for computer scientists.

------
throwaway7645
I know Norvig uses both Lisp and Python, but it seems like he is all Python
these days. Nothing wrong with that, but a little depressing for Lisp.

~~~
js8
It's not a shame for a language to lose against Python. Python has by far the
best focus on usability of the standard libraries of all the languages I have
ever seen (which includes major ones). As they say, "practicality beats
purity".

Let me compare for example Lisp lists with Python lists. Lisp lists are in a
way more low-level, lacking useful things as slices. Sure you can always write
a function to do a slice, but the point is many useful functions are missing
from the standard libraries. I tried to learn Common Lisp and Clojure (I like
the language more than Python) but I was never more productive in it than in
Python for this reason.

This year, I have actually done some AoC in Haskell, and it's a similar deal
as with Lisp. There are plenty libraries, but they just don't work as well
together. An example: I needed a queue. So I used Data.Seq, but, there is no
pop() function. No big deal, for sure, but annoying. Another example: I wanted
to put list or set into a hash table, but unfortunately, these are not defined
as instances of Data.Hashable.

It's actually debatable whether list should be Hashable by default. Sure it
would be practical, but someone could complain about the hashing
implementation. And that's why Python is going to beat Haskell on these
problems, where you simply don't want to worry about thousands of those little
things.

I was actually thinking about building myself a "pythonic" Haskell prelude
which would have similar design to Python standard libraries and the same
attention to consistency.

~~~
hellofunk
I would expect Clojure's standard library to be just as useful as Python. I
did last years contest in Clojure and it was quite straightforward and fairly
little code.

Clojure is much much more usable than CL.

~~~
js8
The way I understood the Clojure's standard library is that for many things
(such as string manipulation) you have to fall back on Java libraries. And
Java standard string libraries are AFAIK terrible compared to Python (again,
no shame here).

~~~
hellofunk
That's certainly not true at all. Clojure has a rich string library where you
can do all sorts of manipulation. Clojure's strings are also native data
sequences so you can use the entire Clojure standard library's tools for
manipulating data right on strings naturally.

I wrote full-time Clojure for two years, and did all of last year's Advent of
Code in Clojure. In my entire life, I have never once written a line of Java
and I have no idea the details of its standard library. That's how well-
encapsulated Clojure is.

------
jblow
This class of problems falls into a weird space for me. They are 'toy
problems' but not I don't feel like I'd have fun doing them.

I had a lot of fun playing Shenzhen I/O and TIS-100, so if you want to do some
programming challenges, I'd recommend trying those.

~~~
joelgrus
Yeah, I made it about 5 days in this year and then quit because I wasn't
having fun.

Too many of the problems had the structure:

* here's Part A * submit solution for Part A * OK, now here's Part B * Part B is just different enough that you have to do a not-fun refactoring of your Part A code (that wouldn't be necessary if you'd just been asked to also design for Part B up front)

It was too much like working with an awful PM who can't decide what they want,
and it mostly just made me angry.

~~~
tptacek
One way to look at it is that the part-2 problems are un-fun retreads of the
part-1 problem.

The other (better, I think!) way of looking at it is that the part-2 problems
are incentive for you to think carefully about your part-1 solution, so that
it generalizes.

Norvig's keypad is a perfect example. Norvig's solution of a sentinel
character generalizes, as would a solution based on a simple graph structure.
But I plowed into it with a flat array of integers and the modulo operator,
and had to rewrite for part-2; my solution was, in the context of the contest,
inferior to Norvig's.

~~~
justinhj
I made a graph and it adapted nicely to part 2. An advantage of the graph is
that it would have handled the keypad becoming 3 dimensional or some other
change that stopped it working as a simple grid. A big disadvantage is I made
several errors while building the graph in both parts which took a while to
track down.

------
plg
I would like to see this done in C

~~~
sinisterstuf
I'd been following along in C, and I was very surprised to see how similar
some solutions were, e.g. as mentioned above[1], drawing a map of the keypad
with special characters for edge detection.

I've never finished an Advent of Code though, and I don't think I'd get
further in another language than C, I just spend most of my Christmas/December
time with family instead of coding; maybe if there was a February of Code I'd
participate more actively.

I actually think C is an _ideal_ language for challenges like these: parse a
simple input file, do one or two things and write out a number. In fact (with
a small number of very big exceptions) my code is usually quite short and
concise, even compared to solutions my friends write in higher level
languages. I originally picked C, not because I thought I'd be finish blazing
fast in it, but because I wanted to learn to use it better (also for work and
fun), so with that said, what little code I've written is publicly displayed
on GitHub[2] for (as Hungarians say) spitting at. It has some comments and
sometimes longish explanations about "design decisions" in the commit
messages. I really did end up learning a lot and I am much more fluent in C
now than before (no more Google/StackOverflowing every single statement,
hooray!), but perhaps the most surprising thing was:

You don't need a Makefile to build `thing` from `thing.c` if you don't need to
pass any fancy arguments or anything, you can just write `make thing` without
a Makefile and if there's a `thing.c` there it'll run gcc on it and produce
your binary!

I'd like to finish these challenges someday. Let's see.

1:
[https://news.ycombinator.com/item?id=13259460](https://news.ycombinator.com/item?id=13259460)

2:
[https://github.com/sinisterstuf/adventofcode](https://github.com/sinisterstuf/adventofcode)

