summaryrefslogtreecommitdiff
path: root/2023/Rust/src/day5.rs
blob: bd57e90122d9a93407ec74a5dab3672b88cff6cf (plain)
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
use std::collections::HashSet;

fn solve_part_one(data: &str) -> u32 {
    let mut almanac = Almanac::from(data);
    let mut seeds = almanac.seeds.clone();
    let mut nseeds = vec![];
    for i in (0..seeds.len()).step_by(2) {
        for j in seeds[i]..seeds[i] + seeds[i + 1] {
            nseeds.push(j);
        }
    }
    almanac.seeds = nseeds;

    let mut seeds = almanac.seeds.clone();
    for (_, maps) in almanac.maps.iter() {
        for seed in seeds.iter_mut() {
            let tmp = seed.clone();
            for seed_map in maps.iter() {
                if seed_map.contains(tmp) {
                    *seed += (seed_map.dest as i64 - seed_map.src as i64) as i64;
                }
            }
        }
    }
    *seeds.iter().min().unwrap() as u32
}

fn solve_part_two(data: &str) -> u64 {
    let mut almanac = Almanac::from(data);
    let seeds = almanac.seeds.clone();
    let mut set: HashSet<i64> = HashSet::new();
    let mut sum = 0;
    for i in (0..seeds.len()).step_by(2) {
        for j in seeds[i]..seeds[i] + seeds[i + 1] {
            set.insert(j);
        }
        sum += seeds[i] + seeds[i + 1];
    }
    dbg!(set.len());
    sum as u64
}

type Seeds = Vec<i64>;

#[derive(Debug)]
struct Almanac<'a> {
    seeds: Seeds,
    maps: Vec<(&'a str, Vec<SeedMap>)>,
}

impl<'a> From<&'a str> for Almanac<'a> {
    fn from(data: &'a str) -> Self {
        let data: Vec<&str> = data.split("\n\n").collect();
        let (_, seeds) = data[0].split_once(": ").unwrap();
        let seeds: Vec<_> = seeds
            .split(' ')
            .map(|x| x.parse::<i64>().unwrap())
            .collect();
        let mut maps: Vec<(&'a str, Vec<SeedMap>)> = Vec::new();
        for map in data.iter().skip(1) {
            let (desc, seed_maps) = map.split_once(':').unwrap();
            let (name, _) = desc.split_once(' ').unwrap();
            let mut v = vec![];
            for smap in seed_maps.trim_start().trim_end().split('\n') {
                v.push(SeedMap::from(smap));
            }
            maps.push((name, v));
        }
        Self { seeds, maps }
    }
}

#[derive(Debug)]
struct SeedMap {
    src: usize,
    dest: usize,
    range_len: usize,
}

impl SeedMap {
    fn contains(&self, seed: i64) -> bool {
        (self.src..self.src + self.range_len).contains(&(seed as usize))
    }
}

impl From<&str> for SeedMap {
    fn from(seed_map: &str) -> Self {
        let map: Vec<_> = seed_map
            .split(' ')
            .map(|x| x.parse::<usize>().expect("Should be parsabel to usize"))
            .collect();
        Self {
            src: map[1],
            dest: map[0],
            range_len: map[2],
        }
    }
}

fn main() {
    let test = include_str!("../input/day5.test");
    let prod = include_str!("../input/day5.prod");
    println!("part_1 test: {:?}", solve_part_one(test));
    println!("part_1 prod {:?}", solve_part_one(prod));
    // println!("part_2 test: {:?}", solve_part_two(test));
    // println!("part_2 prod {:?}", solve_part_two(prod));
}