summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2019/rust/Cargo.toml1
-rw-r--r--2019/rust/day02/Cargo.toml7
-rw-r--r--2019/rust/day02/src/main.rs93
3 files changed, 101 insertions, 0 deletions
diff --git a/2019/rust/Cargo.toml b/2019/rust/Cargo.toml
index f2bad2a..d52cdc3 100644
--- a/2019/rust/Cargo.toml
+++ b/2019/rust/Cargo.toml
@@ -1,4 +1,5 @@
[workspace]
members = [
"day01",
+ "day02",
]
diff --git a/2019/rust/day02/Cargo.toml b/2019/rust/day02/Cargo.toml
new file mode 100644
index 0000000..bd205ba
--- /dev/null
+++ b/2019/rust/day02/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "day02"
+version = "0.1.0"
+authors = ["cos <cos>"]
+edition = "2018"
+
+[dependencies]
diff --git a/2019/rust/day02/src/main.rs b/2019/rust/day02/src/main.rs
new file mode 100644
index 0000000..0d3362a
--- /dev/null
+++ b/2019/rust/day02/src/main.rs
@@ -0,0 +1,93 @@
+use std::io::{self, BufRead};
+use std::env;
+
+// https://stackoverflow.com/q/37888042/remove-single-trailing-newline-from-string-without-cloning
+fn trim_newline(s: &mut String) {
+ if s.ends_with('\n') {
+ s.pop();
+ if s.ends_with('\r') {
+ s.pop();
+ }
+ }
+}
+
+fn read_input() -> Vec<usize> {
+ let stdin = io::stdin();
+
+ // Far from neat, but gets the job done...
+ stdin.lock().split(b',').map(|v| {
+ let mut s = String::from_utf8(v.unwrap()).unwrap();
+ trim_newline(&mut s);
+ let u:u32 = s.parse().unwrap();
+ u as usize
+ }).collect()
+}
+
+fn restore_gravity_assist(window:&mut [usize], noun:usize, verb:usize) {
+ window[0] = noun;
+ window[1] = verb;
+}
+
+fn add(ip:usize, memory:&mut Vec<usize>) {
+ let result = memory[ip + 3];
+ let left = memory[ip + 1];
+ let right = memory[ip + 2];
+ memory[result] = memory[left] + memory[right];
+}
+
+fn mul(ip:usize, memory:&mut Vec<usize>) {
+ let result = memory[ip + 3];
+ let left = memory[ip + 1];
+ let right = memory[ip + 2];
+ memory[result] = memory[left] * memory[right];
+}
+
+fn intcode(mut memory:Vec<usize>) -> usize {
+ let mut ip = 0;
+ while ip < memory.len() {
+ let op = memory[ip];
+ match op {
+ 1 => { add(ip, &mut memory); ip += 4 },
+ 2 => { mul(ip, &mut memory); ip += 4 },
+ 99 => break,
+ op => panic!("Invalid operation {}", op),
+ }
+ }
+ memory[0]
+}
+
+fn first_puzzle(mut memory:Vec<usize>) -> usize {
+ println!("No argument provided, hence attemping to solve first puzzle.");
+
+ restore_gravity_assist(&mut memory[1..3], 12, 2);
+ intcode(memory)
+}
+
+fn second_puzzle(desired:usize, mut memory:Vec<usize>) -> Option<usize> {
+ println!("Desired output {} specified. Assuming second puzzle to search for it.", desired);
+ for noun in 0..100 {
+ for verb in 0..100 {
+ restore_gravity_assist(&mut memory[1..3], noun, verb);
+ if intcode(memory.clone()) == desired {
+ return Some(100 * noun + verb);
+ }
+ }
+ }
+
+ None
+}
+
+fn main() {
+ let memory = read_input();
+
+ let needle = env::args().nth(1);
+ let solution = match needle {
+ None => Some(first_puzzle(memory)),
+ Some(n) => second_puzzle(n.parse().unwrap_or(0), memory),
+ };
+
+ match solution {
+ Some(s) => println!("Solution: {}.", s),
+ _ => println!("No solution found."),
+ }
+}