From: Brett Parker Date: Thu, 10 Dec 2020 02:11:48 +0000 (+0000) Subject: Day 13 2019 X-Git-Url: https://git.sommitrealweird.co.uk/advent-of-code-2019.git/commitdiff_plain/79304811c66e5ce6d4898a33dd8f4799a5d1c5d3 Day 13 2019 - Don't rely on the prompt from "read -p", it doesn't display on non-interactive sessions, so we can't easily work out what's going on - Add exit with high score incase we didn't clear the blocks --- diff --git a/day13/computer.sh b/day13/computer.sh new file mode 100644 index 0000000..1e9c60e --- /dev/null +++ b/day13/computer.sh @@ -0,0 +1,152 @@ +#!/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 + echo "input: " + read input + input=${input//\n/} + input=${input//\r/} + echo >&2 + echo "$instruction: '$input'" >&2 + echo >&2 + 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) + echo >&2 + echo "$instruction: '$val1' '$val2'" >&2 + echo >&2 + 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' >&2 +} + diff --git a/day13/input.txt b/day13/input.txt new file mode 100644 index 0000000..a9a41da --- /dev/null +++ b/day13/input.txt @@ -0,0 +1 @@ +1,380,379,385,1008,2399,462045,381,1005,381,12,99,109,2400,1102,0,1,383,1101,0,0,382,20101,0,382,1,21001,383,0,2,21102,37,1,0,1105,1,578,4,382,4,383,204,1,1001,382,1,382,1007,382,44,381,1005,381,22,1001,383,1,383,1007,383,20,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1102,-1,1,384,1106,0,119,1007,392,42,381,1006,381,161,1101,0,1,384,21002,392,1,1,21101,0,18,2,21102,1,0,3,21101,138,0,0,1105,1,549,1,392,384,392,21002,392,1,1,21102,1,18,2,21102,3,1,3,21101,0,161,0,1106,0,549,1101,0,0,384,20001,388,390,1,20101,0,389,2,21102,1,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,21002,389,1,2,21102,1,205,0,1105,1,393,1002,390,-1,390,1102,1,1,384,20101,0,388,1,20001,389,391,2,21102,228,1,0,1105,1,578,1206,1,261,1208,1,2,381,1006,381,253,21002,388,1,1,20001,389,391,2,21102,253,1,0,1105,1,393,1002,391,-1,391,1101,1,0,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,279,0,0,1106,0,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21102,304,1,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1102,1,1,384,1005,384,161,21002,388,1,1,21002,389,1,2,21101,0,0,3,21101,0,338,0,1105,1,549,1,388,390,388,1,389,391,389,20101,0,388,1,20101,0,389,2,21102,1,4,3,21102,1,365,0,1106,0,549,1007,389,19,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,318,20,15,1,1,22,109,3,22101,0,-2,1,21202,-1,1,2,21102,1,0,3,21102,1,414,0,1106,0,549,21201,-2,0,1,22102,1,-1,2,21101,429,0,0,1106,0,601,2101,0,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2105,1,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22101,0,-3,-7,109,-8,2106,0,0,109,4,1202,-2,44,566,201,-3,566,566,101,639,566,566,1201,-1,0,0,204,-3,204,-2,204,-1,109,-4,2106,0,0,109,3,1202,-1,44,593,201,-2,593,593,101,639,593,593,21002,0,1,-2,109,-3,2105,1,0,109,3,22102,20,-2,1,22201,1,-1,1,21102,443,1,2,21101,114,0,3,21102,1,880,4,21102,1,630,0,1106,0,456,21201,1,1519,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,2,2,0,2,2,2,2,2,0,2,2,2,0,0,0,2,2,2,2,2,2,0,2,2,0,0,2,2,2,0,2,2,2,2,0,0,2,0,2,2,0,1,1,0,2,2,0,2,2,2,2,2,0,2,2,0,2,2,2,0,0,0,2,0,2,2,0,0,2,2,2,0,2,2,2,2,2,0,2,0,0,2,2,0,0,1,1,0,2,2,0,2,2,2,2,2,2,0,2,2,2,2,0,2,2,0,0,2,0,0,0,2,0,0,2,2,2,2,2,0,2,2,0,2,2,2,0,2,0,1,1,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,0,0,2,2,2,0,2,2,2,0,2,2,0,0,0,2,2,2,2,2,2,0,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,0,2,0,2,2,0,2,0,2,0,2,0,2,2,2,0,2,0,0,0,2,0,2,2,0,0,2,2,2,2,2,0,2,0,1,1,0,0,2,2,2,2,2,2,2,2,0,2,2,0,0,2,0,2,0,2,0,0,2,2,0,0,2,2,0,0,0,2,0,2,0,2,2,2,0,2,2,0,1,1,0,0,0,0,0,0,2,0,2,0,0,2,2,0,2,2,0,0,2,0,0,2,2,2,2,2,2,2,2,0,2,2,0,0,0,2,2,2,2,2,2,0,1,1,0,0,2,2,2,2,0,0,0,0,2,0,0,2,2,0,2,2,2,2,2,2,0,2,2,2,0,2,2,2,0,2,2,2,2,2,2,0,2,0,2,0,1,1,0,2,0,2,2,2,2,2,0,0,2,2,2,2,2,0,2,2,2,2,2,2,0,2,0,0,0,2,2,0,2,0,0,2,0,2,2,2,2,2,2,0,1,1,0,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,0,2,2,2,2,2,2,0,2,2,2,2,2,2,0,0,0,2,2,0,2,0,1,1,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,0,2,0,2,2,0,2,2,0,2,2,2,0,2,2,0,0,2,0,2,0,2,2,0,0,1,1,0,0,2,2,2,2,0,2,0,2,2,0,2,2,2,2,2,2,0,2,0,0,0,0,2,0,2,2,2,2,2,0,0,2,0,2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,56,72,33,24,73,85,29,45,48,12,58,96,32,17,48,17,9,49,78,6,48,98,91,23,28,37,16,54,30,88,69,69,23,59,33,61,89,94,79,64,42,13,82,45,98,57,57,80,6,2,67,86,26,84,80,47,72,38,22,73,75,4,3,47,96,34,52,22,26,90,74,84,37,68,37,73,86,59,27,67,52,22,63,92,41,46,68,93,55,3,6,78,32,82,8,34,41,77,29,92,77,81,17,90,40,50,27,80,82,96,66,21,67,96,69,12,39,65,93,7,91,97,55,95,64,9,91,48,23,44,96,67,38,43,26,70,64,17,47,98,35,54,89,31,67,18,36,42,52,19,71,4,47,21,43,77,6,64,45,94,49,52,54,85,9,78,73,44,56,3,37,15,45,16,78,98,82,27,59,13,26,75,73,18,74,20,63,65,56,55,98,34,10,97,55,70,51,25,9,16,10,79,49,58,13,92,19,25,79,33,48,5,78,86,94,48,39,3,43,90,35,45,56,60,51,92,4,52,64,63,18,70,44,82,70,29,72,53,91,36,75,95,57,61,42,79,98,26,8,73,10,3,69,95,69,39,13,70,90,66,96,97,21,35,38,43,21,79,91,5,92,93,48,25,31,15,39,58,51,68,46,93,10,56,16,5,54,34,54,68,22,97,18,14,96,52,92,62,62,62,43,62,73,41,85,36,81,81,1,41,92,94,78,32,72,15,30,54,86,1,60,28,20,94,15,52,60,68,63,15,45,39,66,65,42,35,28,31,83,59,87,69,83,22,58,45,22,70,86,98,44,13,37,24,67,80,7,67,16,10,88,54,60,76,97,37,63,31,61,91,10,61,97,76,59,40,28,15,45,50,86,61,30,11,85,87,53,10,88,40,69,82,60,57,38,74,35,44,33,98,80,47,3,51,56,12,28,86,26,91,45,10,92,18,63,4,66,47,73,18,57,51,32,79,25,41,61,68,78,34,71,3,33,29,40,25,15,72,88,51,20,76,70,10,20,38,13,27,92,97,60,22,54,73,20,51,27,87,51,41,73,61,1,31,94,11,74,56,34,9,74,31,20,91,63,75,1,54,62,31,30,60,74,67,13,83,65,10,63,38,65,75,94,85,98,53,59,63,42,21,93,13,55,36,76,53,14,30,71,2,84,16,82,87,57,74,57,29,48,14,73,4,22,91,81,94,41,67,27,82,20,4,89,43,92,36,70,29,45,82,65,49,2,63,78,18,13,75,76,50,85,64,37,4,57,41,18,15,65,70,44,85,72,11,36,35,84,4,70,49,47,20,10,80,79,59,89,1,87,5,22,87,31,23,38,35,49,71,33,46,81,64,43,59,46,51,62,33,89,61,66,64,92,23,30,56,17,71,85,18,2,72,2,42,31,13,53,35,17,91,73,73,48,95,20,26,23,10,65,4,40,6,79,49,84,7,15,49,90,45,24,42,76,21,97,3,63,42,30,92,55,38,44,53,67,44,42,36,28,9,17,66,92,44,51,55,57,59,6,50,52,97,21,45,19,17,21,76,86,32,23,56,78,93,97,13,93,87,32,83,89,23,21,63,40,87,83,95,95,74,57,60,82,48,45,18,93,63,74,31,30,43,50,28,69,60,43,81,86,67,64,17,67,27,79,49,92,21,71,59,32,83,29,72,3,62,47,95,76,63,32,53,32,28,75,50,22,37,43,20,10,13,80,80,19,43,55,23,14,70,32,80,4,44,4,40,35,44,55,41,68,80,68,25,27,97,39,30,24,42,52,88,87,36,23,83,58,50,85,60,97,72,97,51,37,83,40,59,52,25,83,8,76,14,20,94,43,45,75,47,12,67,46,56,30,74,1,28,41,42,74,21,36,22,80,69,23,12,62,25,39,77,8,46,56,64,43,34,8,54,85,43,20,84,24,13,64,92,68,7,61,49,46,16,87,54,24,94,70,63,63,33,43,30,29,34,22,23,98,20,90,14,77,27,89,39,13,3,77,47,462045 diff --git a/day13/run.sh b/day13/run.sh new file mode 100755 index 0000000..8c8a139 --- /dev/null +++ b/day13/run.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +exec 3/dev/null | arcade_screen diff --git a/day13/run2.sh b/day13/run2.sh new file mode 100755 index 0000000..daccab3 --- /dev/null +++ b/day13/run2.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +exec 3output.txt + +basedir=$(dirname $(readlink -f ${BASH_SOURCE})) + +. $basedir/computer.sh +. $basedir/screen.sh + +instructions[0]=2 + +coproc computer (run_program instructions 2>computer_output.txt) + +comp_pid=${computer_PID} +comp_stdin=${computer[1]} +comp_stdout=${computer[0]} + +paddle_x=0 +paddle_y=0 +ball_x=0 +ball_y=0 +ball_dir_left=-2 +ball_dir_up=0 +ball_started=-1 +where_paddle_should_be_x=0 + +get_joystick_direction() { + if [ $ball_dir_left -eq -2 ]; then + echo "0" + return + fi + + if [ $paddle_x -lt $ball_x ]; then + paddle_dir=1 + elif [ $paddle_x -gt $ball_x ]; then + paddle_dir=-1 + elif [ $paddle_x -eq $ball_x ]; then + paddle_dir=0 + fi + + echo "Where we think the paddle should be: $where_ball_will_be_on_paddle_line" >&4 + echo "Where we are: $paddle_x,$paddle_y" >&4 + echo "Where the ball is: $ball_x, $ball_y" >&4 + echo "Direction of ball: $ball_dir_left,$ball_dir_up" >&4 + echo "Direction of paddle: $paddle_dir" >&4 + + echo "$paddle_dir" +} + +update_paddle_pos() { + paddle_x=$1 + paddle_y=$2 +} + +update_ball_pos() { + local x=$1 + local y=$2 + + # work out if we're going up or down + # left or right + if [ $x -gt $ball_x ]; then + ball_dir_left=1 + elif [ $x -lt $ball_x ]; then + ball_dir_left=-1 + else + ball_dir_left=0 + fi + + if [ $y -gt $ball_y ]; then + ball_dir_up=1 + elif [ $y -lt $ball_y ]; then + ball_dir_up=-1 + else + ball_dir_up=0 + fi + + ball_x=$x + ball_y=$y +} + +arcade_screen_init + +while ps -p $comp_pid >/dev/null 2>/dev/null; do + read -u $comp_stdout x || break + if [ $x == "input:" ]; then + echo "$(get_joystick_direction)" >&$comp_stdin + continue # go back to main loop + fi + echo "x: '$x'" >&4 + if [ "x$x" == "xinput: " ]; then + continue + fi + read -u $comp_stdout y || break + echo "y: '$y'" >&4 + read -u $comp_stdout z || break + echo "z: '$z'" >&4 + + case $z in + 3) + update_paddle_pos $x $y + ;; + 4) + update_ball_pos $x $y + ;; + esac + + if [ $x -eq -1 ]; then + update_score_board $z + continue + fi + arcade_screen_update $x $y $z +done + +arcade_screen_finish diff --git a/day13/screen.sh b/day13/screen.sh new file mode 100644 index 0000000..3bc3956 --- /dev/null +++ b/day13/screen.sh @@ -0,0 +1,140 @@ +__arcade_score=0 + +clear_screen() { + echo -en '\033[2J' +} + +move_cursor() { + local x=$1 + local y=$2 + + # program assumes 0 based, we're 1 based, apparently + x=$((x+1)) + y=$((y+1)) + + echo -en '\033['$y';'$x'f' +} + +draw_tile() { + local tile_type=$1 + + case $tile_type in + 0) + # blank + echo -n ' ' + ;; + 1) + # wall + echo -n '|' + ;; + 2) + # block + echo -n '#' + ;; + 3) + # horizontal paddle + echo -n '=' + ;; + 4) + # ball + echo -n 'o' + ;; + esac +} + +hide_cursor() { + tput civis +} + +show_cursor() { + tput cvvis +} + +draw_score_board() { + local value=${1:-0} + local scoreboard_y=20 + local scoreboard_width=43 + move_cursor 0 $scoreboard_y + printf "+" + printf "%.0s-" {1..42} + printf "+\n" + printf "|" + printf "%.0s " {1..42} + printf "|\n" + printf "+" + printf "%.0s-" {1..42} + printf "+\n" + update_score_board +} + +update_score_board() { + local value=${1:-$__arcade_score} + move_cursor 2 21 + if [ $value -gt 0 ]; then + __arcade_score=$value + fi + printf '% 40d' $value +} + +arcade_screen_init() { + clear_screen + hide_cursor + draw_score_board +} + +arcade_screen_update() { + local x=$1 + local y=$2 + local tile=$3 + + move_cursor $x $y + draw_tile $tile +} + +arcade_screen_finish() { + move_cursor 0 23 + show_cursor + echo high score: $__arcade_score +} + +arcade_screen() { + local max_y=0 + local max_x=0 + local -A blocks + + # first, clear the screen and hide the cursor + clear_screen + hide_cursor + + draw_score_board + + while read x; do + read y + read tile + if [ $x -gt $max_x ]; then + max_x=$x + fi + if [ $y -gt $max_y ]; then + max_y=$y + fi + move_cursor $x $y + draw_tile $tile + + case $tile in + 0) + if [ ${blocks[$x,$y]+a} ]; then + unset blocks[$x,$y] + fi + ;; + 2) + blocks[$x,$y]=1 + ;; + esac + done + + move_cursor 0 $((max_y+4)) + echo "We have ${#blocks[@]} blocks on the screen" + echo "The maximum x was $max_x" + echo "The maximum y was $max_y" + show_cursor +}