Remove redundant bit of code
[advent-of-code-2020.git] / day14 / dockingdata_v2.sh
1 #!/bin/bash
2
3 filename="${1:-p2_208.txt}"
4
5 declare -A mem
6
7 parse_line() {
8     local line="$1"
9     local key=${line% = *}
10     local value=${line#* = }
11     declare -g cur_mask
12     local base_mask
13     local mask
14
15     if [ $key == "mask" ]; then
16         cur_mask=$value
17     else
18         # it's a memory instruction, yay
19         loc=${key%]}
20         loc=${loc#*[}
21         base_mask=$(get_base_mask $cur_mask $loc)
22         unset masks
23         get_masks $base_mask
24         for mask in "${masks[@]}"; do
25             loc=$(get_value $mask $loc)
26             mem[$loc]=$value
27         done
28     fi
29 }
30
31 get_base_mask() {
32     local mask=$1
33     local value=$2
34     local newmask=""
35
36     # here we literally translate the string to contain X if
37     # it's an X, and then check against the value and if either
38     # value or mask has a 1 in that position set it to 1 other
39     # wise set it to 0
40     for (( a=0; a<36; a++ )); do
41         if [ ${mask:$a:1} == "X" ]; then
42             newmask+="X"
43         elif [ ${mask:$a:1} -eq 1 ] || [ $((value & 2**(35-$a))) -gt 0 ]; then
44             newmask+="1"
45         else
46             newmask+="0"
47         fi
48     done
49
50     echo $newmask
51 }
52
53 get_masks() {
54     local string="$1"
55     local test="${string/X/b}"
56     local mask1
57     local mask2
58     declare -g -a masks
59
60     if [ "$string" == "$test" ]; then
61         masks+=( $string )
62         return 0
63     fi
64
65     # do the 2 potential replacements and run them through
66     mask1=${string/X/1}
67     get_masks $mask1
68     mask2=${string/X/0}
69     get_masks $mask2
70 }
71
72 get_value() {
73     local mask="$1"
74     local value="$2"
75     local mask_part1=${mask//X/0}
76     local mask_part2=${mask//1/X}
77     mask_part2=${mask_part2//0/1}
78     mask_part2=${mask_part2//X/0}
79     value=$((value | 2#$mask_part1))
80     value=$(( ~ $value & (2**36)-1 ))
81     value=$((value | 2#$mask_part2))
82     value=$(( ~ $value & (2**36)-1 ))
83     echo $value
84 }
85
86 exec 3<"$filename"
87 while read -u 3 line; do
88     parse_line "$line"
89 done
90
91 total=0
92 for key in ${!mem[@]}; do
93     total=$((total+${mem[$key]}))
94 done
95
96 echo "Total: $total"