Use read_opcode function
This commit is contained in:
@ -46,8 +46,8 @@ cdv () { # OPCODE 7
|
||||
REG_C=$(( REG_A / (2 ** OPERAND) ))
|
||||
}
|
||||
|
||||
# Get combo operand
|
||||
get_combo () {
|
||||
# Interpret operand value
|
||||
if [[ $OPERAND -eq 0 ]]
|
||||
then
|
||||
printf "$1"
|
||||
@ -76,6 +76,7 @@ get_combo () {
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the program is a quine
|
||||
check_quine () {
|
||||
for (( i=0; i<INPUT_LEN; i++ ))
|
||||
do
|
||||
@ -85,3 +86,42 @@ check_quine () {
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Interpret opcode
|
||||
read_opcode () {
|
||||
local OPCODE=$1
|
||||
local OPERAND=$2
|
||||
if [[ $OPCODE -eq 0 ]]
|
||||
then
|
||||
adv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 1 ]]
|
||||
then
|
||||
bxl "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 2 ]]
|
||||
then
|
||||
bst "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 3 ]]
|
||||
then
|
||||
# jnz itself moves the pointer
|
||||
jnz "$OPERAND"
|
||||
elif [[ $OPCODE -eq 4 ]]
|
||||
then
|
||||
bxc "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 5 ]]
|
||||
then
|
||||
out "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 6 ]]
|
||||
then
|
||||
bdv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 7 ]]
|
||||
then
|
||||
cdv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
fi
|
||||
}
|
||||
|
@ -23,39 +23,7 @@ while [[ $POINTER -lt $INPUT_LEN ]]
|
||||
do
|
||||
OPCODE=${INPUT[$POINTER]}
|
||||
OPERAND=${INPUT[$POINTER+1]}
|
||||
if [[ $OPCODE -eq 0 ]]
|
||||
then
|
||||
adv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 1 ]]
|
||||
then
|
||||
bxl "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 2 ]]
|
||||
then
|
||||
bst "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 3 ]]
|
||||
then
|
||||
# jnz itself moves the pointer
|
||||
jnz "$OPERAND"
|
||||
elif [[ $OPCODE -eq 4 ]]
|
||||
then
|
||||
bxc "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 5 ]]
|
||||
then
|
||||
out "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 6 ]]
|
||||
then
|
||||
bdv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 7 ]]
|
||||
then
|
||||
cdv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
fi
|
||||
read_opcode "$OPCODE" "$OPERAND"
|
||||
printf "Registers A : %s B: %s C : %s\n" "$REG_A" "$REG_B" "$REG_C" >&2
|
||||
printf "Pointer : %s\n" "$POINTER" >&2
|
||||
(( ITER-- ))
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
FILE=$1
|
||||
ITER=99
|
||||
DEBUG=false
|
||||
|
||||
REG_A=$(grep 'Register A:' "$FILE" | cut -f2 -d: )
|
||||
REG_B=$(grep 'Register B:' "$FILE" | cut -f2 -d: )
|
||||
@ -14,137 +15,17 @@ printf "Input : " >&2
|
||||
printf "%s " "${INPUT[@]}" >&2
|
||||
printf "\n" >&2
|
||||
|
||||
adv () { # OPCODE 0
|
||||
printf "OPCODE : 0 OP: adv OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$( get_combo "$1" )
|
||||
REG_A=$(( REG_A / (2 ** OPERAND) ))
|
||||
}
|
||||
bxl () { # OPCODE 1
|
||||
printf "OPCODE : 1 OP: bxl OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$1
|
||||
REG_B=$(( REG_B ^ OPERAND ))
|
||||
}
|
||||
bst () { # OPCODE 2
|
||||
printf "OPCODE : 2 OP: bst OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$( get_combo "$1" )
|
||||
REG_B=$(( OPERAND % 8 ))
|
||||
}
|
||||
jnz () { # OPCODE 3
|
||||
printf "OPCODE : 3 OP: jnz OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$1
|
||||
if [[ $REG_A -eq 0 ]]
|
||||
then
|
||||
return 0
|
||||
else
|
||||
POINTER=$OPERAND
|
||||
fi
|
||||
}
|
||||
bxc () { # OPCODE 4
|
||||
printf "OPCODE : 4 OP: bxc OPERAND: %s\n" "$1" >&2
|
||||
# OPERAND=$1 # Deprecated for legacy reasons
|
||||
REG_B=$(( REG_B ^ REG_C ))
|
||||
}
|
||||
out () { # OPCODE 5
|
||||
printf "OPCODE : 5 OP: out OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$( get_combo "$1" )
|
||||
printf "%s\n" "$(( OPERAND % 8 ))"
|
||||
}
|
||||
bdv () { # OPCODE 6
|
||||
printf "OPCODE : 6 OP: bdv OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$( get_combo "$1" )
|
||||
REG_B=$(( REG_A / (2 ** OPERAND) ))
|
||||
}
|
||||
cdv () { # OPCODE 7
|
||||
printf "OPCODE : 7 OP: cdv OPERAND: %s\n" "$1" >&2
|
||||
OPERAND=$( get_combo "$1" )
|
||||
REG_C=$(( REG_A / (2 ** OPERAND) ))
|
||||
}
|
||||
# Load machine operations
|
||||
. machine.sh
|
||||
|
||||
get_combo () {
|
||||
# Interpret operand value
|
||||
if [[ $OPERAND -eq 0 ]]
|
||||
then
|
||||
printf "$1"
|
||||
elif [[ $OPERAND -eq 1 ]]
|
||||
then
|
||||
printf "$1"
|
||||
elif [[ $OPERAND -eq 2 ]]
|
||||
then
|
||||
printf "$1"
|
||||
elif [[ $OPERAND -eq 3 ]]
|
||||
then
|
||||
printf "$1"
|
||||
elif [[ $OPERAND -eq 4 ]]
|
||||
then
|
||||
printf "%s" "$REG_A"
|
||||
elif [[ $OPERAND -eq 5 ]]
|
||||
then
|
||||
printf "%s" "$REG_B"
|
||||
elif [[ $OPERAND -eq 6 ]]
|
||||
then
|
||||
printf "%s" "$REG_C"
|
||||
elif [[ $OPERAND -eq 7 ]]
|
||||
then
|
||||
printf "Reserved operand. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_quine () {
|
||||
for (( i=0; i<INPUT_LEN; i++ ))
|
||||
do
|
||||
if [[ ${INPUT[$i]} != "${OUTPUT[$i]}" ]]
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
while ! check_quine
|
||||
POINTER=0
|
||||
while [[ $POINTER -lt $INPUT_LEN ]]
|
||||
do
|
||||
read -r -a OUTPUT <<<"$(
|
||||
POINTER=0
|
||||
while [[ $POINTER -lt $INPUT_LEN ]]
|
||||
do
|
||||
OPCODE=${INPUT[$POINTER]}
|
||||
OPERAND=${INPUT[$POINTER+1]}
|
||||
if [[ $OPCODE -eq 0 ]]
|
||||
then
|
||||
adv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 1 ]]
|
||||
then
|
||||
bxl "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 2 ]]
|
||||
then
|
||||
bst "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 3 ]]
|
||||
then
|
||||
# jnz itself moves the pointer
|
||||
jnz "$OPERAND"
|
||||
elif [[ $OPCODE -eq 4 ]]
|
||||
then
|
||||
bxc "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 5 ]]
|
||||
then
|
||||
out "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 6 ]]
|
||||
then
|
||||
bdv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
elif [[ $OPCODE -eq 7 ]]
|
||||
then
|
||||
cdv "$OPERAND"
|
||||
(( POINTER+=2 ))
|
||||
fi
|
||||
printf "Registers A : %s B: %s C : %s\n" "$REG_A" "$REG_B" "$REG_C" >&2
|
||||
printf "Pointer : %s\n" "$POINTER" >&2
|
||||
(( ITER-- ))
|
||||
if [[ $ITER -eq 0 ]] ; then break ;fi
|
||||
done | paste -s -d ","
|
||||
)"
|
||||
done
|
||||
OPCODE=${INPUT[$POINTER]}
|
||||
OPERAND=${INPUT[$POINTER+1]}
|
||||
read_opcode "$OPCODE" "$OPERAND"
|
||||
printf "Registers A : %s B: %s C : %s\n" "$REG_A" "$REG_B" "$REG_C" >&2
|
||||
printf "Pointer : %s\n" "$POINTER" >&2
|
||||
(( ITER-- ))
|
||||
if [[ $ITER -eq 0 ]] ; then break ;fi
|
||||
done | paste -s -d ","
|
||||
|
Reference in New Issue
Block a user