6eb2b08e46e5e5530f42beb0576e0bec33b8be63
[advent-of-code-2020.git] / day4 / count_valid_passports_2.sh
1 #!/bin/bash
2
3 declare -a data
4 cur_data=""
5 seperator=""
6 valid_count=0
7
8 required_fields=(byr iyr eyr hgt hcl ecl pid)
9
10 check_year() {
11     value=$1
12     min=$2
13     max=$3
14
15     if [ $value -ge $min ] && [ $value -le $max ]; then
16         exit 0
17     fi
18     exit 1
19 }
20
21 check_height() {
22     value=$1
23     units=${value:$((${#value}-2)):2}
24     value=${value:0:$((${#value}-2))}
25     case $units in
26         in)
27             if [ $value -ge 59 ] && [ $value -le 76 ]; then
28                 exit 0
29             fi
30             ;;
31         cm)
32             if [ $value -ge 150 ] && [ $value -le 193 ]; then
33                 exit 0
34             fi
35             ;;
36         *)
37             ;;
38     esac
39     exit 1
40 }
41
42 check_hair() {
43     value=$1
44
45     if [ ${value:0:1} != "#" ]; then
46         exit 1
47     fi
48
49     if [[ $value =~ /^[a-f0-9]{6}$/ ]]; then
50         exit 1
51     fi
52
53     exit 0
54 }
55
56 check_eyes() {
57     colour="$1"
58     case $colour in
59         amb|blu|brn|gry|grn|hzl|oth)
60             exit 0
61             ;;
62         *)
63             exit 1
64             ;;
65     esac
66     exit 1
67 }
68
69 check_data() {
70     local -n record=$1
71     for x in ${!record[@]}; do
72         value=${record[$x]}
73         case $x in
74             byr)
75                 if ! ( check_year $value 1920 2002 ); then
76                     exit 1
77                 fi
78                 ;;
79             iyr)
80                 if ! ( check_year $value 2010 2020 ); then
81                     exit 1
82                 fi
83                 ;;
84             eyr)
85                 if ! ( check_year $value 2020 2030 ); then
86                     exit 1
87                 fi
88                 ;;
89             hgt)
90                 if ! ( check_height $value ); then
91                     exit 1
92                 fi
93                 ;;
94             hcl)
95                 if ! ( check_hair $value ); then
96                     exit 1
97                 fi
98                 ;;
99             ecl)
100                 if ! ( check_eyes $value ); then
101                     exit 1
102                 fi
103                 ;;
104             pid)
105                 value=${record[$x]}
106                 if [ ${#value} -ne 9 ]; then
107                     exit 1
108                 fi
109                 ;;
110             *)
111                 ;;
112         esac
113     done
114
115     exit 0
116 }
117
118 exec 3<input.txt
119
120 while read -u 3 line; do
121     if [ "$line" = "" ]; then
122         data+=("$cur_data")
123         seperator=""
124         cur_data=""
125         continue
126     fi
127     cur_data="${cur_data}${seperator}$line"
128     seperator=" "
129 done
130
131 # on the last line, if cur_data isn't empty, add that to the array
132 if [ "$cur_data" != "" ]; then
133     data+=("$cur_data")
134 fi
135
136 for (( i=0; i<${#data[@]}; i++ )); do
137     record="${data[$i]}"
138     declare -A kvp
139     for field in $record; do
140         key=${field%:*}
141         value=${field#*:}
142         kvp[$key]=$value
143     done
144     for field in ${required_fields[@]}; do
145         if ! [ ${kvp[$field]+a} ]; then
146             continue 2
147         fi
148     done
149     if ( check_data kvp ); then
150         valid_count=$((valid_count+1))
151     fi
152     unset kvp
153 done
154
155 echo "$valid_count valid entries"