X-Git-Url: https://git.sommitrealweird.co.uk/advent-of-code-2020.git/blobdiff_plain/61a73a00535337fa5b2780440d643052877ca036..c526bc47733dd9abefd93635326c58344966878f:/day14/dockingdata_v2.sh diff --git a/day14/dockingdata_v2.sh b/day14/dockingdata_v2.sh new file mode 100755 index 0000000..08aed81 --- /dev/null +++ b/day14/dockingdata_v2.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +filename="${1:-p2_208.txt}" + +declare -A mem + +parse_line() { + local line="$1" + local key=${line% = *} + local value=${line#* = } + declare -g cur_mask + local base_mask + local mask + + if [ $key == "mask" ]; then + cur_mask=$value + else + # it's a memory instruction, yay + unset masks + get_masks $base_mask + + loc=${key%]} + loc=${loc#*[} + base_mask=$(get_base_mask $cur_mask $loc) + unset masks + get_masks $base_mask + for mask in "${masks[@]}"; do + loc=$(get_value $mask $loc) + mem[$loc]=$value + done + fi +} + +get_base_mask() { + local mask=$1 + local value=$2 + local newmask="" + + # here we literally translate the string to contain X if + # it's an X, and then check against the value and if either + # value or mask has a 1 in that position set it to 1 other + # wise set it to 0 + for (( a=0; a<36; a++ )); do + if [ ${mask:$a:1} == "X" ]; then + newmask+="X" + elif [ ${mask:$a:1} -eq 1 ] || [ $((value & 2**(35-$a))) -gt 0 ]; then + newmask+="1" + else + newmask+="0" + fi + done + + echo $newmask +} + +get_masks() { + local string="$1" + local test="${string/X/b}" + local mask1 + local mask2 + declare -g -a masks + + if [ "$string" == "$test" ]; then + masks+=( $string ) + return 0 + fi + + # do the 2 potential replacements and run them through + mask1=${string/X/1} + get_masks $mask1 + mask2=${string/X/0} + get_masks $mask2 +} + +get_value() { + local mask="$1" + local value="$2" + local mask_part1=${mask//X/0} + local mask_part2=${mask//1/X} + mask_part2=${mask_part2//0/1} + mask_part2=${mask_part2//X/0} + value=$((value | 2#$mask_part1)) + value=$(( ~ $value & (2**36)-1 )) + value=$((value | 2#$mask_part2)) + value=$(( ~ $value & (2**36)-1 )) + echo $value +} + +exec 3<"$filename" +while read -u 3 line; do + parse_line "$line" +done + +total=0 +for key in ${!mem[@]}; do + total=$((total+${mem[$key]})) +done + +echo "Total: $total"