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 { 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(reader: T) -> io::Result<(String, String)> { let w = 1000; let maxnum = 1500; let mut sheet: Vec = vec![0; w * w]; let mut double: i64 = 0; let mut free: Vec = vec![false; maxnum as usize]; for line in reader.lines() { let claim = line.unwrap().parse::().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")) }