From 1db46ed0b066408d81dbf6579da2ad26f3a8f6e9 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Fri, 30 Jul 2021 17:18:48 +0200 Subject: [PATCH] day 21 part 1 (bash) --- 2020/day21/OUTPUT | 4 ++ 2020/day21/README | 22 +++++++- 2020/day21/ex1.bash | 119 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 2020/day21/OUTPUT create mode 100755 2020/day21/ex1.bash diff --git a/2020/day21/OUTPUT b/2020/day21/OUTPUT new file mode 100644 index 0000000..f5bef5c --- /dev/null +++ b/2020/day21/OUTPUT @@ -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 + diff --git a/2020/day21/README b/2020/day21/README index 2a54841..19ca46a 100644 --- a/2020/day21/README +++ b/2020/day21/README @@ -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: -You can also [Share] this puzzle. \ No newline at end of file + +Although it hasn't changed, you can still get your puzzle input. + +You can also [Share] this puzzle. diff --git a/2020/day21/ex1.bash b/2020/day21/ex1.bash new file mode 100755 index 0000000..1e87efd --- /dev/null +++ b/2020/day21/ex1.bash @@ -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