mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-26 21:30:31 +01:00
Implement day 3.
Wasted way too much trying to do this cleverly.
This commit is contained in:
@@ -5,3 +5,4 @@ authors = ["Bert Peters <bert@bertptrs.nl>"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.32"
|
clap = "2.32"
|
||||||
|
regex = "1.1.0"
|
||||||
|
|||||||
130
2018/src/day03.rs
Normal file
130
2018/src/day03.rs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::io;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
use common;
|
||||||
|
use regex;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
struct Claim {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Claim {
|
||||||
|
|
||||||
|
pub fn xrange(&self) -> Range<usize> {
|
||||||
|
self.x..(self.x + self.width)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yrange(&self) -> Range<usize> {
|
||||||
|
self.y..(self.y + self.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Day03 {
|
||||||
|
claims: Vec<Claim>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Day03 {
|
||||||
|
pub fn new() -> Day03 {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_claims(&mut self, input: &mut io::Read) {
|
||||||
|
let reader = io::BufReader::new(input);
|
||||||
|
self.claims.clear();
|
||||||
|
|
||||||
|
let matcher = regex::Regex::new(r"^#(\d+) @ (\d+),(\d+): (\d+)x(\d+)$").unwrap();
|
||||||
|
|
||||||
|
for line in reader.lines() {
|
||||||
|
let line = line.unwrap();
|
||||||
|
let matched = matcher.captures(&line).unwrap();
|
||||||
|
|
||||||
|
let claim = Claim{
|
||||||
|
x: matched.get(2).unwrap().as_str().parse().unwrap(),
|
||||||
|
y: matched.get(3).unwrap().as_str().parse().unwrap(),
|
||||||
|
width: matched.get(4).unwrap().as_str().parse().unwrap(),
|
||||||
|
height: matched.get(5).unwrap().as_str().parse().unwrap(),
|
||||||
|
};
|
||||||
|
self.claims.push(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl common::Solution for Day03 {
|
||||||
|
fn part1(&mut self, input: &mut io::Read) -> String {
|
||||||
|
self.read_claims(input);
|
||||||
|
let mut claim_map = HashMap::new();
|
||||||
|
|
||||||
|
for claim in &self.claims {
|
||||||
|
for x in claim.xrange() {
|
||||||
|
for y in claim.yrange() {
|
||||||
|
*claim_map.entry((x, y)).or_insert(0) += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let multi_claim = claim_map.values()
|
||||||
|
.filter(|&&x| x > 1)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
format!("{}", multi_claim)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(&mut self, input: &mut io::Read) -> String {
|
||||||
|
self.read_claims(input);
|
||||||
|
let mut claim_map: HashMap<(usize, usize), Vec<usize>> = HashMap::new();
|
||||||
|
let mut overlaps: Vec<HashSet<usize>> = Vec::new();
|
||||||
|
overlaps.resize(self.claims.len(), HashSet::new());
|
||||||
|
|
||||||
|
for (idx, claim) in self.claims.iter().enumerate() {
|
||||||
|
for x in claim.xrange() {
|
||||||
|
for y in claim.yrange() {
|
||||||
|
let entry = claim_map.entry((x, y)).or_insert(Vec::new());
|
||||||
|
for claim in entry.iter() {
|
||||||
|
overlaps[*claim].insert(idx);
|
||||||
|
overlaps[idx].insert(*claim);
|
||||||
|
}
|
||||||
|
|
||||||
|
&entry.push(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let uncontested = overlaps.iter().position(|x| x.is_empty()).unwrap();
|
||||||
|
format!("{}", uncontested + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use common::Solution;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SAMPLE_INPUT: &[u8] = b"#1 @ 1,3: 4x4
|
||||||
|
#2 @ 3,1: 4x4
|
||||||
|
#3 @ 5,5: 2x2";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
let mut instance = Day03::new();
|
||||||
|
let result = instance.part1(&mut SAMPLE_INPUT);
|
||||||
|
assert_eq!("4", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
let mut instance = Day03::new();
|
||||||
|
let result = instance.part2(&mut SAMPLE_INPUT);
|
||||||
|
assert_eq!("3", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
extern crate regex;
|
||||||
use clap::{Arg, App};
|
use clap::{Arg, App};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
@@ -6,11 +7,13 @@ use std::io;
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod day01;
|
pub mod day01;
|
||||||
pub mod day02;
|
pub mod day02;
|
||||||
|
pub mod day03;
|
||||||
|
|
||||||
fn get_impl(day: &str) -> Box<common::Solution> {
|
fn get_impl(day: &str) -> Box<common::Solution> {
|
||||||
match day.parse() {
|
match day.parse() {
|
||||||
Ok(1) => Box::new(day01::Day01::new()),
|
Ok(1) => Box::new(day01::Day01::new()),
|
||||||
Ok(2) => Box::new(day02::Day02::new()),
|
Ok(2) => Box::new(day02::Day02::new()),
|
||||||
|
Ok(3) => Box::new(day03::Day03::new()),
|
||||||
Ok(val) => panic!("Unimplemented day {}", val),
|
Ok(val) => panic!("Unimplemented day {}", val),
|
||||||
_ => panic!("Invalid number"),
|
_ => panic!("Invalid number"),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user