Format all

This commit is contained in:
James Hogge
2025-12-27 06:45:39 +00:00
parent 0db0cff560
commit 4533333153
8 changed files with 187 additions and 134 deletions

View File

@@ -10,7 +10,7 @@ struct Machine {
#[allow(dead_code)] #[allow(dead_code)]
lights: Vec<u64>, lights: Vec<u64>,
buttons: Vec<Vec<usize>>, buttons: Vec<Vec<usize>>,
joltages: Vec<u64> joltages: Vec<u64>,
} }
impl FromStr for Machine { impl FromStr for Machine {
@@ -19,42 +19,46 @@ impl FromStr for Machine {
let groups: Vec<_> = s.split(' ').collect(); let groups: Vec<_> = s.split(' ').collect();
let lights_part = groups[0]; let lights_part = groups[0];
let lights = lights_part[1..lights_part.len()-1] let lights = lights_part[1..lights_part.len() - 1]
.chars() .chars()
.map(|c| if c == '#' { 1 } else { 0 }) .map(|c| if c == '#' { 1 } else { 0 })
.collect(); .collect();
let buttons: Vec<_> = (1..groups.len()-1) let buttons: Vec<_> = (1..groups.len() - 1)
.map(|i| parse_button_group(groups[i])) .map(|i| parse_button_group(groups[i]))
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
let joltages_part = groups[groups.len()-1]; let joltages_part = groups[groups.len() - 1];
let joltages: Vec<_> = joltages_part[1..joltages_part.len()-1] let joltages: Vec<_> = joltages_part[1..joltages_part.len() - 1]
.split(',') .split(',')
.map(|j_s| j_s.parse::<u64>()) .map(|j_s| j_s.parse::<u64>())
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
Ok(Machine { lights, buttons , joltages }) Ok(Machine {
lights,
buttons,
joltages,
})
} }
} }
fn parse_button_group(s: &str) -> Result<Vec<usize>, ParseIntError> { fn parse_button_group(s: &str) -> Result<Vec<usize>, ParseIntError> {
s[1..s.len()-1].split(',') s[1..s.len() - 1]
.split(',')
.map(str::parse::<usize>) .map(str::parse::<usize>)
.collect() .collect()
} }
fn parity_solve(machine: &Machine, target: &[u64]) -> Vec<u64> { fn parity_solve(machine: &Machine, target: &[u64]) -> Vec<u64> {
let mut solutions: Vec<u64> = Vec::new(); let mut solutions: Vec<u64> = Vec::new();
for selection in 0..(1 << machine.buttons.len()) { for selection in 0..(1 << machine.buttons.len()) {
let mut parity = target.iter().rev() 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() { for (i, button) in machine.buttons.iter().enumerate() {
if selection & (1 << i) != 0 { if selection & (1 << i) != 0 {
parity = button.iter().fold(parity, |parity, j| { parity = button.iter().fold(parity, |parity, j| parity ^ (1 << j));
parity ^ (1 << j)
});
} }
} }
if parity == 0 { if parity == 0 {
@@ -65,7 +69,11 @@ fn parity_solve(machine: &Machine, target: &[u64]) -> Vec<u64> {
} }
fn minimum_solve(machine: &Machine) -> u64 { fn minimum_solve(machine: &Machine) -> u64 {
fn apply_button<'a>(machine: &Machine, button_idx: usize, current: &'a mut Vec<u64>) -> Option<&'a mut 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] { for i in &machine.buttons[button_idx] {
if current[*i] == 0 { if current[*i] == 0 {
return None; return None;
@@ -76,8 +84,12 @@ fn minimum_solve(machine: &Machine) -> u64 {
} }
fn recurse(machine: &Machine, target: &[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 target.iter().sum::<u64>() == 0 {
if max_cnt <= 0 { return None }; return Some(0);
};
if max_cnt <= 0 {
return None;
};
let parity_solutions = parity_solve(machine, target); let parity_solutions = parity_solve(machine, target);
@@ -85,8 +97,8 @@ fn minimum_solve(machine: &Machine) -> u64 {
let mut current_storage = target.to_vec(); let mut current_storage = target.to_vec();
for parity_sln in parity_solutions { for parity_sln in parity_solutions {
current_storage.copy_from_slice(target); current_storage.copy_from_slice(target);
let current = (0..machine.buttons.len()) let current =
.fold(Some(&mut current_storage), |state, i| { (0..machine.buttons.len()).fold(Some(&mut current_storage), |state, i| {
if parity_sln & (1 << i) != 0 { if parity_sln & (1 << i) != 0 {
apply_button(machine, i, state?) apply_button(machine, i, state?)
} else { } else {
@@ -96,17 +108,19 @@ fn minimum_solve(machine: &Machine) -> u64 {
let Some(current) = current else { continue }; let Some(current) = current else { continue };
let parity_ones = parity_sln.count_ones() as i64; let parity_ones = parity_sln.count_ones() as i64;
let new_max_cnt = let new_max_cnt = (match min_presses {
(match min_presses { None => max_cnt,
None => max_cnt, Some(ms) => min(ms as i64, max_cnt),
Some(ms) => min(ms as i64, max_cnt) } - parity_ones)
} - parity_ones) / 2; / 2;
let new_target: Vec<_> = current.iter().map(|&x| x / 2).collect(); let new_target: Vec<_> = current.iter().map(|&x| x / 2).collect();
let Some(sln) = recurse(machine, &new_target, new_max_cnt) else { continue }; let Some(sln) = recurse(machine, &new_target, new_max_cnt) else {
continue;
};
let presses = parity_ones as u64 + 2u64 * sln; let presses = parity_ones as u64 + 2u64 * sln;
min_presses = Some(match min_presses { min_presses = Some(match min_presses {
None => presses, None => presses,
Some(ms) => min(ms, presses) Some(ms) => min(ms, presses),
}); });
} }
min_presses min_presses
@@ -119,7 +133,8 @@ fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("10-input.txt")?; let f = File::open("10-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let machines: Vec<_> = reader.lines() let machines: Vec<_> = reader
.lines()
.map(|l| Ok(l?.parse::<Machine>()?)) .map(|l| Ok(l?.parse::<Machine>()?))
.collect::<Result<_, Box<dyn Error>>>()?; .collect::<Result<_, Box<dyn Error>>>()?;
println!("Parsed {} machines", machines.len()); println!("Parsed {} machines", machines.len());

View File

@@ -1,30 +1,31 @@
use std::{collections::HashMap, fs::File, io::{self, BufRead, BufReader}}; use std::{
collections::HashMap,
fs::File,
io::{self, BufRead, BufReader},
};
#[derive(Clone)] #[derive(Clone)]
enum GraphNode { enum GraphNode {
Output, Output,
Branch(Vec<String>) Branch(Vec<String>),
} }
fn count_paths( fn count_paths(
node: &str, node: &str,
nodes: &HashMap<String, GraphNode>, nodes: &HashMap<String, GraphNode>,
memo: &mut HashMap<String, usize> memo: &mut HashMap<String, usize>,
) -> usize { ) -> usize {
if let Some(&count) = memo.get(node) { if let Some(&count) = memo.get(node) {
return count; return count;
} }
let count = let count = match nodes.get(node) {
match nodes.get(node) { None => 0,
None => 0, Some(GraphNode::Output) => 1,
Some(GraphNode::Output) => 1, Some(GraphNode::Branch(children)) => {
Some(GraphNode::Branch(children)) => { children.iter().map(|c| count_paths(c, nodes, memo)).sum()
children.iter() }
.map(|c| count_paths(c, nodes, memo)) };
.sum()
}
};
memo.insert(node.to_string(), count); memo.insert(node.to_string(), count);
count count
} }
@@ -33,7 +34,8 @@ fn main() -> Result<(), io::Error> {
let f = File::open("11-input.txt")?; let f = File::open("11-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let nodes: HashMap<String, GraphNode> = reader.lines() let nodes: HashMap<String, GraphNode> = reader
.lines()
.map(|line| { .map(|line| {
let line = line?; let line = line?;
let parts: Vec<_> = line.split(' ').collect(); let parts: Vec<_> = line.split(' ').collect();
@@ -48,23 +50,38 @@ fn main() -> Result<(), io::Error> {
.collect::<Result<_, io::Error>>()?; .collect::<Result<_, io::Error>>()?;
let svr_paths = count_paths("svr", &nodes, &mut HashMap::new()); let svr_paths = count_paths("svr", &nodes, &mut HashMap::new());
let missing_fft_paths = count_paths("svr", let missing_fft_paths = count_paths(
&(nodes.clone() "svr",
.into_iter() &(nodes
.filter(|(k, _)| k != "fft") .clone()
.collect()), &mut HashMap::new()); .into_iter()
let missing_dac_paths = count_paths("svr", .filter(|(k, _)| k != "fft")
&(nodes.clone() .collect()),
.into_iter() &mut HashMap::new(),
.filter(|(k, _)| k != "dac") );
.collect()), &mut HashMap::new()); let missing_dac_paths = count_paths(
let missing_both_paths = count_paths("svr", "svr",
&(nodes.clone() &(nodes
.into_iter() .clone()
.filter(|(k, _)| k != "fft" && k != "dac") .into_iter()
.collect()), &mut HashMap::new()); .filter(|(k, _)| k != "dac")
.collect()),
&mut HashMap::new(),
);
let missing_both_paths = count_paths(
"svr",
&(nodes
.clone()
.into_iter()
.filter(|(k, _)| k != "fft" && k != "dac")
.collect()),
&mut HashMap::new(),
);
println!(
"Result {}",
svr_paths + missing_both_paths - missing_fft_paths - missing_dac_paths
);
println!("Result {}", svr_paths + missing_both_paths - missing_fft_paths - missing_dac_paths);
Ok(()) Ok(())
} }

View File

@@ -1,27 +1,30 @@
use std::convert::Infallible; use std::convert::Infallible;
use std::error::Error; use std::error::Error;
use std::num::ParseIntError; use std::num::ParseIntError;
use std::string::ParseError; use std::{
use std::{fs::File, io::{self, BufRead, BufReader}, str::FromStr}; fs::File,
io::{BufRead, BufReader},
str::FromStr,
};
struct Piece { struct Piece {
cells: Vec<Vec<bool>> cells: Vec<Vec<bool>>,
} }
impl FromStr for Piece { impl FromStr for Piece {
type Err = Infallible; type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let cells = let cells = s
s.split('\n').map(|row| { .split('\n')
row.chars().filter_map(|c| { .map(|row| {
match c { row.chars()
.filter_map(|c| match c {
'#' => Some(true), '#' => Some(true),
'.' => Some(false), '.' => Some(false),
_ => None _ => None,
} })
}) .collect()
.collect()
}) })
.collect(); .collect();
Ok(Piece { cells }) Ok(Piece { cells })
@@ -40,17 +43,14 @@ impl Piece {
} }
fn true_area(&self) -> u64 { fn true_area(&self) -> u64 {
self.cells.iter() self.cells.iter().flatten().filter(|&&b| b).count() as u64
.flatten()
.filter(|&&b| b)
.count() as u64
} }
} }
struct Region { struct Region {
width: u64, width: u64,
height: u64, height: u64,
requirements: Vec<u64> requirements: Vec<u64>,
} }
impl FromStr for Region { impl FromStr for Region {
@@ -61,26 +61,36 @@ impl FromStr for Region {
let (width_str, height_str) = area_str.split_once('x').unwrap(); let (width_str, height_str) = area_str.split_once('x').unwrap();
let width = width_str.parse::<u64>()?; let width = width_str.parse::<u64>()?;
let height = height_str.parse::<u64>()?; let height = height_str.parse::<u64>()?;
let requirements = requirements_str.split(' ') let requirements = requirements_str
.filter_map(|s| s.parse::<u64>().ok()) .split(' ')
.collect(); .filter_map(|s| s.parse::<u64>().ok())
Ok(Region { width, height, requirements }) .collect();
Ok(Region {
width,
height,
requirements,
})
} }
} }
fn is_solveable(pieces: &[Piece], region: &Region) -> bool { fn is_solveable(pieces: &[Piece], region: &Region) -> bool {
// Lower area bound = perfectly packed // Lower area bound = perfectly packed
let region_area = region.width * region.height; let region_area = region.width * region.height;
let used_area: u64 = pieces.iter() let used_area: u64 = pieces
.iter()
.zip(region.requirements.iter()) .zip(region.requirements.iter())
.map(|(piece, cnt)| piece.true_area() * cnt) .map(|(piece, cnt)| piece.true_area() * cnt)
.sum(); .sum();
if used_area > region_area { return false }; if used_area > region_area {
return false;
};
// Upper area bound = 3x3 pieces // Upper area bound = 3x3 pieces
let available_3x3s = region.width / 3 * region.height / 3; let available_3x3s = region.width / 3 * region.height / 3;
let piece_cnt: u64 = region.requirements.iter().sum(); let piece_cnt: u64 = region.requirements.iter().sum();
if piece_cnt <= available_3x3s { return true }; if piece_cnt <= available_3x3s {
return true;
};
println!("Non-trivial solution"); println!("Non-trivial solution");
false false
@@ -90,24 +100,23 @@ fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("12-input.txt")?; let f = File::open("12-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let lines: Vec<_> = reader.lines().collect::<Result<_,_>>()?; let lines: Vec<_> = reader.lines().collect::<Result<_, _>>()?;
let (lines_pieces, lines_regions) = lines.split_at(30); let (lines_pieces, lines_regions) = lines.split_at(30);
let pieces: Vec<_> = lines_pieces.chunks(5) let pieces: Vec<_> = lines_pieces
.map(|lines| { .chunks(5)
Ok(lines[1..lines.len()-1].join("\n").parse::<Piece>()?) .map(|lines| Ok(lines[1..lines.len() - 1].join("\n").parse::<Piece>()?))
})
.collect::<Result<_, Box<dyn Error>>>()?; .collect::<Result<_, Box<dyn Error>>>()?;
let regions: Vec<_> = lines_regions.iter() let regions: Vec<_> = lines_regions
.map(|line| { .iter()
Ok(line.parse::<Region>()?) .map(|line| Ok(line.parse::<Region>()?))
})
.collect::<Result<_, Box<dyn Error>>>()?; .collect::<Result<_, Box<dyn Error>>>()?;
let result: u64 = regions.iter() let result: u64 = regions
.iter()
.filter(|region| is_solveable(&pieces, region)) .filter(|region| is_solveable(&pieces, region))
.count() as u64; .count() as u64;
println!("Result: {}", result); println!("Result: {}", result);
Ok(()) Ok(())
} }

View File

@@ -29,9 +29,7 @@ fn main() -> Result<(), io::Error> {
let f = File::open("2-input.txt")?; let f = File::open("2-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let range_line = reader.lines().next().unwrap()?; let range_line = reader.lines().next().unwrap()?;
let mut ranges: Vec<_> = range_line.split(",") let mut ranges: Vec<_> = range_line.split(",").map(parse_range).collect();
.map(parse_range)
.collect();
ranges.sort_unstable(); ranges.sort_unstable();
let mut total: i64 = 0; let mut total: i64 = 0;

View File

@@ -4,13 +4,9 @@ use std::{
}; };
fn max_joltage(s: &str) -> u64 { fn max_joltage(s: &str) -> u64 {
let values: Vec<_> = s let values: Vec<_> = s.chars().map(|x| x.to_digit(10).unwrap()).collect();
.chars()
.map(|x| x.to_digit(10).unwrap())
.collect();
let max_idx = |xs: &[u32]| { let max_idx = |xs: &[u32]| {
xs.iter() xs.iter()
.enumerate() .enumerate()
.fold(0, |max, (i, &x)| if x > xs[max] { i } else { max }) .fold(0, |max, (i, &x)| if x > xs[max] { i } else { max })
@@ -27,11 +23,7 @@ fn main() -> Result<(), io::Error> {
let f = File::open("3-input.txt")?; let f = File::open("3-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let total: u64 = reader.lines() let total: u64 = reader.lines().map(|l| max_joltage(&l.unwrap())).sum();
.map(|l| {
max_joltage(&l.unwrap())
})
.sum();
println!("Result: {}", total); println!("Result: {}", total);
Ok(()) Ok(())
} }

View File

@@ -15,9 +15,7 @@ const NEIGHBOURS: [(i32, i32); 8] = [
]; ];
fn parse_grid_line(line: &str) -> Vec<bool> { fn parse_grid_line(line: &str) -> Vec<bool> {
line.chars() line.chars().map(|c| c == '@').collect()
.map(|c| c == '@')
.collect()
} }
fn get_grid_cell(grid: &[Vec<bool>], x: i32, y: i32) -> bool { fn get_grid_cell(grid: &[Vec<bool>], x: i32, y: i32) -> bool {
@@ -65,7 +63,7 @@ fn main() -> Result<(), io::Error> {
.lines() .lines()
.map(|line| Ok(parse_grid_line(&line?))) .map(|line| Ok(parse_grid_line(&line?)))
.collect::<Result<_, io::Error>>()?; .collect::<Result<_, io::Error>>()?;
let mut current_grid = original_grid.clone(); let mut current_grid = original_grid.clone();
let last_grid = loop { let last_grid = loop {
let next_grid = update_grid(&current_grid); let next_grid = update_grid(&current_grid);

View File

@@ -1,4 +1,10 @@
use std::{error::Error, fs::File, io::{BufRead, BufReader}, num::ParseIntError, str::FromStr}; use std::{
error::Error,
fs::File,
io::{BufRead, BufReader},
num::ParseIntError,
str::FromStr,
};
#[derive(Debug)] #[derive(Debug)]
struct Node { struct Node {
@@ -12,7 +18,7 @@ impl Node {
let dx = i64::from(a.x) - i64::from(b.x); let dx = i64::from(a.x) - i64::from(b.x);
let dy = i64::from(a.y) - i64::from(b.y); let dy = i64::from(a.y) - i64::from(b.y);
let dz = i64::from(a.z) - i64::from(b.z); let dz = i64::from(a.z) - i64::from(b.z);
dx*dx + dy*dy + dz*dz dx * dx + dy * dy + dz * dz
} }
} }
@@ -31,7 +37,7 @@ impl FromStr for Node {
#[derive(Debug)] #[derive(Debug)]
struct DisjointSet<T> { struct DisjointSet<T> {
nodes: Vec<T>, nodes: Vec<T>,
parents: Vec<usize> parents: Vec<usize>,
} }
impl<T> DisjointSet<T> { impl<T> DisjointSet<T> {
@@ -67,13 +73,14 @@ fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("8-input.txt")?; let f = File::open("8-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let nodes: Vec<_> = reader.lines() let nodes: Vec<_> = reader
.lines()
.map(|l| Ok(l?.parse::<Node>()?)) .map(|l| Ok(l?.parse::<Node>()?))
.collect::<Result<_, Box<dyn Error>>>()?; .collect::<Result<_, Box<dyn Error>>>()?;
let mut edges: Vec<(i64, usize, usize)> = Vec::new(); let mut edges: Vec<(i64, usize, usize)> = Vec::new();
for i in 0..nodes.len() { for i in 0..nodes.len() {
for j in i+1..nodes.len() { for j in i + 1..nodes.len() {
let sqr_dist = Node::square_dist(&nodes[i], &nodes[j]); let sqr_dist = Node::square_dist(&nodes[i], &nodes[j]);
edges.push((sqr_dist, i, j)); edges.push((sqr_dist, i, j));
} }
@@ -81,7 +88,8 @@ fn main() -> Result<(), Box<dyn Error>> {
edges.sort_unstable_by_key(|(d, _, _)| *d); edges.sort_unstable_by_key(|(d, _, _)| *d);
let mut ds: DisjointSet<_> = DisjointSet::new(nodes); let mut ds: DisjointSet<_> = DisjointSet::new(nodes);
let connections: Vec<_> = edges.iter() let connections: Vec<_> = edges
.iter()
.filter_map(|(_, i, j)| ds.union(*i, *j).map(|_| (*i, *j))) .filter_map(|(_, i, j)| ds.union(*i, *j).map(|_| (*i, *j)))
.collect(); .collect();
@@ -91,4 +99,4 @@ fn main() -> Result<(), Box<dyn Error>> {
let last_to = &nodes[last_connection.1]; let last_to = &nodes[last_connection.1];
println!("Result {}", u64::from(last_from.x) * u64::from(last_to.x)); println!("Result {}", u64::from(last_from.x) * u64::from(last_to.x));
Ok(()) Ok(())
} }

View File

@@ -5,7 +5,6 @@ use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::str::FromStr; use std::str::FromStr;
#[derive(Debug)] #[derive(Debug)]
struct ParseVertexError; struct ParseVertexError;
@@ -17,11 +16,10 @@ impl Display for ParseVertexError {
impl Error for ParseVertexError {} impl Error for ParseVertexError {}
#[derive(Debug)] #[derive(Debug)]
struct Vertex { struct Vertex {
x: i64, x: i64,
y: i64 y: i64,
} }
impl FromStr for Vertex { impl FromStr for Vertex {
@@ -29,20 +27,23 @@ impl FromStr for Vertex {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut values = s.split(',').map(str::parse::<i64>); let mut values = s.split(',').map(str::parse::<i64>);
let Some(Ok(x)) = values.next() else { return Err(ParseVertexError) }; let Some(Ok(x)) = values.next() else {
let Some(Ok(y)) = values.next() else { return Err(ParseVertexError) }; return Err(ParseVertexError);
};
let Some(Ok(y)) = values.next() else {
return Err(ParseVertexError);
};
Ok(Vertex { x, y }) Ok(Vertex { x, y })
} }
} }
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
struct Segment { struct Segment {
lo: i64, lo: i64,
hi: i64, hi: i64,
truncate_lo: bool, truncate_lo: bool,
truncate_hi: bool, truncate_hi: bool,
dist: Option<i64> dist: Option<i64>,
} }
impl Segment { impl Segment {
@@ -52,9 +53,7 @@ impl Segment {
hi: max(start.x, end.x), hi: max(start.x, end.x),
truncate_lo: false, truncate_lo: false,
truncate_hi: false, truncate_hi: false,
dist: dist: if start.x < end.x { Some(start.y) } else { None },
if start.x < end.x { Some(start.y) }
else { None }
} }
} }
} }
@@ -77,7 +76,6 @@ impl Debug for Segment {
} }
} }
fn rect_area(x1: i64, x2: i64, y1: i64, y2: i64) -> i64 { fn rect_area(x1: i64, x2: i64, y1: i64, y2: i64) -> i64 {
(1 + i64::abs(x1 - x2)) * (1 + i64::abs(y1 - y2)) (1 + i64::abs(x1 - x2)) * (1 + i64::abs(y1 - y2))
} }
@@ -87,7 +85,9 @@ fn rect_from_point(state: &[Segment], v: &Vertex) -> i64 {
let mut max_y = i64::MIN; let mut max_y = i64::MIN;
for segment in state { for segment in state {
if segment.hi <= v.x { continue } if segment.hi <= v.x {
continue;
}
let Some(seg_y) = segment.dist else { break }; let Some(seg_y) = segment.dist else { break };
if seg_y >= max_y { if seg_y >= max_y {
@@ -103,7 +103,9 @@ fn rect_from_point(state: &[Segment], v: &Vertex) -> i64 {
let mut max_y = i64::MIN; let mut max_y = i64::MIN;
for segment in state.iter().rev() { for segment in state.iter().rev() {
if segment.lo >= v.x { continue } if segment.lo >= v.x {
continue;
}
let Some(seg_y) = segment.dist else { break }; let Some(seg_y) = segment.dist else { break };
if seg_y >= max_y { if seg_y >= max_y {
@@ -125,8 +127,16 @@ fn update_state(state: &mut Vec<Segment>, incoming: Segment) {
if incoming.lo <= current.lo && current.hi <= incoming.hi { if incoming.lo <= current.lo && current.hi <= incoming.hi {
state.remove(i); state.remove(i);
} else if current.lo < incoming.lo && incoming.hi < current.hi { } else if current.lo < incoming.lo && incoming.hi < current.hi {
state.push(Segment { hi: incoming.lo, truncate_hi: true, ..current }); state.push(Segment {
state.push(Segment { lo: incoming.hi, truncate_lo: true, ..current }); hi: incoming.lo,
truncate_hi: true,
..current
});
state.push(Segment {
lo: incoming.hi,
truncate_lo: true,
..current
});
state.remove(i); state.remove(i);
} else if current.lo < incoming.lo && incoming.lo < current.hi { } else if current.lo < incoming.lo && incoming.lo < current.hi {
state[i].hi = incoming.lo; state[i].hi = incoming.lo;
@@ -143,11 +153,11 @@ fn update_state(state: &mut Vec<Segment>, incoming: Segment) {
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("9-input.txt")?; let f = File::open("9-input.txt")?;
let reader = BufReader::new(f); let reader = BufReader::new(f);
let vertices: Vec<_> = reader.lines() let vertices: Vec<_> = reader
.lines()
.map(|l| Ok(l?.parse::<Vertex>()?)) .map(|l| Ok(l?.parse::<Vertex>()?))
.collect::<Result<_, Box<dyn Error>>>()?; .collect::<Result<_, Box<dyn Error>>>()?;
let mut horizontal_edges: Vec<(usize, usize)> = Vec::new(); let mut horizontal_edges: Vec<(usize, usize)> = Vec::new();
for i in 0..vertices.len() { for i in 0..vertices.len() {
let j = (i + 1) % vertices.len(); let j = (i + 1) % vertices.len();
@@ -158,7 +168,13 @@ fn main() -> Result<(), Box<dyn Error>> {
horizontal_edges.sort_unstable_by_key(|e| vertices[e.0].y); horizontal_edges.sort_unstable_by_key(|e| vertices[e.0].y);
let mut max_area: i64 = 0; let mut max_area: i64 = 0;
let mut state = vec![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 { for e in horizontal_edges {
let start = &vertices[e.0]; let start = &vertices[e.0];
let end = &vertices[e.1]; let end = &vertices[e.1];
@@ -169,4 +185,4 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("Result {}", max_area); println!("Result {}", max_area);
Ok(()) Ok(())
} }