diff --git a/src/10-factory.rs b/src/10-factory.rs index a104251..b6f1eb0 100644 --- a/src/10-factory.rs +++ b/src/10-factory.rs @@ -1,57 +1,60 @@ use std::cmp::min; +use std::error::Error; use std::fs::File; -use std::io::{self, BufRead, BufReader}; +use std::io::{BufRead, BufReader}; +use std::num::ParseIntError; use std::str::FromStr; -use std::u64; #[derive(Debug)] struct Machine { + #[allow(dead_code)] lights: Vec, - buttons: Vec>, + buttons: Vec>, joltages: Vec } impl FromStr for Machine { - type Err = io::Error; + type Err = ParseIntError; fn from_str(s: &str) -> Result { let groups: Vec<_> = s.split(' ').collect(); + let lights_part = groups[0]; let lights = lights_part[1..lights_part.len()-1] .chars() - .rev() .map(|c| if c == '#' { 1 } else { 0 }) .collect(); let buttons: Vec<_> = (1..groups.len()-1) .map(|i| parse_button_group(groups[i])) - .collect(); + .collect::>()?; let joltages_part = groups[groups.len()-1]; let joltages: Vec<_> = joltages_part[1..joltages_part.len()-1] .split(',') - .map(|j_s| j_s.parse::().unwrap()) - .collect(); + .map(|j_s| j_s.parse::()) + .collect::>()?; - Ok(Machine { lights: lights, buttons: buttons , joltages: joltages }) + Ok(Machine { lights, buttons , joltages }) } } -fn parse_button_group(s: &str) -> Vec { +fn parse_button_group(s: &str) -> Result, ParseIntError> { s[1..s.len()-1].split(',') - .map(|x_s| x_s.parse::().unwrap()) + .map(str::parse::) .collect() } -fn parity_solve(machine: &Machine, target: &Vec) -> Vec { + +fn parity_solve(machine: &Machine, target: &[u64]) -> Vec { let mut solutions: Vec = Vec::new(); for selection in 0..(1 << machine.buttons.len()) { let mut parity = target.iter().rev() - .fold(0, |state, x| (state << 1) + (x & 1)); + .fold(0, |state, x| (state << 1) | (x & 1)); for (i, button) in machine.buttons.iter().enumerate() { if selection & (1 << i) != 0 { - for j in button { - parity ^= 1 << j; - } + parity = button.iter().fold(parity, |parity, j| { + parity ^ (1 << j) + }); } } if parity == 0 { @@ -62,25 +65,28 @@ fn parity_solve(machine: &Machine, target: &Vec) -> Vec { } fn minimum_solve(machine: &Machine) -> u64 { - fn apply_button(machine: &Machine, button_idx: usize, mut current: Vec) -> Option> { + fn apply_button<'a>(machine: &Machine, button_idx: usize, current: &'a mut Vec) -> Option<&'a mut Vec> { for i in &machine.buttons[button_idx] { - if current[*i as usize] == 0 { + if current[*i] == 0 { return None; } - current[*i as usize] -= 1; + current[*i] -= 1; } Some(current) } - fn recurse(machine: &Machine, target: &Vec, max_cnt: i64) -> Option { + fn recurse(machine: &Machine, target: &[u64], max_cnt: i64) -> Option { if target.iter().sum::() == 0 { return Some(0) }; if max_cnt <= 0 { return None }; let parity_solutions = parity_solve(machine, target); - let mut min_solution = None; + + let mut min_presses = None; + let mut current_storage = target.to_vec(); for parity_sln in parity_solutions { + current_storage.copy_from_slice(target); let current = (0..machine.buttons.len()) - .fold(Some(target.clone()), |state, i| { + .fold(Some(&mut current_storage), |state, i| { if parity_sln & (1 << i) != 0 { apply_button(machine, i, state?) } else { @@ -91,40 +97,34 @@ fn minimum_solve(machine: &Machine) -> u64 { let parity_ones = parity_sln.count_ones() as i64; let new_max_cnt = - (match min_solution { + (match min_presses { None => max_cnt, Some(ms) => min(ms as i64, max_cnt) } - parity_ones) / 2; - let new_target = current.iter().map(|&x| x / 2).collect(); - let sln = recurse(machine, &new_target, new_max_cnt); - let Some(sln) = sln else { continue }; - min_solution = - match min_solution { - None => Some(parity_ones as u64 + 2u64 * sln), - Some(ms) => Some(min(ms, parity_ones as u64 + 2u64 * sln)) - }; + let new_target: Vec<_> = current.iter().map(|&x| x / 2).collect(); + let Some(sln) = recurse(machine, &new_target, new_max_cnt) else { continue }; + let presses = parity_ones as u64 + 2u64 * sln; + min_presses = Some(match min_presses { + None => presses, + Some(ms) => min(ms, presses) + }); } - min_solution + min_presses } - let result = recurse(machine, &machine.joltages, i64::MAX).unwrap_or(0); - println!("Result: {}", result); - result + recurse(machine, &machine.joltages, i64::MAX).unwrap_or(0) } -fn main() -> Result<(), io::Error> { +fn main() -> Result<(), Box> { let f = File::open("10-input.txt")?; let reader = BufReader::new(f); let machines: Vec<_> = reader.lines() - .map(|l| l?.parse::()) - .collect::>()?; - println!("Parsed {} machines: \n {:?}", machines.len(), machines); - - let presses: u64 = machines.iter() - .map(|m| minimum_solve(&m)) - .sum(); + .map(|l| Ok(l?.parse::()?)) + .collect::>>()?; + println!("Parsed {} machines", machines.len()); + let presses: u64 = machines.iter().map(minimum_solve).sum(); println!("Result: {}", presses); Ok(()) } diff --git a/src/12-christmas-tree-farm.rs b/src/12-christmas-tree-farm.rs index 51b9282..309abf6 100644 --- a/src/12-christmas-tree-farm.rs +++ b/src/12-christmas-tree-farm.rs @@ -1,3 +1,7 @@ +use std::convert::Infallible; +use std::error::Error; +use std::num::ParseIntError; +use std::string::ParseError; use std::{fs::File, io::{self, BufRead, BufReader}, str::FromStr}; struct Piece { @@ -5,27 +9,28 @@ struct Piece { } impl FromStr for Piece { - type Err = (); + type Err = Infallible; fn from_str(s: &str) -> Result { - let cells: Vec<_> = + let cells = s.split('\n').map(|row| { - row.chars().fold(Vec::new(), |mut state, c| { + row.chars().filter_map(|c| { match c { - '#' => state.push(true), - '.' => state.push(false), - _ => () - }; - state + '#' => Some(true), + '.' => Some(false), + _ => None + } }) + .collect() }) .collect(); - Ok(Piece { cells: cells }) + Ok(Piece { cells }) } } impl Piece { - fn bounds_area(&self) -> u64 { + #[allow(dead_code)] + fn bounding_area(&self) -> u64 { let height = self.cells.len(); if height > 0 { (self.cells[0].len() * height) as u64 @@ -37,8 +42,8 @@ impl Piece { fn true_area(&self) -> u64 { self.cells.iter() .flatten() - .map(|&b| if b { 1 } else { 0 }) - .sum() + .filter(|&&b| b) + .count() as u64 } } @@ -49,21 +54,17 @@ struct Region { } impl FromStr for Region { - type Err = (); + type Err = ParseIntError; fn from_str(s: &str) -> Result { let (area_str, requirements_str) = s.split_once(':').unwrap(); let (width_str, height_str) = area_str.split_once('x').unwrap(); - let width = width_str.parse::().unwrap(); - let height = height_str.parse::().unwrap(); - let requirements: Vec<_> = requirements_str.split(' ') - .fold(Vec::new(), |mut state, count| { - if let Ok(count) = count.parse::() { - state.push(count); - } - state - }); - Ok(Region { width: width, height: height, requirements: requirements }) + let width = width_str.parse::()?; + let height = height_str.parse::()?; + let requirements = requirements_str.split(' ') + .filter_map(|s| s.parse::().ok()) + .collect(); + Ok(Region { width, height, requirements }) } } @@ -71,7 +72,7 @@ fn is_solveable(pieces: &[Piece], region: &Region) -> bool { // Lower area bound = perfectly packed let region_area = region.width * region.height; let used_area: u64 = pieces.iter() - .zip(region.requirements.clone()) + .zip(region.requirements.iter()) .map(|(piece, cnt)| piece.true_area() * cnt) .sum(); if used_area > region_area { return false }; @@ -85,7 +86,7 @@ fn is_solveable(pieces: &[Piece], region: &Region) -> bool { false } -fn main() -> Result<(), io::Error> { +fn main() -> Result<(), Box> { let f = File::open("12-input.txt")?; let reader = BufReader::new(f); @@ -94,25 +95,19 @@ fn main() -> Result<(), io::Error> { let pieces: Vec<_> = lines_pieces.chunks(5) .map(|lines| { - lines[1..lines.len()-1].join("\n").parse::().unwrap() + Ok(lines[1..lines.len()-1].join("\n").parse::()?) }) - .collect(); + .collect::>>()?; let regions: Vec<_> = lines_regions.iter() .map(|line| { - line.parse::().unwrap() + Ok(line.parse::()?) }) - .collect(); + .collect::>>()?; - let result = regions.iter() - .map(|region| { - if is_solveable(&pieces, region) { - 1 - } else { - 0 - } - }) - .sum::(); + let result: u64 = regions.iter() + .filter(|region| is_solveable(&pieces, region)) + .count() as u64; println!("Result: {}", result); Ok(()) } \ No newline at end of file diff --git a/src/2-gift-shop.rs b/src/2-gift-shop.rs index 3449f51..11cbf2e 100644 --- a/src/2-gift-shop.rs +++ b/src/2-gift-shop.rs @@ -1,4 +1,5 @@ use std::{ + cmp::max, fs::File, io::{self, BufRead, BufReader}, }; @@ -8,48 +9,37 @@ fn parse_range(s: &str) -> (i64, i64) { (low_s.parse().unwrap(), high_s.parse().unwrap()) } -fn invalid_in_range(low: i64, high: i64) -> i64 { - let mut total: i64 = 0; - for i in low..=high { - let len = i.ilog10() + 1; - for j in (2..=len).filter(|x| len % x == 0) { - let split = 10i64.pow(len / j); - let target = i % split; - let mut mut_i = i; - while mut_i > 0 && (mut_i % split) == target { - mut_i /= split; - } - if mut_i == 0 { - // println!("{} in {}-{}", i, low, high); - total += i; - break; - } +fn is_invalid(value: i64) -> bool { + let len = value.ilog10() + 1; + for j in (1..len).filter(|x| len % x == 0) { + let split = 10_i64.pow(j); + let target = value % split; + let mut mut_value = value; + while mut_value > 0 && (mut_value % split) == target { + mut_value /= split; + } + if mut_value == 0 { + return true; } } - total + false } fn main() -> Result<(), io::Error> { let f = File::open("2-input.txt")?; let reader = BufReader::new(f); - let mut ranges = reader - .lines() - .next() - .unwrap() - .unwrap() - .split(",") + let range_line = reader.lines().next().unwrap()?; + let mut ranges: Vec<_> = range_line.split(",") .map(parse_range) - .collect::>(); + .collect(); ranges.sort_unstable(); let mut total: i64 = 0; let mut last: i64 = 0; for (low, high) in ranges { - let low = low.max(last); - if low <= high { - total += invalid_in_range(low, high); - } - last = high + 1; + let low = max(low, last); + last = max(high + 1, last); + total += (low..last).filter(|x| is_invalid(*x)).sum::(); } println!("Result {}", total); Ok(()) diff --git a/src/3-lobby.rs b/src/3-lobby.rs index 59e3b8d..3b27469 100644 --- a/src/3-lobby.rs +++ b/src/3-lobby.rs @@ -4,12 +4,13 @@ use std::{ }; fn max_joltage(s: &str) -> u64 { - let values = s + let values: Vec<_> = s .chars() .map(|x| x.to_digit(10).unwrap()) - .collect::>(); + .collect(); let max_idx = |xs: &[u32]| { + xs.iter() .enumerate() .fold(0, |max, (i, &x)| if x > xs[max] { i } else { max }) @@ -26,10 +27,11 @@ fn main() -> Result<(), io::Error> { let f = File::open("3-input.txt")?; let reader = BufReader::new(f); - let mut total: u64 = 0; - for line in reader.lines() { - total += max_joltage(line?.as_str()) as u64; - } + let total: u64 = reader.lines() + .map(|l| { + max_joltage(&l.unwrap()) + }) + .sum(); println!("Result: {}", total); Ok(()) } diff --git a/src/4-printing-department.rs b/src/4-printing-department.rs index 654f2a3..b13e89c 100644 --- a/src/4-printing-department.rs +++ b/src/4-printing-department.rs @@ -14,6 +14,12 @@ const NEIGHBOURS: [(i32, i32); 8] = [ (1, 1), ]; +fn parse_grid_line(line: &str) -> Vec { + line.chars() + .map(|c| c == '@') + .collect() +} + fn get_grid_cell(grid: &[Vec], x: i32, y: i32) -> bool { let (Ok(ux), Ok(uy)) = (usize::try_from(x), usize::try_from(y)) else { return false; @@ -55,21 +61,19 @@ fn count_all_true(grid: &[Vec]) -> usize { fn main() -> Result<(), io::Error> { let f = File::open("4-input.txt")?; let reader = BufReader::new(f); - let original_grid = reader + let original_grid: Vec<_> = reader .lines() - .collect::, _>>()? - .iter() - .map(|s| s.chars().map(|c| c == '@').collect::>()) - .collect::>(); - - let mut last_grid = original_grid.clone(); - loop { - let next_grid = update_grid(&last_grid); - if next_grid == last_grid { - break; + .map(|line| Ok(parse_grid_line(&line?))) + .collect::>()?; + + let mut current_grid = original_grid.clone(); + let last_grid = loop { + let next_grid = update_grid(¤t_grid); + if next_grid == current_grid { + break next_grid; } - last_grid = next_grid; - } + current_grid = next_grid; + }; println!( "Result: {}", diff --git a/src/7-laboratories.rs b/src/7-laboratories.rs index 01f2938..38b6b7a 100644 --- a/src/7-laboratories.rs +++ b/src/7-laboratories.rs @@ -7,38 +7,40 @@ fn main() -> Result<(), io::Error> { let f = File::open("7-input.txt")?; let reader = BufReader::new(f); - let lines: Vec<_> = reader.lines().collect::>()?; - let initial_state: Vec<_> = lines[0] + let mut lines = reader.lines(); + let first = lines.next().transpose()?.unwrap(); + + let mut current_state: Vec<_> = first .chars() .map(|c| if c == 'S' { 1 } else { 0 }) .collect(); + let mut next_state = vec![0; current_state.len()]; + let mut splits: u64 = 0; - let (final_state, splits) = - lines[1..] - .iter() - .fold((initial_state, 0u64), |(state, mut splits), row| { - let mut next_state = vec![0; state.len()]; - for (i, c) in row.chars().enumerate() { - match (c, state[i]) { - (_, 0) => (), - ('.', x) => { - next_state[i] += x; - } - ('^', x) => { - splits += 1; - if i > 0 { - next_state[i - 1] += x; - } - if i < state.len() - 1 { - next_state[i + 1] += x; - } - } - _ => (), + for line in lines { + for (i, c) in line?.chars().enumerate() { + match (c, current_state[i]) { + (_, 0) => (), + ('.', x) => { + next_state[i] += x; + } + ('^', x) => { + splits += 1; + if i > 0 { + next_state[i - 1] += x; + } + if i < current_state.len() - 1 { + next_state[i + 1] += x; } } - (next_state, splits) - }); - let paths: u64 = final_state.iter().sum(); + _ => (), + } + } + std::mem::swap(&mut current_state, &mut next_state); + next_state.fill(0); + } + + let paths: u64 = current_state.iter().sum(); println!("Result: {} splits, {} paths", splits, paths); Ok(()) } diff --git a/src/8-playground.rs b/src/8-playground.rs index dedbcb3..fc2a9af 100644 --- a/src/8-playground.rs +++ b/src/8-playground.rs @@ -1,6 +1,6 @@ -use std::{collections::HashMap, fs::File, hash::Hash,io::{self, BufRead, BufReader}}; +use std::{error::Error, fs::File, io::{BufRead, BufReader}, num::ParseIntError, str::FromStr}; -#[derive(PartialEq, Eq, Clone, Hash, Debug)] +#[derive(Debug)] struct Node { x: u32, y: u32, @@ -16,88 +16,79 @@ impl Node { } } -impl From<&str> for Node { - fn from(value: &str) -> Self { - let coords: Vec<_> = value.split(',').map(|s| s.parse::().unwrap()).collect(); - Node { - x: coords[0], - y: coords[1], - z: coords[2] - } +impl FromStr for Node { + type Err = ParseIntError; + fn from_str(s: &str) -> Result { + let mut it = s.split(',').map(str::parse::); + Ok(Node { + x: it.next().unwrap()?, + y: it.next().unwrap()?, + z: it.next().unwrap()?, + }) } } -#[derive(Debug, Clone)] -struct Edge { - a: Node, - b: Node -} - #[derive(Debug)] struct DisjointSet { - parents: HashMap> + nodes: Vec, + parents: Vec } -impl FromIterator for DisjointSet { - fn from_iter>(iter: I) -> Self { - DisjointSet { - parents: iter.into_iter().map(|x| (x, None)).collect() - } +impl DisjointSet { + fn new(nodes: Vec) -> Self { + let parents = (0..nodes.len()).collect(); + DisjointSet { nodes, parents } } -} -impl DisjointSet { - fn representative(&mut self, x: &T) -> Option { - match self.parents.get(x)?.clone() { - None => Some(x.clone()), - Some(p) => { - let rep = self.representative(&p)?; - self.parents.insert(x.clone(), Some(rep.clone())); - Some(rep) - } + fn representative_idx(&mut self, i: usize) -> usize { + let rep = self.parents[i]; + if rep == i { + rep + } else { + let rep = self.representative_idx(rep); + self.parents[i] = rep; + rep } } - fn union(&mut self, a: &T, b: &T) -> Option { - let rep_a = self.representative(a).unwrap(); - let rep_b = self.representative(b).unwrap(); - if rep_a != rep_b { - self.parents.insert(rep_a, Some(rep_b.clone())); - Some(rep_b) + fn union(&mut self, i: usize, j: usize) -> Option { + let rep_i = self.representative_idx(i); + let rep_j = self.representative_idx(j); + if rep_i != rep_j { + self.parents[rep_j] = rep_i; + Some(rep_i) } else { None } } } -fn main() -> Result<(), io::Error> { +fn main() -> Result<(), Box> { let f = File::open("8-input.txt")?; let reader = BufReader::new(f); - let nodes: Vec = reader.lines() - .map(|lr| lr.map(|l| l.as_str().into())) - .collect::>()?; - let node_cnt = nodes.len(); + let nodes: Vec<_> = reader.lines() + .map(|l| Ok(l?.parse::()?)) + .collect::>>()?; - let mut all_edges: Vec<_> = - (0..node_cnt).flat_map(|a| { - let na = &nodes[a]; - (a+1..node_cnt).map(|b| { - let nb = &nodes[b]; - let sqr_dist = Node::square_dist(na, nb); - (sqr_dist, Edge {a: na.clone(), b: nb.clone()}) - }) - }) - .filter(|(_, e)| e.a != e.b) - .collect(); - all_edges.sort_unstable_by_key(|(d, _)| *d); + let mut edges: Vec<(i64, usize, usize)> = Vec::new(); + for i in 0..nodes.len() { + for j in i+1..nodes.len() { + let sqr_dist = Node::square_dist(&nodes[i], &nodes[j]); + edges.push((sqr_dist, i, j)); + } + } + edges.sort_unstable_by_key(|(d, _, _)| *d); - let mut ds: DisjointSet<_> = nodes.clone().into_iter().collect(); - let connections: Vec<_> = all_edges.iter() - .filter_map(|(_, e)| ds.union(&e.a, &e.b).map(|_|e.clone())) + let mut ds: DisjointSet<_> = DisjointSet::new(nodes); + let connections: Vec<_> = edges.iter() + .filter_map(|(_, i, j)| ds.union(*i, *j).map(|_| (*i, *j))) .collect(); + let nodes = ds.nodes; let last_connection = connections.last().unwrap(); - println!("Result {}", u64::from(last_connection.a.x) * u64::from(last_connection.b.x)); + let last_from = &nodes[last_connection.0]; + let last_to = &nodes[last_connection.1]; + println!("Result {}", u64::from(last_from.x) * u64::from(last_to.x)); Ok(()) } \ No newline at end of file diff --git a/src/9-movie-theater.rs b/src/9-movie-theater.rs index f59bb9e..8297a38 100644 --- a/src/9-movie-theater.rs +++ b/src/9-movie-theater.rs @@ -1,32 +1,42 @@ -use std::{cmp::{max, min, Ordering}, fs::File, i64, io::{self, BufRead, BufReader, ErrorKind}, fmt::Debug, str::FromStr}; +use std::cmp::{Ordering, max, min}; +use std::error::Error; +use std::fmt::{Debug, Display}; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::str::FromStr; -#[derive(Clone, Copy, Debug)] + +#[derive(Debug)] +struct ParseVertexError; + +impl Display for ParseVertexError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "cannot parse vertex") + } +} + +impl Error for ParseVertexError {} + + +#[derive(Debug)] struct Vertex { x: i64, y: i64 } impl FromStr for Vertex { - type Err = io::Error; + type Err = ParseVertexError; fn from_str(s: &str) -> Result { - let parts: Vec<_> = s.split(',') - .map(|s| s.parse::()) - .collect(); + let mut values = s.split(',').map(str::parse::); - let err = io::Error::new(ErrorKind::Other, "Unable to parse vertex"); - let Some(&Ok(x)) = parts.get(0) else { return Err(err) }; - let Some(&Ok(y)) = parts.get(1) else { return Err(err) }; - Ok(Vertex { x: x, y: y}) + let Some(Ok(x)) = values.next() else { return Err(ParseVertexError) }; + let Some(Ok(y)) = values.next() else { return Err(ParseVertexError) }; + Ok(Vertex { x, y }) } } -#[derive(Debug)] -struct Edge { - a: Vertex, - b: Vertex -} -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] struct Segment { lo: i64, hi: i64, @@ -36,14 +46,14 @@ struct Segment { } impl Segment { - fn new(e: Edge) -> Segment { + fn new(start: &Vertex, end: &Vertex) -> Segment { Segment { - lo: min(e.a.x, e.b.x), - hi: max(e.a.x, e.b.x), + lo: min(start.x, end.x), + hi: max(start.x, end.x), truncate_lo: false, truncate_hi: false, dist: - if e.a.x < e.b.x { Some(e.a.y) } + if start.x < end.x { Some(start.y) } else { None } } } @@ -51,33 +61,28 @@ impl Segment { impl PartialOrd for Segment { fn partial_cmp(&self, other: &Self) -> Option { - if self.hi <= other.lo { - Some(Ordering::Less) - } else if other.hi <= self.lo { - Some(Ordering::Greater) - } else { - Some(Ordering::Equal) - } + Some(self.cmp(&other)) } } impl Ord for Segment { fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).unwrap() + self.lo.cmp(&other.lo) } } impl Debug for Segment { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(format!("({}, {})", self.lo, self.hi).as_str()) + write!(f, "({}, {})", self.lo, self.hi) } } + fn rect_area(x1: i64, x2: i64, y1: i64, y2: i64) -> i64 { (1 + i64::abs(x1 - x2)) * (1 + i64::abs(y1 - y2)) } -fn rect_from_point(state: &Vec, v: &Vertex) -> i64 { +fn rect_from_point(state: &[Segment], v: &Vertex) -> i64 { let mut max_area = i64::MIN; let mut max_y = i64::MIN; @@ -116,7 +121,7 @@ fn rect_from_point(state: &Vec, v: &Vertex) -> i64 { fn update_state(state: &mut Vec, incoming: Segment) { for i in (0..state.len()).rev() { - let current = state[i]; + let current = state[i].clone(); if incoming.lo <= current.lo && current.hi <= incoming.hi { state.remove(i); } else if current.lo < incoming.lo && incoming.hi < current.hi { @@ -135,34 +140,31 @@ fn update_state(state: &mut Vec, incoming: Segment) { state.sort(); } -fn main() -> Result<(), io::Error> { +fn main() -> Result<(), Box> { let f = File::open("9-input.txt")?; let reader = BufReader::new(f); let vertices: Vec<_> = reader.lines() - .map(|l| l?.parse::()) - .collect::>()?; - - let mut edges: Vec = Vec::new(); + .map(|l| Ok(l?.parse::()?)) + .collect::>>()?; + + + let mut horizontal_edges: Vec<(usize, usize)> = Vec::new(); for i in 0..vertices.len() { let j = (i + 1) % vertices.len(); - edges.push(Edge { - a: vertices[i], - b: vertices[j] - }); + if vertices[i].y == vertices[j].y { + horizontal_edges.push((i, j)); + } } - edges.sort_unstable_by_key(|e| e.a.y + e.b.y); - - let horizontal_edges: Vec<_> = edges.into_iter() - .filter(|e| e.a.y == e.b.y) - .collect(); + horizontal_edges.sort_unstable_by_key(|e| vertices[e.0].y); let mut max_area: i64 = 0; - let mut state: Vec = Vec::new(); - state.push(Segment { lo: i64::MIN, hi: i64::MAX, truncate_lo: false, truncate_hi: false, dist: None }); + let mut state = vec![Segment { lo: i64::MIN, hi: i64::MAX, truncate_lo: false, truncate_hi: false, dist: None }]; for e in horizontal_edges { - max_area = max(max_area, rect_from_point(&state, &e.a)); - max_area = max(max_area, rect_from_point(&state, &e.b)); - update_state(&mut state, Segment::new(e)); + let start = &vertices[e.0]; + let end = &vertices[e.1]; + max_area = max(max_area, rect_from_point(&state, start)); + max_area = max(max_area, rect_from_point(&state, end)); + update_state(&mut state, Segment::new(start, end)); } println!("Result {}", max_area);