--- /dev/null
+#!/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"