闘魂Elixir ── Advent of code 2023 Day 11 Part 1 を Livebook で楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>

https://qiita.com/advent-calendar/2023/elixir

## はじめに

@torifukukaiou さんの ~~パク~~ リスペクト記事です

https://qiita.com/torifukukaiou/items/5361b81407b15e7c2f00

Elixir Livebook で Advent of Code 2023 の問題を解いてみます

https://adventofcode.com/2023

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/aoc/2023/2023_day11_part1.livemd

問題はこちら

https://adventofcode.com/2023/day/11

## セットアップ

Kino AOC をインストールします

```elixir
Mix.install([
  {:kino_aoc, "~> 0.1.5"}
])
```

Kino AOC の使い方はこちらを参照

https://qiita.com/RyoWakabayashi/items/3d3abcf9134cee4dff05

## 入力の取得

Day 11 の入力を取得します

![スクリーンショット 2023-12-29 12.04.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/4ef51acd-1a73-9d29-fcca-a1e8da062f9f.png)

## 私の答え

私の答えです。
折りたたんでおきます。
▶を押して開いてください。

<details><summary>details</summary>

回答用のモジュールです

入力を扱いやすい形にするための `parse` と、回答を作るための `resolve` 関数を持っています

```elixir
defmodule Resolver do
  def parse(input) do
    orig_space =
      input
      |> String.split("\n")
      |> Enum.with_index()
      |> Enum.map(fn {line, row} ->
        line
        |> String.codepoints()
        |> Enum.with_index()
        |> Enum.filter(fn {cell, _} -> cell == "#" end)
        |> Enum.map(fn {_, col} -> {row, col} end)
      end)
      |> Enum.concat()
  
    max_row =
      orig_space
      |> Enum.map(fn {row, _} -> row end)
      |> Enum.max()

    max_col =
      orig_space
      |> Enum.map(fn {col, _} -> col end)
      |> Enum.max()

    empty_rows =
      0..max_row
      |> Enum.filter(fn target_row ->
        orig_space
        |> Enum.map(fn {row, _} -> row end)
        |> Enum.member?(target_row)
        |> Kernel.!()
      end)

    empty_cols =
      0..max_col
      |> Enum.filter(fn target_col ->
        orig_space
        |> Enum.map(fn {_, col} -> col end)
        |> Enum.member?(target_col)
        |> Kernel.!()
      end)

    orig_space
    |> Enum.map(fn {row, col} ->
      ex_rows = Enum.count(empty_rows, fn empty_row -> row > empty_row end)
      ex_cols = Enum.count(empty_cols, fn empty_col -> col > empty_col end)
      
      {row + ex_rows, col + ex_cols}
    end)
  end

  def resolve(space) do
    space
    |> Enum.with_index()
    |> Enum.map(fn {{src_row, src_col}, src_index} ->
      space
      |> Enum.with_index()
      |> Enum.map(fn {{dst_row, dst_col}, dst_index} ->
        if src_index >= dst_index do
          0
        else
          abs(dst_row - src_row) + abs(dst_col - src_col)
        end
      end)
      |> Enum.sum()
    end)
    |> Enum.sum()
  end
end
```

`parse` で銀河 = `"#"` のところだけ座標を取得します

空白行、空白列は2倍に膨らむ = 各座標は空白行、空白列を超えている分だけ加算される、という計算をして、 `parse`　の時点で膨張後の結果を取得しています

`resolve` では単純に各銀河間の距離を計算し、足しています

同じ組み合わせは計算しないよう、 `src_index >= dst_index` の場合は 0 にしています

</details>

## まとめ

Part 1 なのでここまでは簡単ですが、、、

Part 2 はどうなることか

https://qiita.com/RyoWakabayashi/items/13d517e06026abe8a1c9