Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50c1ad8458 | ||
|
|
5be2ca974e |
No files matched your search
@@ -0,0 +1 @@
|
||||
6967128031985339734736617280757038645745239290236581123874156665793751514720983617223858831792394521856119568164901557909564178891524619506666506195863925923014993023578874449690848884327968251127532261526073368241228992411935648185959886726847737539273014339031792790792181163051839724753167987312745189256012985096956465302299649632218176609140515847891570764951297112116773162211261180304738674164465189313169822290998065973987773519329134522837998977277795401965985111235892379859166544548520224968389423571472361776489613276127278129549321775058665191172457931730268248458944488752324062679047636539342011633567959256508397931398545527467667612596775360548544327439557146594531983927888755819778387135182176722477666223468574324931412377114749849943118511597585591951878321693622159731206251299725451260217825277179316870624526444285286618504385405933927184735432887376231168495240401479989280307715599967406448265096126268528998737643457885176674752226724147813478356498503199103821247485446662256272865360373548839825962624369223867028736696949890976630347080246094825594915668966939453080358862211921947782211051993580374011612635238245279646362326795988816653504285902983109486299911603193692558597124869762814068338572672760817282262867939895853091139150485810794664664152377932903447184983249462459626784359482660343463863392276675318244807463171287538793947799752174695482275016731270101212678135282810693420504127611162936136351139405084188230155355984562674250243995703719874755704812491040753412376721971169926356966893994518224925476926439679385357906661657087905048177095586863833021627724251497669913419599778759172623963133261383699942627149616868708529164197985565476080108310282573186348864792556864423597555431385371702120469770132428221340732285837473305843576917341391708632896720909716141826775814464345517485477860141087674390101367891265905190561534382232212520453553287793312683799643802596212445702939866495827499483259293675823623298018272552199310831939873412687441636993773993176512861127867892217748973877726269301031248545379892739016649972847452323045898710605121996085143069564994553893463697514552897093805272211340251799689887564074936740684915389491217265882727243360398328603164806793927371322099417449806731417716468728272796247046465795293590507055393152306539229283883099723471592885407343692264935434644737916545841069391563799514239121781277934850107638766198702917494593283194422926161384185369774831749981781335567731371551342694637030508962334381296568247286737594586735893533323927177413743710495282681646505575621624632681221073813954612357668794413815404829918193423235862078515215942296468865807159595315283257556916683791104187691334684227514563574465898488849224608449631185199257684968674765958311777149721924703576648647277377628627393730408899908841528995845812639571732438227464122016861099586969199552921253772338837195785951927287445980357771512445583172663152994756762631352633773558149429541912453799141363479465153478465457836716364217784321903780269619526253991323733814813142107069652356639854745650964944801831327686228968194922886213415632914940378012536727781631616923767178669788577043742066303027902126998184698739681032315789418355967250825348968125368050672452503385297952582581234595808644525812232252787199556143988975816814535495945147134352228298132135765135301389405460988333202875771521421889119220771876318161665384646715772718866789522862447034581533777181307439572696697078215311454713452099875572537750285032379487124281198361654669517473497944696621567675902365918212868998289444315591668779513088551650902157527640794045618050678974622641216184828179208128495290221615541050605672463318314593117927769472969744123088479446531844606691645062189917412370421083806969647182622846407192305787882268657029604860317144826512558967754225426581825186809399253382685399364551779883983556972635321328105673559220611722813066953537596297882756578847172956425568891590799377973713205026422710708262224388966270745154703354364374733078364019451972996393152122332426974748668294308371457041668837544386958745756028706430829480256815221267663688861566413175217683683955493017593041901476506161745399388994988151771166323572497924859065282055813957919285332797583081364642163375245057781973223633859740608894617065395940532399617389346752291193648157995940611615737473672229613934401974198178164252953491753113443059527347584832159937895178402316781718331811379143884325749981387979249934127824448729522817543480861188839127782890819782231685325020823985683151287724865453924258321377268932893948466691991540192942448634696786677578897149165942257746679376485490687826927296632322541875711279651550276968871946744440677563997233229318319785658768601641389927838657413335663793582878748829762233148036123184646369939131425874514531929450642168274341921911813115549125344849587421616395216565358513633176218559311914409776771957366466862663976881858094487010473790886423716163543874215915216341593146237638614588916527979617483352135Line truncated
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
use crate::day_solver::DaySolver;
|
||||
use num::Integer;
|
||||
|
||||
pub struct Day9 {
|
||||
disk_map: Vec<u8>
|
||||
}
|
||||
|
||||
impl Day9 {
|
||||
|
||||
pub fn create(input: String) -> Self {
|
||||
Day9 {
|
||||
disk_map: input.chars().map(|c| (c as u8) - b'0').collect()
|
||||
}
|
||||
}
|
||||
|
||||
// fn print_layout(disk_blocks: &Vec<Block>) {
|
||||
// for block in disk_blocks {
|
||||
// match block {
|
||||
// Block::File(size, idx) => {
|
||||
// for _ in 0..*size {
|
||||
// print!("{}", idx);
|
||||
// }
|
||||
// }
|
||||
// Block::Empty(size) => {
|
||||
// print!("{}", ".".repeat(*size));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// println!();
|
||||
// }
|
||||
}
|
||||
|
||||
impl DaySolver for Day9 {
|
||||
|
||||
|
||||
fn solve_part1(&mut self) -> String {
|
||||
|
||||
let mut cur_disk_idx = 0usize;
|
||||
let mut disk_map_idx = 0usize;
|
||||
let mut disk_map_idx_rev = self.disk_map.len() + (self.disk_map.len() % 2);
|
||||
let mut left_to_move = 0u8;
|
||||
|
||||
let mut res = 0usize;
|
||||
|
||||
while disk_map_idx <= disk_map_idx_rev {
|
||||
if disk_map_idx.is_even() {
|
||||
// We're reading a file from the front of the disk map
|
||||
let left_in_file = if disk_map_idx == disk_map_idx_rev { left_to_move } else { self.disk_map[disk_map_idx] };
|
||||
for _ in 0..left_in_file {
|
||||
// print!("{}({})", disk_map_idx / 2, cur_disk_idx);
|
||||
res += cur_disk_idx * (disk_map_idx / 2);
|
||||
cur_disk_idx += 1;
|
||||
}
|
||||
} else {
|
||||
// We're reading empty space
|
||||
for _ in 0..self.disk_map[disk_map_idx] {
|
||||
// So let's grab some blocks from files at the end of the disk map
|
||||
while left_to_move == 0 && disk_map_idx_rev > disk_map_idx {
|
||||
disk_map_idx_rev -= 2;
|
||||
left_to_move = self.disk_map[disk_map_idx_rev];
|
||||
}
|
||||
if disk_map_idx_rev < disk_map_idx {
|
||||
break
|
||||
}
|
||||
// print!("{}({})", disk_map_idx_rev / 2, cur_disk_idx);
|
||||
res += cur_disk_idx * (disk_map_idx_rev / 2);
|
||||
cur_disk_idx += 1;
|
||||
left_to_move -= 1;
|
||||
}
|
||||
}
|
||||
disk_map_idx += 1;
|
||||
}
|
||||
|
||||
res.to_string()
|
||||
}
|
||||
|
||||
fn solve_part2(&mut self) -> String {
|
||||
|
||||
// Somewhat nicer data structure
|
||||
let mut disk_blocks: Vec<Block> = Vec::new();
|
||||
for (i, b) in self.disk_map.iter().enumerate() {
|
||||
if i.is_even() {
|
||||
disk_blocks.push(Block::File(b.to_owned().into(), i / 2))
|
||||
} else if b > &0 {
|
||||
disk_blocks.push(Block::Empty(b.to_owned().into()))
|
||||
}
|
||||
}
|
||||
|
||||
// Self::print_layout(&disk_blocks);
|
||||
|
||||
let original_disk = disk_blocks.clone();
|
||||
for block in original_disk.iter().rev() {
|
||||
if let Block::File(size, idx) = block {
|
||||
// Self::print_layout(&disk_blocks);
|
||||
// println!("{:?}", disk_blocks);
|
||||
// Try to move the file
|
||||
let move_target = disk_blocks.iter().enumerate()
|
||||
.find(|(_, b) | if let Block::Empty(s) = b { s >= size } else { false })
|
||||
// To prevent double borrowing, we need to clone the block here
|
||||
.map(|(i, b)| (i, b.to_owned()));
|
||||
if let Some((can_move_to_idx, b)) = move_target.to_owned() {
|
||||
match b {
|
||||
Block::Empty(empty_size) => {
|
||||
let original_index = disk_blocks.iter().position(|b| b == block).unwrap();
|
||||
// Never move blocks to the right
|
||||
if can_move_to_idx >= original_index { continue; }
|
||||
|
||||
// We replace the original block by an empty one
|
||||
// Note that, because we never move blocks to the right, it doesn't matter that the empty space around the block we're moving is inaccurate.
|
||||
disk_blocks[original_index] = Block::Empty(size.to_owned());
|
||||
disk_blocks[can_move_to_idx] = Block::File(size.to_owned(), idx.to_owned());
|
||||
if &empty_size > size {
|
||||
// Add additional empty space
|
||||
disk_blocks.insert(can_move_to_idx + 1, Block::Empty(empty_size.to_owned() - size.to_owned()))
|
||||
}
|
||||
}
|
||||
_ => panic!("uhm?")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Self::print_layout(&disk_blocks);
|
||||
let mut checksum = 0usize;
|
||||
let mut cur_disk_idx = 0usize;
|
||||
for block in disk_blocks {
|
||||
match block {
|
||||
Block::File(size, idx) => {
|
||||
for _ in 0..size {
|
||||
checksum += cur_disk_idx * idx;
|
||||
cur_disk_idx += 1;
|
||||
}
|
||||
}
|
||||
Block::Empty(size) => {
|
||||
cur_disk_idx += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
checksum.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
enum Block {
|
||||
Empty(usize),
|
||||
File(usize, usize)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1_basic() {
|
||||
let mut day = Day9::create("12345".to_string());
|
||||
assert_eq!("60", day.solve_part1());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
let mut day = Day9::create("2333133121414131402".to_string());
|
||||
assert_eq!("1928", day.solve_part1());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
let mut day = Day9::create("2333133121414131402".to_string());
|
||||
assert_eq!("2858", day.solve_part2());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2_bonus() {
|
||||
let mut day = Day9::create("2931514".to_string());
|
||||
assert_eq!("180", day.solve_part2());
|
||||
}
|
||||
+4
-2
@@ -9,6 +9,7 @@ use crate::day5::Day5;
|
||||
use crate::day6::Day6;
|
||||
use crate::day7::Day7;
|
||||
use crate::day8::Day8;
|
||||
use crate::day9::Day9;
|
||||
use crate::day_solver::DaySolver;
|
||||
use crate::util::read_file;
|
||||
|
||||
@@ -22,6 +23,7 @@ mod day5;
|
||||
mod day6;
|
||||
mod day7;
|
||||
mod day8;
|
||||
mod day9;
|
||||
|
||||
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
||||
|
||||
@@ -101,7 +103,7 @@ fn build_day_solver(day: u8, input: String) -> Option<Box<dyn DaySolver>> {
|
||||
6 => Some(Box::new(Day6::create(input))),
|
||||
7 => Some(Box::new(Day7::create(input))),
|
||||
8 => Some(Box::new(Day8::create(input))),
|
||||
// 9 => Some(Box::new(Day9::create(input))),
|
||||
9 => Some(Box::new(Day9::create(input))),
|
||||
// 10 => Some(Box::new(Day10::create(input))),
|
||||
// 11 => Some(Box::new(Day11::create(input))),
|
||||
// 12 => Some(Box::new(Day12::create(input))),
|
||||
@@ -188,7 +190,7 @@ fn solve_all(silent: bool) -> AocBenchResult {
|
||||
for day in 1..(max_day + 1) {
|
||||
bench_results.push(solve(day, silent));
|
||||
}
|
||||
return AocBenchResult {
|
||||
AocBenchResult {
|
||||
read_file: bench_results.iter().map(|t| t.read_file).sum(),
|
||||
init: bench_results.iter().map(|t| t.init).sum(),
|
||||
part1: bench_results.iter().map(|t| t.part1).sum(),
|
||||
|
||||
Reference in new issue
Block a user