Rename days to 2 digits always
[advent-of-code-2019.git] / day07 / computer.sh
diff --git a/day07/computer.sh b/day07/computer.sh
new file mode 100644 (file)
index 0000000..1486f23
--- /dev/null
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+declare -a data
+
+run_program() {
+    local -n od=$1
+    data=("${od[@]}")
+    pos=0
+    declare -a immediate
+    while [ $pos -le ${#data[@]} ]; do
+        # first, printf the value to 5 digits
+        instruction=$(printf "%05d" ${data[$pos]})
+        for (( a=0; a<3; a++ )); do
+            immediate[$((3-a))]=${instruction:$a:1}
+        done
+        instruction=${instruction:3}
+        param_count=3
+        case $instruction in
+            01|02)
+                # 01 - add, 02 multiply
+                symbol="+"
+                if [ $instruction == "02" ]; then
+                    symbol="*"
+                fi
+                val1=${data[$((pos+1))]}
+                val2=${data[$((pos+2))]}
+                res_loc=${data[$((pos+3))]}
+                if [ ${immediate[1]} -eq 0 ]; then
+                    val1=${data[$val1]}
+                fi
+                if [ ${immediate[2]} -eq 0 ]; then
+                    val2=${data[$val2]}
+                fi
+                data[$res_loc]=$(($val1 $symbol $val2))
+                ;;
+            03)
+                # 03 - read input
+                read -p "input: " input
+                res_loc=${data[$((pos+1))]}
+                data[$res_loc]=$input
+                param_count=1
+                ;;
+            04)
+                # 04 - output
+                if [ ${immediate[1]} -eq 1 ]; then
+                    echo ${data[$((pos+1))]}
+                else
+                    res_loc=${data[$((pos+1))]}
+                    echo ${data[$res_loc]}
+                fi
+                param_count=1
+                ;;
+            05|06)
+                # 05 - jump-if-true, 06 - jump-if-false
+                val=${data[$((pos+1))]}
+                jumpto=${data[$((pos+2))]}
+                param_count=2
+                if [ ${immediate[1]} -eq 0 ]; then
+                    val=${data[$val]}
+                fi
+                if [ ${immediate[2]} -eq 0 ]; then
+                    jumpto=${data[$jumpto]}
+                fi
+                if ( [ $val -ne 0 ] && [ "$instruction" == "05" ] ) ||
+                    ( [ $val -eq 0 ] && [ "$instruction" == "06" ] ); then
+                    pos=$jumpto
+                    continue
+                fi
+                ;;
+            07|08)
+                # 07 - is less than, 08 - is equal
+                val1=${data[$((pos+1))]}
+                val2=${data[$((pos+2))]}
+                res_pos=${data[$((pos+3))]}
+                if [ ${immediate[1]} -eq 0 ]; then
+                    val1=${data[$val1]}
+                fi
+                if [ ${immediate[2]} -eq 0 ]; then
+                    val2=${data[$val2]}
+                fi
+                data[$res_pos]=0
+                if [ "$instruction" == "07" ]; then
+                    if [ $val1 -lt $val2 ]; then
+                        data[$res_pos]=1
+                    fi
+                else
+                    if [ $val1 -eq $val2 ]; then
+                        data[$res_pos]=1
+                    fi
+                fi
+                ;;
+            99)
+                break
+                ;;
+            *)
+                echo "Invalid opcode: $instruction at position $pos"
+                exit 1
+        esac
+        pos=$(($pos+$param_count+1))
+    done
+}
+