Most of part 2
authorBrett Parker <iDunno@sommitrealweird.co.uk>
Tue, 8 Dec 2020 09:25:33 +0000 (09:25 +0000)
committerBrett Parker <iDunno@sommitrealweird.co.uk>
Tue, 8 Dec 2020 09:25:33 +0000 (09:25 +0000)
day11/computer.sh [new file with mode: 0644]
day11/input.txt [new file with mode: 0644]
day11/robot.sh [new file with mode: 0644]
day11/run.sh [new file with mode: 0755]
day11/run2.sh [new file with mode: 0755]

diff --git a/day11/computer.sh b/day11/computer.sh
new file mode 100644 (file)
index 0000000..b8fa4cf
--- /dev/null
@@ -0,0 +1,144 @@
+#!/bin/bash
+
+declare -a data
+
+get_value() {
+    local -n da=$1
+    local index=$2
+
+    if [ $index -lt 0 ]; then
+        echo "Index negative, give up!"
+        exit 2
+    fi
+
+    if ! [ ${da[$index]+a} ]; then
+        da[$index]=0
+    fi
+
+    echo "${da[$index]}"
+}
+
+get_param() {
+    local -n dap=$1
+    local pos=$2
+    local mode=$3
+    local relative_base=$4
+
+    loc=$(get_param_loc dap $pos $mode $relative_base)
+
+    get_value dap $loc
+}
+
+get_param_loc() {
+    local -n dapl=$1
+    local pos=$2
+    local mode=$3
+    local relative_base=$4
+
+    case $mode in
+        0)
+            get_value dapl $pos
+            ;;
+        1)
+            echo $pos
+            ;;
+        2)
+            move_by=$(get_value dapl $pos)
+            echo $((relative_base+$move_by))
+            ;;
+        *)
+            echo "Unknown parameter mode: $mode"
+            exit 2
+            ;;
+    esac
+}
+
+run_program() {
+    local -n od=$1
+    local relative_base=0
+    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
+        echo -n $'\r'"    "$'\r'$instruction >&2
+        case $instruction in
+            01|02)
+                # 01 - add, 02 multiply
+                symbol="+"
+                if [ $instruction == "02" ]; then
+                    symbol="*"
+                fi
+                val1=$(get_param data $((pos+1)) ${immediate[1]} $relative_base)
+                val2=$(get_param data $((pos+2)) ${immediate[2]} $relative_base)
+                res_loc=$(get_param_loc data $((pos+3)) ${immediate[3]} $relative_base)
+                data[$res_loc]=$(($val1 $symbol $val2))
+                ;;
+            03)
+                # 03 - read input
+                echo -n $'\r'"    "$'\r' >&2
+                read -p "input: " input
+                res_loc=$(get_param_loc data $((pos+1)) ${immediate[1]} $relative_base)
+                data[$res_loc]=$input
+                param_count=1
+                ;;
+            04)
+                # 04 - output
+                val=$(get_param data $((pos+1)) ${immediate[1]} $relative_base)
+                echo -n $'\r'"    "$'\r' >&2
+                echo $val
+                param_count=1
+                ;;
+            05|06)
+                # 05 - jump-if-true, 06 - jump-if-false
+                val=$(get_param data $((pos+1)) ${immediate[1]} $relative_base)
+                jumpto=$(get_param data $((pos+2)) ${immediate[2]} $relative_base)
+                param_count=2
+                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=$(get_param data $((pos+1)) ${immediate[1]} $relative_base)
+                val2=$(get_param data $((pos+2)) ${immediate[2]} $relative_base)
+                res_pos=$(get_param_loc data $((pos+3)) ${immediate[3]} $relative_base)
+                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
+                ;;
+            09)
+                # adjust relative base
+                param_count=1
+                val=$(get_param data $((pos+1)) ${immediate[1]} $relative_base)
+                relative_base=$((relative_base+$val))
+                ;;
+            99)
+                break
+                ;;
+            *)
+                echo "Invalid opcode: $instruction at position $pos"
+                exit 1
+                ;;
+        esac
+        pos=$(($pos+$param_count+1))
+    done
+    echo -n $'\r'"    "$'\r'
+    echo -n $'\r'"    "$'\r'
+}
+
diff --git a/day11/input.txt b/day11/input.txt
new file mode 100644 (file)
index 0000000..b1a2f81
--- /dev/null
@@ -0,0 +1 @@
+3,8,1005,8,332,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,101,0,8,28,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,51,1,1103,5,10,1,1104,9,10,2,1003,0,10,1,5,16,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,1001,8,0,88,1006,0,2,1006,0,62,2,8,2,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,121,1006,0,91,1006,0,22,1006,0,23,1006,0,1,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,155,1006,0,97,1,1004,2,10,2,1003,6,10,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1002,8,1,187,1,104,15,10,2,107,9,10,1006,0,37,1006,0,39,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,102,1,8,223,2,2,17,10,1,1102,5,10,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1001,8,0,253,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,1002,8,1,276,1006,0,84,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,301,2,1009,9,10,1006,0,10,2,102,15,10,101,1,9,9,1007,9,997,10,1005,10,15,99,109,654,104,0,104,1,21102,1,936995738516,1,21101,0,349,0,1105,1,453,21102,1,825595015976,1,21102,1,360,0,1105,1,453,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21102,46375541763,1,1,21101,0,407,0,1105,1,453,21102,1,179339005019,1,21101,0,418,0,1106,0,453,3,10,104,0,104,0,3,10,104,0,104,0,21102,825012036372,1,1,21102,441,1,0,1105,1,453,21101,988648461076,0,1,21101,452,0,0,1105,1,453,99,109,2,22102,1,-1,1,21102,40,1,2,21102,484,1,3,21101,0,474,0,1106,0,517,109,-2,2105,1,0,0,1,0,0,1,109,2,3,10,204,-1,1001,479,480,495,4,0,1001,479,1,479,108,4,479,10,1006,10,511,1102,1,0,479,109,-2,2105,1,0,0,109,4,2102,1,-1,516,1207,-3,0,10,1006,10,534,21101,0,0,-3,21202,-3,1,1,22101,0,-2,2,21102,1,1,3,21102,553,1,0,1106,0,558,109,-4,2106,0,0,109,5,1207,-3,1,10,1006,10,581,2207,-4,-2,10,1006,10,581,22102,1,-4,-4,1105,1,649,21202,-4,1,1,21201,-3,-1,2,21202,-2,2,3,21101,0,600,0,1105,1,558,21201,1,0,-4,21101,0,1,-1,2207,-4,-2,10,1006,10,619,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,641,22102,1,-1,1,21102,1,641,0,106,0,516,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0
diff --git a/day11/robot.sh b/day11/robot.sh
new file mode 100644 (file)
index 0000000..c5b5613
--- /dev/null
@@ -0,0 +1,149 @@
+#!/bin/bash
+
+set -u
+
+__robot_direction=u
+__robot_lowest_x=0
+__robot_lowest_y=0
+__robot_highest_x=0
+__robot_highest_y=0
+__robot_cur_x=0
+__robot_cur_y=0
+__robot_start_on_white=0
+declare -A __robot_grid
+declare -A __robot_painted
+
+reset_robot() {
+    __robot_direction=u
+    __robot_lowest_x=0
+    __robot_lowest_y=0
+    __robot_highest_x=0
+    __robot_highest_y=0
+    __robot_cur_x=0
+    __robot_cur_y=0
+    __robot_start_on_white=0
+    unset __robot_grid
+    unset __robot_painted
+    declare -g -A __robot_grid
+    declare -g -A __robot_painted
+}
+
+get_robot_paint_colour() {
+    get_paint_colour $__robot_cur_x $__robot_cur_y
+}
+
+get_paint_colour() {
+    x=$1
+    y=$2
+
+    if [ ${__robot_grid[$x,$y]+a} ]; then
+        echo ${__robot_grid[$x,$y]}
+    else
+        if [ $x -eq 0 ] && [ $y -eq 0 ] && [ $__start_on_white -eq 1 ]; then
+            echo 1
+        else
+            echo 0
+        fi
+    fi
+}
+
+set_robot_start_on_white() {
+    start=${1:-1}
+
+    __robot_start_on_white=$start
+}
+
+set_robot_paint_colour() {
+    paint_colour=$1
+
+    __robot_grid[$__robot_cur_x,$__robot_cur_y]=$paint_colour
+    if ! [ ${__robot_painted[$__robot_cur_x,$__robot_cur_y]+a} ]; then
+        __robot_painted[$__robot_cur_x,$__robot_cur_y]=1
+    fi
+}
+
+get_robot_paint_count() {
+    echo ${#__robot_painted[@]}
+}
+
+do_robot_move() {
+    direction=$1
+
+    case $direction in
+        0)
+            case $__robot_direction in
+                u)
+                    __robot_direction=l
+                    __robot_cur_x=$((__robot_cur_x - 1))
+                    ;;
+                l)
+                    __robot_direction=d
+                    __robot_cur_y=$((__robot_cur_y - 1))
+                    ;;
+                d)
+                    __robot_direction=r
+                    __robot_cur_x=$((__robot_cur_x + 1))
+                    ;;
+                r)
+                    __robot_direction=u
+                    __robot_cur_y=$((__robot_cur_y + 1))
+                    ;;
+            esac
+            ;;
+        1)
+            case $__robot_direction in
+                u)
+                    __robot_direction=r
+                    __robot_cur_x=$((__robot_cur_x + 1))
+                    ;;
+                r)
+                    __robot_direction=d
+                    __robot_cur_y=$((__robot_cur_y - 1))
+                    ;;
+                d)
+                    __robot_direction=l
+                    __robot_cur_x=$((__robot_cur_x - 1))
+                    ;;
+                l)
+                    __robot_direction=u
+                    __robot_cur_y=$((__robot_cur_y + 1))
+                    ;;
+            esac
+            ;;
+    esac
+
+    # adjust min/max
+    if [ $__robot_cur_x -lt $__robot_lowest_x ]; then
+        __robot_lowest_x=$__robot_cur_x
+    fi
+
+    if [ $__robot_cur_x -gt $__robot_highest_x ]; then
+        __robot_highest_x=$__robot_cur_x
+    fi
+
+    if [ $__robot_cur_y -lt $__robot_lowest_y ]; then
+        __robot_lowest_y=$__robot_cur_y
+    fi
+
+    if [ $__robot_cur_y -gt $__robot_highest_y ]; then
+        __robot_highest_y=$__robot_cur_y
+    fi
+}
+
+do_robot_paint_and_move() {
+    paint_colour=$1
+    direction=$2
+    set_robot_paint_colour $paint_colour
+    do_robot_move $direction
+}
+
+draw_panel() {
+    colours=("." "#")
+
+    for (( y=$__robot_lowest_y; y<=$__robot_highest_y; y++ )); do
+        for (( x=$__robot_lowest_x; x<=$__robot_highest_x; x++ )); do
+            echo -n ${colours[$(get_paint_colour $x $y)]}
+        done
+        echo
+    done
+}
diff --git a/day11/run.sh b/day11/run.sh
new file mode 100755 (executable)
index 0000000..353ce16
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+set -u
+
+exec 3<input.txt
+
+OLDIFS=$IFS
+IFS=","
+read -u 3 -a data
+IFS=$OLDIFS
+
+base_dir=$(dirname $(readlink -f $BASH_SOURCE))
+. computer.sh
+. robot.sh
+
+# start the computer as a coproc
+coproc computer (run_program data)
+
+while ( kill -0 $computer_PID >/dev/null 2>&1 ); do
+    get_robot_paint_colour >&${computer[1]}
+    read -u ${computer[0]} direction
+    read -u ${computer[0]} colour
+    do_robot_paint_and_move $direction $colour
+    sleep 0.1
+done
+
+# just incase the spinner is still about
+echo -n $'\r'"                "$'\r'
+
+# we've done all the painting, now lets display it
+draw_panel
+
+echo
+echo "Painted: $(get_robot_paint_count) panels at least once"
diff --git a/day11/run2.sh b/day11/run2.sh
new file mode 100755 (executable)
index 0000000..9520560
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+set -u
+set -e
+
+exec 3<input.txt
+
+OLDIFS=$IFS
+IFS=","
+read -u 3 -a data
+IFS=$OLDIFS
+
+base_dir=$(dirname $(readlink -f $BASH_SOURCE))
+. computer.sh
+. robot.sh
+
+# start the computer as a coproc
+coproc computer (run_program data)
+
+while ( kill -0 $computer_PID >/dev/null 2>&1 ); do
+    get_robot_paint_colour >&${computer[1]}
+    read -u ${computer[0]} direction
+    read -u ${computer[0]} colour
+    do_robot_paint_and_move $direction $colour
+    sleep 0.1
+done
+
+# just incase the spinner is still about
+echo -n $'\r'"                "$'\r'
+
+# we've done all the painting, now lets display it
+draw_panel
+
+echo
+echo "Painted: $(get_robot_paint_count) panels at least once"