summaryrefslogtreecommitdiff
path: root/day05/src/main.rs
blob: ce90869f8ef8c92c76713d441f667aacd6f9a2d9 (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::io;

#[derive(Clone)]
struct Range {
    first: i64,
    last: i64,
}

impl Range {
    fn new(first: i64, last: i64) -> Self {
        assert!(first <= last);
        Self { first, last }
    }

    fn contains(&self, value: i64) -> bool {
        value >= self.first && value <= self.last
    }

    fn len(&self) -> i64 {
        1 + self.last - self.first
    }
}

fn in_ranges(ranges: &Vec<Range>, value: i64) -> bool {
    for range in ranges {
        if range.contains(value) {
            return true;
        }
    }
    false
}

fn merge_or_add(ranges: &mut Vec<Range>, range: &Range) {
    if range.len() == 0 {
        return;
    }
    let i = ranges.partition_point(|x| x.last < range.first);
    if i == ranges.len() {
        ranges.push(range.clone());
        return;
    }
    if ranges[i].first > range.last {
        ranges.insert(i, range.clone());
        return;
    }
    if ranges[i].contains(range.first) {
        if ranges[i].contains(range.last) {
            // Whole range is swallowed
            return;
        }
        merge_or_add(ranges, &Range::new(ranges[i].last + 1, range.last));
        return;
    }
    if ranges[i].contains(range.last) {
        ranges.insert(i, Range::new(range.first, ranges[i].first - 1));
        return;
    }

    let before = Range::new(range.first, ranges[i].first - 1);
    let after = Range::new(ranges[i].last + 1, range.last);

    ranges.insert(i, before);
    merge_or_add(ranges, &after);
}

fn remove_overlap(ranges: &Vec<Range>) -> Vec<Range> {
    let mut ret = Vec::new();

    for range in ranges {
        merge_or_add(&mut ret, range);
    }

    ret
}

fn main() {
    let mut ranges = Vec::new();

    loop {
        let mut buffer = String::new();
        let bytes = io::stdin().read_line(&mut buffer).unwrap();
        if bytes == 0 || buffer == "\n" {
            break;
        }
        let mut iter = buffer.trim_end().split('-');
        let first = iter.next().unwrap().parse::<i64>().unwrap();
        let last = iter.next().unwrap().parse::<i64>().unwrap();
        ranges.push(Range::new(first, last));
    }

    ranges.sort_by(|a, b| a.first.cmp(&b.first));

    let mut available = Vec::new();

    loop {
        let mut buffer = String::new();
        let bytes = io::stdin().read_line(&mut buffer).unwrap();
        if bytes == 0 {
            break;
        }
        available.push(buffer.trim_end().parse::<i64>().unwrap());
    }

    let mut fresh = 0;

    for ingredient in available {
        if in_ranges(&ranges, ingredient) {
            fresh += 1;
        }
    }

    println!("Fresh ingrediences {}", fresh);

    let ranges2 = remove_overlap(&ranges);

    let mut fresh2 = 0;

    for range in ranges2 {
        fresh2 += range.len();
    }

    println!("Fresh ids {}", fresh2);
}