code-shoily

code-shoily

Advent of Code 2021 - Day 3

Just did part 1. Part 2 seems to be demanding too much of my reading time so will get to that after I am done with some chores.

Oh here is the repository just in case someone wants the template generator.

I just did the dumbest path - read > transpose each > get most and least common > multiply :smiley: I am sure folks will come up with super smart solutions any time now :wink:

defmodule AdventOfCode.Y2021.Day03 do
  @moduledoc """
  --- Day 3: Binary Diagnostic ---
  Problem Link: https://adventofcode.com/2021/day/3
  """
  use AdventOfCode.Helpers.InputReader, year: 2021, day: 3

  def run_1 do
    input!()
    |> parse()
    |> transpose()
    |> bit_frequencies()
    |> get_min_max()
    |> Tuple.product()
  end

  def run_2, do: {:not_implemented, 2}
  def parse(data), do: data |> String.split("\n", trim: true) |> Enum.map(&String.graphemes/1)
  defp transpose(data), do: data |> Enum.zip() |> Enum.map(&Tuple.to_list/1)

  defp bit_frequencies(data) do
    data
    |> Enum.map(&Enum.frequencies/1)
    |> Enum.reduce([], fn
      %{"0" => lo, "1" => hi}, acc when lo > hi -> [{0, 1} | acc]
      _, acc -> [{1, 0} | acc]
    end)
  end

  defp to_integer_by(encoded_data, index) do
    encoded_data
    |> Enum.map_join(&elem(&1, index))
    |> String.reverse()
    |> String.to_integer(2)
  end

  defp get_min_max(encoded_data) do
    {to_integer_by(encoded_data, 0), to_integer_by(encoded_data, 1)}
  end
end

First Post! Switch mode

Aetherus

Aetherus

There’s a little bit faster solution for part 1, you only need to calculate gamma or epsilon, not both.

Suppose we calculated gamma, then epsilon is just (~~~gamma) &&& 0b111111111111, or (1 <<< 12) - 1 - gamma.

Most Liked

bjorng

bjorng

Erlang Core Team

The ~~~ operator when given a positive number always returns a negative number. It does that simulate that an integer holds an infinite number of bits. If the number starts with an infinite number of ones, the number is negative. If it starts with an infinite number of zeroes, it is positive.

When I first learned Erlang, it took me a while to figure out why that’s make sense.

Yes, an infinite number of bits. Fortunately the runtime system is smart enough to not store all them explicitly. :wink:

Aetherus

Aetherus

Again, my solution:

Part 1

#!/usr/bin/env elixir

use Bitwise

max = ((1 <<< 12) - 1)

gamma =
  File.stream!("input.txt")
  |> Stream.map(&String.trim/1)
  |> Stream.map(&String.split(&1, "", trim: true))
  |> Enum.zip()
  |> Enum.map(&Tuple.to_list/1)
  |> Stream.map(&Enum.frequencies/1)
  |> Stream.map(&Enum.max_by(&1, fn {_, f} -> f end))
  |> Stream.map(&elem(&1, 0))
  |> Enum.join("")
  |> String.to_integer(2)

epsilon = max - gamma

IO.inspect(epsilon * gamma)

Part 2

#!/usr/bin/env elixir

defmodule P2 do
  def o2([elem], _pos), do: to_i(elem)

  def o2(list, pos) do
    groups = Enum.group_by(list, &elem(&1, pos))
    group0 = groups["0"] || []
    group1 = groups["1"] || []
    if length(group0) > length(group1) do
      o2(group0, pos + 1)
    else
      o2(group1, pos + 1)
    end
  end

  def co2([elem], _pos), do: to_i(elem)

  def co2(list, pos) do
    groups = Enum.group_by(list, &elem(&1, pos))
    group0 = groups["0"] || []
    group1 = groups["1"] || []
    if length(group1) < length(group0) do
      co2(group1, pos + 1)
    else
      co2(group0, pos + 1)
    end
  end

  defp to_i(tuple), do:
    tuple
    |> Tuple.to_list()
    |> Enum.join("")
    |> String.to_integer(2)
end

input =
  File.stream!("input.txt")
  |> Stream.map(&String.trim/1)
  |> Stream.map(&String.split(&1, "", trim: true))
  |> Enum.map(&List.to_tuple/1)

IO.inspect(P2.o2(input, 0) * P2.co2(input, 0))
josevalim

josevalim

Creator of Elixir

My solution: https://github.com/josevalim/aoc/blob/main/2021/day-03.livemd

Live streaming: Twitch - we also solved part 1 with Nx and had a bit of fun with Livebook. :slight_smile:

Last Post!

adamu

adamu

I did it with bitstrings. But I wasn’t clever enough to notice you can skip calculating eplison.

Also, yes I know it’s 2022. Had submarine problems.

  def part2(input) do
    oxygen_generator_rating = find_rating2(input, 0, :most)
    co2_scrubber_rating = find_rating2(input, 0, :least)
    oxygen_generator_rating * co2_scrubber_rating
  end

  defp find_rating2([bits], _bits_seen, _mode) do
    <<value::size(bit_size(bits))>> = bits
    value
  end

  defp find_rating2(values, bits_seen, mode) do
    bit = find_common(values, bits_seen, mode)

    values
    |> filter_by_bit(bits_seen, bit)
    |> find_rating2(bits_seen + 1, mode)
  end

  defp find_common(values, bits_seen, mode) do
    {zeros, ones} =
      values
      |> Enum.map(fn <<_::size(bits_seen), bit::1, _rest::bits>> -> bit end)
      |> Enum.reduce({_zeros = 0, _ones = 0}, fn
        0, {zeros, ones} -> {zeros + 1, ones}
        1, {zeros, ones} -> {zeros, ones + 1}
      end)

    case mode do
      :most -> if zeros <= ones, do: 1, else: 0
      :least -> if zeros <= ones, do: 0, else: 1
    end
  end

  defp filter_by_bit(values, num_prev_bits, bit) do
    Enum.filter(values, &match?(<<_::size(num_prev_bits), ^bit::1, _rest::bits>>, &1))
  end

https://git.adamu.jp/adam/AdventOfCode/src/branch/main/2021/day3.exs

Where Next?

Trending in Challenges Top

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement