Improve solutions

This commit is contained in:
James Hogge
2025-12-27 06:42:38 +00:00
parent 8e31c24d4d
commit 0db0cff560
8 changed files with 250 additions and 264 deletions

View File

@@ -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<u64>,
buttons: Vec<Vec<u64>>,
buttons: Vec<Vec<usize>>,
joltages: Vec<u64>
}
impl FromStr for Machine {
type Err = io::Error;
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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::<Result<_, _>>()?;
let joltages_part = groups[groups.len()-1];
let joltages: Vec<_> = joltages_part[1..joltages_part.len()-1]
.split(',')
.map(|j_s| j_s.parse::<u64>().unwrap())
.collect();
.map(|j_s| j_s.parse::<u64>())
.collect::<Result<_, _>>()?;
Ok(Machine { lights: lights, buttons: buttons , joltages: joltages })
Ok(Machine { lights, buttons , joltages })
}
}
fn parse_button_group(s: &str) -> Vec<u64> {
fn parse_button_group(s: &str) -> Result<Vec<usize>, ParseIntError> {
s[1..s.len()-1].split(',')
.map(|x_s| x_s.parse::<u64>().unwrap())
.map(str::parse::<usize>)
.collect()
}
fn parity_solve(machine: &Machine, target: &Vec<u64>) -> Vec<u64> {
fn parity_solve(machine: &Machine, target: &[u64]) -> Vec<u64> {
let mut solutions: Vec<u64> = 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<u64>) -> Vec<u64> {
}
fn minimum_solve(machine: &Machine) -> u64 {
fn apply_button(machine: &Machine, button_idx: usize, mut current: Vec<u64>) -> Option<Vec<u64>> {
fn apply_button<'a>(machine: &Machine, button_idx: usize, current: &'a mut Vec<u64>) -> Option<&'a mut Vec<u64>> {
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<u64>, max_cnt: i64) -> Option<u64> {
fn recurse(machine: &Machine, target: &[u64], max_cnt: i64) -> Option<u64> {
if target.iter().sum::<u64>() == 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<dyn Error>> {
let f = File::open("10-input.txt")?;
let reader = BufReader::new(f);
let machines: Vec<_> = reader.lines()
.map(|l| l?.parse::<Machine>())
.collect::<Result<_,_>>()?;
println!("Parsed {} machines: \n {:?}", machines.len(), machines);
let presses: u64 = machines.iter()
.map(|m| minimum_solve(&m))
.sum();
.map(|l| Ok(l?.parse::<Machine>()?))
.collect::<Result<_, Box<dyn Error>>>()?;
println!("Parsed {} machines", machines.len());
let presses: u64 = machines.iter().map(minimum_solve).sum();
println!("Result: {}", presses);
Ok(())
}

View File

@@ -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<Self, Self::Err> {
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<Self, Self::Err> {
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::<u64>().unwrap();
let height = height_str.parse::<u64>().unwrap();
let requirements: Vec<_> = requirements_str.split(' ')
.fold(Vec::new(), |mut state, count| {
if let Ok(count) = count.parse::<u64>() {
state.push(count);
}
state
});
Ok(Region { width: width, height: height, requirements: requirements })
let width = width_str.parse::<u64>()?;
let height = height_str.parse::<u64>()?;
let requirements = requirements_str.split(' ')
.filter_map(|s| s.parse::<u64>().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<dyn Error>> {
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::<Piece>().unwrap()
Ok(lines[1..lines.len()-1].join("\n").parse::<Piece>()?)
})
.collect();
.collect::<Result<_, Box<dyn Error>>>()?;
let regions: Vec<_> = lines_regions.iter()
.map(|line| {
line.parse::<Region>().unwrap()
Ok(line.parse::<Region>()?)
})
.collect();
.collect::<Result<_, Box<dyn Error>>>()?;
let result = regions.iter()
.map(|region| {
if is_solveable(&pieces, region) {
1
} else {
0
}
})
.sum::<u64>();
let result: u64 = regions.iter()
.filter(|region| is_solveable(&pieces, region))
.count() as u64;
println!("Result: {}", result);
Ok(())
}

View File

@@ -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::<Vec<_>>();
.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::<i64>();
}
println!("Result {}", total);
Ok(())

View File

@@ -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::<Vec<_>>();
.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(())
}

View File

@@ -14,6 +14,12 @@ const NEIGHBOURS: [(i32, i32); 8] = [
(1, 1),
];
fn parse_grid_line(line: &str) -> Vec<bool> {
line.chars()
.map(|c| c == '@')
.collect()
}
fn get_grid_cell(grid: &[Vec<bool>], 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<bool>]) -> 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::<Result<Vec<_>, _>>()?
.iter()
.map(|s| s.chars().map(|c| c == '@').collect::<Vec<_>>())
.collect::<Vec<_>>();
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::<Result<_, io::Error>>()?;
let mut current_grid = original_grid.clone();
let last_grid = loop {
let next_grid = update_grid(&current_grid);
if next_grid == current_grid {
break next_grid;
}
last_grid = next_grid;
}
current_grid = next_grid;
};
println!(
"Result: {}",

View File

@@ -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::<Result<_, _>>()?;
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(())
}

View File

@@ -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::<u32>().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<Self, Self::Err> {
let mut it = s.split(',').map(str::parse::<u32>);
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<T> {
parents: HashMap<T, Option<T>>
nodes: Vec<T>,
parents: Vec<usize>
}
impl<T: Eq + Hash> FromIterator<T> for DisjointSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
DisjointSet {
parents: iter.into_iter().map(|x| (x, None)).collect()
}
impl<T> DisjointSet<T> {
fn new(nodes: Vec<T>) -> Self {
let parents = (0..nodes.len()).collect();
DisjointSet { nodes, parents }
}
}
impl<T: Eq + Hash + Clone> DisjointSet<T> {
fn representative(&mut self, x: &T) -> Option<T> {
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<T> {
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<usize> {
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<dyn Error>> {
let f = File::open("8-input.txt")?;
let reader = BufReader::new(f);
let nodes: Vec<Node> = reader.lines()
.map(|lr| lr.map(|l| l.as_str().into()))
.collect::<Result<_, _>>()?;
let node_cnt = nodes.len();
let nodes: Vec<_> = reader.lines()
.map(|l| Ok(l?.parse::<Node>()?))
.collect::<Result<_, Box<dyn Error>>>()?;
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(())
}

View File

@@ -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<Self, Self::Err> {
let parts: Vec<_> = s.split(',')
.map(|s| s.parse::<i64>())
.collect();
let mut values = s.split(',').map(str::parse::<i64>);
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<Ordering> {
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<Segment>, 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<Segment>, v: &Vertex) -> i64 {
fn update_state(state: &mut Vec<Segment>, 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<Segment>, incoming: Segment) {
state.sort();
}
fn main() -> Result<(), io::Error> {
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("9-input.txt")?;
let reader = BufReader::new(f);
let vertices: Vec<_> = reader.lines()
.map(|l| l?.parse::<Vertex>())
.collect::<Result<_, _>>()?;
let mut edges: Vec<Edge> = Vec::new();
.map(|l| Ok(l?.parse::<Vertex>()?))
.collect::<Result<_, Box<dyn Error>>>()?;
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<Segment> = 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);