rename repo, subdir for yearly challenges
This commit is contained in:
121
2020/day18/ex1.bash
Executable file
121
2020/day18/ex1.bash
Executable file
@@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# ex1.bash: Advent2020 game, day 18/game 1.
|
||||
|
||||
CMD=${0##*/}
|
||||
set -o noglob
|
||||
|
||||
# shellcheck disable=2034
|
||||
declare -a STACK=()
|
||||
declare -a LINE=()
|
||||
|
||||
function enqueue() {
|
||||
local -n stack="$1"
|
||||
local var="$2"
|
||||
stack=("$var" "${stack[@]}")
|
||||
}
|
||||
function dequeue() {
|
||||
# shellcheck disable=2178
|
||||
local -n stack="$1"
|
||||
local -n var="$2"
|
||||
local last=$((${#stack[@]} - 1))
|
||||
var=${stack[$last]}
|
||||
unset 'stack[$last]'
|
||||
stack=( "${stack[@]}" ) # pack
|
||||
}
|
||||
function eval_op() {
|
||||
# shellcheck disable=2034
|
||||
local -n lvalop="$1" loptop="$2"
|
||||
# shellcheck disable=2034
|
||||
local v v1 v2 op res=-1
|
||||
while ((${#lvalop[@]} > 1)); do
|
||||
dequeue lvalop v1
|
||||
dequeue lvalop v2
|
||||
dequeue loptop op
|
||||
# shellcheck disable=SC1102
|
||||
v=$((v1 "$op" v2))
|
||||
enqueue lvalop "$v"
|
||||
((res++))
|
||||
done
|
||||
return "$res"
|
||||
}
|
||||
|
||||
function find_paren() {
|
||||
local -n expr_="$1"
|
||||
local -n var_="$2"
|
||||
local -i i
|
||||
local k val
|
||||
var_=-1
|
||||
for k in "${!expr_[@]}"; do
|
||||
val=${expr_[$k]}
|
||||
[[ $val == '(' ]] && i="$k"
|
||||
if [[ $val == ')' ]]; then
|
||||
# shellcheck disable=SC2034
|
||||
var_="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function eval_expr() {
|
||||
local -i cur="$2" val len=${#LINE[@]}
|
||||
local op
|
||||
# shellcheck disable=SC2034
|
||||
local -a lstack=() lop=() LINE_=()
|
||||
|
||||
while ((cur < len)); do
|
||||
symbol=${LINE[$cur]}
|
||||
case "$symbol" in
|
||||
[0-9]*)
|
||||
enqueue lstack "${LINE[$cur]}"
|
||||
unset 'LINE[$cur]'
|
||||
;;
|
||||
\))
|
||||
break
|
||||
;;
|
||||
[\+\*]*)
|
||||
enqueue lop "${LINE[$cur]}"
|
||||
unset 'LINE[$cur]'
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
eval_op lstack lop
|
||||
|
||||
((cur++))
|
||||
done
|
||||
dequeue lstack val
|
||||
LINE[$cur]="$val"
|
||||
LINE=("${LINE[@]}") # pack
|
||||
}
|
||||
|
||||
declare -i res=0 paren=0
|
||||
|
||||
while read -r line; do
|
||||
# cleanup input line, force split around operators and parens
|
||||
line=${line//\*/ * }
|
||||
line=${line//+/ + }
|
||||
line=${line//-/ - }
|
||||
line=${line//\// \/ }
|
||||
line=${line//\(/ \( }
|
||||
line=${line//\)/ \) }
|
||||
read -ra LINE <<< "$line"
|
||||
paren=0
|
||||
while ((${#LINE[@]} > 1 && paren >= 0)); do
|
||||
find_paren LINE paren
|
||||
if (( paren >= 0 )); then
|
||||
unset 'LINE[$paren]'
|
||||
LINE=("${LINE[@]}") # pack
|
||||
eval_expr STACK "$paren"
|
||||
fi
|
||||
done
|
||||
if ((${#LINE[@]} > 1)); then
|
||||
eval_expr STACK 0
|
||||
fi
|
||||
((res+=LINE[0]))
|
||||
done
|
||||
|
||||
printf "%s : res=%d\n" "$CMD" "$res"
|
||||
|
||||
exit 0
|
Reference in New Issue
Block a user