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 }