DEVELOPMENT ENVIRONMENT

~liljamo/aoc2024

ref: 849a172cb5a7c9112602c0ef98510654801e2f15 aoc2024/src/day5/mod.rs -rw-r--r-- 3.1 KiB
849a172cJonni Liljamo feat: day5 a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::{
    fs::File,
    io::{BufRead, BufReader},
    path::Path,
};

pub fn solve(input: &Path) -> anyhow::Result<()> {
    println!("part one: {}", part_one(input)?);
    println!("part two: {}", part_two(input)?);

    Ok(())
}

fn part_one(input: &Path) -> anyhow::Result<i32> {
    let reader = BufReader::new(File::open(input)?);

    let mut reading_rules = true;
    let mut rules = vec![];
    let mut pages_to_update = vec![];
    for line in reader.lines() {
        let line = line?;
        if line.is_empty() {
            reading_rules = false;
            continue;
        }
        if reading_rules {
            rules.push(
                line.split("|")
                    .map(|s| s.parse::<i32>().unwrap())
                    .collect::<Vec<i32>>(),
            )
        } else {
            pages_to_update.push(
                line.split(",")
                    .map(|s| s.parse::<i32>().unwrap())
                    .collect::<Vec<i32>>(),
            )
        }
    }

    let mut answer = 0;
    for pages in pages_to_update {
        if is_in_order(&pages, &rules) {
            answer += pages[pages.len() / 2];
        }
    }
    Ok(answer)
}

fn is_in_order(pages: &[i32], rules: &[Vec<i32>]) -> bool {
    for (left_index, page) in pages.iter().enumerate() {
        for rule in rules.iter().filter(|&r| r[0] == *page) {
            if let Some(right_index) = pages.iter().position(|n| *n == rule[1]) {
                if right_index < left_index {
                    return false;
                }
            }
        }
    }
    true
}

fn part_two(input: &Path) -> anyhow::Result<i32> {
    let reader = BufReader::new(File::open(input)?);

    let mut reading_rules = true;
    let mut rules = vec![];
    let mut pages_to_update = vec![];
    for line in reader.lines() {
        let line = line?;
        if line.is_empty() {
            reading_rules = false;
            continue;
        }
        if reading_rules {
            rules.push(
                line.split("|")
                    .map(|s| s.parse::<i32>().unwrap())
                    .collect::<Vec<i32>>(),
            )
        } else {
            pages_to_update.push(
                line.split(",")
                    .map(|s| s.parse::<i32>().unwrap())
                    .collect::<Vec<i32>>(),
            )
        }
    }

    let mut answer = 0;
    for pages in pages_to_update
        .iter()
        .filter(|pages| !is_in_order(pages, &rules))
    {
        answer += ordered(pages, &rules)[pages.len() / 2];
    }
    Ok(answer)
}

fn ordered(pages: &[i32], rules: &[Vec<i32>]) -> Vec<i32> {
    let mut pages = pages.to_owned();
    'w: while !is_in_order(&pages, rules) {
        for (left_index, page) in pages.iter().enumerate() {
            for rule in rules.iter().filter(|&r| r[0] == *page) {
                if let Some(right_index) = pages.iter().position(|n| *n == rule[1]) {
                    if right_index < left_index {
                        pages.swap(right_index, left_index);
                        continue 'w;
                    }
                }
            }
        }
    }
    pages
}