kwando

kwando

Advent of Code 2022 - Day 18

Today was fun and I got it right the first time :slight_smile: MapSets saves the day again.

First Post!

lud

lud

A slightly different take on the same general idea:

defmodule Aoe.Y22.Day18 do
  alias Aoe.Input, warn: false

  def read_file!(file, _part) do
    Input.stream_file_lines(file, trim: true)
  end

  def parse_input!(input, _part) do
    input |> Enum.map(&parse_line/1)
  end

  defp parse_line(line) do
    [x, y, z] = line |> String.split(",") |> Enum.map(&String.to_integer/1)
    {x, y, z}
  end

  def part_one(cube_list) do
    lookup_map = Map.new(cube_list, &{&1, true})

    surf_map =
      Enum.reduce(cube_list, %{}, fn cube, surf_map ->
        Map.put(surf_map, cube, n_uncovered(cube, lookup_map))
      end)

    surf_map |> Map.values() |> Enum.sum()
  end

  def part_two(cube_list) do
    lookup_map = Map.new(cube_list, &{&1, true})

    xl = Enum.reduce(cube_list, &min_x/2) - 1
    yl = Enum.reduce(cube_list, &min_y/2) - 1
    zl = Enum.reduce(cube_list, &min_z/2) - 1

    xh = Enum.reduce(cube_list, &max_x/2) + 1
    yh = Enum.reduce(cube_list, &max_y/2) + 1
    zh = Enum.reduce(cube_list, &max_z/2) + 1

    path_start = {xl, yl, zl}
    max_range = {xh, yh, zh}

    explored = explore([path_start], {path_start, max_range}, lookup_map, %{})

    explored |> Map.values() |> Enum.sum()
  end

  defp explore([cur | open], minmax, lookup_map, explored) do
    {lava_neighs, free_neighs} = split_neighs(cur, lookup_map, minmax)
    faces = length(lava_neighs)
    explored = Map.put(explored, cur, faces)
    free_neighs = Enum.filter(free_neighs, &(&1 not in open and not Map.has_key?(explored, &1)))
    explore(free_neighs ++ open, minmax, lookup_map, explored)
  end

  defp explore([], _, _, explored) do
    explored
  end

  defp split_neighs(cube, lookup_map, minmax) do
    neighs = cardinal_neighbours(cube)
    {lava_neighs, free_neighs} = Enum.split_with(neighs, &Map.has_key?(lookup_map, &1))
    free_neighs = clamp_neighs(free_neighs, minmax)
    {lava_neighs, free_neighs}
  end

  defp clamp_neighs(cubes, minmax) do
    Enum.filter(cubes, &in_boundary(&1, minmax))
  end

  defp in_boundary({x, y, z}, {{xl, yl, zl}, {xh, yh, zh}}) do
    x >= xl and x <= xh and
      y >= yl and y <= yh and
      z >= zl and z <= zh
  end

  defp n_uncovered(cube, lookup_map) do
    cube |> cardinal_neighbours() |> Enum.reject(&Map.has_key?(lookup_map, &1)) |> Enum.count()
  end

  defp cardinal_neighbours({x, y, z}) do
    [
      {x - 1, y, z},
      {x + 1, y, z},
      {x, y - 1, z},
      {x, y + 1, z},
      {x, y, z - 1},
      {x, y, z + 1}
    ]
  end

  defp max_x({a, _, _}, {b, _, _}), do: max(a, b)
  defp max_x({a, _, _}, b) when is_integer(b), do: max(a, b)
  defp min_x({a, _, _}, {b, _, _}), do: min(a, b)
  defp min_x({a, _, _}, b) when is_integer(b), do: min(a, b)
  defp max_y({_, a, _}, {_, b, _}), do: max(a, b)
  defp max_y({_, a, _}, b) when is_integer(b), do: max(a, b)
  defp min_y({_, a, _}, {_, b, _}), do: min(a, b)
  defp min_y({_, a, _}, b) when is_integer(b), do: min(a, b)
  defp max_z({_, _, a}, {_, _, b}), do: max(a, b)
  defp max_z({_, _, a}, b) when is_integer(b), do: max(a, b)
  defp min_z({_, _, a}, {_, _, b}), do: min(a, b)
  defp min_z({_, _, a}, b) when is_integer(b), do: min(a, b)
end

Quick and fun today :smiley:

Where Next?

Popular in Challenges Top

LostKobrakai
This topic is about Day 9 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
sasajuric
Note: This topic is to talk about Day 12 of the Advent of Code. For general discussion about the Advent of Code 2018 and links to topics...
New
sneako
Note by the Moderators: This topic is to talk about the first day of the Advent of Code. For general discussion about the Advent of Code...
New
QuinnWilton
Note: This topic is to talk about Day 7 of the Advent of Code 2019 . There is a private leaderboard for elixirforum members. You can joi...
New
bjorng
Note: This topic is to talk about Day 13 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can joi...
New
bjorng
Here is my solution for day 1 of Advent of Code: defmodule Day01 do def part1(input) do all = parse(input) {first, second} = E...
New
bjorng
This topic is about Day 15 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adve...
New
bjorng
This topic is about Day 10 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums ): https://adv...
New
New
coen.bakker
Since I started using Elixir, I have benefited greatly from being able to study various open-source projects. The codebase of LiveBook, i...
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New

We're in Beta

About us Mission Statement