summaryrefslogtreecommitdiff
path: root/2018/src/day3.rs
blob: baba8fe30e095ca73ebd8e9255c4f37130c49163 (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
use std::io;
use std::io::BufRead;
use std::str::FromStr;

struct Point {
    x: usize,
    y: usize
}

struct Claim {
    id: i16,
    origin: Point,
    size: Point
}

impl FromStr for Claim {
    type Err = std::num::ParseIntError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let bytes = s.as_bytes();
        let mut cursor = 1;
        let mut idx = 1;

        while bytes[idx].is_ascii_digit() { idx += 1; }
        let id = s[cursor..idx].parse()?;

        idx = idx + 3;
        cursor = idx;
        while bytes[idx].is_ascii_digit() { idx += 1; }
        let ox = s[cursor..idx].parse()?;

        idx = idx + 1;
        cursor = idx;
        while bytes[idx].is_ascii_digit() { idx += 1; }
        let oy = s[cursor..idx].parse()?;

        idx = idx + 2;
        cursor = idx;
        while bytes[idx].is_ascii_digit() { idx += 1; }
        let sx = s[cursor..idx].parse()?;

        let sy = s[idx+1..].parse()?;

        Ok(Claim {
            id: id,
            origin: Point {x: ox, y: oy},
            size: Point {x: sx, y: sy}
        })
    }
}

pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> {
    let w = 1000;
    let maxnum = 1500;

    let mut sheet: Vec<i16> = vec![0; w * w];
    let mut double: i64 = 0;
    let mut free: Vec<bool> = vec![false; maxnum as usize];

    for line in reader.lines() {
        let claim = line.unwrap().parse::<Claim>().unwrap();
        assert!(0 < claim.id && claim.id < maxnum);

        free[claim.id as usize] = true;

        for y in claim.origin.y .. claim.origin.y + claim.size.y {
            for x in claim.origin.x .. claim.origin.x + claim.size.x {
                let val = sheet[w * y + x];
                if val > 0 {
                    free[val as usize] = false;
                    free[claim.id as usize] = false;
                    double += 1;
                    sheet[w * y + x] = -1;
                } else if val == 0 {
                    sheet[w * y + x] = claim.id;
                } else {
                    free[claim.id as usize] = false;
                }
            }
        }
    }

    let part1 = double;

    for i in 1 .. maxnum as usize {
        if free[i] {
            return Ok((part1.to_string(), i.to_string()));
        }
    }

    Err(io::Error::new(io::ErrorKind::Other, "Invalid input"))
}