AOC 2024, Day 05: Print Queue¶
Day 5 of Advent of Code 2024, Print Queue, brings us to the North Pole's printing department, where safety is key as the Elves prepare for the sleigh launch. Our task is to ensure that updates to the safety manual are printed in the correct order. The challenge combines order validation, sorting, and some arithmetic to guarantee a smooth process.
Elf Shenanigans¶
Part 1: Checking the Order¶
For the first part, we verify that the updates follow the specified ordering rules. For each rule X|Y
, page X
must appear before page Y
. Once the updates are validated, we calculate the middle page number of the valid updates and sum them.
Part 2: Fixing the Order¶
For the second part, we need to reorder the updates that don't follow the rules. After applying the correct order, we, like in part 1, find the middle page number for each corrected update and sum them up.
Santa's Ingenious Solutions¶
using Pages = string[];
using PageUpdates = string[][];
using PagePrecedenceRules = System.Collections.Generic.Comparer<string>;
namespace AdventOfCode.Y2024;
[AocPuzzle(2024, 5, "Print Queue", "C#")]
public sealed class Day05 : IAocDay<int>
{
public static int Part1(AocInput input) =>
input.Text
.Pipe(SleighLaunchSafetyManual)
.Pipe(manual => manual.Updates
.Where(pages => ElfPageSorting(manual.PrecedenceRules, pages))
.Sum(ExtractMiddlePage)
);
public static int Part2(AocInput input) =>
input.Text
.Pipe(SleighLaunchSafetyManual)
.Pipe(manual => manual.Updates
.Where(pages => ElfPageSorting(manual.PrecedenceRules, pages) is false)
.Select(pages => pages.OrderBy(p => p, manual.PrecedenceRules).ToArray())
.Sum(ExtractMiddlePage)
);
private static SafetyManual SleighLaunchSafetyManual(string text)
{
var parts = text.Split("\n\n");
var ordering = parts[0].Split('\n').ToHashSet();
var updates = parts[1].Split('\n').Select(u => u.Split(',')).ToArray();
return new SafetyManual(
updates,
PagePrecedenceRules.Create((p1, p2) => ordering.Contains($"{p1}|{p2}") ? -1 : 1)
);
}
private static bool ElfPageSorting(PagePrecedenceRules precedenceRules, Pages pages) =>
pages.SequenceEqual(pages.OrderBy(p => p, precedenceRules));
private static int ExtractMiddlePage(Pages pages) =>
int.Parse(pages[pages.Length / 2]);
private readonly record struct SafetyManual(PageUpdates Updates, PagePrecedenceRules PrecedenceRules);
}
open AdventOfCode.Lib
[<AocPuzzle(2024, 5, "Print Queue", "F#")>]
module Fay05 =
type Pages = string array
type PageUpdates = string array array
type PagePrecedenceRules = System.Collections.Generic.Comparer<string>
type SafetyManual = {
Updates: PageUpdates
PrecedenceRules: PagePrecedenceRules
}
let sleighLaunchSafetyManual (text: string) =
let parts = text.Split("\n\n")
let ordering = parts[0].Split('\n') |> Set.ofArray
let updates = parts[1].Split('\n') |> Array.map _.Split(',')
let precedenceRules =
PagePrecedenceRules.Create(fun p1 p2 -> if ordering.Contains $"%s{p1}|%s{p2}" then -1 else 1)
{ Updates = updates; PrecedenceRules = precedenceRules }
let elfPageSorting (precedenceRules: PagePrecedenceRules) (pages: Pages) =
pages = Array.sortWith (fun p1 p2 -> precedenceRules.Compare(p1, p2)) pages
let extractMiddlePage (pages: Pages) = int pages[Array.length pages / 2]
let part1 (input: AocInput) =
input.Text
|> sleighLaunchSafetyManual
|> fun manual ->
manual.Updates
|> Array.filter (elfPageSorting manual.PrecedenceRules)
|> Array.sumBy extractMiddlePage
let part2 (input: AocInput) =
input.Text
|> sleighLaunchSafetyManual
|> fun manual ->
manual.Updates
|> Array.filter (fun pages -> not (elfPageSorting manual.PrecedenceRules pages))
|> Array.map (Array.sortWith (fun p1 p2 -> manual.PrecedenceRules.Compare(p1, p2)))
|> Array.sumBy extractMiddlePage
from aoc.core import AocInput
from dataclasses import dataclass
from functools import cmp_to_key
from typing import Callable
type Pages = list[str]
type PageUpdates = list[Pages]
type PagePrecedenceRules = Callable[[str, str], int]
@dataclass(frozen=True, slots=True)
class SafetyManual:
updates: PageUpdates
precedence_rules: PagePrecedenceRules
def sleigh_launch_safety_manual(text: str) -> SafetyManual:
parts = text.split("\n\n")
ordering = set(parts[0].split("\n"))
updates = [u.split(",") for u in parts[1].split("\n")]
precedence_rules = lambda p1, p2: -1 if f"{p1}|{p2}" in ordering else 1
return SafetyManual(updates, precedence_rules)
def elf_page_sorting(precedence_rules: PagePrecedenceRules, pages: Pages) -> bool:
return pages == sorted(pages, key=cmp_to_key(precedence_rules))
def extract_middle_page(pages: Pages) -> int:
return int(pages[len(pages) // 2])
def part1(input: AocInput) -> int:
manual = sleigh_launch_safety_manual(input.text)
return sum(
extract_middle_page(p)
for p in [
p for p in manual.updates if elf_page_sorting(manual.precedence_rules, p)
]
)
def part2(input: AocInput) -> int:
manual = sleigh_launch_safety_manual(input.text)
return sum(
extract_middle_page(p)
for p in [
sorted(p, key=cmp_to_key(manual.precedence_rules))
for p in [p for p in manual.updates if elf_page_sorting(manual.precedence_rules, p) is False]
]
)
Santa's & Elves' Reflections¶
Day 5 of Advent of Code 2024 presents a logical challenge in dependency management and sorting. The key to solving both parts lies in understanding how to validate page orders and using sorting techniques for reordering. With the right approach, we've ensured that the North Pole's safety manuals are properly updated for the upcoming sleigh launch!
Check out the repository for solutions: AdventOfCode & AdventOfCode.Lib.