github.com/mnlphlp/aoc22@v0.0.0-20230330151331-c1dc4bff1b9b/aoc22_rust/src/day05.rs (about)

     1  use crate::types::Task;
     2  
     3  fn parse_stacks(input: &str, test: bool) -> Vec<Vec<u8>> {
     4      let mut stack_lines = vec![];
     5      let mut stack_count = 0;
     6  
     7      for l in input.lines() {
     8          if l.trim_start().starts_with("[") {
     9              stack_lines.push(l);
    10          } else {
    11              stack_count = l.bytes().filter(|b| *b != b' ').count();
    12              break;
    13          }
    14      }
    15      if test {
    16          println!("creating {stack_count} stacks from following lines:");
    17          for line in &stack_lines {
    18              println!("{line}");
    19          }
    20      }
    21      let mut stacks = vec![];
    22      for _ in 0..stack_count {
    23          stacks.push(vec![]);
    24      }
    25      for line in stack_lines.iter().rev() {
    26          for j in 0..stack_count {
    27              let item = line.as_bytes()[1 + j * 4];
    28              if item != b' ' {
    29                  stacks[j].push(item)
    30              }
    31          }
    32      }
    33      return stacks;
    34  }
    35  
    36  fn parse_input(input: &str, test: bool) -> (Vec<Vec<u8>>, Vec<[usize; 3]>) {
    37      let stacks = parse_stacks(input, test);
    38      if test {
    39          println!("parsed following stacks:");
    40          for s in &stacks {
    41              println!("{s:?}");
    42          }
    43      }
    44      let instructions = parse_instructions(input);
    45      if test {
    46          println!("parsed following instructions:\n{instructions:?}");
    47      }
    48      return (stacks, instructions);
    49  }
    50  
    51  fn parse_instructions(input: &str) -> Vec<[usize; 3]> {
    52      let mut instructions = vec![];
    53      for l in input.lines() {
    54          if l.starts_with("move") {
    55              let parts: Vec<&str> = l.split(" ").collect();
    56              let mut inst = [0; 3];
    57              inst[0] = parts[1].parse::<usize>().unwrap();
    58              inst[1] = parts[3].parse::<usize>().unwrap();
    59              inst[1] -= 1;
    60              inst[2] = parts[5].parse::<usize>().unwrap();
    61              inst[2] -= 1;
    62              instructions.push(inst);
    63          }
    64      }
    65      return instructions;
    66  }
    67  
    68  fn do_moves(
    69      stacks: &mut Vec<Vec<u8>>,
    70      instructions: &Vec<[usize; 3]>,
    71      move_at_once: bool,
    72      _test: bool,
    73  ) {
    74      for inst in instructions {
    75          let count = inst[0];
    76          let from_stack = inst[1];
    77          let to_stack = inst[2];
    78          if move_at_once {
    79              let mut items = stacks[from_stack][stacks[from_stack].len() - count..].to_owned();
    80              let stack_len = stacks[from_stack].len();
    81              stacks[from_stack].truncate(stack_len - count);
    82              stacks[to_stack].append(&mut items);
    83          } else {
    84              for _i in 0..count {
    85                  let item = stacks[from_stack].pop().unwrap();
    86                  stacks[to_stack].push(item);
    87              }
    88          }
    89      }
    90  }
    91  
    92  pub fn solve(input: &str, test: bool, task: Task) -> (String, String) {
    93      let mut res1 = String::from("");
    94      let mut res2 = String::from("");
    95      let (mut stacks, instructions) = parse_input(input, test);
    96      let mut stacks2 = stacks.clone();
    97  
    98      // move one item at a time
    99      if !matches!(task, Task::Two) {
   100          do_moves(&mut stacks, &instructions, false, test);
   101          res1 = "".into();
   102          for s in stacks {
   103              if s.len() > 0 {
   104                  res1.push_str(&format!("{}", *s.last().unwrap() as char));
   105              }
   106          }
   107      }
   108  
   109      if !matches!(task, Task::One) {
   110          // move all items at once
   111          do_moves(&mut stacks2, &instructions, true, test);
   112          res2 = "".into();
   113          for s in stacks2 {
   114              if s.len() > 0 {
   115                  res2.push_str(&(*s.last().unwrap() as char).to_string());
   116              }
   117          }
   118      }
   119  
   120      return (res1, res2);
   121  }