[Advent of Code 2024] Day 5: Print Queue

この記事は、[mae616 Advent of Code Advent Calendar 2024](https://qiita.com/advent-calendar/2024/mae616) の5日目の記事です。

https://qiita.com/advent-calendar/2024/mae616

このアドベントカレンダーは皆勤賞のQiitaくんのぬいぐるみに惹かれて挑戦している大変ゆるい挑戦のものです。そんな感じで読んでいただければ幸いです。

5日間やって、だんだんひたすら自分がプログラミングで遊んでるのをただ書いてる記事として、ちょっと楽しくなってきました。
ChatGPTさんに「こんな記事でいいの？」で聞くと「こういうのでいいんだよ、こういうので」と返されたので、今回のアドベントカレンダーが終わったら同じようなノリで、次の時期の投稿マラソンでも書いてみようかと思い始めてます٩( ᐛ )و

---

前の日: [[Advent of Code 2024] Day 4: Ceres Search](https://qiita.com/mae616/items/fc83c5e720b35e6d6239)
次の日: [[Advent of Code 2024] Day 6: Guard Gallivant](https://qiita.com/mae616/items/9752e5f53b87a5f6469e)

# 今日のお題

https://adventofcode.com/

https://adventofcode.com/2024/day/5

# 5日目の物語
> ■ 5日目: 印刷キュー
> セレスでの調査に満足した歴史学者たちの隊は、次に『地下17階の文房具の山』を調べることを提案します。

今回はQueueの問題ですかね٩( ᐛ )و

> クリスマスが近づき、北極の印刷部門は例年以上に忙しくなっています。その間も歴史学者たちはこの歴史的に重要な施設を調べ続けている中で、『見慣れたプリンター』を操作するエルフがあなたを呼び寄せます。

『見慣れたプリンター』もAdvent of Code 2017と繋がってるみたいですね。

> エルフはあなたを知っているようで、すぐに「新しいそりの発射安全マニュアルの更新が正しく印刷できない」ことを説明し始めます。安全マニュアルの更新を怠るのは大変な事態を招くので、あなたは手を貸すことにします。

だんだんファンタジーの世界観に慣れてきました٩( ᐛ )و

# 1問目
おお、問題が長い ꉂꉂ( ᐛ )

例:
```
47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13

75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47
```
最初のセクション `Number|Number` のところはページの『印刷順番のルール』が1行ごとに指定されています。
最初のルール、`47|53` は、更新にページ番号 `47` とページ番号 `53` の両方が含まれている場合、ページ番号 `47` はページ番号 `53` より前に印刷されなければならないことを意味します。（`47` は必ずしも `53` の直前である必要はなく、他のページがその間に入ることは許されています。）

2番目のセクション(`Number,Number,Number ...`)では、各『更新するページ番号』が指定されています。最初の更新、`75,47,61,53,29` は、この更新がページ番号 `75`、`47`、`61`、`53`、`29`で構成されていることを意味します。

プリンターをできるだけ早く動かすために、『印刷順番のルール』に従った、正しい順番になっている『更新するページ番号』を特定します。

(長いので正しい順番かの証明は、Advent of Codeのページをご参照ください)

そして、正しい順番で印刷されている更新だけの真ん中のページの合計を求めてください。
上記の例では、

75,47,<INS>61</INS>,53,29
97,61,<INS>53</INS>,29,13
75,<INS>29</INS>,13

が正しい順番の更新と真ん中のページ番号になり、`61 + 53 + 29 =` の `143` が答えになります。
　

んー。これ、自分まだあんまり競プロ問題を数多く解いてないので、もしかしたら多分今の自分ではベストプラクティスが浮かばない系のやつですかね ꉂꉂ( ᐛ )
まあ、いいや。そのうちちゃんと勉強しよ ꉂꉂ( ᐛ )

## 解いてみたコード
```js: ./day5_1/main
function main(input) {
  const args = input.split("\n");

  const rules = [];
  const prints = [];
  for (const arg of args) {
    if (arg === "") continue;
    if (arg.includes("|")) {
      rules.push(arg.split("|").map(Number));
    } else if (arg.includes(",")) {
      prints.push(arg.split(",").map(Number));
    }
  }

  let sum = 0;
  for (const print of prints) {
    let hit = true;
    for (const rule of rules) {
      let index = 0;
      for (const r of rule) {
        if (!print.includes(r)) {
          break;
        }

        if (!print.includes(r, index)) {
          hit = false;
          break;
        }
        index = print.indexOf(r, index);
      }

      if (!hit) {
        break;
      }
    }

    if (hit) {
      const mid = Math.trunc(print.length / 2);
      sum += print[mid];
    }
  }
  console.log(sum);
}

main(require("fs").readFileSync("./input/puzzle.txt", "utf8"));
```

https://github.com/mae616/adventOfCode2024/tree/main/day5_1

下記で実行できます。
```zsh
cd day5_1
node main.js
```

# 2問目
1問目で間違ってる順番となった各更新について、『印刷順番のルール』に従って印刷ページを並び替えてください。
正しく並び替えた後、その並び替えた更新の真ん中のページの合計を求めてください。

　
あ、これわかんない ꉂꉂ( ᐛ )
これがQueueなのかな？

## 解いてみたコード
```js: ./day5_2/main.js
function main(input) {
  const args = input.split("\n");

  const rules = [];
  const prints = [];
  for (const arg of args) {
    if (arg === "") continue;
    if (arg.includes("|")) {
      rules.push(arg.split("|").map(Number));
    } else if (arg.includes(",")) {
      prints.push(arg.split(",").map(Number));
    }
  }

  let sum = 0;
  for (const print of prints) {
    if (!passRule(print, rules)) {
      const newPrint = sortAgain(print, rules);
      const mid = Math.trunc(newPrint.length / 2);
      sum += newPrint[mid];
    }
  }
  console.log(sum);
}

function passRule(print, rules) {
  let hit = true;
  for (const rule of rules) {
    let index = 0;
    for (const r of rule) {
      if (!print.includes(r)) {
        break;
      }

      if (!print.includes(r, index)) {
        hit = false;
        break;
      }
      index = print.indexOf(r, index);
    }

    if (!hit) {
      break;
    }
  }
  return hit;
}

function sortAgain(arr, rules) {
  let result = [...arr];
  while (!passRule(result, rules)) {
    for (const rule of rules) {
      let index = 0;
      for (const r of rule) {
        if (!result.includes(r)) {
          break;
        }

        if (!result.includes(r, index)) {
          const i = result.indexOf(r);
          const temp = result[i];
          result = [...result.slice(0, i), ...result.slice(i + 1), temp];
        }
        index = result.indexOf(r, index);
      }
    }
  }
  return result;
}

main(require("fs").readFileSync("./input/puzzle.txt", "utf8"));
```

すみません。「とりあえずQueueの問題っぽいから後ろに足してけばいいのかな」で解きました。
ちゃんと勉強して理解しないと、ですね。賢い頭が欲しいです ꉂꉂ( ᐛ )

https://github.com/mae616/adventOfCode2024/tree/main/day5_2

今日は終わりです٩( ᐛ )و
お疲れさまです٩( ᐛ )و

---

今日の海外の人は...
https://www.reddit.com/r/adventofcode/
2問目を難しく考えすぎた、との意見が多いようですね。みんな総当たりみたいですね。
しかし、かかった時間が分や秒で海外の人こわいですね ꉂꉂ( ᐛ )
このプリンターいつも壊れているのかな ꉂꉂ( ᐛ )

では、また明日