--- /dev/null
+#!/bin/bash
+
+set -u
+
+filename="${1:-input.txt}"
+
+exec 3<"$filename"
+
+declare -a all_inputs
+declare -a all_outputs
+
+while read -u 3 -d "|" inputs; do
+ all_inputs+=("$inputs")
+ read -u 3 outputs
+ all_outputs+=("$outputs")
+done
+
+one_count=0 # 2 on signals
+seven_count=0 # 3 on signals
+four_count=0 # 4 on signals
+eight_count=0 # 7 on signals
+
+for output in "${all_outputs[@]}"; do
+ read -a seperates <<<$output
+ for s in "${seperates[@]}"; do
+ case ${#s} in
+ 2)
+ ((one_count+=1))
+ ;;
+ 3)
+ ((seven_count+=1))
+ ;;
+ 4)
+ ((four_count+=1))
+ ;;
+ 7)
+ ((eight_count+=1))
+ ;;
+ esac
+ done
+done
+
+echo "1 count: $one_count"
+echo "4 count: $four_count"
+echo "7 count: $seven_count"
+echo "8 count: $eight_count"
+echo
+echo "Total: $((one_count+$four_count+$seven_count+$eight_count))"
+
+declare -A seg_vals=( [a]=1 [b]=2 [c]=4 [d]=8 [e]=16 [f]=32 [g]=64 )
+declare -A char_map=( [119]=0 [36]=1 [93]=2 [109]=3 [46]=4 [107]=5 [123]=6 [37]=7 [127]=8 [111]=9 )
+
+get_digits() {
+ local input="$1"
+ local output="$2"
+ local -A segcounts=( [a]=0 [b]=0 [c]=0 [d]=0 [e]=0 [f]=0 [g]=0 )
+ local -A segmap=( [a]= [b]= [c]= [d]= [e]= [f]= [g]= )
+
+ read -a segs <<<"${input}"
+ for seg in "${segs[@]}"; do
+ for (( a=0; a<${#seg}; a++ )); do
+ ((segcounts[${seg:$a:1}]+=1))
+ done
+ done
+
+ # we've now got some counts, so we can do *some* of the mappings
+ for seg_name in "${!segcounts[@]}"; do
+ case ${segcounts[$seg_name]} in
+ 4)
+ segmap[$seg_name]=e
+ ;;
+ 6)
+ segmap[$seg_name]=b
+ ;;
+ 9)
+ segmap[$seg_name]=f
+ ;;
+ 7)
+ segmap[$seg_name]=dg
+ ;;
+ 8)
+ segmap[$seg_name]=ac
+ ;;
+ esac
+ done
+
+ # now go through segs again, this time checking how long the string is, because from that
+ # we can find 7, which will give us a.
+
+ for seg in "${segs[@]}"; do
+ case ${#seg} in
+ 2)
+ # this is number 1 - it has a c but no a
+ for (( a=0; a<${#seg}; a++ )); do
+ if [ ${segmap[${seg:$a:1}]} == "ac" ]; then
+ segmap[${seg:$a:1}]=c
+ break
+ fi
+ done
+ # because we've worked out where a is, we now go find the one that thinks it's a or c
+ for seg_name in "${!segmap[@]}"; do
+ if [ "${segmap[$seg_name]}" == "ac" ]; then
+ segmap[$seg_name]=a
+ break
+ fi
+ done
+ ;;
+ 4)
+ # this is number 4
+ for (( a=0; a<${#seg}; a++ )); do
+ if [ ${segmap[${seg:$a:1}]} == "dg" ]; then
+ segmap[${seg:$a:1}]=d
+ break
+ fi
+ done
+ for seg_name in "${!segmap[@]}"; do
+ if [ "${segmap[$seg_name]}" == "dg" ]; then
+ segmap[$seg_name]=g
+ break
+ fi
+ done
+ ;;
+ esac
+ done
+
+ output_digits=""
+
+ # finally, we can get each of the digits in the output, so go through the output
+ read -a charsets <<<"${output}"
+ for chars in "${charsets[@]}"; do
+ char_value=0
+ for (( a=0; a<${#chars}; a++ )); do
+ ((char_value+=${seg_vals[${segmap[${chars:$a:1}]}]}))
+ done
+ if [ "${char_map[$char_value]+abc}" ]; then
+ output_digits+=${char_map[$char_value]}
+ else
+ declare -p segmap >&2
+ echo "Chars: $chars" >&2
+ exit 1
+ fi
+ done
+
+ # remove any leading 0s the cheating way
+ echo $((10#$output_digits))
+}
+
+# Now lets start playing with the first input and try working out the outputs
+
+total_output_count=0
+
+for (( a=0; a<${#all_inputs[@]}; a++ )); do
+ ((total_output_count+=$(get_digits "${all_inputs[$a]}" "${all_outputs[$a]}")))
+done
+
+echo "Sum of all output digits: $total_output_count"