Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::fs;
- #[derive(Clone, PartialEq, Debug)]
- enum DiskStuff {
- FreeSpace,
- FileBlock(i32),
- }
- fn main() {
- let input: Vec<DiskStuff> = fs::read_to_string("input")
- .expect("couldn't read the file")
- .trim()
- .chars()
- .enumerate()
- .map(|(i, character)| {
- let num: u32 = character.to_digit(10).unwrap();
- if i % 2 == 0 {
- (0..num)
- .map(|_| DiskStuff::FileBlock(i as i32 / 2))
- .collect::<Vec<DiskStuff>>()
- } else {
- (0..num)
- .map(|_| DiskStuff::FreeSpace)
- .collect::<Vec<DiskStuff>>()
- }
- })
- .flatten()
- .collect::<Vec<DiskStuff>>();
- // inpu2 is the input passed to the part2 function.
- // here's how the program will parse 133
- // [[FileBlock(0)], [FreeSpace, FreeSpace, FreeSpace], [FileBlock(1), FileBlock(1), FileBlock(1)]]
- let input2: Vec<Vec<DiskStuff>> = fs::read_to_string("input")
- .expect("couldn't read the file")
- .trim()
- .chars()
- .enumerate()
- .map(|(i, character)| {
- let num: u32 = character.to_digit(10).unwrap();
- if i % 2 == 0 {
- (0..num)
- .map(|_| DiskStuff::FileBlock(i as i32/2))
- .collect::<Vec<DiskStuff>>()
- } else {
- (0..num)
- .map(|_| DiskStuff::FreeSpace)
- .collect::<Vec<DiskStuff>>()
- }
- })
- .filter(|x| !x.is_empty())
- .collect::<Vec<Vec<DiskStuff>>>();
- println!("{:?}", input2);
- part1(&input);
- part2(&input2);
- }
- fn part1(input: &Vec<DiskStuff>) {
- let mut defragged = input.clone();
- while defragged.contains(&DiskStuff::FreeSpace) {
- let last = defragged.pop().expect("couldn't pop");
- if last == DiskStuff::FreeSpace {
- continue;
- }
- let first_free_space = defragged
- .iter()
- .position(|x| x == &DiskStuff::FreeSpace)
- .expect("couldn't find first free space");
- defragged.remove(first_free_space);
- defragged.insert(first_free_space, last);
- }
- let checksum = defragged
- .iter()
- .enumerate()
- .fold(0 as i64, |acc, (i, x)| {
- if let DiskStuff::FileBlock(val) = x {
- acc + i as i64 * *val as i64
- } else {
- acc
- }
- });
- println!("Part 1: {}", checksum);
- }
- fn part2(input: &Vec<Vec<DiskStuff>>) {
- let mut defragged: Vec<Vec<_>> = input.clone();
- for file_i in (0..defragged.len()).rev() { // loop through the files in reversed order
- let file = defragged[file_i].clone();
- if let DiskStuff::FileBlock(_) = file[0] { // checks if the file chunk is type of FileBlock
- let needed_space = file.len(); // needed space is basically the amount of fileblocks a file contains
- if let Some(free_space_index) = defragged.iter().enumerate().position(|(i, x)| {
- // this if statement checks for the first position with enough free space.
- matches!(x[0], DiskStuff::FreeSpace) && x.len() >= needed_space && i < file_i
- // the conditions it should satisfy are:
- // 1. it's a type FreeSpace
- // 2. The free space length is bigger or equal to the needed space
- // 3. the index is smaller than the current file index
- }) {
- defragged[free_space_index] = (0..(defragged[free_space_index].len() - needed_space))
- .map(|_| DiskStuff::FreeSpace)
- .collect(); // susbstracts the needed_space from the free space it found.
- defragged.remove(file_i); // removes the file from its current position
- let leave_blank: Vec<_> = (0..needed_space).map(|_| DiskStuff::FreeSpace).collect();
- // leave_blank is a temporary variable that creates a free space chunk that's the same size as the file
- defragged.insert(file_i, leave_blank);
- // leave the blank space created where the file previously was
- if defragged[free_space_index].is_empty() {
- // if the free space we found is empty after removing its contents remove the entire thing.
- defragged.remove(free_space_index);
- }
- // finally insert the file at the position where the free space was
- defragged.insert(free_space_index, file.clone());
- }
- }
- }
- // this creates a visual reperesentation of the final disk layout
- println!(
- "{}",
- defragged
- .iter()
- .flatten()
- .map(|i| match i {
- DiskStuff::FreeSpace => ".".to_string(),
- DiskStuff::FileBlock(x) => x.to_string(),
- })
- .collect::<String>()
- );
- // calculates the final checksum
- let checksum = defragged
- .iter()
- .flatten()
- .enumerate()
- .fold(0 as i128, |acc, (i, x)| {
- if let DiskStuff::FileBlock(val) = x {
- acc + i as i128 * *val as i128
- } else {
- acc
- }
- });
- println!("Part 2: {}", checksum);
- }
Advertisement
Add Comment
Please, Sign In to add comment