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 day7;
 | 
			
		||||
pub mod day8;
 | 
			
		||||
pub mod day9;
 | 
			
		||||
 | 
			
		||||
pub mod day14;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
 | 
			
		||||
use advent_derive::advent_day;
 | 
			
		||||
 | 
			
		||||
use crate::error::AdventError;
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct Part1{}
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ use day5::Day5;
 | 
			
		||||
use day6::Day6;
 | 
			
		||||
use day7::Day7;
 | 
			
		||||
use day8::Day8;
 | 
			
		||||
use day9::Day9;
 | 
			
		||||
use day14::Day14;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -49,7 +50,7 @@ fn main() -> Result<(), AdventError> {
 | 
			
		||||
        Box::new(Day6::new()),
 | 
			
		||||
        Box::new(Day7::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()),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user