Files
advent-of-code/day04/ex2.bash

126 lines
2.7 KiB
Bash
Executable File

#!/bin/bash
#
# ex2.bash: Advent2020 game, day 4/game 2.
CMD=${0##*/}
shopt -s extglob
declare -A KEYS=( ["byr"]="" ["iyr"]="" ["eyr"]="" ["hgt"]="" ["hcl"]="" ["ecl"]=""
["pid"]="" ["cid"]="" )
NKEYS=${#KEYS[@]}
function reset_array() { # reset array values
local -n array=${1}
local key
#echo before reset: ${KEYS[@]}
for key in "${!array[@]}"; do
array[$key]=""
done
#echo after reset: ${KEYS[@]}
}
# returns 1 if $1 length is $2
function check_length() {
return $((${#1} != $2))
}
function check_digits() {
[[ "$1" =~ ^[[:digit:]]+$ ]] && return 0 || return 1
}
# returns 1 if $1 is between $2 and $3
function check_range() {
(($1 >= $2 && $1 <= $3)) && return 0 || return 1
}
declare -A COLORS=( ["amb"]="" ["blu"]="" ["brn"]="" ["gry"]=""
["grn"]="" ["hzl"]="" ["oth"]="" )
function check_eye() {
[[ -v COLORS["$1"] ]] && return 0 || return 1
}
function check_height() {
local -i ret=1
local val="$1" unit=${val: -2}
local num=${val%%$unit}
#printf "unit=%s hgt=%s\n" "$unit" "$num"
case "$unit" in
"cm") check_digits "$num" && check_range "$num" 150 193 && ret=0
;;
"in") check_digits "$num" && check_range "$num" 59 76 && ret=0
;;
esac
return $ret
}
function check_hair() {
[[ "$1" =~ ^#[a-f0-9]{6}$ ]] && return 0 || return 1
}
function check_key() {
local -i valid=0
local key="$1" val="${KEYS[$key]}"
#printf "KEY/VAL = %s=[%s]\n" "$key" "$val"
case "$key" in
cid) valid=1
;;
byr) check_digits "$val" &&
check_length "$val" 4 &&
check_range "$val" 1920 2002 && valid=1
;;
iyr) check_digits "$val" &&
check_length "$val" 4 &&
check_range "$val" 2010 2020 && valid=1
;;
eyr) check_digits "$val" &&
check_length "$val" 4 &&
check_range "$val" 2020 2030 && valid=1
;;
pid) check_digits "$val" &&
check_length "$val" 9 && valid=1
;;
ecl) check_eye "$val" && valid=1
;;
hcl) check_hair "$val" && valid=1
;;
hgt) check_height "$val" && valid=1
;;
# TODO
*) valid=1
;;
esac
#printf "%s=[%s] : valid=%d\n" "$key" "$val" $valid
#[[ ! $key == "cid" ]] && [[ -z ${KEYS[$key]} ]] && valid=0 && break
return $valid
}
function passport_valid() {
local -i ret=0
for key in "${!KEYS[@]}"; do
#printf "current key: %s\n" "$key"
[[ $key != "cid" ]] && #[[ -z ${KEYS[$key]} ]] &&
check_key "$key" && ret=1 && break
done
return $ret
}
declare -i current=0 nvalids=0
while read -r line; do
if [[ -z "$line" ]]; then
((current++))
passport_valid && ((nvalids ++))
reset_array KEYS
continue
fi
for pair in $line; do
key=${pair%%:*}
val=${pair##*:}
[[ -v KEYS[$key] ]] && KEYS[$key]="$val" # valid key
done
done
((current++))
passport_valid && ((nvalids ++))
printf "%s : valid=%d/%d\n" "$CMD" "$nvalids" "$current"
exit 0