I've decided to try using notmuch
for my email instead of mu
.
This is mostly due to the tagging nature (instead of folders), as well as the
built-in hooks that run pre- and post- indexing. It makes setting up certain
behaviours, along with afew
, much easier than in GMail's filters.
I've also moved to using lieer
to sync the GMail inbox, as it hopefully
gets along nicer with large GMail inboxs, which is the case when you're
accepting the flood of emails from watching the GitLab project. The initial
sync is going very slowly though. lieer
syncs GMail's labels with notmuch
's
tags, and so syncing, tagging, and syncing 1.1 million emails can take some
time. I guess that's another reason to start using notmuch
: it was easy to set
up hooks to delete threads of issues and merge requests that are either closed
or merged, so hopefully that number drops quickly. I should modify my current
hook to preserve threads that I was involved in...
The main reason for the lack of posts is that its been a busy year. My travels
are as follows:
-
Hawaii, for a wedding
-
Montreal, for fun
-
Whitby, for a wedding
-
Portugal, for fun
-
Niagara-on-the-lake, for a wedding
-
North Carolina, for a wedding
-
Sarnia, for a wedding
Not all of these were long trips, and the longest was Portugal at 10 days, but
boy does it feel like a lot!
I've also bought a house this year. Maybe not the most perfect time to buy, but
we had the money and actually found a wonderful place in Toronto. It's a
completely different neighbourhood than we previously lived in, but it's
extremely walkable, bikeable, and right off the subway. I can easily continue my
car-free life.
That's right! This blog is now live on the gemini
protocol. Using your
favourite gemini browser, you can now see all this text in lo-fi glory.
Another multi-day combo post! I didn't get to start day 8 until late, and
finished it with 10 minutes to spare. Thus, no time to write a post yesterday.
A giant whale has decided your submarine is its next meal, and it's much
faster than you are. There's nowhere to run!
Thanks to the help of some crabs, we'll get past that whale!
This seems like a great job for simply brute-forcing the whole thing. I am sure
there is a way to utilize a binary search to find the answer, but I'm also
sure I'm in no mood to figure it out. Part one is still pretty small:
let p1_sol crabs =
List.fold_left
(fun min_fuel pos ->
let new_fuel =
List.fold_left (fun x y -> max y pos - min y pos + x) 0 crabs
in
if new_fuel < min_fuel then new_fuel else min_fuel)
Int.max_int crabs
let p1 =
let sol = p1_sol input in
Int.to_string sol
Once again I fold_left
over all the crabs, calculating the fuel cost for the
rest of the crabs, and finding the smallest total.
⭐ one done!
I've been busy so this is going to be a bit longer but also contain 3 whole
solutions!
Okay, the submarine is moving, we can see where we're going. Now to make
sure systems are ✔.
Today's struggle in learning was motivation. Fridays are tricky that
way, sometimes it's a mad rush to get everything done in time for
Saturday, others it's just a slog to the weekend. Today was the latter.
I found the first problem's trickiest bit to be how to parse the list
properly. Only after eating dinner and not being distracted by hunger
did the solution become obvious.
Now that I know where I am going, I get to figure out how to pilot the
submarine! The first puzzle is perfect for List.fold_left
:
let follow_instruction (x, y) (dir, num) match dir with
| "up" -> (x, y - num)
| "down" -> (x, y + num)
| "forward" -> (x + num, y)
| direction -> raise (Direction direction)
let p1_sol input let x, y = List.fold_left follow_instruction (0, 0) input in
x * y
I just match on the direction I am going and increment the correct
direction. All that's left is to compute the answer (multiply the
coordinates together).
If I just match on the four directions, up
, down
, forward
, then
ocaml complains that the match is not fully matched. Its type system
does not allow for uncaught matches, which are dependent on the type of
the variable. Here, the uncaught matches are literally every string of
characters that isn't one of the directions. The correct answer is to
parse these directions into a variant, a plain symbol-thing that is a
specific set of options: Up | Down | Forward
, and lift this error up
to where I parse the line. I didn't do that though, so I have to check
it here and throw if it is incorrect. As I feel very confident here
that it would not be, I think I am pretty safe.
☆ one done!
Ah, it has begun! The story this year is pretty good:
You're minding your own business on a ship at sea when the overboard alarm
goes off! You rush to see if you can help. Apparently, one of the Elves
tripped and accidentally sent the sleigh keys flying into the ocean!
Of course, our first instinct is to climb into the handy to have submarine and
get to work! The puzzle input is a list of numbers, each measuring the depth of
the water. First, I need to calculate the (rough) rate of change by counting the
number of times the depth increases.
This is a pretty simple job for some quick recursion!
let rec p1_sol input count match input with
| []
| [ _ ] -> count
| h1 :: h2 :: t ->
if h1 < h2 then p1_sol (h2 :: t) (count + 1) else p1_sol (h2 :: t) count
Here, input
is the list of numbers and count
is how often it has increased.
I match on the full list to see if there are at least 2 elements, so I can
compare them. If the second is higher, I increment the count by one. I pass the
rest of the list, including the second element, back to my function to compare
it to the next element and so on until the list is processed, and all in one
pass!
I find it interesting that recursive functions in ocaml must explicitly be
marked as recursive with the rec
tag. This goes for mutually recursive
functions, too! They use rec
and and
to indicate that one may call the other
and vice versa. I am not sure why this is, but I assume it is to indicate to the
compiler that, while p1_sol
doesn't exist yet, it is currently being defined
and don't worry too much.
⭐ one done!
Writing posts can be a bit troublesome to set up, and my major posting season is
nearly here! Fortunately, I can customize emacs a bit to make this whole process
at least a bit more optimized.
This will be my fourth (😮) year doing the Advent of Code challenges!
The first three years, I have attempted the challenges in elixir. I was
new to elixir, and (while still an amateur) I've grown pretty
comfortable with the language. It was fun creating simple OTP processes
to handle "communication" between two "computers", but I felt it was
time to strike out and learn something new!
I'm working on a big refactoring of my one elixir library, unleash
,
and one of the changes I'm working on is moving from using behaviour
s
and towards using protocol
s instead, but this means parsing a bunch
of JSON objects into their appropriate structs. While Poison
can
already do this, I don't want to be dependant on a single JSON library
(for now), and it doesn't quite tackle the problem at hand, so I got
to work.
After migrating two of the eight strategies to this new format, I saw a
lot of boilerplate, and got to work (learning to) writing a macro.
Alright, let's get technical.
An excellent question! When trying to figure out my migration away from
my static site and towards a dynamic site, I wanted to keep the one
thing I truly loved from the static site: an excellent writing and
editing experience.
As it so happens, at some point I decided to try out mu4e as a mail
client and found that it makes dealing with email so much easier by
eliminating the hassle of the bad web UI presented by anything that
wasn't Inbox (which, even then, still had its issues). The major
caveat being that I had to actually make use of custom filters and
folders to stay organized as well. Looking back, GMail's automatic
categorization was holding me back from actually putting the work in to
make my email the way I wanted it to be.
I've recently been making small to GitLab's email UX as
well, and I'm slowly working towards opening the floodgates and setting
my notification level to "watching" for the main project in an effort
to dogfood our email workflows.
All this to say: mu4e has fundamentally changed how I interact with
email. It has turned it from an annoying, slow click-based web app to an
amazingly quick, keyboard-based tool essential to my day-to-day.
Part of that all means that the authoring of these posts can happen in
the same place all my other writing happens! After all, why leave
emacs when you don't have to? All the customization around how I write
code now applies directly to how I write these blog posts. Now that the
core editing experience has been salvaged from the static site, the rest
can tumble from there.
If you've taken a peak at the source for this site, you might have
noticed a flake.nix
file sitting squarely at the root of the
project. I've been using NixOS on my home lab for about 5 years now,
although poorly until about 2 years ago, and for the most part I've
enjoyed my experience.
This is it! My new home on the internet!
I was tempted to find a spectacular "UNDER CONSTRUCTION" banner to put
up, but one of the ideas is that this place will always be "under
construction".
My old blog will remain up, and I'm sure I'll eventually add something
there to direct people here, but right now I am more excited about
making sure this works before I direct them to an empty site.