Compare commits
No commits in common. "68b71fe79449cd2be389f0cc2e461111edd4dacc" and "2cbcc69ff300390eb7299eb45f65e66bb7d1ed29" have entirely different histories.
68b71fe794
...
2cbcc69ff3
@ -1,4 +1,3 @@
|
|||||||
use std::num;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -12,16 +11,14 @@ 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" => Ok(Inst::AddX(line[5..].parse::<i64>()?)),
|
"addx" => match 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
7
day11/Cargo.lock
generated
@ -1,7 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "day11"
|
|
||||||
version = "0.1.0"
|
|
@ -1,8 +0,0 @@
|
|||||||
[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]
|
|
@ -1,55 +0,0 @@
|
|||||||
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
|
|
@ -1,158 +0,0 @@
|
|||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
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
|
|
Loading…
Reference in New Issue
Block a user