Advent of code Day 3
[advent-of-code-2021.git] / day03 / diag.sh
1 #!/bin/bash
2
3 set -e
4 set -u
5
6 filename="${1:-example.txt}"
7
8 exec 3<"$filename"
9
10 line_length=0
11 declare -a most_common=( 0 )
12 declare -a all_binaries
13 line_count=0
14
15 while read -u 3 line; do
16     all_binaries+=($line)
17     if [ $line_length -eq 0 ]; then
18         line_length=${#line}
19     fi
20     for (( i=0; i < $line_length; i++ )); do
21         if [ ${#most_common[@]} -lt $i ]; then
22             most_common[$i]=0
23         fi
24         if [ ${line:$i:1} -eq 1 ]; then
25             ((most_common[$i]+=1))
26         fi
27     done
28     ((line_count+=1))
29 done
30
31 half_line_count=$((line_count/2))
32 binary_string=""
33 inverse_binary_string=""
34
35 for (( i=0; i < $line_length; i++ )); do
36     if [ ${most_common[$i]} -gt $half_line_count ]; then
37         binary_string+=1
38         inverse_binary_string+=0
39     else
40         binary_string+=0
41         inverse_binary_string+=1
42     fi
43 done
44
45 total=$((2#$binary_string * 2#$inverse_binary_string))
46
47 echo Answer: $total
48
49 declare -a co2_scrubber
50 declare -a o2_generator
51
52 # first populate co2_scrubbers and o2_generator
53
54 co2_filter_digit=1
55 o2_generator_digit=0
56
57 if [ ${most_common[0]} -gt $half_line_count ]; then
58     co2_filter_digit=0
59     o2_generator_digit=1
60 else
61     co2_filter_digit=1
62     o2_generator_digit=0
63 fi
64
65 for val in "${all_binaries[@]}"; do
66     if [ ${val:0:1} -eq $co2_filter_digit ]; then
67         co2_scrubber+=($val)
68     fi
69     if [ ${val:0:1} -eq $o2_generator_digit ]; then
70         o2_generator+=($val)
71     fi
72 done
73
74 get_most_common() {
75     offset=$1
76     local -n arr=$2
77     ones=0
78     zeros=0
79
80     for val in "${arr[@]}"; do
81         part=${val:$offset:1}
82         if [ $part -eq 1 ]; then
83             ((ones+=1))
84         else
85             ((zeros+=1))
86         fi
87     done
88
89     if [ $ones -gt $zeros ]; then
90         echo 1
91     elif [ $ones -lt $zeros ]; then
92         echo 0
93     else
94         echo 2
95     fi
96 }
97
98 get_least_common() {
99     offset=$1
100     array_name=$2
101
102     val=$(get_most_common $offset $array_name)
103     case $val in
104         0)
105             echo 1
106             ;;
107         1)
108             echo 0
109             ;;
110         2)
111             echo 2
112             ;;
113     esac
114 }
115
116 filter_array() {
117     val=$1
118     pos=$2
119     local -n arr=$3
120
121     if [ ${#arr[@]} -eq 1 ]; then
122         return
123     fi
124
125     declare -a new_arr
126     for thing in "${arr[@]}"; do
127         if [ ${thing:$pos:1} -eq $val ]; then
128             new_arr+=($thing)
129         fi
130     done
131
132     arr=("${new_arr[@]}")
133 }
134
135 for ((i=1; i < $line_length; i++)); do
136     co2_filter=$(get_least_common $i co2_scrubber)
137     o2_filter=$(get_most_common $i o2_generator)
138
139     if [ $co2_filter -eq 2 ]; then
140         co2_filter=0
141     fi
142
143     if [ $o2_filter -eq 2 ]; then
144         o2_filter=1
145     fi
146
147     filter_array $co2_filter $i co2_scrubber
148     filter_array $o2_filter $i o2_generator
149 done
150
151 # we've only got 1 in each - so...
152 echo Life Support Rating: $((2#${o2_generator[0]} * 2#${co2_scrubber[0]}))