Advent of code Day 3
[advent-of-code-2021.git] / day03 / diag.sh
diff --git a/day03/diag.sh b/day03/diag.sh
new file mode 100755 (executable)
index 0000000..9e8c823
--- /dev/null
@@ -0,0 +1,152 @@
+#!/bin/bash
+
+set -e
+set -u
+
+filename="${1:-example.txt}"
+
+exec 3<"$filename"
+
+line_length=0
+declare -a most_common=( 0 )
+declare -a all_binaries
+line_count=0
+
+while read -u 3 line; do
+    all_binaries+=($line)
+    if [ $line_length -eq 0 ]; then
+        line_length=${#line}
+    fi
+    for (( i=0; i < $line_length; i++ )); do
+        if [ ${#most_common[@]} -lt $i ]; then
+            most_common[$i]=0
+        fi
+        if [ ${line:$i:1} -eq 1 ]; then
+            ((most_common[$i]+=1))
+        fi
+    done
+    ((line_count+=1))
+done
+
+half_line_count=$((line_count/2))
+binary_string=""
+inverse_binary_string=""
+
+for (( i=0; i < $line_length; i++ )); do
+    if [ ${most_common[$i]} -gt $half_line_count ]; then
+        binary_string+=1
+        inverse_binary_string+=0
+    else
+        binary_string+=0
+        inverse_binary_string+=1
+    fi
+done
+
+total=$((2#$binary_string * 2#$inverse_binary_string))
+
+echo Answer: $total
+
+declare -a co2_scrubber
+declare -a o2_generator
+
+# first populate co2_scrubbers and o2_generator
+
+co2_filter_digit=1
+o2_generator_digit=0
+
+if [ ${most_common[0]} -gt $half_line_count ]; then
+    co2_filter_digit=0
+    o2_generator_digit=1
+else
+    co2_filter_digit=1
+    o2_generator_digit=0
+fi
+
+for val in "${all_binaries[@]}"; do
+    if [ ${val:0:1} -eq $co2_filter_digit ]; then
+        co2_scrubber+=($val)
+    fi
+    if [ ${val:0:1} -eq $o2_generator_digit ]; then
+        o2_generator+=($val)
+    fi
+done
+
+get_most_common() {
+    offset=$1
+    local -n arr=$2
+    ones=0
+    zeros=0
+
+    for val in "${arr[@]}"; do
+        part=${val:$offset:1}
+        if [ $part -eq 1 ]; then
+            ((ones+=1))
+        else
+            ((zeros+=1))
+        fi
+    done
+
+    if [ $ones -gt $zeros ]; then
+        echo 1
+    elif [ $ones -lt $zeros ]; then
+        echo 0
+    else
+        echo 2
+    fi
+}
+
+get_least_common() {
+    offset=$1
+    array_name=$2
+
+    val=$(get_most_common $offset $array_name)
+    case $val in
+        0)
+            echo 1
+            ;;
+        1)
+            echo 0
+            ;;
+        2)
+            echo 2
+            ;;
+    esac
+}
+
+filter_array() {
+    val=$1
+    pos=$2
+    local -n arr=$3
+
+    if [ ${#arr[@]} -eq 1 ]; then
+        return
+    fi
+
+    declare -a new_arr
+    for thing in "${arr[@]}"; do
+        if [ ${thing:$pos:1} -eq $val ]; then
+            new_arr+=($thing)
+        fi
+    done
+
+    arr=("${new_arr[@]}")
+}
+
+for ((i=1; i < $line_length; i++)); do
+    co2_filter=$(get_least_common $i co2_scrubber)
+    o2_filter=$(get_most_common $i o2_generator)
+
+    if [ $co2_filter -eq 2 ]; then
+        co2_filter=0
+    fi
+
+    if [ $o2_filter -eq 2 ]; then
+        o2_filter=1
+    fi
+
+    filter_array $co2_filter $i co2_scrubber
+    filter_array $o2_filter $i o2_generator
+done
+
+# we've only got 1 in each - so...
+echo Life Support Rating: $((2#${o2_generator[0]} * 2#${co2_scrubber[0]}))