Advertisement
Ihmemies

Terrible day 09

Dec 9th, 2024
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.81 KB | Source Code | 0 0
  1. use std::fmt::{self, Display};
  2.  
  3. use crate::{Fro, Solution, TaskResult};
  4. use super::utils::*;
  5.  
  6. #[derive(Debug, Clone)]
  7. struct Block {
  8.     id: usize,
  9.     data: char,
  10. }
  11.  
  12. impl Display for Block {
  13.     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  14.        if self.data == '.' {
  15.            writeln!(f, "Empty data block")
  16.        } else {
  17.            writeln!(f, "{:?}", self)
  18.        }        
  19.    }
  20. }
  21.  
  22. // Can add more shared vars here
  23. pub struct DiskFragmenter {
  24.    data: Vec<Block>
  25. }
  26.  
  27. // Can be used to implement fancier task-specific parsing
  28. impl Fro for DiskFragmenter  {
  29.    fn fro(input: &str) -> Self{
  30.        let mut data: Vec<Block> = Vec::new();
  31.        let mut i = 0;
  32.        let mut data_idx = 0;
  33.        input
  34.            .chars()
  35.            .for_each(|c| {
  36.                let len = c as u8 -48;
  37.                let mut data_added = false;
  38.                for _ in (0..len) {
  39.                    if i % 2 == 0 {
  40.                        data.push(Block {id: data_idx, data: c});  
  41.                        data_added = true;                    
  42.                    } else {
  43.                        data.push(Block {id: i, data: '.'});
  44.                    }                    
  45.                }  
  46.                if data_added { data_idx += 1; }                    
  47.                i += 1;
  48.            });
  49.        Self { data }
  50.    }
  51. }
  52.  
  53. // Main solvers
  54. impl Solution for DiskFragmenter {
  55.    fn silver(&self) -> TaskResult {
  56.        let mut defrag = self.data.clone();
  57.  
  58.        // first find the next free space, and hold it in index
  59.        let mut next_free = 0;
  60.        let mut next_end = defrag.len()-1;
  61.  
  62.        while let Some(idx) = Self::next_free_idx(&defrag, next_free) {
  63.            // Find next data block from end
  64.            if let Some(end) = Self::next_end_idx(&defrag, next_end) {                
  65.                if idx >= end { break } // Finish condition
  66.                
  67.                // Swap the free space with data from the end
  68.                defrag.swap(idx, end);                
  69.                next_free = idx + 1;
  70.                next_end = end - 1;
  71.            }
  72.            else { break } // No more data blocks to process            
  73.        }
  74.        TaskResult::Usize(Self::checksum(defrag))          
  75.    }
  76.    
  77.  
  78.    fn gold(&self) -> TaskResult {  
  79.        let mut defrag = self.data.clone();
  80.        let mut seek_start = 0;
  81.        let mut seek_end = defrag.len()-1;
  82.  
  83.        //defrag.iter().enumerate().for_each(|(idx, d)| print!("idx: {}, {}", idx, d));
  84.        //println!("start processing");
  85.  
  86.        // Start processing a file
  87.        while let Some(end) = Self::next_end_idx(&defrag, seek_end) {
  88.            println!("end: {}", end);
  89.            if seek_start == end { // end condition
  90.                break;
  91.            }
  92.  
  93.            // Skip empty blocks
  94.            if defrag[end].data == '.' {                
  95.                seek_end = end.saturating_sub(1);
  96.                continue;
  97.            }
  98.                
  99.            // Found a file
  100.            let file_length = defrag[end].data.to_digit(10).unwrap() as usize;    
  101.            let file_start = end + 1 - file_length;      
  102.  
  103.            //println!("seeking: start: {}, end: {}, fl: {}", seek_start, &(file_start), file_length);
  104.            // Find room for file
  105.            if let Some(free_range) =
  106.                Self::free_block(&defrag, &seek_start, &(file_start), &file_length)
  107.            {
  108.                //println!("defragging: free range: {:?}, end: {}, fl: {}",                     free_range, end, file_length);
  109.                let file_start = end+1-file_length;
  110.                Self::move_file(&mut defrag, &free_range, &file_start, &file_length);                
  111.            }  
  112.            seek_end = file_start.saturating_sub(1);
  113.              
  114.        }
  115.        //println!();
  116.        //defrag.iter().enumerate().for_each(|(idx, d)| print!("idx: {}, {}", idx, d));
  117.        TaskResult::Usize(Self::checksum(defrag))  
  118.  
  119.        // 00992111777.44.333....5555.6666.....8888..
  120.        //TaskResult::Usize(Self::checksum(defrag))  
  121.    }
  122. }
  123.  
  124. // For assisting functions
  125. impl DiskFragmenter {
  126.    // cargo test --lib tests::free_block -- --nocapture
  127.    fn free_block(
  128.        defrag: &[Block],
  129.        start: &usize,  
  130.        end: &usize,      
  131.        seek_len: &usize
  132.    )
  133.        -> Option<(usize, usize)>
  134.    {
  135.        let mut continuous = false;
  136.        let mut found = 0;
  137.  
  138.        for offset in (*start..=*end) {            
  139.            if defrag[offset].data == '.' {  
  140.                if !continuous { continuous = true };  
  141.                found += 1;          
  142.  
  143.                if found == *seek_len {
  144.                    return Some( (offset + 1 - seek_len, offset) );
  145.                }
  146.                continue;
  147.            }      
  148.            // Reset state            
  149.            continuous = false;
  150.            found = 0;
  151.        }
  152.        None
  153.    }
  154.  
  155.    fn move_file(
  156.        defrag: &mut [Block],
  157.        free_block: &(usize, usize),
  158.        file_start: &usize,
  159.        file_length: &usize,
  160.    ) -> bool {
  161.        //println!("{:?}, fe:{}, fl:{}", free_block, file_start, file_length);
  162.        (0..*file_length).for_each(|i| {  
  163.            defrag.swap(free_block.0+i, file_start+i);
  164.        });
  165.  
  166.        true
  167.    }
  168.    
  169.  
  170.    fn next_free_idx(defrag: &[Block], start: usize) -> Option<usize> {
  171.        (start..defrag.len()).find(|&i| defrag[i].data == '.')
  172.    }
  173.  
  174.    fn next_end_idx(defrag: &[Block], end: usize) -> Option<usize> {
  175.        (0..=end).rev().find(|&i| defrag[i].data != '.')
  176.    }
  177.  
  178.    fn checksum(defrag: Vec<Block>) -> usize {
  179.        defrag
  180.        .iter()
  181.        .enumerate()
  182.        .map(|(i, val)| if val.data != '.' { val.id * i } else { 0 })
  183.        .sum()
  184.    }
  185. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement