2018: day03: implement FromStr instead of fn parse

This commit is contained in:
Antoine Martin 2019-11-18 14:27:45 +01:00
parent 8de2538d0e
commit a6ff14b260

View file

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::error::Error; use std::error::Error;
use std::str::FromStr;
use super::err; use super::err;
use super::Result; use super::Result;
@ -22,6 +23,9 @@ struct Claim {
id: usize, id: usize,
} }
impl FromStr for Claim {
type Err = Box<dyn Error>;
/// Parses a claim from a line /// Parses a claim from a line
/// ///
/// Fails if the line is badly formatted. The expected format is: /// Fails if the line is badly formatted. The expected format is:
@ -29,29 +33,31 @@ struct Claim {
/// ```text /// ```text
/// #ID @ X,Y: WxH /// #ID @ X,Y: WxH
/// ``` /// ```
fn parse(line: &str) -> Option<Claim> { fn from_str(s: &str) -> Result<Self> {
// skip '#' in line // skip '#' in line
let line = &line[1..]; let s = &s[1..];
// find ' @ ' separator // find ' @ ' separator
let at = line.find(" @ ")?; let at = s
let id = line[..at].parse().ok()?; .find(" @ ")
let line = &line[(at + 3)..]; .ok_or_else(|| err!("` @ ` delimiter not found"))?;
let id = s[..at].parse()?;
let s = &s[(at + 3)..];
// parse 'X,Y: WxH // parse 'X,Y: WxH
let comma = line.find(',')?; let comma = s.find(',').ok_or_else(|| err!("`,` delimiter not found"))?;
let colon = line.find(':')?; let colon = s.find(':').ok_or_else(|| err!("`:` delimiter not found"))?;
let x = line[..comma].parse().ok()?; let x = s[..comma].parse()?;
let y = line[(comma + 1)..colon].parse().ok()?; let y = s[(comma + 1)..colon].parse()?;
// reduce line to 'WxH' // reduce line to 'WxH'
let line = &line[(colon + 2)..]; let s = &s[(colon + 2)..];
let sep = line.find('x')?; let sep = s.find('x').ok_or_else(|| err!("`x` delimiter not found"))?;
let width = line[..sep].parse().ok()?; let width = s[..sep].parse()?;
let height = line[(sep + 1)..].parse().ok()?; let height = s[(sep + 1)..].parse()?;
Some(Claim { Ok(Claim {
x, x,
y, y,
width, width,
@ -59,13 +65,16 @@ fn parse(line: &str) -> Option<Claim> {
id, id,
}) })
} }
}
fn part1(input: &str) -> Result<u64> { fn part1(input: &str) -> Result<u64> {
let mut res = 0; let mut res = 0;
let mut map: HashMap<(usize, usize), u64> = HashMap::new(); let mut map: HashMap<(usize, usize), u64> = HashMap::new();
for line in input.lines() { for line in input.lines() {
let claim = parse(line).ok_or_else(|| err!("Couldn't parse line: {}", line))?; let claim: Claim = line
.parse()
.or_else(|e| Err(err!("couldn't parse line: `{}`, {}", line, e)))?;
for i in 0..claim.width { for i in 0..claim.width {
for j in 0..claim.height { for j in 0..claim.height {
@ -92,7 +101,9 @@ fn part2(input: &str) -> Result<usize> {
let mut set = HashSet::new(); let mut set = HashSet::new();
for line in input.lines() { for line in input.lines() {
let claim = parse(line).ok_or_else(|| err!("Couldn't parse line: {}", line))?; let claim: Claim = line
.parse()
.or_else(|e| Err(err!("couldn't parse line: `{}`, {}", line, e)))?;
set.insert(claim.id); set.insert(claim.id);
for i in 0..claim.width { for i in 0..claim.width {