diff --git a/src/10-factory.rs b/src/10-factory.rs index b6f1eb0..f3a0b2a 100644 --- a/src/10-factory.rs +++ b/src/10-factory.rs @@ -10,7 +10,7 @@ struct Machine { #[allow(dead_code)] lights: Vec, buttons: Vec>, - joltages: Vec + joltages: Vec, } impl FromStr for Machine { @@ -19,42 +19,46 @@ impl FromStr for Machine { let groups: Vec<_> = s.split(' ').collect(); let lights_part = groups[0]; - let lights = lights_part[1..lights_part.len()-1] + let lights = lights_part[1..lights_part.len() - 1] .chars() .map(|c| if c == '#' { 1 } else { 0 }) .collect(); - let buttons: Vec<_> = (1..groups.len()-1) + let buttons: Vec<_> = (1..groups.len() - 1) .map(|i| parse_button_group(groups[i])) .collect::>()?; - let joltages_part = groups[groups.len()-1]; - let joltages: Vec<_> = joltages_part[1..joltages_part.len()-1] + let joltages_part = groups[groups.len() - 1]; + let joltages: Vec<_> = joltages_part[1..joltages_part.len() - 1] .split(',') .map(|j_s| j_s.parse::()) .collect::>()?; - Ok(Machine { lights, buttons , joltages }) + Ok(Machine { + lights, + buttons, + joltages, + }) } } fn parse_button_group(s: &str) -> Result, ParseIntError> { - s[1..s.len()-1].split(',') + s[1..s.len() - 1] + .split(',') .map(str::parse::) .collect() } - 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() + let mut parity = target + .iter() + .rev() .fold(0, |state, x| (state << 1) | (x & 1)); for (i, button) in machine.buttons.iter().enumerate() { if selection & (1 << i) != 0 { - parity = button.iter().fold(parity, |parity, j| { - parity ^ (1 << j) - }); + parity = button.iter().fold(parity, |parity, j| parity ^ (1 << j)); } } if parity == 0 { @@ -65,7 +69,11 @@ fn parity_solve(machine: &Machine, target: &[u64]) -> Vec { } fn minimum_solve(machine: &Machine) -> u64 { - fn apply_button<'a>(machine: &Machine, button_idx: usize, current: &'a mut Vec) -> Option<&'a mut Vec> { + 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] == 0 { return None; @@ -76,8 +84,12 @@ fn minimum_solve(machine: &Machine) -> u64 { } fn recurse(machine: &Machine, target: &[u64], max_cnt: i64) -> Option { - if target.iter().sum::() == 0 { return Some(0) }; - if max_cnt <= 0 { return None }; + if target.iter().sum::() == 0 { + return Some(0); + }; + if max_cnt <= 0 { + return None; + }; let parity_solutions = parity_solve(machine, target); @@ -85,8 +97,8 @@ fn minimum_solve(machine: &Machine) -> u64 { 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(&mut current_storage), |state, i| { + let current = + (0..machine.buttons.len()).fold(Some(&mut current_storage), |state, i| { if parity_sln & (1 << i) != 0 { apply_button(machine, i, state?) } else { @@ -96,17 +108,19 @@ fn minimum_solve(machine: &Machine) -> u64 { let Some(current) = current else { continue }; let parity_ones = parity_sln.count_ones() as i64; - let new_max_cnt = - (match min_presses { - None => max_cnt, - Some(ms) => min(ms as i64, max_cnt) - } - parity_ones) / 2; + let new_max_cnt = (match min_presses { + None => max_cnt, + Some(ms) => min(ms as i64, max_cnt), + } - parity_ones) + / 2; 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; min_presses = Some(match min_presses { None => presses, - Some(ms) => min(ms, presses) + Some(ms) => min(ms, presses), }); } min_presses @@ -119,7 +133,8 @@ fn main() -> Result<(), Box> { let f = File::open("10-input.txt")?; let reader = BufReader::new(f); - let machines: Vec<_> = reader.lines() + let machines: Vec<_> = reader + .lines() .map(|l| Ok(l?.parse::()?)) .collect::>>()?; println!("Parsed {} machines", machines.len()); diff --git a/src/11-reactor.rs b/src/11-reactor.rs index 2c596a1..3372727 100644 --- a/src/11-reactor.rs +++ b/src/11-reactor.rs @@ -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)] enum GraphNode { Output, - Branch(Vec) + Branch(Vec), } fn count_paths( node: &str, nodes: &HashMap, - memo: &mut HashMap + memo: &mut HashMap, ) -> usize { if let Some(&count) = memo.get(node) { return count; } - let count = - match nodes.get(node) { - None => 0, - Some(GraphNode::Output) => 1, - Some(GraphNode::Branch(children)) => { - children.iter() - .map(|c| count_paths(c, nodes, memo)) - .sum() - } - }; + let count = match nodes.get(node) { + None => 0, + Some(GraphNode::Output) => 1, + Some(GraphNode::Branch(children)) => { + children.iter().map(|c| count_paths(c, nodes, memo)).sum() + } + }; memo.insert(node.to_string(), count); count } @@ -33,7 +34,8 @@ fn main() -> Result<(), io::Error> { let f = File::open("11-input.txt")?; let reader = BufReader::new(f); - let nodes: HashMap = reader.lines() + let nodes: HashMap = reader + .lines() .map(|line| { let line = line?; let parts: Vec<_> = line.split(' ').collect(); @@ -48,23 +50,38 @@ fn main() -> Result<(), io::Error> { .collect::>()?; let svr_paths = count_paths("svr", &nodes, &mut HashMap::new()); - let missing_fft_paths = count_paths("svr", - &(nodes.clone() - .into_iter() - .filter(|(k, _)| k != "fft") - .collect()), &mut HashMap::new()); - let missing_dac_paths = count_paths("svr", - &(nodes.clone() - .into_iter() - .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()); + let missing_fft_paths = count_paths( + "svr", + &(nodes + .clone() + .into_iter() + .filter(|(k, _)| k != "fft") + .collect()), + &mut HashMap::new(), + ); + let missing_dac_paths = count_paths( + "svr", + &(nodes + .clone() + .into_iter() + .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(()) -} \ No newline at end of file +} diff --git a/src/12-christmas-tree-farm.rs b/src/12-christmas-tree-farm.rs index 309abf6..e0b3ecb 100644 --- a/src/12-christmas-tree-farm.rs +++ b/src/12-christmas-tree-farm.rs @@ -1,27 +1,30 @@ 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}; +use std::{ + fs::File, + io::{BufRead, BufReader}, + str::FromStr, +}; struct Piece { - cells: Vec> + cells: Vec>, } impl FromStr for Piece { type Err = Infallible; fn from_str(s: &str) -> Result { - let cells = - s.split('\n').map(|row| { - row.chars().filter_map(|c| { - match c { + let cells = s + .split('\n') + .map(|row| { + row.chars() + .filter_map(|c| match c { '#' => Some(true), '.' => Some(false), - _ => None - } - }) - .collect() + _ => None, + }) + .collect() }) .collect(); Ok(Piece { cells }) @@ -40,17 +43,14 @@ impl Piece { } fn true_area(&self) -> u64 { - self.cells.iter() - .flatten() - .filter(|&&b| b) - .count() as u64 + self.cells.iter().flatten().filter(|&&b| b).count() as u64 } } struct Region { width: u64, height: u64, - requirements: Vec + requirements: Vec, } 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 = 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 }) + let requirements = requirements_str + .split(' ') + .filter_map(|s| s.parse::().ok()) + .collect(); + Ok(Region { + width, + height, + requirements, + }) } } 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() + let used_area: u64 = pieces + .iter() .zip(region.requirements.iter()) .map(|(piece, cnt)| piece.true_area() * cnt) .sum(); - if used_area > region_area { return false }; + if used_area > region_area { + return false; + }; // Upper area bound = 3x3 pieces let available_3x3s = region.width / 3 * region.height / 3; 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"); false @@ -90,24 +100,23 @@ fn main() -> Result<(), Box> { let f = File::open("12-input.txt")?; let reader = BufReader::new(f); - let lines: Vec<_> = reader.lines().collect::>()?; + let lines: Vec<_> = reader.lines().collect::>()?; let (lines_pieces, lines_regions) = lines.split_at(30); - let pieces: Vec<_> = lines_pieces.chunks(5) - .map(|lines| { - Ok(lines[1..lines.len()-1].join("\n").parse::()?) - }) + let pieces: Vec<_> = lines_pieces + .chunks(5) + .map(|lines| Ok(lines[1..lines.len() - 1].join("\n").parse::()?)) .collect::>>()?; - let regions: Vec<_> = lines_regions.iter() - .map(|line| { - Ok(line.parse::()?) - }) + let regions: Vec<_> = lines_regions + .iter() + .map(|line| Ok(line.parse::()?)) .collect::>>()?; - let result: u64 = regions.iter() + 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 11cbf2e..4dd7972 100644 --- a/src/2-gift-shop.rs +++ b/src/2-gift-shop.rs @@ -29,9 +29,7 @@ fn main() -> Result<(), io::Error> { let f = File::open("2-input.txt")?; let reader = BufReader::new(f); let range_line = reader.lines().next().unwrap()?; - let mut ranges: Vec<_> = range_line.split(",") - .map(parse_range) - .collect(); + let mut ranges: Vec<_> = range_line.split(",").map(parse_range).collect(); ranges.sort_unstable(); let mut total: i64 = 0; diff --git a/src/3-lobby.rs b/src/3-lobby.rs index 3b27469..b5cee8f 100644 --- a/src/3-lobby.rs +++ b/src/3-lobby.rs @@ -4,13 +4,9 @@ use std::{ }; fn max_joltage(s: &str) -> u64 { - let values: Vec<_> = s - .chars() - .map(|x| x.to_digit(10).unwrap()) - .collect(); + let values: Vec<_> = s.chars().map(|x| x.to_digit(10).unwrap()).collect(); let max_idx = |xs: &[u32]| { - xs.iter() .enumerate() .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 reader = BufReader::new(f); - let total: u64 = reader.lines() - .map(|l| { - max_joltage(&l.unwrap()) - }) - .sum(); + 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 b13e89c..34d889d 100644 --- a/src/4-printing-department.rs +++ b/src/4-printing-department.rs @@ -15,9 +15,7 @@ const NEIGHBOURS: [(i32, i32); 8] = [ ]; fn parse_grid_line(line: &str) -> Vec { - line.chars() - .map(|c| c == '@') - .collect() + line.chars().map(|c| c == '@').collect() } fn get_grid_cell(grid: &[Vec], x: i32, y: i32) -> bool { @@ -65,7 +63,7 @@ fn main() -> Result<(), io::Error> { .lines() .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); diff --git a/src/8-playground.rs b/src/8-playground.rs index fc2a9af..7d9d0bb 100644 --- a/src/8-playground.rs +++ b/src/8-playground.rs @@ -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)] struct Node { @@ -12,7 +18,7 @@ impl Node { let dx = i64::from(a.x) - i64::from(b.x); let dy = i64::from(a.y) - i64::from(b.y); 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)] struct DisjointSet { nodes: Vec, - parents: Vec + parents: Vec, } impl DisjointSet { @@ -67,13 +73,14 @@ fn main() -> Result<(), Box> { let f = File::open("8-input.txt")?; let reader = BufReader::new(f); - let nodes: Vec<_> = reader.lines() + let nodes: Vec<_> = reader + .lines() .map(|l| Ok(l?.parse::()?)) .collect::>>()?; let mut edges: Vec<(i64, usize, usize)> = Vec::new(); 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]); edges.push((sqr_dist, i, j)); } @@ -81,7 +88,8 @@ fn main() -> Result<(), Box> { edges.sort_unstable_by_key(|(d, _, _)| *d); 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))) .collect(); @@ -91,4 +99,4 @@ fn main() -> Result<(), Box> { 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 8297a38..4e75552 100644 --- a/src/9-movie-theater.rs +++ b/src/9-movie-theater.rs @@ -5,7 +5,6 @@ use std::fs::File; use std::io::{BufRead, BufReader}; use std::str::FromStr; - #[derive(Debug)] struct ParseVertexError; @@ -17,11 +16,10 @@ impl Display for ParseVertexError { impl Error for ParseVertexError {} - #[derive(Debug)] struct Vertex { x: i64, - y: i64 + y: i64, } impl FromStr for Vertex { @@ -29,20 +27,23 @@ impl FromStr for Vertex { fn from_str(s: &str) -> Result { let mut values = s.split(',').map(str::parse::); - let Some(Ok(x)) = values.next() else { return Err(ParseVertexError) }; - let Some(Ok(y)) = values.next() else { return Err(ParseVertexError) }; + 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(Clone, PartialEq, Eq)] struct Segment { lo: i64, hi: i64, truncate_lo: bool, truncate_hi: bool, - dist: Option + dist: Option, } impl Segment { @@ -52,9 +53,7 @@ impl Segment { hi: max(start.x, end.x), truncate_lo: false, truncate_hi: false, - dist: - if start.x < end.x { Some(start.y) } - else { None } + dist: 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 { (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; for segment in state { - if segment.hi <= v.x { continue } + if segment.hi <= v.x { + continue; + } let Some(seg_y) = segment.dist else { break }; if seg_y >= max_y { @@ -103,7 +103,9 @@ fn rect_from_point(state: &[Segment], v: &Vertex) -> i64 { let mut max_y = i64::MIN; 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 }; if seg_y >= max_y { @@ -125,8 +127,16 @@ fn update_state(state: &mut Vec, incoming: Segment) { if incoming.lo <= current.lo && current.hi <= incoming.hi { state.remove(i); } else if current.lo < incoming.lo && incoming.hi < current.hi { - state.push(Segment { hi: incoming.lo, truncate_hi: true, ..current }); - state.push(Segment { lo: incoming.hi, truncate_lo: true, ..current }); + state.push(Segment { + hi: incoming.lo, + truncate_hi: true, + ..current + }); + state.push(Segment { + lo: incoming.hi, + truncate_lo: true, + ..current + }); state.remove(i); } else if current.lo < incoming.lo && incoming.lo < current.hi { state[i].hi = incoming.lo; @@ -143,11 +153,11 @@ fn update_state(state: &mut Vec, incoming: Segment) { fn main() -> Result<(), Box> { let f = File::open("9-input.txt")?; let reader = BufReader::new(f); - let vertices: Vec<_> = reader.lines() + let vertices: Vec<_> = reader + .lines() .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(); @@ -158,7 +168,13 @@ fn main() -> Result<(), Box> { horizontal_edges.sort_unstable_by_key(|e| vertices[e.0].y); 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 { let start = &vertices[e.0]; let end = &vertices[e.1]; @@ -169,4 +185,4 @@ fn main() -> Result<(), Box> { println!("Result {}", max_area); Ok(()) -} \ No newline at end of file +}