X-Git-Url: https://git.sommitrealweird.co.uk/advent-of-code-2021.git/blobdiff_plain/8f18738f33eafb7a8d704bb8d7b762566453cd99..9017e242041b51939c88e7e99221923965e919e1:/day16/decoder.sh diff --git a/day16/decoder.sh b/day16/decoder.sh new file mode 100755 index 0000000..fe67cbd --- /dev/null +++ b/day16/decoder.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +set -u + +filename=${1:-p1_16.txt} +debug=${2:-0} + +exec 3<"${filename}" + +declare -A hex_to_binary=( [0]="0000" [1]="0001" [2]="0010" [3]="0011" [4]="0100" [5]="0101" [6]="0110" [7]="0111" [8]="1000" [9]="1001" [A]="1010" [B]="1011" [C]="1100" [D]="1101" [E]="1110" [F]="1111" ) + +read -u 3 hex_string + +declare -g __packets="" +for (( a=0; a<${#hex_string}; a++ )); do + __packets+=${hex_to_binary[${hex_string:$a:1}]} +done + +declare -g __versions_total=0 + +declare __packet_offset=0 + +if [ $debug == "0" ]; then + echo_verbose() { true; } +else + echo_verbose() { echo "$@" >&2; } +fi + +parse_version() { + declare -g __packet_version=$((2#${__packets:$__packet_offset:3})) + ((__packet_offset+=3)) + echo_verbose "Packet version: $__packet_version" +} + +parse_type() { + declare -g __packet_type=$((2#${__packets:$__packet_offset:3})) + ((__packet_offset+=3)) + echo_verbose "Packet type: $__packet_type" +} + +parse_literal() { + local keep_going=${__packets:$__packet_offset:1} + local binary_value="" + ((__packet_offset+=1)) + while [ $keep_going -eq 1 ]; do + binary_value+=${__packets:$__packet_offset:4} + ((__packet_offset+=4)) + keep_going=${__packets:$__packet_offset:1} + ((__packet_offset+=1)) + done + # if we're here, we're on to the last group + binary_value+=${__packets:$__packet_offset:4} + ((__packet_offset+=4)) + declare -g __packet_literal=$((2#$binary_value)) + echo_verbose "Packet literal: $__packet_literal" +} + +parse_operator() { + local len_type=$((2#${__packets:$__packet_offset:1})) + ((__packet_offset+=1)) + + case $len_type in + 0) + __packets_length=$((2#${__packets:$__packet_offset:15})) + ((__packet_offset+=15)) + ;; + 1) + __packets_count=$((2#${__packets:$__packet_offset:11})) + ((__packet_offset+=11)) + ;; + esac +} + +parse_packets() { + # we'll first need the version and the type, so grab those + local pversion + local ptype + + while [ $__packet_offset -lt ${#__packets} ]; do + parse_version + parse_type + version=$__packet_version + ptype=$__packet_type + + ((__versions_total+=$version)) + + echo_verbose "Remaining: ${__packets:$__packet_offset}" + + case $ptype in + 4) + parse_literal + ;; + *) + parse_operator + ;; + esac + + if [ $(($__packet_offset+7)) -ge ${#__packets} ]; then + break + fi + done +} + +parse_packets + +echo "Total: $__versions_total"