Andrew Fontaine

Mostly code
me

🇨🇦 software engineer, runs on ☕

  • Currently in Sault Ste. Marie, ON
  • Working remotely as a Frontend Engineer for

I see I am trying not to crash today. I’ve been given some pretty simple instructions on how to handle tracking how gravity applies to the moons, so first I’ll go about implementing that. A moon can be a map that contains its position and its velocity: %{p: {0, 0, 0}, v: {0, 0, 0}}

  defp apply_velocity(%{p: {x1, y1, z1}, v: {x2, y2, z2} = v}) do
    %{p: {x1 + x2, y1 + y2, z1 + z2}, v: v}
  end

  defp set_velocity(%{p: p1, v: v1}, %{p: p2}) do
    %{p: p1, v: apply_gravity(v1, gravity_diff(p1, p2))}
  end

  defp apply_gravity({x1, y1, z1}, {x2, y2, z2}) do
    {x1 + x2, y1 + y2, z1 + z2}
  end

  defp gravity_diff({x1, y1, z1}, {x2, y2, z2}) do
    {gravity_diff(x1, x2), gravity_diff(y1, y2), gravity_diff(z1, z2)}
  end

  defp gravity_diff(p1, p2) when p1 > p2, do: -1
  defp gravity_diff(p1, p2) when p1 == p2, do: 0
  defp gravity_diff(p1, p2) when p1 < p2, do: 1

apply_gravity/2 takes the positions of 2 moons, and computes how gravity affects the velocity of the first moon. gravity_diff/2 takes two positions and calculates how gravity affects the first moon by returning a differential, such as {-1, 1, 0}. set_velocity/2 uses the above two functions to apply gravity to the first moon, as computed above, and apply_velocity/1 alters the given moon’s position by its velocity. All that’s left is to chunk the moons through it for 1000 steps and calculate the final energy output.

Read more.

More intcode problems! First, I’ll tune up the intcode computer a little bit. I noticed day 9 ran a little slow, and I think it’s because the program is a list. In elixir, lists are implemented as linked lists, which don’t have the best access time, as the list needs to be iterated through to find the element at the given index, so read-heavy operations, like the intcode computer, can suffer, especially as the intcode computer appends a memory space at the end of the list to use as variables. Iterating through 1000 items every time I need to read an element there can take its toll! I can do better.

I also wasn’t pleased with how the list had to expand when writing to an address outside of the bounds of the current memory space. I wanted something that didn’t need to grow as much while also providing an easy way of returning a default for address that I don’t know about yet. A Map is perfect for this!

Read more.

Cool, asteroids! Not cool, trigonometry!

Let me just search my brain for math I haven’t used in years, no problem at all. Let’s see… if I have one asteroid, x, and two others, y and z, and the angle between x and y is the same as x and z, the only one of y and z is visible. For the first problem, calculating the angles between all the asteroids and eliminating duplicates will show how many other asteroids are visible from a single asteroid.

Read more.

As of today, I’ve beaten my previous year’s record (by one ⭐), but, oh, was it a struggle. The task today is to boost a distress signal to discover what trouble those elves are up to now. First step is to add another parameter mode to the intcode computer! I need to add an offset value to the computer to keep track of the relative mode’s base offset, and add some ways to read the memory utilizing this parameter mode.

  defstruct program: [],
            position: 0,
            input: [],
            output: [],
            offset: 0

  defp parameter(0, x, prog, _computer), do: Enum.at(prog, x, 0)

  defp parameter(1, x, _prog, _computer), do: x

  defp parameter(2, x, prog, %__MODULE__{offset: offset}), do: Enum.at(prog, x + offset, 0)

Notice that I have to pass the computer struct into all of these functions so that I can access the offset in the new mode. I think I could alter this here to drop the prog parameter and pull it from the computer struct as well, but I have some other plans to tune up this computer.

Read more.

Saving a mars rover for the elves today! Why do they have to send the password as an image though? Just send me a text, jeez! Anyway, first step is to check and make sure the image was fully received. I can use Stream.chunk_every/2 to turn my list of digits to a list of layers. The only difference is that Stream versions of Enum functions return Streams that are lazily evaluated instead of iterating through the list all at once.

  defp parse_input() do
    input_stream()
    |> Enum.at(0)
    |> String.graphemes()
    |> Stream.map(&String.to_integer/1)
  end

  defp parse_layers(stream, x, y), do: Stream.chunk_every(stream, x * y)

All that’s left is to find the layer that has the least number of 0s, and return the checksum.

Read more.
Older Newer