Skip to content

Instantly share code, notes, and snippets.

@rhowe
Created December 17, 2019 07:38
Show Gist options
  • Save rhowe/42c8047c0a6703ca94d1bbc96bbf6bc8 to your computer and use it in GitHub Desktop.
Save rhowe/42c8047c0a6703ca94d1bbc96bbf6bc8 to your computer and use it in GitHub Desktop.
AOC2019day17part1
#!/bin/bash -eu
getloc() {
case $1 in
0) echo "$2" ;;
1) echo "Can't get location of immediate value" >&2 && exit 1 ;;
2) echo "$((rb + $2))" ;;
esac
}
getval() {
case $1 in
0) echo "${ram[$2]}" ;;
1) echo "$2" ;;
2) echo "${ram[rb+$2]}" ;;
esac
}
printinstr() {
local instr=$1 ; shift
while [ $# -gt 0 ]; do
case "$1" in
0) instr="$instr [$2]" ;;
1) instr="$instr $2" ;;
2) instr="$instr [$2 + rb($rb)]" ;;
esac
shift 2
done
echo "$0 $instr"
}
add() { ram[$(getloc "$5" "$6")]=$(($(getval "$1" "$2") + $(getval "$3" "$4"))) ; }
mul() { ram[$(getloc "$5" "$6")]=$(($(getval "$1" "$2") * $(getval "$3" "$4"))) ; }
cmpl() { ram[$(getloc "$5" "$6")]=$(($(getval "$1" "$2") < $(getval "$3" "$4") ? 1 : 0 )) ; }
cmpe() { ram[$(getloc "$5" "$6")]=$(($(getval "$1" "$2") == $(getval "$3" "$4") ? 1 : 0 )) ; }
jmpt() { [ "$(getval "$1" "$2")" -eq 0 ] || pc=$(getval "$3" "$4") ; }
jmpf() { [ "$(getval "$1" "$2")" -ne 0 ] || pc=$(getval "$3" "$4") ; }
addrb() { ((rb+=$(getval "$1" "$2"))) ; }
outb() { getval "$1" "$2" ; }
inb() { ram[$(getloc "$1" "$2")]=$(<inputfile) ; }
bdb() {
local ramcopy=("${ram[@]}")
ramcopy[pc]="$(tput setaf 10)${ramcopy[pc]}$(tput setaf 15)<"
bdbout=$(
echo -e "$0\t$pc/$rb\t$(seq 0 15 | xargs | tr \ \\t)"
for addr in $(seq 0 16 "${#ramcopy[@]}"); do
echo "$0 $addr: ${ramcopy[*]:addr:16}" | tr \ \\t
done)
echo "$bdbout" >&2
}
run() {
local -ai program ram
IFS=, read -r -a program < "$1"
shift
inputs=("$@")
[ -z "${DEBUG:-}" ] || echo "$0: program start: ${inputs[*]}" >&2
ram=("${program[@]}" $(yes 0|head -n 128))
declare -i pc=0 rb=0
while : ; do
[ "${DEBUG:-}" != 2 ] || bdb
local opcode opfunc
local -i argc args=()
printf -v opcode %05d "${ram[pc++]}"
case "${opcode: -2:2}" in
01) opfunc=add argc=3 ;;
02) opfunc=mul argc=3 ;;
03) opfunc=inb argc=1 ;;
04) opfunc=outb argc=1 ;;
05) opfunc=jmpt argc=2 ;;
06) opfunc=jmpf argc=2 ;;
07) opfunc=cmpl argc=3 ;;
08) opfunc=cmpe argc=3 ;;
09) opfunc=addrb argc=1 ;;
99) break ;;
*)
echo "Unknown opcode $opcode at $((pc-1))" >&2
return 1
;;
esac
for ((arg=0; arg < argc; arg++)); do
args+=("${opcode: -3-arg:1}" "${ram[@]:pc++:1}")
done
[ -z "${DEBUG:-}" ] || printinstr "$opfunc" "${args[@]}" >&2
"$opfunc" "${args[@]}"
done
}
readonly -f add mul inb outb jmpt jmpf cmpl cmpe addrb run bdb getval getloc printinstr
export -f add mul inb outb jmpt jmpf cmpl cmpe addrb run bdb getval getloc printinstr
draw() {
while true; do
read -r char
printf \\x$(printf %x $char)
done
}
run "$@" | draw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment