rustfmt
This commit is contained in:
parent
0cd663ae2a
commit
dadd414faa
1 changed files with 224 additions and 221 deletions
445
src/day5/main.rs
445
src/day5/main.rs
|
@ -4,295 +4,298 @@ use std::io::{self, BufRead, BufReader, Write};
|
|||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Mode {
|
||||
Position,
|
||||
Immediate,
|
||||
Position,
|
||||
Immediate,
|
||||
}
|
||||
|
||||
impl Default for Mode {
|
||||
fn default() -> Self {
|
||||
Mode::Position
|
||||
}
|
||||
fn default() -> Self {
|
||||
Mode::Position
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Mode {
|
||||
fn from(b: bool) -> Self {
|
||||
match b {
|
||||
false => Mode::Position,
|
||||
true => Mode::Immediate,
|
||||
}
|
||||
}
|
||||
fn from(b: bool) -> Self {
|
||||
match b {
|
||||
false => Mode::Position,
|
||||
true => Mode::Immediate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
struct Modes {
|
||||
a: Mode,
|
||||
b: Mode,
|
||||
c: Mode,
|
||||
a: Mode,
|
||||
b: Mode,
|
||||
c: Mode,
|
||||
}
|
||||
|
||||
impl From<(Mode, Mode, Mode)> for Modes {
|
||||
fn from(modes: (Mode, Mode, Mode)) -> Self {
|
||||
Modes {
|
||||
a: modes.0,
|
||||
b: modes.1,
|
||||
c: modes.2,
|
||||
}
|
||||
}
|
||||
fn from(modes: (Mode, Mode, Mode)) -> Self {
|
||||
Modes {
|
||||
a: modes.0,
|
||||
b: modes.1,
|
||||
c: modes.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ModedOpcode> for Modes {
|
||||
fn from(mo: &ModedOpcode) -> Self {
|
||||
mo.modes
|
||||
}
|
||||
fn from(mo: &ModedOpcode) -> Self {
|
||||
mo.modes
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Opcode {
|
||||
Add,
|
||||
Multiply,
|
||||
Input,
|
||||
Output,
|
||||
JumpIfTrue,
|
||||
JumpIfFalse,
|
||||
LessThan,
|
||||
Equals,
|
||||
Halt,
|
||||
Add,
|
||||
Multiply,
|
||||
Input,
|
||||
Output,
|
||||
JumpIfTrue,
|
||||
JumpIfFalse,
|
||||
LessThan,
|
||||
Equals,
|
||||
Halt,
|
||||
}
|
||||
|
||||
impl From<&ModedOpcode> for Opcode {
|
||||
fn from(mo: &ModedOpcode) -> Self {
|
||||
mo.op
|
||||
}
|
||||
fn from(mo: &ModedOpcode) -> Self {
|
||||
mo.op
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Opcode {
|
||||
fn from(i: i64) -> Self {
|
||||
match i {
|
||||
1 => Opcode::Add,
|
||||
2 => Opcode::Multiply,
|
||||
3 => Opcode::Input,
|
||||
4 => Opcode::Output,
|
||||
5 => Opcode::JumpIfTrue,
|
||||
6 => Opcode::JumpIfFalse,
|
||||
7 => Opcode::LessThan,
|
||||
8 => Opcode::Equals,
|
||||
99 => Opcode::Halt,
|
||||
_ => panic!("invalid opcode {}", i),
|
||||
}
|
||||
}
|
||||
fn from(i: i64) -> Self {
|
||||
match i {
|
||||
1 => Opcode::Add,
|
||||
2 => Opcode::Multiply,
|
||||
3 => Opcode::Input,
|
||||
4 => Opcode::Output,
|
||||
5 => Opcode::JumpIfTrue,
|
||||
6 => Opcode::JumpIfFalse,
|
||||
7 => Opcode::LessThan,
|
||||
8 => Opcode::Equals,
|
||||
99 => Opcode::Halt,
|
||||
_ => panic!("invalid opcode {}", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ModedOpcode {
|
||||
modes: Modes,
|
||||
op: Opcode,
|
||||
modes: Modes,
|
||||
op: Opcode,
|
||||
}
|
||||
|
||||
impl From<i64> for ModedOpcode {
|
||||
fn from(i: i64) -> Self {
|
||||
let code = i % 100;
|
||||
let a = i % 1000 >= 100;
|
||||
let b = i % 10000 >= 1000;
|
||||
let c = i > 10000;
|
||||
let modes = (Mode::from(a), Mode::from(b), Mode::from(c)).into();
|
||||
ModedOpcode {
|
||||
modes: modes,
|
||||
op: Opcode::from(code),
|
||||
}
|
||||
}
|
||||
fn from(i: i64) -> Self {
|
||||
let code = i % 100;
|
||||
let a = i % 1000 >= 100;
|
||||
let b = i % 10000 >= 1000;
|
||||
let c = i > 10000;
|
||||
let modes = (Mode::from(a), Mode::from(b), Mode::from(c)).into();
|
||||
ModedOpcode {
|
||||
modes: modes,
|
||||
op: Opcode::from(code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
println!("Hello, i am {}.", env::args().next().unwrap());
|
||||
let filename = env::args().nth(1).expect("provide file as first param");
|
||||
let computer = Computer::from(File::open(filename)?);
|
||||
computer.clone().run();
|
||||
Ok(())
|
||||
println!("Hello, i am {}.", env::args().next().unwrap());
|
||||
let filename = env::args().nth(1).expect("provide file as first param");
|
||||
let computer = Computer::from(File::open(filename)?);
|
||||
computer.clone().run();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Computer {
|
||||
pos: usize,
|
||||
program: Vec<i64>,
|
||||
modes: Modes,
|
||||
pos: usize,
|
||||
program: Vec<i64>,
|
||||
modes: Modes,
|
||||
}
|
||||
|
||||
impl Clone for Computer {
|
||||
fn clone(&self) -> Self {
|
||||
Computer {
|
||||
pos: 0,
|
||||
program: self.program.clone(),
|
||||
modes: Default::default(),
|
||||
}
|
||||
}
|
||||
fn clone(&self) -> Self {
|
||||
Computer {
|
||||
pos: 0,
|
||||
program: self.program.clone(),
|
||||
modes: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Computer {
|
||||
fn from(f: File) -> Self {
|
||||
let f = BufReader::new(f);
|
||||
let program: Vec<i64> = f
|
||||
.split(b',')
|
||||
.map(|o| {
|
||||
let o = o.unwrap();
|
||||
let mut o = o.iter().peekable();
|
||||
let sign = if o.peek() == Some(&&b'-') { -1 } else { 1 };
|
||||
o.filter(|i| **i >= b'0' && **i <= b'9')
|
||||
.fold(0, |s, i| ((i - b'0') as i64 + 10 * s))
|
||||
* sign
|
||||
})
|
||||
.collect();
|
||||
program.into()
|
||||
}
|
||||
fn from(f: File) -> Self {
|
||||
let f = BufReader::new(f);
|
||||
let program: Vec<i64> = f
|
||||
.split(b',')
|
||||
.map(|o| {
|
||||
let o = o.unwrap();
|
||||
let mut o = o.iter().peekable();
|
||||
let sign = if o.peek() == Some(&&b'-') { -1 } else { 1 };
|
||||
o.filter(|i| **i >= b'0' && **i <= b'9')
|
||||
.fold(0, |s, i| ((i - b'0') as i64 + 10 * s))
|
||||
* sign
|
||||
})
|
||||
.collect();
|
||||
program.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<i64>> for Computer {
|
||||
fn from(program: Vec<i64>) -> Self {
|
||||
Computer {
|
||||
pos: 0,
|
||||
program: program,
|
||||
modes: Default::default(),
|
||||
}
|
||||
}
|
||||
fn from(program: Vec<i64>) -> Self {
|
||||
Computer {
|
||||
pos: 0,
|
||||
program: program,
|
||||
modes: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Computer {
|
||||
fn update(&mut self, u: Vec<(usize, i64)>) -> Computer {
|
||||
let mut computer = self.clone();
|
||||
for (pos, val) in u {
|
||||
computer.program[pos] = val;
|
||||
}
|
||||
computer
|
||||
}
|
||||
fn update(&mut self, u: Vec<(usize, i64)>) -> Computer {
|
||||
let mut computer = self.clone();
|
||||
for (pos, val) in u {
|
||||
computer.program[pos] = val;
|
||||
}
|
||||
computer
|
||||
}
|
||||
|
||||
fn run(&mut self) -> i64 {
|
||||
loop {
|
||||
let instruction = self.program[self.pos];
|
||||
let instruction = ModedOpcode::from(instruction);
|
||||
self.modes = (&instruction).into();
|
||||
let advance = match (&instruction).into() {
|
||||
Opcode::Add => self.add(),
|
||||
Opcode::Multiply => self.multiply(),
|
||||
Opcode::Input => self.input(),
|
||||
Opcode::Output => self.output(),
|
||||
Opcode::JumpIfTrue => self.jump_if_true(),
|
||||
Opcode::JumpIfFalse => self.jump_if_false(),
|
||||
Opcode::LessThan => self.less_than(),
|
||||
Opcode::Equals => self.equals(),
|
||||
Opcode::Halt => return self.program[0],
|
||||
};
|
||||
self.pos += advance;
|
||||
}
|
||||
}
|
||||
fn run(&mut self) -> i64 {
|
||||
loop {
|
||||
let instruction = self.program[self.pos];
|
||||
let instruction = ModedOpcode::from(instruction);
|
||||
self.modes = (&instruction).into();
|
||||
let advance = match (&instruction).into() {
|
||||
Opcode::Add => self.add(),
|
||||
Opcode::Multiply => self.multiply(),
|
||||
Opcode::Input => self.input(),
|
||||
Opcode::Output => self.output(),
|
||||
Opcode::JumpIfTrue => self.jump_if_true(),
|
||||
Opcode::JumpIfFalse => self.jump_if_false(),
|
||||
Opcode::LessThan => self.less_than(),
|
||||
Opcode::Equals => self.equals(),
|
||||
Opcode::Halt => return self.program[0],
|
||||
};
|
||||
self.pos += advance;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_a(&self) -> i64 {
|
||||
let a = self.program[self.pos + 1];
|
||||
match self.modes.a {
|
||||
Mode::Position => self.program[a as usize],
|
||||
Mode::Immediate => a,
|
||||
}
|
||||
}
|
||||
fn get_a(&self) -> i64 {
|
||||
let a = self.program[self.pos + 1];
|
||||
match self.modes.a {
|
||||
Mode::Position => self.program[a as usize],
|
||||
Mode::Immediate => a,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_a(&mut self, value: i64) {
|
||||
let a = self.program[self.pos + 1];
|
||||
match self.modes.a {
|
||||
Mode::Position => self.program[a as usize] = value,
|
||||
Mode::Immediate => self.program[self.pos] = value,
|
||||
}
|
||||
}
|
||||
fn set_a(&mut self, value: i64) {
|
||||
let a = self.program[self.pos + 1];
|
||||
match self.modes.a {
|
||||
Mode::Position => self.program[a as usize] = value,
|
||||
Mode::Immediate => self.program[self.pos] = value,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_b(&self) -> i64 {
|
||||
let b = self.program[self.pos + 2];
|
||||
match self.modes.b {
|
||||
Mode::Position => self.program[b as usize],
|
||||
Mode::Immediate => b,
|
||||
}
|
||||
}
|
||||
fn get_b(&self) -> i64 {
|
||||
let b = self.program[self.pos + 2];
|
||||
match self.modes.b {
|
||||
Mode::Position => self.program[b as usize],
|
||||
Mode::Immediate => b,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_c(&mut self, value: i64) {
|
||||
let c = self.program[self.pos + 3];
|
||||
match self.modes.c {
|
||||
Mode::Position => self.program[c as usize] = value,
|
||||
Mode::Immediate => self.program[self.pos] = value,
|
||||
}
|
||||
}
|
||||
fn set_c(&mut self, value: i64) {
|
||||
let c = self.program[self.pos + 3];
|
||||
match self.modes.c {
|
||||
Mode::Position => self.program[c as usize] = value,
|
||||
Mode::Immediate => self.program[self.pos] = value,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self) -> usize {
|
||||
self.set_c(self.get_a() + self.get_b());
|
||||
4
|
||||
}
|
||||
fn add(&mut self) -> usize {
|
||||
self.set_c(self.get_a() + self.get_b());
|
||||
4
|
||||
}
|
||||
|
||||
fn multiply(&mut self) -> usize {
|
||||
self.set_c(self.get_a() * self.get_b());
|
||||
4
|
||||
}
|
||||
fn multiply(&mut self) -> usize {
|
||||
self.set_c(self.get_a() * self.get_b());
|
||||
4
|
||||
}
|
||||
|
||||
fn input(&mut self) -> usize {
|
||||
let mut line = String::new();
|
||||
print!("input: ");
|
||||
io::stdout().flush().expect("unable to flush output");
|
||||
io::stdin().lock().read_line(&mut line).expect("input failed");
|
||||
let value = line.trim().parse().expect("numeric input required");
|
||||
self.set_a(value);
|
||||
2
|
||||
}
|
||||
fn input(&mut self) -> usize {
|
||||
let mut line = String::new();
|
||||
print!("input: ");
|
||||
io::stdout().flush().expect("unable to flush output");
|
||||
io::stdin()
|
||||
.lock()
|
||||
.read_line(&mut line)
|
||||
.expect("input failed");
|
||||
let value = line.trim().parse().expect("numeric input required");
|
||||
self.set_a(value);
|
||||
2
|
||||
}
|
||||
|
||||
fn output(&mut self) -> usize {
|
||||
println!("output: {}", self.get_a());
|
||||
2
|
||||
}
|
||||
fn output(&mut self) -> usize {
|
||||
println!("output: {}", self.get_a());
|
||||
2
|
||||
}
|
||||
|
||||
fn jump_if_true(&mut self) -> usize {
|
||||
if self.get_a() > 0 {
|
||||
self.pos = self.get_b() as usize;
|
||||
return 0;
|
||||
}
|
||||
3
|
||||
}
|
||||
fn jump_if_true(&mut self) -> usize {
|
||||
if self.get_a() > 0 {
|
||||
self.pos = self.get_b() as usize;
|
||||
return 0;
|
||||
}
|
||||
3
|
||||
}
|
||||
|
||||
fn jump_if_false(&mut self) -> usize {
|
||||
if self.get_a() == 0 {
|
||||
self.pos = self.get_b() as usize;
|
||||
return 0;
|
||||
}
|
||||
3
|
||||
}
|
||||
fn jump_if_false(&mut self) -> usize {
|
||||
if self.get_a() == 0 {
|
||||
self.pos = self.get_b() as usize;
|
||||
return 0;
|
||||
}
|
||||
3
|
||||
}
|
||||
|
||||
fn less_than(&mut self) -> usize {
|
||||
if self.get_a() < self.get_b() {
|
||||
self.set_c(1)
|
||||
} else {
|
||||
self.set_c(0)
|
||||
}
|
||||
4
|
||||
}
|
||||
fn less_than(&mut self) -> usize {
|
||||
if self.get_a() < self.get_b() {
|
||||
self.set_c(1)
|
||||
} else {
|
||||
self.set_c(0)
|
||||
}
|
||||
4
|
||||
}
|
||||
|
||||
fn equals(&mut self) -> usize {
|
||||
if self.get_a() == self.get_b() {
|
||||
self.set_c(1)
|
||||
} else {
|
||||
self.set_c(0)
|
||||
}
|
||||
4
|
||||
}
|
||||
fn equals(&mut self) -> usize {
|
||||
if self.get_a() == self.get_b() {
|
||||
self.set_c(1)
|
||||
} else {
|
||||
self.set_c(0)
|
||||
}
|
||||
4
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example1() {
|
||||
let program: Vec<i64> = vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50];
|
||||
assert_eq!(Computer::from(program).run(), 3500)
|
||||
}
|
||||
#[test]
|
||||
fn example1() {
|
||||
let program: Vec<i64> = vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50];
|
||||
assert_eq!(Computer::from(program).run(), 3500)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example2() {
|
||||
let program: Vec<i64> = vec![1, 0, 0, 0, 99];
|
||||
assert_eq!(Computer::from(program).run(), 2)
|
||||
}
|
||||
#[test]
|
||||
fn example2() {
|
||||
let program: Vec<i64> = vec![1, 0, 0, 0, 99];
|
||||
assert_eq!(Computer::from(program).run(), 2)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example3() {
|
||||
let program: Vec<i64> = vec![1, 1, 1, 4, 99, 5, 6, 0, 99];
|
||||
assert_eq!(Computer::from(program).run(), 30)
|
||||
}
|
||||
#[test]
|
||||
fn example3() {
|
||||
let program: Vec<i64> = vec![1, 1, 1, 4, 99, 5, 6, 0, 99];
|
||||
assert_eq!(Computer::from(program).run(), 30)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue