Compare commits

..

2 Commits

Author SHA1 Message Date
68b71fe794 d11p1 2024-03-12 21:02:25 -07:00
6fe087abb2 d10p2 trying question mark 2024-03-12 09:21:21 -07:00
6 changed files with 262 additions and 4 deletions

View File

@ -1,3 +1,4 @@
use std::num;
use std::env;
use std::process;
use std::fs::File;
@ -11,14 +12,16 @@ enum Inst{
#[derive(Debug)]
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> {
match &line[..4] {
"noop" => Ok(Inst::Noop),
"addx" => match line[5..].parse::<i64>() {
Ok(operand) => Ok(Inst::AddX(operand)),
Err(e) => Err(ParseError(e.to_string())),
},
"addx" => Ok(Inst::AddX(line[5..].parse::<i64>()?)),
_ => Err(ParseError(String::from("bad instruction"))),
}
}

7
day11/Cargo.lock generated Normal file
View 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
View 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
View 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
View 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
View 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