diff --git a/day19/Makefile b/day19/Makefile new file mode 100644 index 0000000..224acfb --- /dev/null +++ b/day19/Makefile @@ -0,0 +1,30 @@ +INPUT := INPUT.txt +SHELL := /bin/bash +CFLAGS := -w -g +#CFLAGS := -w -g -pg +#CFLAGS := -w -O3 +TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n" +export PATH := .:$(PATH) + +.PHONY: clean all compile deploy ex1 ex2 + +all: ex1 ex2 + +output: + @$(MAKE) --no-print-directory all 2>&1 > OUTPUT + +compile: ex1-c ex2-c + +ex1: + @$(TIME) ex1.bash < $(INPUT) 2>&1 + @#$(TIME) ex1-c 2020 < $(INPUT) 2>&1 + +ex2: + @$(TIME) ex2.bash < $(INPUT) 2>&1 + @#$(TIME) ex1-c 30000000 < $(INPUT) 2>&1 + +clean: + @rm -f ex1-c ex2-c core + +deploy: + @$(MAKE) -C .. deploy diff --git a/day19/ex1.bash b/day19/ex1.bash new file mode 100755 index 0000000..cceb2fe --- /dev/null +++ b/day19/ex1.bash @@ -0,0 +1,63 @@ +#!/bin/bash +# +# ex1.bash: Advent2020 game, day 19/game 1. + +CMD=${0##*/} +set -o noglob +shopt -s extglob + +declare -a RULE=() MATCH=() STRING=() +# shellcheck disable=SC2034 +declare var_0 +declare -i res=0 + +# build a regexp use-able by bash =~ operator. +# Recursively replace rules, until we get final text values. +# To avoid running subshell, we must create local variables w/ different +# names at each recursion level (to avoid "circular name reference" error). +function buildtree { + local -i prof="$1" # to allow ≠ local names + local -n upname="$2" # caller variable name + local name="var_$prof" # local var name, w/ depth + eval "local $name" # ... declared here + shift 2 + local args=$* res="" arg + + for arg in $args; do + if [[ -z "${arg/[|ab]}" ]]; then + res+="$arg" + else + if [[ ! -v MATCH[$arg] ]]; then + buildtree "$((prof+1))" "$name" "${RULE[$arg]}" + MATCH[$arg]="(${!name})" + fi + res+=${MATCH[$arg]} + fi + done + # shellcheck disable=SC2034 + upname="$res" +} + +while read -r line; do + case ${line:0:1} in + [0-9]*) # rule + rule=${line%:*} + val=${line#*: } + RULE[$rule]="${val//\"}" + ;; + [a-z]*) # string + STRING+=("$line") + ;; + esac +done + +buildtree 1 var_0 0 +#printf "RULE ZERO = %s\n" "${MATCH[0]}" + +for str in "${STRING[@]}"; do + [[ "$str" =~ ^${MATCH[0]}$ ]] && ((res++)) +done + +printf "%s : res=%d\n" "$CMD" "$res" + +exit 0