summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcos <cos>2019-12-09 21:16:35 +0100
committercos <cos>2019-12-09 21:22:43 +0100
commit4c6c41b055d857f7dc2599262720a83da8d215be (patch)
tree6ebf781da98bf4f1cffa6045651e184468a771b4
parent7c464db6ffb3872f46a422f7ee0345f46bffbeae (diff)
downloadadventofcode-4c6c41b055d857f7dc2599262720a83da8d215be.zip
Add day09, 2019
-rw-r--r--2019/rust/Cargo.toml1
-rw-r--r--2019/rust/day09/Cargo.toml8
-rwxr-xr-x2019/rust/day09/both_parts.sh3
-rw-r--r--2019/rust/day09/programs/template21
-rw-r--r--2019/rust/day09/programs/test-add_immediate_immediate_position.iac29
-rw-r--r--2019/rust/day09/programs/test-add_immediate_immediate_position.out1
-rw-r--r--2019/rust/day09/programs/test-add_immediate_position_position.iac29
-rw-r--r--2019/rust/day09/programs/test-add_immediate_position_position.out1
-rw-r--r--2019/rust/day09/programs/test-add_position_immediate_position.iac32
-rw-r--r--2019/rust/day09/programs/test-add_position_immediate_position.out1
-rw-r--r--2019/rust/day09/programs/test-add_position_position_position.iac32
-rw-r--r--2019/rust/day09/programs/test-add_position_position_position.out1
-rw-r--r--2019/rust/day09/programs/test-eq_immediate_immediate_position.iac30
-rw-r--r--2019/rust/day09/programs/test-eq_immediate_immediate_position.out1
-rw-r--r--2019/rust/day09/programs/test-eq_immediate_position_position.iac30
-rw-r--r--2019/rust/day09/programs/test-eq_immediate_position_position.out1
-rw-r--r--2019/rust/day09/programs/test-eq_position_immediate_position.iac30
-rw-r--r--2019/rust/day09/programs/test-eq_position_immediate_position.out1
-rw-r--r--2019/rust/day09/programs/test-eq_position_position_position.iac30
-rw-r--r--2019/rust/day09/programs/test-eq_position_position_position.out1
-rw-r--r--2019/rust/day09/programs/test-halt.iac21
-rw-r--r--2019/rust/day09/programs/test-halt.out0
-rw-r--r--2019/rust/day09/programs/test-in_position_out_position.iac28
-rw-r--r--2019/rust/day09/programs/test-in_position_out_position.in1
-rw-r--r--2019/rust/day09/programs/test-in_position_out_position.out1
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_immediate_immediate.iac28
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_immediate_immediate.out1
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_immediate_position.iac31
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_immediate_position.out1
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_position_immediate.iac31
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_position_immediate.out1
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_position_position.iac34
-rw-r--r--2019/rust/day09/programs/test-jmpfalse_position_position.out1
-rw-r--r--2019/rust/day09/programs/test-jmptrue_immediate_immediate.iac29
-rw-r--r--2019/rust/day09/programs/test-jmptrue_immediate_immediate.out1
-rw-r--r--2019/rust/day09/programs/test-jmptrue_immediate_position.iac31
-rw-r--r--2019/rust/day09/programs/test-jmptrue_immediate_position.out1
-rw-r--r--2019/rust/day09/programs/test-jmptrue_position_immediate.iac28
-rw-r--r--2019/rust/day09/programs/test-jmptrue_position_immediate.out1
-rw-r--r--2019/rust/day09/programs/test-jmptrue_position_position.iac31
-rw-r--r--2019/rust/day09/programs/test-jmptrue_position_position.out1
-rw-r--r--2019/rust/day09/programs/test-out_immediate.iac11
-rw-r--r--2019/rust/day09/programs/test-out_immediate.out1
-rw-r--r--2019/rust/day09/src/main.rs353
-rwxr-xr-x2019/rust/day09/test_ops.sh85
45 files changed, 1035 insertions, 0 deletions
diff --git a/2019/rust/Cargo.toml b/2019/rust/Cargo.toml
index 91b5060..420d5ab 100644
--- a/2019/rust/Cargo.toml
+++ b/2019/rust/Cargo.toml
@@ -8,4 +8,5 @@ members = [
"day06",
"day07",
"day08",
+ "day09",
]
diff --git a/2019/rust/day09/Cargo.toml b/2019/rust/day09/Cargo.toml
new file mode 100644
index 0000000..88218ce
--- /dev/null
+++ b/2019/rust/day09/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "day09"
+version = "0.1.0"
+authors = ["cos <cos>"]
+edition = "2018"
+
+[dependencies]
+getopts = "0.2"
diff --git a/2019/rust/day09/both_parts.sh b/2019/rust/day09/both_parts.sh
new file mode 100755
index 0000000..fb654a1
--- /dev/null
+++ b/2019/rust/day09/both_parts.sh
@@ -0,0 +1,3 @@
+echo 1|../target/release/day09 --mode stdio --program input
+echo 2|../target/release/day09 --mode stdio --program input
+
diff --git a/2019/rust/day09/programs/template b/2019/rust/day09/programs/template
new file mode 100644
index 0000000..b417129
--- /dev/null
+++ b/2019/rust/day09/programs/template
@@ -0,0 +1,21 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Halt
+99
diff --git a/2019/rust/day09/programs/test-add_immediate_immediate_position.iac b/2019/rust/day09/programs/test-add_immediate_immediate_position.iac
new file mode 100644
index 0000000..a9b7495
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_immediate_immediate_position.iac
@@ -0,0 +1,29 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Add
+1101,8,14,7
+
+4,7
+
+# Halt
+99
+
+# Result
+0
diff --git a/2019/rust/day09/programs/test-add_immediate_immediate_position.out b/2019/rust/day09/programs/test-add_immediate_immediate_position.out
new file mode 100644
index 0000000..2bd5a0a
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_immediate_immediate_position.out
@@ -0,0 +1 @@
+22
diff --git a/2019/rust/day09/programs/test-add_immediate_position_position.iac b/2019/rust/day09/programs/test-add_immediate_position_position.iac
new file mode 100644
index 0000000..20188cf
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_immediate_position_position.iac
@@ -0,0 +1,29 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Add
+101,14,8,7
+
+4,7
+
+# Halt
+99
+
+# Result
+0, 13
diff --git a/2019/rust/day09/programs/test-add_immediate_position_position.out b/2019/rust/day09/programs/test-add_immediate_position_position.out
new file mode 100644
index 0000000..f64f5d8
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_immediate_position_position.out
@@ -0,0 +1 @@
+27
diff --git a/2019/rust/day09/programs/test-add_position_immediate_position.iac b/2019/rust/day09/programs/test-add_position_immediate_position.iac
new file mode 100644
index 0000000..b5894d8
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_position_immediate_position.iac
@@ -0,0 +1,32 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Add
+1001,8,9,7
+
+4,7
+
+# Halt
+99
+
+# Result
+0, 21
+
+# Halt
+99
diff --git a/2019/rust/day09/programs/test-add_position_immediate_position.out b/2019/rust/day09/programs/test-add_position_immediate_position.out
new file mode 100644
index 0000000..64bb6b7
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_position_immediate_position.out
@@ -0,0 +1 @@
+30
diff --git a/2019/rust/day09/programs/test-add_position_position_position.iac b/2019/rust/day09/programs/test-add_position_position_position.iac
new file mode 100644
index 0000000..c68d932
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_position_position_position.iac
@@ -0,0 +1,32 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Add
+1,8,9,7
+
+4,7
+
+# Halt
+99
+
+# Result
+0, 11, 81
+
+# Halt
+99
diff --git a/2019/rust/day09/programs/test-add_position_position_position.out b/2019/rust/day09/programs/test-add_position_position_position.out
new file mode 100644
index 0000000..cd5b025
--- /dev/null
+++ b/2019/rust/day09/programs/test-add_position_position_position.out
@@ -0,0 +1 @@
+92
diff --git a/2019/rust/day09/programs/test-eq_immediate_immediate_position.iac b/2019/rust/day09/programs/test-eq_immediate_immediate_position.iac
new file mode 100644
index 0000000..4bdf1d1
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_immediate_immediate_position.iac
@@ -0,0 +1,30 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Add
+1108,5,5,7
+
+# Out
+4,7
+
+# Halt
+99
+
+# Result
+0
diff --git a/2019/rust/day09/programs/test-eq_immediate_immediate_position.out b/2019/rust/day09/programs/test-eq_immediate_immediate_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_immediate_immediate_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-eq_immediate_position_position.iac b/2019/rust/day09/programs/test-eq_immediate_position_position.iac
new file mode 100644
index 0000000..caaeee9
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_immediate_position_position.iac
@@ -0,0 +1,30 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Add
+108,99,6,7
+
+# Out
+4,7
+
+# Halt
+99
+
+# Result
+0
diff --git a/2019/rust/day09/programs/test-eq_immediate_position_position.out b/2019/rust/day09/programs/test-eq_immediate_position_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_immediate_position_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-eq_position_immediate_position.iac b/2019/rust/day09/programs/test-eq_position_immediate_position.iac
new file mode 100644
index 0000000..51f2129
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_position_immediate_position.iac
@@ -0,0 +1,30 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Equals
+1008,6,99,7
+
+# Out
+4,7
+
+# Halt
+99
+
+# Result
+0
diff --git a/2019/rust/day09/programs/test-eq_position_immediate_position.out b/2019/rust/day09/programs/test-eq_position_immediate_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_position_immediate_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-eq_position_position_position.iac b/2019/rust/day09/programs/test-eq_position_position_position.iac
new file mode 100644
index 0000000..de2bc1f
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_position_position_position.iac
@@ -0,0 +1,30 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Equals
+8,6,6,7
+
+# Out
+4,7
+
+# Halt
+99
+
+# Result
+0
diff --git a/2019/rust/day09/programs/test-eq_position_position_position.out b/2019/rust/day09/programs/test-eq_position_position_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-eq_position_position_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-halt.iac b/2019/rust/day09/programs/test-halt.iac
new file mode 100644
index 0000000..b417129
--- /dev/null
+++ b/2019/rust/day09/programs/test-halt.iac
@@ -0,0 +1,21 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# Halt
+99
diff --git a/2019/rust/day09/programs/test-halt.out b/2019/rust/day09/programs/test-halt.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/2019/rust/day09/programs/test-halt.out
diff --git a/2019/rust/day09/programs/test-in_position_out_position.iac b/2019/rust/day09/programs/test-in_position_out_position.iac
new file mode 100644
index 0000000..1892ecf
--- /dev/null
+++ b/2019/rust/day09/programs/test-in_position_out_position.iac
@@ -0,0 +1,28 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# In
+3,5
+# Out
+4,5
+# Halt
+99
+
+# Output value
+0
diff --git a/2019/rust/day09/programs/test-in_position_out_position.in b/2019/rust/day09/programs/test-in_position_out_position.in
new file mode 100644
index 0000000..425151f
--- /dev/null
+++ b/2019/rust/day09/programs/test-in_position_out_position.in
@@ -0,0 +1 @@
+40
diff --git a/2019/rust/day09/programs/test-in_position_out_position.out b/2019/rust/day09/programs/test-in_position_out_position.out
new file mode 100644
index 0000000..425151f
--- /dev/null
+++ b/2019/rust/day09/programs/test-in_position_out_position.out
@@ -0,0 +1 @@
+40
diff --git a/2019/rust/day09/programs/test-jmpfalse_immediate_immediate.iac b/2019/rust/day09/programs/test-jmpfalse_immediate_immediate.iac
new file mode 100644
index 0000000..e926e3e
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_immediate_immediate.iac
@@ -0,0 +1,28 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpFalse
+1106,0,5
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
diff --git a/2019/rust/day09/programs/test-jmpfalse_immediate_immediate.out b/2019/rust/day09/programs/test-jmpfalse_immediate_immediate.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_immediate_immediate.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmpfalse_immediate_position.iac b/2019/rust/day09/programs/test-jmpfalse_immediate_position.iac
new file mode 100644
index 0000000..7048632
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_immediate_position.iac
@@ -0,0 +1,31 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpFalse
+106,0,8
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
+
+# Jump target
+5
diff --git a/2019/rust/day09/programs/test-jmpfalse_immediate_position.out b/2019/rust/day09/programs/test-jmpfalse_immediate_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_immediate_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmpfalse_position_immediate.iac b/2019/rust/day09/programs/test-jmpfalse_position_immediate.iac
new file mode 100644
index 0000000..4b00314
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_position_immediate.iac
@@ -0,0 +1,31 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpFalse
+1006,8,5
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
+
+# Value
+0
diff --git a/2019/rust/day09/programs/test-jmpfalse_position_immediate.out b/2019/rust/day09/programs/test-jmpfalse_position_immediate.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_position_immediate.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmpfalse_position_position.iac b/2019/rust/day09/programs/test-jmpfalse_position_position.iac
new file mode 100644
index 0000000..ea536f7
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_position_position.iac
@@ -0,0 +1,34 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpFalse
+6,9,8
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
+
+# Target addr
+5
+
+# Value
+0
diff --git a/2019/rust/day09/programs/test-jmpfalse_position_position.out b/2019/rust/day09/programs/test-jmpfalse_position_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmpfalse_position_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmptrue_immediate_immediate.iac b/2019/rust/day09/programs/test-jmptrue_immediate_immediate.iac
new file mode 100644
index 0000000..cc4d669
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_immediate_immediate.iac
@@ -0,0 +1,29 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpTrue
+1105,1,5
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
+
diff --git a/2019/rust/day09/programs/test-jmptrue_immediate_immediate.out b/2019/rust/day09/programs/test-jmptrue_immediate_immediate.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_immediate_immediate.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmptrue_immediate_position.iac b/2019/rust/day09/programs/test-jmptrue_immediate_position.iac
new file mode 100644
index 0000000..a25b903
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_immediate_position.iac
@@ -0,0 +1,31 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpTrue
+105,1,8
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
+
+# Jump target
+5
diff --git a/2019/rust/day09/programs/test-jmptrue_immediate_position.out b/2019/rust/day09/programs/test-jmptrue_immediate_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_immediate_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmptrue_position_immediate.iac b/2019/rust/day09/programs/test-jmptrue_position_immediate.iac
new file mode 100644
index 0000000..a4f4245
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_position_immediate.iac
@@ -0,0 +1,28 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpTrue
+1005,0,5
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
diff --git a/2019/rust/day09/programs/test-jmptrue_position_immediate.out b/2019/rust/day09/programs/test-jmptrue_position_immediate.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_position_immediate.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-jmptrue_position_position.iac b/2019/rust/day09/programs/test-jmptrue_position_position.iac
new file mode 100644
index 0000000..ed68de5
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_position_position.iac
@@ -0,0 +1,31 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+#
+# 1 (3) Add
+# 2 (3) Mul
+# 7 (3) LessThan
+# 8 (3) Equals
+# 3 (1) In
+# 4 (1) Out
+# 5 (2) JmpTrue
+# 6 (2) JmpFalse
+# 9 (1) BaseMod
+# 99 (0) Halt
+
+# JmpTrue
+5,0,8
+
+# Out
+104,-1
+104,1
+
+# Halt
+99
+
+# Addr
+5
diff --git a/2019/rust/day09/programs/test-jmptrue_position_position.out b/2019/rust/day09/programs/test-jmptrue_position_position.out
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/2019/rust/day09/programs/test-jmptrue_position_position.out
@@ -0,0 +1 @@
+1
diff --git a/2019/rust/day09/programs/test-out_immediate.iac b/2019/rust/day09/programs/test-out_immediate.iac
new file mode 100644
index 0000000..4aa8ccf
--- /dev/null
+++ b/2019/rust/day09/programs/test-out_immediate.iac
@@ -0,0 +1,11 @@
+# ABCDE
+# 210xx
+#
+# DE - two-digit opcode, xx == opcode x
+# C - mode of 1st parameter, 0 == position mode
+# B - mode of 2nd parameter, 1 == immediate mode
+# A - mode of 3rd parameter, 0 == relative mode,
+
+# Out immediate
+104,123
+99
diff --git a/2019/rust/day09/programs/test-out_immediate.out b/2019/rust/day09/programs/test-out_immediate.out
new file mode 100644
index 0000000..190a180
--- /dev/null
+++ b/2019/rust/day09/programs/test-out_immediate.out
@@ -0,0 +1 @@
+123
diff --git a/2019/rust/day09/src/main.rs b/2019/rust/day09/src/main.rs
new file mode 100644
index 0000000..ce7e236
--- /dev/null
+++ b/2019/rust/day09/src/main.rs
@@ -0,0 +1,353 @@
+use std::env;
+use std::io::{self, BufRead, BufReader};
+use std::fs::File;
+
+type BusWidth = i128;
+type IOType = i128;
+type IOData = Vec<IOType>;
+
+fn read_program(filename: &str) -> Vec<BusWidth> {
+ let f = File::open(filename).expect(filename);
+ let f = BufReader::new(f);
+
+ f.lines()
+ .filter(|line| match line {
+ Ok(s) => {
+ let b = s.as_bytes();
+ if b.len() == 0 || b.len() > 0 && b[0] == b'#' { false } else { true }
+ },
+ _ => true,
+ })
+ .map(|line| match line {
+ Ok(line) => {
+ let data:Vec<BusWidth> = line.split(',').map(|e| { e.trim_start().trim_end() })
+ .filter(|v| match v.parse::<BusWidth>() { Ok(_) => true, _ => {
+ eprintln!("Could not parse: {:?}", v);
+ false
+ },
+ })
+ .map(|r| r.parse().unwrap())
+ .collect();
+
+ data
+ },
+ Err(_) => panic!("Could not parse {}.", filename),
+ }).flatten().collect()
+}
+
+#[derive(Clone, Debug)]
+struct Memory {
+ mem: Vec<BusWidth>,
+}
+
+impl Memory {
+ fn new() -> Memory {
+ Memory { mem: Vec::new(), }
+ }
+
+ fn init(&mut self, mem:Vec<BusWidth>) {
+ self.mem = mem;
+ }
+
+ fn read(&self, address: usize) -> BusWidth {
+ match self.mem.get(address) {
+ Some(value) => *value,
+ None => 0,
+ }
+ }
+
+ fn write(&mut self, address: usize, value: BusWidth) {
+ if self.len() < address {
+ self.mem.resize(address*2, 0);
+ }
+ self.mem[address] = value;
+ }
+
+ fn len(&self) -> usize {
+ self.mem.len()
+ }
+}
+
+#[derive(Debug)]
+struct Registers {
+ ip: usize,
+ base: usize,
+}
+
+#[derive(Debug)]
+enum Arithm {
+ Add,
+ Mul,
+ LessThan,
+ Equals,
+}
+
+#[derive(Debug)]
+enum IO {
+ In,
+ Out,
+}
+
+#[derive(Debug)]
+enum Jmp {
+ JmpTrue,
+ JmpFalse,
+}
+
+#[derive(Debug)]
+enum RegOp {
+ BaseMod,
+}
+
+#[derive(Debug, PartialEq)]
+enum ParameterMode {
+ Position,
+ Immediate,
+ Relative,
+}
+
+#[derive(Debug, PartialEq)]
+enum DataDirection {
+ Read,
+ Write,
+}
+
+#[derive(PartialEq)]
+enum IOMethod {
+ StdIO,
+ Variables,
+}
+
+struct Intcode {
+ r: Registers,
+ io_method: IOMethod,
+ input: IOData,
+ output: IOData,
+}
+
+impl Intcode {
+ fn new() -> Intcode {
+ Intcode {
+ r: Registers { ip: 0, base: 0, },
+ io_method: IOMethod::Variables,
+ input: vec![],
+ output: vec![],
+ }
+ }
+
+ fn param_to_argument(&self, mode: &ParameterMode, mem: &Memory, offset: usize,
+ dir: &DataDirection) -> usize
+ {
+ match mode {
+ ParameterMode::Position => {
+ if mem.read(offset) < 0 {
+ panic!("Attempt to address negative memory at IP: {}");
+ }
+ mem.read(offset) as usize
+ },
+ ParameterMode::Immediate => {
+ if *dir == DataDirection::Write {
+ panic!("Immediate parameter mode at IP: {}", self.r.ip);
+ }
+ offset
+ },
+ ParameterMode::Relative => {
+ if (mem.read(offset) + self.r.base as BusWidth) < 0 {
+ panic!("Attempt to address negative memory at IP: {}");
+ }
+ (mem.read(offset) + self.r.base as BusWidth) as usize
+ },
+ }
+ }
+
+ fn arithm(&self, op: Arithm, modes: Vec<ParameterMode>, memory: &mut Memory) {
+ let parameter_directions =
+ [DataDirection::Read, DataDirection::Read, DataDirection::Write];
+ let params:Vec<usize> = (0..parameter_directions.len())
+ .zip(parameter_directions.iter())
+ .map(|(p, d)| {
+ self.param_to_argument(&modes[p], memory, self.r.ip + 1 + p, d)
+ }).collect();
+ let left = params[0];
+ let right = params[1];
+ let result = params[2];
+
+ match op {
+ Arithm::Add => memory.write(result, memory.read(left) + memory.read(right)),
+ Arithm::Mul => memory.write(result, memory.read(left) * memory.read(right)),
+ Arithm::LessThan => memory.write(result, if memory.read(left) < memory.read(right) {
+ 1 } else { 0 }),
+ Arithm::Equals => memory.write(result, if memory.read(left) == memory.read(right) {
+ 1 } else { 0 }),
+ }
+ }
+
+ fn jmp(&mut self, op: Jmp, modes: Vec<ParameterMode>, memory: &mut Memory)
+ {
+ let parameter_directions = [DataDirection::Read, DataDirection::Read];
+ let params:Vec<usize> = (0..parameter_directions.len())
+ .zip(parameter_directions.iter())
+ .map(|(p, d)| {
+ self.param_to_argument(&modes[p], memory, self.r.ip + 1 + p, d)
+ }).collect();
+ let value = params[0];
+ let address = params[1];
+
+ self.r.ip = match op {
+ Jmp::JmpTrue => (if memory.read(value) != 0 {
+ memory.read(address) as usize } else { self.r.ip + 3 }),
+ Jmp::JmpFalse => (if memory.read(value) == 0 {
+ memory.read(address) as usize } else { self.r.ip + 3 }),
+ };
+
+ }
+
+ fn regop(&mut self, op: RegOp, modes: Vec<ParameterMode>, memory: &mut Memory)
+ {
+ let parameter_directions = [DataDirection::Read];
+ let params:Vec<usize> = (0..parameter_directions.len())
+ .zip(parameter_directions.iter())
+ .map(|(p, d)| {
+ self.param_to_argument(&modes[p], memory, self.r.ip + 1 + p, d)
+ }).collect();
+ let value = memory.read(params[0]);
+
+ match op {
+ RegOp::BaseMod => {
+ if value < 0 {
+ self.r.base -= (-1 * value) as usize;
+ } else {
+ self.r.base += value as usize;
+ }
+ },
+ };
+ }
+
+ fn io_in(&mut self, _op: IO, modes: Vec<ParameterMode>, memory:&mut Memory)
+ {
+ let parameter_directions = [DataDirection::Write];
+ let params:Vec<usize> = (0..parameter_directions.len())
+ .zip(parameter_directions.iter())
+ .map(|(p, d)| {
+ self.param_to_argument(&modes[p], memory, self.r.ip + 1 + p, d)
+ }).collect();
+ let address = params[0];
+ let stdin = io::stdin();
+
+ match &self.io_method {
+ IOMethod::StdIO => {
+ let mut value: Option<BusWidth> = None;
+ while {
+ stdin.lock().lines().next().map(|s| {
+ match s {
+ Ok(v) => {
+ let parsed_string = v.trim_end().trim_start().parse::<BusWidth>();
+ match parsed_string {
+ Ok(v) => { value = Some(v); value },
+ _ => None,
+ };
+ value
+ },
+ _ => { None },
+ }
+ });
+ if value == None {
+ eprintln!("Could not parse input, please retry.");
+ true
+ } else {
+ false
+ }
+ } {}
+ match value {
+ Some(v) => memory.write(address, v),
+ _ => {},
+ };
+ },
+ IOMethod::Variables => {
+ memory.write(address, self.input.remove(0) as BusWidth);
+ },
+ }
+ }
+
+ fn io_out(&mut self, _op: IO, modes: Vec<ParameterMode>, memory:&mut Memory )
+ {
+ let parameter_directions = [DataDirection::Read];
+ let params:Vec<usize> = (0..parameter_directions.len())
+ .zip(parameter_directions.iter())
+ .map(|(p, d)| {
+ self.param_to_argument(&modes[p], memory, self.r.ip + 1 + p, d)
+ }).collect();
+ let address = params[0];
+
+ let o = memory.read(address);
+ println!("{}", o);
+ match &self.io_method {
+ IOMethod::Variables => self.output.push(o as IOType),
+ _ => {},
+ }
+ }
+
+ fn intcode(&mut self, mut memory:Memory)
+ {
+ while self.r.ip < memory.len() {
+ let op = memory.read(self.r.ip) % 100;
+ let modes:Vec<ParameterMode> = (2..=4)
+ .map(|e| memory.read(self.r.ip) / 10i32.pow(e) as BusWidth % 10)
+ .map(|n| match n {
+ 0 => ParameterMode::Position,
+ 1 => ParameterMode::Immediate,
+ 2 => ParameterMode::Relative,
+ p => panic!("Invalid parameter mode {} at IP: {}", p, self.r.ip),
+ }).collect();
+
+ match op {
+ 1 => { self.arithm(Arithm::Add, modes, &mut memory); self.r.ip += 4 },
+ 2 => { self.arithm(Arithm::Mul, modes, &mut memory); self.r.ip += 4 },
+ 7 => { self.arithm(Arithm::LessThan, modes, &mut memory); self.r.ip += 4 },
+ 8 => { self.arithm(Arithm::Equals, modes, &mut memory); self.r.ip += 4 },
+ 3 => { self.io_in( IO::In, modes, &mut memory); self.r.ip += 2 },
+ 4 => { self.io_out(IO::Out, modes, &mut memory); self.r.ip += 2 },
+ 5 => { self.jmp( Jmp::JmpTrue, modes, &mut memory); },
+ 6 => { self.jmp( Jmp::JmpFalse, modes, &mut memory); },
+ 9 => { self.regop(RegOp::BaseMod, modes, &mut memory); self.r.ip += 2},
+ 99 => break,
+ op => panic!("Invalid operation {} at IP: {}", op, self.r.ip),
+ }
+ }
+ }
+}
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let mut opts = getopts::Options::new();
+ opts.reqopt("m", "mode", "Mode of IO operations", "[arg|stdio]");
+ opts.reqopt("p", "program", "File to load program from", "FILE");
+ let matches = match opts.parse(&args[1..]) {
+ Ok(m) => { m }
+ Err(f) => { panic!(f.to_string()) }
+ };
+ let program:String = matches.opt_str("program").unwrap();
+ let mode = matches.opt_str("mode").unwrap();
+ let mut memory = Memory::new();
+ memory.init(read_program(&program));
+ let mut cpu = Intcode::new();
+
+ if mode == "arg" {
+ cpu.io_method = IOMethod::Variables;
+ let input:IOData = matches.free[0].split(",").map(|v| {
+ let i = v.trim_end().parse().unwrap();
+ i
+ }).collect();
+ cpu.input = input;
+ while cpu.input.len() > 1 {
+ cpu.intcode(memory.clone());
+ }
+ } else if mode == "stdio" {
+ cpu.io_method = IOMethod::StdIO;
+
+ cpu.intcode(memory.clone());
+ } else {
+ panic!("Unknown mode: {}", mode);
+ }
+}
diff --git a/2019/rust/day09/test_ops.sh b/2019/rust/day09/test_ops.sh
new file mode 100755
index 0000000..4e78122
--- /dev/null
+++ b/2019/rust/day09/test_ops.sh
@@ -0,0 +1,85 @@
+#!/bin/sh -e
+
+E="../target/debug/day09"
+
+### https://adventofcode.com/2019/day/2
+
+# Opcode 1 adds together numbers read from two positions and stores the result
+# in a third position. The three integers immediately after the opcode tell you
+# these three positions - the first two indicate the positions from which you
+# should read the input values, and the third indicates the position at which
+# the output should be stored.
+
+# Opcode 2 works exactly like opcode 1, except it multiplies the two inputs
+# instead of adding them. Again, the three integers after the opcode indicate
+# where the inputs and outputs are, not their values.
+
+### https://adventofcode.com/2019/day/5
+
+# Opcode 3 takes a single integer as input and saves it to the position given
+# by its only parameter. For example, the instruction 3,50 would take an input
+# value and store it at address 50.
+
+# Opcode 4 outputs the value of its only parameter. For example, the
+# instruction 4,50 would output the value at address 50.
+
+# Each parameter of an instruction is handled based on its parameter mode.
+# Right now, your ship computer already understands parameter mode 0, position
+# mode, which causes the parameter to be interpreted as a position - if the
+# parameter is 50, its value is the value stored at address 50 in memory. Until
+# now, all parameters have been in position mode.
+
+# Now, your ship computer will also need to handle parameters in mode 1,
+# immediate mode. In immediate mode, a parameter is interpreted as a value - if
+# the parameter is 50, its value is simply 50.
+
+# Opcode 5 is jump-if-true: if the first parameter is non-zero, it sets the
+# instruction pointer to the value from the second parameter. Otherwise, it
+# does nothing.
+
+# Opcode 6 is jump-if-false: if the first parameter is zero, it sets the
+# instruction pointer to the value from the second parameter. Otherwise, it
+# does nothing.
+
+# Opcode 7 is less than: if the first parameter is less than the second
+# parameter, it stores 1 in the position given by the third parameter.
+# Otherwise, it stores 0.
+
+# Opcode 8 is equals: if the first parameter is equal to the second parameter,
+# it stores 1 in the position given by the third parameter. Otherwise, it
+# stores 0.
+
+### https://adventofcode.com/2019/day/9
+
+# Opcode 9 adjusts the relative base by the value of its only parameter. The
+# relative base increases (or decreases, if the value is negative) by the value
+# of the parameter.
+
+PROGRAMS=${@:-programs/test-*.iac}
+for PROGRAM in ${PROGRAMS}
+do
+ echo "Starting ${PROGRAM}"
+ if [ -e ${PROGRAM%.iac}.in ]; then
+ INPUT=`cat ${PROGRAM%.iac}.in`
+ else
+ INPUT="0"
+ fi
+
+ if [ -e ${PROGRAM%.iac}.out ]; then
+ EXPECTED="`cat ${PROGRAM%.iac}.out`"
+ else
+ EXPECTED=""
+ fi
+
+ OUTPUT=`echo "${INPUT}" | RUST_BACKTRACE=1 \
+ "${E}" --program "${PROGRAM}" --mode stdio '0' | tee /dev/stderr`
+ echo "${PROGRAM} finished"
+ if [ "${EXPECTED}" = "${OUTPUT}" ]; then
+ echo "Expected output recieved: ${OUTPUT}"
+ else
+ echo "Incorrect output!"
+ echo "Expected |${EXPECTED}| != Actual |${OUTPUT}|"
+ exit 1
+ fi
+ echo ""
+done