From 1639af81fc99916950d31e684c3750f45e813875 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 10 Dec 2024 00:17:46 +0100 Subject: [PATCH] feat: day 9 p2 + fmt / clippy --- src/bin/08.rs | 83 ++++++++++++++--------------- src/bin/09.rs | 142 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 151 insertions(+), 74 deletions(-) diff --git a/src/bin/08.rs b/src/bin/08.rs index 471fc54..39b56ea 100644 --- a/src/bin/08.rs +++ b/src/bin/08.rs @@ -15,14 +15,14 @@ impl Pos { Self { x, y } } - fn diff(&self, other: &Self) -> Self { + fn diff(self, other: Self) -> Self { Self { x: other.x - self.x, y: other.y - self.y, } } - fn add(&self, other: &Self) -> Self { + fn add(self, other: Self) -> Self { Self { x: self.x + other.x, y: self.y + other.y, @@ -30,16 +30,15 @@ impl Pos { } fn is_valid(&self, max: &Self) -> bool { - self.x >= 0 && self.x < max.x - && self.y >= 0 && self.y < max.y + self.x >= 0 && self.x < max.x && self.y >= 0 && self.y < max.y } } fn get_antinodes(p1: &Pos, p2: &Pos, max: &Pos) -> Vec { - let d1 = p1.diff(&p2); - let d2 = p2.diff(&p1); - let p1b = p1.add(&d2); - let p2b = p2.add(&d1); + let d1 = p1.diff(*p2); + let d2 = p2.diff(*p1); + let p1b = p1.add(d2); + let p2b = p2.add(d1); let mut res: Vec = Vec::new(); if p1b.is_valid(max) { res.push(p1b); @@ -50,31 +49,27 @@ fn get_antinodes(p1: &Pos, p2: &Pos, max: &Pos) -> Vec { res } -fn get_antinodes_p2(p1: &Pos, p2: &Pos, max: &Pos) -> Vec { - let d1 = p2.diff(&p1); - let mut succ1: Vec = successors( - Some(*p1), - |p| { - let s = p.add(&d1); - if s.is_valid(max) { - Some(s) - } else { - None - } +fn get_antinodes_p2(p1: Pos, p2: Pos, max: &Pos) -> Vec { + let d1 = p2.diff(p1); + let mut succ1: Vec = successors(Some(p1), |p| { + let s = p.add(d1); + if s.is_valid(max) { + Some(s) + } else { + None } - ).collect(); - let d2 = p1.diff(&p2); - let succ2: Vec = successors( - Some(*p2), - |p| { - let s = p.add(&d2); - if s.is_valid(max) { - Some(s) - } else { - None - } + }) + .collect(); + let d2 = p1.diff(p2); + let succ2: Vec = successors(Some(p2), |p| { + let s = p.add(d2); + if s.is_valid(max) { + Some(s) + } else { + None } - ).collect(); + }) + .collect(); succ1.extend(succ2); succ1.into_iter().map(|p| p.to_owned()).collect() } @@ -113,7 +108,7 @@ fn parse_line(line: &str, y: usize) -> Vec<(char, Pos)> { // } // } -fn parse_input(input: &str) -> (Pos, HashMap::>) { +fn parse_input(input: &str) -> (Pos, HashMap>) { let mut antenna: HashMap> = HashMap::new(); let lines = input.lines().collect::>(); let map_size = Pos::init(lines[0].len() as i8, lines.len() as i8); @@ -122,7 +117,7 @@ fn parse_input(input: &str) -> (Pos, HashMap::>) { .enumerate() .flat_map(|(y, l)| parse_line(l, y)) .for_each(|(c, p)| { - antenna.entry(c).or_insert(Vec::new()).push(p); + antenna.entry(c).or_default().push(p); }); (map_size, antenna) } @@ -131,11 +126,12 @@ pub fn part_one(input: &str) -> Option { let (map_size, antenna) = parse_input(input); let mut antinodes: Vec = antenna .values() - .flat_map(|ps| ps.into_iter() - .combinations(2) - .flat_map(|a| get_antinodes(a[0], a[1], &map_size)) - .collect::>() - ) + .flat_map(|ps| { + ps.iter() + .combinations(2) + .flat_map(|a| get_antinodes(a[0], a[1], &map_size)) + .collect::>() + }) .collect(); antinodes.sort(); antinodes.dedup(); @@ -146,11 +142,12 @@ pub fn part_two(input: &str) -> Option { let (map_size, antenna) = parse_input(input); let mut antinodes: Vec = antenna .values() - .flat_map(|ps| ps.into_iter() - .combinations(2) - .flat_map(|a| get_antinodes_p2(a[0], a[1], &map_size)) - .collect::>() - ) + .flat_map(|ps| { + ps.iter() + .combinations(2) + .flat_map(|a| get_antinodes_p2(*a[0], *a[1], &map_size)) + .collect::>() + }) .collect(); antinodes.sort(); antinodes.dedup(); diff --git a/src/bin/09.rs b/src/bin/09.rs index d3ccbf4..bcb85db 100644 --- a/src/bin/09.rs +++ b/src/bin/09.rs @@ -1,26 +1,110 @@ advent_of_code::solution!(9); +use std::collections::VecDeque; + const MEMORY_SIZE: usize = 100_000; +#[derive(Debug, Clone)] +struct Blocks { + file_id: Option, + size: u8, +} + +impl Blocks { + fn get_checksum(&self, offset: u64) -> u64 { + if let Some(id) = self.file_id { + let mut chk: u64 = 0; + for x in 0..self.size { + chk += (offset + (x as u64)) * (id as u64); + } + chk + } else { + 0 + } + } +} + #[derive(Debug)] struct MemoryP2 { + memory: VecDeque, } impl MemoryP2 { fn init(ds: Vec) -> Self { - todo!() + let mut file_nb: u16 = 0; + let mut is_file = true; + let mut memory: VecDeque = VecDeque::new(); + ds.into_iter().for_each(|bs| { + let file_id = if is_file { + let id = file_nb; + file_nb += 1; + is_file = false; + Some(id) + } else { + is_file = true; + None + }; + if bs > 0 { + memory.push_back(Blocks { + file_id, + size: bs as u8, + }); + } + }); + Self { memory } } fn fill_empty_blocks(&mut self) { - todo!() + let mut new_list: VecDeque = VecDeque::new(); + while !self.memory.is_empty() { + let mut cur = self.memory.pop_front().unwrap(); + if cur.file_id.is_some() { + new_list.push_back(cur); + continue; + } + // try to find something fitting + let mut tmp: VecDeque = VecDeque::new(); + let mut inserted = false; + while let Some(block) = self.memory.pop_back() { + if block.file_id.is_some() && block.size <= cur.size { + cur.size -= block.size; + let empty_size = block.size; + new_list.push_back(block); + inserted = true; + + self.memory.push_back(Blocks { + file_id: None, + size: empty_size, + }); + break; + } else { + tmp.push_front(block); + } + } + self.memory.extend(tmp); + if cur.size > 0 { + if inserted { + self.memory.push_front(cur); + } else { + new_list.push_back(cur); + } + } + } + self.memory = new_list; } fn compute_checksum(&self) -> u64 { - todo!() + let mut checksum: u64 = 0; + let mut offset = 0; + + for block in &self.memory { + checksum += block.get_checksum(offset); + offset += block.size as u64; + } + checksum } } - #[derive(Debug)] struct MemoryP1 { memory: [Option; MEMORY_SIZE], @@ -28,31 +112,25 @@ struct MemoryP1 { impl MemoryP1 { fn init(ds: Vec) -> Self { - let mut memory: [Option; 100_000] = [None; 100_000]; //[16; 100_000] = [0; 100_000]; + let mut memory: [Option; 100_000] = [None; 100_000]; let mut offset: usize = 0; let mut file_nb: u16 = 0; let mut is_file = true; - ds - .into_iter() - .for_each(|bs| { - match is_file { - true => { - for n in 0..bs { - memory[offset + n as usize] = Some(file_nb); - } - offset += bs as usize; - file_nb += 1; - is_file = false; - }, - false => { - offset += bs as usize; - is_file = true; - } + ds.into_iter().for_each(|bs| match is_file { + true => { + for n in 0..bs { + memory[offset + n as usize] = Some(file_nb); } - }); - Self { - memory, - } + offset += bs as usize; + file_nb += 1; + is_file = false; + } + false => { + offset += bs as usize; + is_file = true; + } + }); + Self { memory } } fn fill_empty_blocks(&mut self) { @@ -70,12 +148,14 @@ impl MemoryP1 { if back_cursor < front_cursor { finished = true; } - - if !finished && self.memory[back_cursor].is_some() && self.memory[front_cursor].is_none() { + + if !finished + && self.memory[back_cursor].is_some() + && self.memory[front_cursor].is_none() + { self.memory[front_cursor] = self.memory[back_cursor]; self.memory[back_cursor] = None; } - } } fn compute_checksum(&self) -> u64 { @@ -90,14 +170,14 @@ impl MemoryP1 { } pub fn part_one(input: &str) -> Option { - let nbs: Vec<_> = input.chars().flat_map(|c|c.to_digit(10u32)).collect(); + let nbs: Vec<_> = input.chars().flat_map(|c| c.to_digit(10u32)).collect(); let mut mem = MemoryP1::init(nbs); mem.fill_empty_blocks(); Some(mem.compute_checksum()) } pub fn part_two(input: &str) -> Option { - let nbs: Vec<_> = input.chars().flat_map(|c|c.to_digit(10u32)).collect(); + let nbs: Vec<_> = input.chars().flat_map(|c| c.to_digit(10u32)).collect(); let mut mem = MemoryP2::init(nbs); mem.fill_empty_blocks(); Some(mem.compute_checksum()) @@ -116,6 +196,6 @@ mod tests { #[test] fn test_part_two() { let result = part_two(&advent_of_code::template::read_file("examples", DAY)); - assert_eq!(result, None); + assert_eq!(result, Some(2858)); } }