Compare commits
	
		
			2 Commits
		
	
	
		
			2cbcc69ff3
			...
			68b71fe794
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 68b71fe794 | |||
| 6fe087abb2 | 
| @@ -1,3 +1,4 @@ | |||||||
|  | use std::num; | ||||||
| use std::env; | use std::env; | ||||||
| use std::process; | use std::process; | ||||||
| use std::fs::File; | use std::fs::File; | ||||||
| @@ -11,14 +12,16 @@ enum Inst{ | |||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| struct ParseError(String); | struct ParseError(String); | ||||||
|  | impl From<num::ParseIntError> for ParseError { | ||||||
|  |     fn from(e: num::ParseIntError) -> Self { | ||||||
|  |         ParseError(e.to_string()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| fn parse_line(line: String) -> Result<Inst, ParseError> { | fn parse_line(line: String) -> Result<Inst, ParseError> { | ||||||
|     match &line[..4] { |     match &line[..4] { | ||||||
|         "noop" => Ok(Inst::Noop), |         "noop" => Ok(Inst::Noop), | ||||||
|         "addx" => match line[5..].parse::<i64>() { |         "addx" => Ok(Inst::AddX(line[5..].parse::<i64>()?)), | ||||||
|             Ok(operand) => Ok(Inst::AddX(operand)), |  | ||||||
|             Err(e) => Err(ParseError(e.to_string())), |  | ||||||
|         }, |  | ||||||
|         _ => Err(ParseError(String::from("bad instruction"))), |         _ => Err(ParseError(String::from("bad instruction"))), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								day11/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								day11/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "day11" | ||||||
|  | version = "0.1.0" | ||||||
							
								
								
									
										8
									
								
								day11/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								day11/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | [package] | ||||||
|  | name = "day11" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  |  | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  |  | ||||||
|  | [dependencies] | ||||||
							
								
								
									
										55
									
								
								day11/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								day11/input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | Monkey 0: | ||||||
|  |   Starting items: 66, 79 | ||||||
|  |   Operation: new = old * 11 | ||||||
|  |   Test: divisible by 7 | ||||||
|  |     If true: throw to monkey 6 | ||||||
|  |     If false: throw to monkey 7 | ||||||
|  |  | ||||||
|  | Monkey 1: | ||||||
|  |   Starting items: 84, 94, 94, 81, 98, 75 | ||||||
|  |   Operation: new = old * 17 | ||||||
|  |   Test: divisible by 13 | ||||||
|  |     If true: throw to monkey 5 | ||||||
|  |     If false: throw to monkey 2 | ||||||
|  |  | ||||||
|  | Monkey 2: | ||||||
|  |   Starting items: 85, 79, 59, 64, 79, 95, 67 | ||||||
|  |   Operation: new = old + 8 | ||||||
|  |   Test: divisible by 5 | ||||||
|  |     If true: throw to monkey 4 | ||||||
|  |     If false: throw to monkey 5 | ||||||
|  |  | ||||||
|  | Monkey 3: | ||||||
|  |   Starting items: 70 | ||||||
|  |   Operation: new = old + 3 | ||||||
|  |   Test: divisible by 19 | ||||||
|  |     If true: throw to monkey 6 | ||||||
|  |     If false: throw to monkey 0 | ||||||
|  |  | ||||||
|  | Monkey 4: | ||||||
|  |   Starting items: 57, 69, 78, 78 | ||||||
|  |   Operation: new = old + 4 | ||||||
|  |   Test: divisible by 2 | ||||||
|  |     If true: throw to monkey 0 | ||||||
|  |     If false: throw to monkey 3 | ||||||
|  |  | ||||||
|  | Monkey 5: | ||||||
|  |   Starting items: 65, 92, 60, 74, 72 | ||||||
|  |   Operation: new = old + 7 | ||||||
|  |   Test: divisible by 11 | ||||||
|  |     If true: throw to monkey 3 | ||||||
|  |     If false: throw to monkey 4 | ||||||
|  |  | ||||||
|  | Monkey 6: | ||||||
|  |   Starting items: 77, 91, 91 | ||||||
|  |   Operation: new = old * old | ||||||
|  |   Test: divisible by 17 | ||||||
|  |     If true: throw to monkey 1 | ||||||
|  |     If false: throw to monkey 7 | ||||||
|  |  | ||||||
|  | Monkey 7: | ||||||
|  |   Starting items: 76, 58, 57, 55, 67, 77, 54, 99 | ||||||
|  |   Operation: new = old + 6 | ||||||
|  |   Test: divisible by 3 | ||||||
|  |     If true: throw to monkey 2 | ||||||
|  |     If false: throw to monkey 1 | ||||||
							
								
								
									
										158
									
								
								day11/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								day11/src/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | |||||||
|  | use std::num::ParseIntError; | ||||||
|  | use std::env; | ||||||
|  | use std::fs::File; | ||||||
|  | use std::io::{self, BufRead, Lines}; | ||||||
|  | use std::collections::VecDeque; | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | enum Operator { Add, Mul } | ||||||
|  | #[derive(Debug)] | ||||||
|  | enum Operand { Old, Imm(u64) } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Operation { left: Operand, op: Operator, right: Operand } | ||||||
|  | impl Operation { | ||||||
|  |     fn perform(&self, old: u64) -> u64 { | ||||||
|  |         let left = match self.left { | ||||||
|  |             Operand::Old => old, | ||||||
|  |             Operand::Imm(x) => x, | ||||||
|  |         }; | ||||||
|  |         let right = match self.right { | ||||||
|  |             Operand::Old => old, | ||||||
|  |             Operand::Imm(x) => x, | ||||||
|  |         }; | ||||||
|  |         match self.op { | ||||||
|  |             Operator::Add => left + right, | ||||||
|  |             Operator::Mul => left * right, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Monkey { | ||||||
|  |     id: u64, | ||||||
|  |     items: VecDeque<u64>, | ||||||
|  |     operation: Operation, | ||||||
|  |     div_by_test: u64, | ||||||
|  |     true_throw: u64, | ||||||
|  |     false_throw: u64, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | enum MonkeyError { | ||||||
|  |     ParseError(), | ||||||
|  |     ParseIntError(ParseIntError), | ||||||
|  |     IoError(io::Error), | ||||||
|  | } | ||||||
|  | impl From<ParseIntError> for MonkeyError { | ||||||
|  |     fn from(e: ParseIntError) -> Self { MonkeyError::ParseIntError(e) } | ||||||
|  | } | ||||||
|  | impl From<io::Error> for MonkeyError { | ||||||
|  |     fn from(e: io::Error) -> Self { MonkeyError::IoError(e) } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn parse_monkey<B: BufRead>( | ||||||
|  |     lines: &mut Lines<B> | ||||||
|  | ) -> Result<Option<Monkey>, MonkeyError> { | ||||||
|  |     let id = match lines.next() { | ||||||
|  |         Some(line) => line? | ||||||
|  |             .strip_prefix("Monkey ").ok_or(MonkeyError::ParseError())? | ||||||
|  |             .strip_suffix(":").ok_or(MonkeyError::ParseError())? | ||||||
|  |             .parse::<u64>()?, | ||||||
|  |         None => return Ok(None), | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     let starting_items = lines.next().ok_or(MonkeyError::ParseError())?? | ||||||
|  |         .strip_prefix("  Starting items: ").ok_or(MonkeyError::ParseError())? | ||||||
|  |         .split(", ") | ||||||
|  |         .map(|item| item.parse::<u64>()) | ||||||
|  |         .collect::<Result<VecDeque<_>, _>>()?; | ||||||
|  |  | ||||||
|  |     let op_line = lines.next().ok_or(MonkeyError::ParseError())??; | ||||||
|  |     let op_vec = op_line | ||||||
|  |         .strip_prefix("  Operation: new = ").ok_or(MonkeyError::ParseError())? | ||||||
|  |         .split(' ').collect::<Vec<_>>(); | ||||||
|  |     let (left, operator, right) = (op_vec[0], op_vec[1], op_vec[2]); | ||||||
|  |     let operation = Operation { | ||||||
|  |         left: match left { | ||||||
|  |             "old" => Operand::Old, | ||||||
|  |             _ => Operand::Imm(left.parse()?) | ||||||
|  |         }, | ||||||
|  |         op: match operator { | ||||||
|  |             "+" => Ok(Operator::Add), | ||||||
|  |             "*" => Ok(Operator::Mul), | ||||||
|  |             _ => Err(MonkeyError::ParseError()) | ||||||
|  |         }?, | ||||||
|  |         right: match right { | ||||||
|  |             "old" => Operand::Old, | ||||||
|  |             _ => Operand::Imm(right.parse()?) | ||||||
|  |         }, | ||||||
|  |     }; | ||||||
|  |          | ||||||
|  |     let test_val = lines.next().ok_or(MonkeyError::ParseError())?? | ||||||
|  |         .strip_prefix("  Test: divisible by ").ok_or(MonkeyError::ParseError())? | ||||||
|  |         .parse::<u64>()?; | ||||||
|  |  | ||||||
|  |     let true_throw = lines.next().ok_or(MonkeyError::ParseError())?? | ||||||
|  |         .strip_prefix("    If true: throw to monkey ") | ||||||
|  |         .ok_or(MonkeyError::ParseError())? | ||||||
|  |         .parse::<u64>()?; | ||||||
|  |     let false_throw = lines.next().ok_or(MonkeyError::ParseError())?? | ||||||
|  |         .strip_prefix("    If false: throw to monkey ") | ||||||
|  |         .ok_or(MonkeyError::ParseError())? | ||||||
|  |         .parse::<u64>()?; | ||||||
|  |  | ||||||
|  |     // Remove empty line if exists | ||||||
|  |     match lines.next() { | ||||||
|  |         None => Ok(()), | ||||||
|  |         Some(Err(e)) => Err(e), | ||||||
|  |         Some(Ok(s)) => Ok(match s.as_str() { | ||||||
|  |             "" => Ok(()), | ||||||
|  |             _ => Err(MonkeyError::ParseError()), | ||||||
|  |         }?), | ||||||
|  |     }?; | ||||||
|  |  | ||||||
|  |     Ok(Some(Monkey { | ||||||
|  |         id: id, | ||||||
|  |         items: starting_items, | ||||||
|  |         operation: operation, | ||||||
|  |         div_by_test: test_val, | ||||||
|  |         true_throw: true_throw, | ||||||
|  |         false_throw: false_throw, | ||||||
|  |     }) | ||||||
|  | )} | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     let file = File::open(&env::args().nth(1).unwrap()).unwrap(); | ||||||
|  |     let mut lines = io::BufReader::new(file).lines(); | ||||||
|  |     let mut monkeys: Vec<Monkey> = Vec::new(); | ||||||
|  |  | ||||||
|  |     loop { | ||||||
|  |         match parse_monkey(&mut lines) { | ||||||
|  |             Ok(None) => break, | ||||||
|  |             Ok(Some(m)) => { assert!(m.id == monkeys.len() as u64); monkeys.push(m) }, | ||||||
|  |             Err(e) => eprintln!("{:?}", e), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     let mut monkey_item_counts = vec![0; monkeys.len()]; | ||||||
|  |  | ||||||
|  |     for _round in 1..=20 { | ||||||
|  |         for i in 0..monkeys.len() { | ||||||
|  |             monkey_item_counts[i] += monkeys[i].items.len(); | ||||||
|  |  | ||||||
|  |             for _item in 0..monkeys[i].items.len() { | ||||||
|  |                 let old_item = monkeys[i].items.pop_front().unwrap(); | ||||||
|  |                 let new_item = monkeys[i].operation.perform(old_item) / 3; | ||||||
|  |                 let new_i = if new_item % monkeys[i].div_by_test == 0 { | ||||||
|  |                     monkeys[i].true_throw | ||||||
|  |                 } else { | ||||||
|  |                     monkeys[i].false_throw | ||||||
|  |                 } as usize; | ||||||
|  |                 monkeys[new_i].items.push_back(new_item); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     monkey_item_counts.sort_by(|x, y| y.cmp(x)); | ||||||
|  |     println!("{:?}", monkey_item_counts[0]*monkey_item_counts[1]); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								day11/test.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								day11/test.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | Monkey 0: | ||||||
|  |   Starting items: 79, 98 | ||||||
|  |   Operation: new = old * 19 | ||||||
|  |   Test: divisible by 23 | ||||||
|  |     If true: throw to monkey 2 | ||||||
|  |     If false: throw to monkey 3 | ||||||
|  |  | ||||||
|  | Monkey 1: | ||||||
|  |   Starting items: 54, 65, 75, 74 | ||||||
|  |   Operation: new = old + 6 | ||||||
|  |   Test: divisible by 19 | ||||||
|  |     If true: throw to monkey 2 | ||||||
|  |     If false: throw to monkey 0 | ||||||
|  |  | ||||||
|  | Monkey 2: | ||||||
|  |   Starting items: 79, 60, 97 | ||||||
|  |   Operation: new = old * old | ||||||
|  |   Test: divisible by 13 | ||||||
|  |     If true: throw to monkey 1 | ||||||
|  |     If false: throw to monkey 3 | ||||||
|  |  | ||||||
|  | Monkey 3: | ||||||
|  |   Starting items: 74 | ||||||
|  |   Operation: new = old + 3 | ||||||
|  |   Test: divisible by 17 | ||||||
|  |     If true: throw to monkey 0 | ||||||
|  |     If false: throw to monkey 1 | ||||||
		Reference in New Issue
	
	Block a user