From fcd5bcce0f3b80350ae94e4c93e86d1dcba9a592 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Wed, 14 Jul 2021 20:30:30 +0200 Subject: [PATCH] day18/2 bash --- day18/Makefile | 2 +- day18/OUTPUT | 8 ++- day18/README | 8 +-- day18/ex2.bash | 168 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 9 deletions(-) create mode 100755 day18/ex2.bash diff --git a/day18/Makefile b/day18/Makefile index 89f8614..a1d3261 100644 --- a/day18/Makefile +++ b/day18/Makefile @@ -8,7 +8,7 @@ export PATH := .:$(PATH) .PHONY: clean all compile deploy ex1 ex2 -all: ex1 +all: ex1 ex2 output: @$(MAKE) --no-print-directory all 2>&1 > OUTPUT diff --git a/day18/OUTPUT b/day18/OUTPUT index 8e2b673..5a84b39 100644 --- a/day18/OUTPUT +++ b/day18/OUTPUT @@ -1,4 +1,8 @@ ex1.bash : res=650217205854 - time: 0:01.73 real, 1.73 user, 0.00 sys - context-switch: 6+1, page-faults: 0+189 + time: 0:01.76 real, 1.74 user, 0.01 sys + context-switch: 5+1, page-faults: 0+188 + +ex2.bash : res=20394514442037 + time: 0:01.54 real, 1.53 user, 0.01 sys + context-switch: 42+1, page-faults: 0+196 diff --git a/day18/README b/day18/README index d08cc46..d9dc03a 100644 --- a/day18/README +++ b/day18/README @@ -36,8 +36,6 @@ Here are a few more examples: Before you can help with the homework, you need to understand it yourself. Evaluate the expression on each line of the homework; what is the sum of the resulting values? Your puzzle answer was 650217205854. - -The first half of this puzzle is complete! It provides one gold star: * --- Part Two --- You manage to answer the child's questions and they finish part 1 of their homework, but get stuck when they reach the next section: advanced math. @@ -63,8 +61,6 @@ Here are the other examples from above: What do you get if you add up the results of evaluating the homework problems using these new rules? -Answer: +Your puzzle answer was 20394514442037. -Although it hasn't changed, you can still get your puzzle input. - -You can also [Share] this puzzle. +Both parts of this puzzle are complete! They provide two gold stars: ** diff --git a/day18/ex2.bash b/day18/ex2.bash new file mode 100755 index 0000000..af1fb3b --- /dev/null +++ b/day18/ex2.bash @@ -0,0 +1,168 @@ +#!/bin/bash +# +# ex2.bash: Advent2020 game, day 18/game 2. + +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 getqueue() { + # shellcheck disable=2178 + local -n stack="$1" + local -n var="$2" + local pos="$3" + + var=${stack[$pos]} + unset 'stack[$pos]' + #stack=( "${stack[@]}" ) # DO NOT pack ! +} +function setqueue() { + local -n stack="$1" + local val="$2" + local pos="$3" + + stack[$pos]="$val" +} +function print_stack() { + # shellcheck disable=2178 + local -n stack="$1" + local k + printf "stack [%s:%d]: " "$1" "${#stack[@]}" + for k in "${!stack[@]}"; do + printf "%s:%s " "$k" "${stack[$k]}" + done + printf "\n" +} + +function eval_plus() { + local -n lvalop="$1" loptop="$2" + local -i v v1 v2 pos last="${#loptop[@]}" + + for ((pos=0; pos 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 + ((cur++)) + done + eval_plus lstack lop + eval_op lstack lop + + 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