Adds day 9
This commit is contained in:
parent
bc0aa70ac3
commit
8c116cb59a
1
resources/input9.txt
Normal file
1
resources/input9.txt
Normal file
File diff suppressed because one or more lines are too long
149
src/days/day9.rs
Normal file
149
src/days/day9.rs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use advent_derive::advent_day;
|
||||||
|
|
||||||
|
use crate::{error::AdventError, input::get_input};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
|
enum Sector {
|
||||||
|
Empty,
|
||||||
|
Chunk(u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Sector {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Empty => write!(f, "(.)"),
|
||||||
|
Self::Chunk(arg0) => write!(f, "({})", arg0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Part1{
|
||||||
|
drive: Vec<Sector>
|
||||||
|
}
|
||||||
|
type Part2 = Part1;
|
||||||
|
|
||||||
|
impl Part1 {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
drive: vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn read_input_part1(part1: &mut Part1, path: &Path) -> Result<(), AdventError> {
|
||||||
|
let line = get_input(path);
|
||||||
|
let mut reading_file = true;
|
||||||
|
let mut current_file_id = 0;
|
||||||
|
for c in line.chars() {
|
||||||
|
let i = c.to_digit(10).unwrap() as u8;
|
||||||
|
if reading_file {
|
||||||
|
for _ in 0..i {
|
||||||
|
part1.drive.push(Sector::Chunk(current_file_id))
|
||||||
|
}
|
||||||
|
current_file_id += 1;
|
||||||
|
} else {
|
||||||
|
for _ in 0..i {
|
||||||
|
part1.drive.push(Sector::Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reading_file = !reading_file
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn checksum(drive: &Vec<Sector>) -> usize {
|
||||||
|
drive.iter().enumerate().map(|(i, sector)| {
|
||||||
|
match sector {
|
||||||
|
Sector::Empty => 0,
|
||||||
|
Sector::Chunk(f) => i * (*f as usize),
|
||||||
|
}
|
||||||
|
}).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_part1(part1: &mut Part1) -> Result<String, AdventError> {
|
||||||
|
let mut empty_index = 0;
|
||||||
|
let mut rev_file_index = 0;
|
||||||
|
loop {
|
||||||
|
empty_index += part1.drive.iter().skip(empty_index).position(|s| { *s == Sector::Empty}).unwrap();
|
||||||
|
rev_file_index += part1.drive.iter().rev().skip(rev_file_index).position(|s| { *s != Sector::Empty}).unwrap();
|
||||||
|
let file_index = part1.drive.len() - 1 - rev_file_index;
|
||||||
|
|
||||||
|
if empty_index > file_index {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part1.drive[empty_index] = part1.drive[file_index];
|
||||||
|
part1.drive[file_index] = Sector::Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let checksum: usize = checksum(&part1.drive);
|
||||||
|
Ok(checksum.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_input_part2(part2: &mut Part2, path: &Path) -> Result<(), AdventError> {
|
||||||
|
read_input_part1(part2, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highest_file_id(part2: &Part2) -> u32 {
|
||||||
|
match part2.drive.iter().rev().find(|s| **s != Sector::Empty).unwrap() {
|
||||||
|
Sector::Empty => panic!("Should not happen"),
|
||||||
|
Sector::Chunk(f) => *f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_pos_and_len(part2: &Part2, id: u32) -> (usize, usize) {
|
||||||
|
let pos = part2.drive.iter().position(|s| match s {
|
||||||
|
Sector::Empty => false,
|
||||||
|
Sector::Chunk(cid) => *cid == id,
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
for j in pos..part2.drive.len() {
|
||||||
|
if part2.drive[j] != Sector::Chunk(id){
|
||||||
|
return (pos, j - pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (pos, part2.drive.len() - pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_empty_slice(part2: &Part2, len: usize) -> usize {
|
||||||
|
let mut pos = 0;
|
||||||
|
loop {
|
||||||
|
pos += part2.drive.iter().skip(pos).position(|s| *s == Sector::Empty).unwrap();
|
||||||
|
if pos + len >= part2.drive.len() {
|
||||||
|
return part2.drive.len();
|
||||||
|
}
|
||||||
|
if part2.drive[pos..pos+len].iter().all(|s| *s == Sector::Empty) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_part2(part2: &mut Part2) -> Result<String, AdventError> {
|
||||||
|
let highest_file_id = highest_file_id(part2);
|
||||||
|
for i in (1..highest_file_id + 1).rev() {
|
||||||
|
let (pos, len) = find_pos_and_len(part2, i);
|
||||||
|
let empty_pos = find_empty_slice(part2, len);
|
||||||
|
|
||||||
|
if empty_pos > pos {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for j in empty_pos..empty_pos+len {
|
||||||
|
part2.drive[j] = Sector::Chunk(i);
|
||||||
|
}
|
||||||
|
for j in pos..pos+len {
|
||||||
|
part2.drive[j] = Sector::Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let checksum: usize = checksum(&part2.drive);
|
||||||
|
Ok(checksum.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[advent_day(Part1, Part2)]
|
||||||
|
struct Day9;
|
@ -23,13 +23,17 @@ pub mod day5;
|
|||||||
pub mod day6;
|
pub mod day6;
|
||||||
pub mod day7;
|
pub mod day7;
|
||||||
pub mod day8;
|
pub mod day8;
|
||||||
|
pub mod day9;
|
||||||
|
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use advent_derive::advent_day;
|
||||||
|
|
||||||
use crate::error::AdventError;
|
use crate::error::AdventError;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
|
||||||
struct Part1{}
|
struct Part1{}
|
||||||
|
@ -12,6 +12,7 @@ use day5::Day5;
|
|||||||
use day6::Day6;
|
use day6::Day6;
|
||||||
use day7::Day7;
|
use day7::Day7;
|
||||||
use day8::Day8;
|
use day8::Day8;
|
||||||
|
use day9::Day9;
|
||||||
use day14::Day14;
|
use day14::Day14;
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ fn main() -> Result<(), AdventError> {
|
|||||||
Box::new(Day6::new()),
|
Box::new(Day6::new()),
|
||||||
Box::new(Day7::new()),
|
Box::new(Day7::new()),
|
||||||
Box::new(Day8::new()),
|
Box::new(Day8::new()),
|
||||||
Box::new(DummyDay::new()),
|
Box::new(Day9::new()),
|
||||||
Box::new(DummyDay::new()),
|
Box::new(DummyDay::new()),
|
||||||
Box::new(DummyDay::new()),
|
Box::new(DummyDay::new()),
|
||||||
Box::new(DummyDay::new()),
|
Box::new(DummyDay::new()),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user