2018: day03: part 1
This commit is contained in:
parent
0968951383
commit
cf17d2779c
1347
aoc2018/input/day03.txt
Normal file
1347
aoc2018/input/day03.txt
Normal file
File diff suppressed because it is too large
Load diff
103
aoc2018/src/day03.rs
Normal file
103
aoc2018/src/day03.rs
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use super::Result;
|
||||||
|
|
||||||
|
const INPUT: &str = include_str!("../input/day03.txt");
|
||||||
|
|
||||||
|
pub fn run() -> Result<()> {
|
||||||
|
println!("part 1: {}", part1(INPUT)?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ParseError {
|
||||||
|
line: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParseError {
|
||||||
|
fn new(line: &str) -> Self {
|
||||||
|
ParseError {
|
||||||
|
line: line.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ParseError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ParseError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
&self.line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(line: &str) -> Option<(usize, usize, usize, usize)> {
|
||||||
|
// remove '#XXX @ ' start of line
|
||||||
|
let line = &line[(line.find(" @ ")? + 3)..];
|
||||||
|
|
||||||
|
// parse 'x,y: NNxNN
|
||||||
|
let comma = line.find(',')?;
|
||||||
|
let colon = line.find(':')?;
|
||||||
|
let x = line[..comma].parse().ok()?;
|
||||||
|
let y = line[(comma + 1)..colon].parse().ok()?;
|
||||||
|
|
||||||
|
// reduce line to 'NNxNN'
|
||||||
|
let line = &line[(colon + 2)..];
|
||||||
|
|
||||||
|
let sep = line.find('x')?;
|
||||||
|
let width = line[..sep].parse().ok()?;
|
||||||
|
let height = line[(sep + 1)..].parse().ok()?;
|
||||||
|
|
||||||
|
Some((x, y, width, height))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> Result<u64> {
|
||||||
|
let mut res = 0;
|
||||||
|
let mut map: HashMap<(usize, usize), u64> = HashMap::default();
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
let (x, y, width, height) = parse(line).ok_or(ParseError::new(line))?;
|
||||||
|
|
||||||
|
for i in 0..width {
|
||||||
|
for j in 0..height {
|
||||||
|
let x = x + i;
|
||||||
|
let y = y + j;
|
||||||
|
|
||||||
|
// add tissue patch at coordinates (x, y)
|
||||||
|
let entry = map.entry((x, y)).or_default();
|
||||||
|
*entry += 1;
|
||||||
|
|
||||||
|
// count overlap the first time only
|
||||||
|
if *entry == 2 {
|
||||||
|
res += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_provided() {
|
||||||
|
let input = "#1 @ 1,3: 4x4
|
||||||
|
#2 @ 3,1: 4x4
|
||||||
|
#3 @ 5,5: 2x2
|
||||||
|
";
|
||||||
|
assert_eq!(part1(input).unwrap(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_real() {
|
||||||
|
assert_eq!(part1(INPUT).unwrap(), 114946);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod day01;
|
pub mod day01;
|
||||||
pub mod day02;
|
pub mod day02;
|
||||||
|
pub mod day03;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
Loading…
Reference in a new issue