day 21 part 1 (bash)

This commit is contained in:
2021-07-30 17:18:48 +02:00
parent 937c1b434b
commit 1db46ed0b0
3 changed files with 143 additions and 2 deletions

4
2020/day21/OUTPUT Normal file
View File

@@ -0,0 +1,4 @@
ex1.bash: res=2211
time: 0:25.09 real, 25.08 user, 0.01 sys
context-switch: 144+1, page-faults: 0+1133

View File

@@ -21,7 +21,25 @@ The first step is to determine which ingredients can't possibly contain any of t
Determine which ingredients cannot possibly contain any of the allergens in your list. How many times do any of those ingredients appear?
To begin, get your puzzle input.
Your puzzle answer was 2211.
The first half of this puzzle is complete! It provides one gold star: *
--- Part Two ---
Now that you've isolated the inert ingredients, you should have enough information to figure out which ingredient contains which allergen.
In the above example:
mxmxvkd contains dairy.
sqjhc contains fish.
fvjkl contains soy.
Arrange the ingredients alphabetically by their allergen and separate them by commas to produce your canonical dangerous ingredient list. (There should not be any spaces in your canonical dangerous ingredient list.) In the above example, this would be mxmxvkd,sqjhc,fvjkl.
Time to stock your raft with supplies. What is your canonical dangerous ingredient list?
Answer:
Although it hasn't changed, you can still get your puzzle input.
You can also [Share] this puzzle.

119
2020/day21/ex1.bash Executable file
View File

@@ -0,0 +1,119 @@
#!/bin/bash
#
# ex1.bash: Advent2020 game, day 21/game 1.
CMD=${0##*/}
shopt -s extglob
set -o noglob
declare -A I_COUNT=()
declare -A CANBE=() I A_RULES=() FOUND=() ALL_I=()
declare -a R
declare -i count=0
# intersect the words of 2 strings into $1
intersect() {
local -n _res="$1"
# shellcheck disable=SC2206
local -a _str1=($2) _str2=($3)
local _i _j
_res=""
for _i in "${_str1[@]}"; do
for _j in "${_str2[@]}"; do
[[ "$_i" == "$_j" ]] && _res+=" $_i"
done
done
_res="${_res##*( )}"
}
# count words in a string and put result in $1
count() {
local -n _res="$1"
# shellcheck disable=SC2206
local -a _str=($2)
_res=${#_str[@]}
}
# remove a word from a string and put result in $1
delw() {
local -n _res="$1"
local _w=$2
# shellcheck disable=SC2206
local -a _str=($3)
local _i
_res=""
for _i in "${_str[@]}"; do
[[ $_i != "$_w" ]] && _res+=" $_i"
done
_res="${_res##*( )}"
_res="${_res%%*( )}"
}
# add a word to string $1, if not already present
addw() {
local -n _s="$1"
# shellcheck disable=SC2206
local _reg="\b$2\b"
[[ "$_s" =~ $_reg ]] || _s+=" $2"
_s="${_s##*( )}"
}
REGEX="(.*) \(contains(.*)\)"
while read -r line; do
[[ "$line" =~ $REGEX ]]
ingr="${BASH_REMATCH[1]}"
all="${BASH_REMATCH[2]}"
all=${all//,}
R[$count]="$ingr"
for ka in $all; do
A_RULES[$ka]+=" $count"
for ki in $ingr; do
addw CANBE[$ka] "$ki"
ALL_I[$ki]="$ki"
done
done
for ki in $ingr; do
(( I_COUNT[$ki]++ ))
done
((count++))
done
declare -i solved=0 count
declare allerg allerg1 ingred
while ((solved==0)); do
solved=1
for allerg in "${!CANBE[@]}"; do
str="${CANBE[$allerg]}"
if [[ -v FOUND["$allerg"] ]]; then
continue
fi
for rule in ${A_RULES[$allerg]}; do
intersect str "${R[$rule]}" "$str"
done
CANBE[$allerg]="$str"
count count "$str"
((count > 1)) && solved=0
if ((count==1)); then
word=$str #{CANBE[$allerg]}
FOUND[$allerg]="${CANBE[$allerg]}"
unset ALL_I["${CANBE[$allerg]}"]
for allerg1 in "${!CANBE[@]}"; do
if [[ "$allerg" != "$allerg1" ]]; then
delw CANBE["$allerg1"] "$word" "${CANBE[$allerg1]}"
fi
done
for rule in "${!R[@]}"; do
delw R[$rule] "$word" "${R[$rule]}"
done
fi
done
done
res=0
for i in "${!ALL_I[@]}"; do
((res+=${I_COUNT[$i]}))
done
printf "%s: res=%d\n" "$CMD" "$res"
exit 0