83e15850e854dbbac65cdef6d144a6861c472ae1
[advent-of-code-2021.git] / day13 / fold.sh
1 #!/bin/bash
2
3 set -u
4
5 declare -a points=()
6 declare -a folds=()
7
8 filename="${1:-example.txt}"
9 exec 3<"$filename"
10
11 max_x=0
12 max_y=0
13
14 while read -u 3 line; do
15     if [ "$line" == "" ]; then
16         break
17     fi
18     x=${line%,*}
19     y=${line#*,}
20     if [ $x -gt $max_x ]; then
21         max_x=$x
22     fi
23     if [ $y -gt $max_y ]; then
24         max_y=$y
25     fi
26     points+=($line)
27 done
28
29 ((max_x+=1))
30 ((max_y+=1))
31
32 while read -u 3 line; do
33     folds+=(${line#fold along })
34 done
35
36 display_map() {
37     for (( y=0; y<$max_y; y++ )); do
38         for (( x=0; x<$max_x; x++ )); do
39             offset=$(((y*$max_x) + $x))
40             case "${map[$offset]}" in
41                 0)
42                     echo -n "."
43                     ;;
44                 1)
45                     echo -n "#"
46                     ;;
47             esac
48         done
49         echo
50     done
51 }
52
53 declare -a map
54
55 # now build a map
56 for (( a=0; a<$(($max_x * $max_y)); a++ )); do
57     map[$a]=0
58 done
59
60 for point in "${points[@]}"; do
61     x=${point%,*}
62     y=${point#*,}
63     offset=$((($y*$max_x)+$x))
64     map[$offset]=1
65 done
66
67 fold() {
68     local line="$1"
69     local axis=${line%=*}
70     local point=${line#*=}
71     local dot="."
72
73     declare -a new_map=()
74
75     case $axis in
76         x)
77             local new_max_x=$(($max_x - $point - 1))
78             if [ $point -gt $new_max_x ]; then
79                 new_max_x=$point
80             fi
81             local adj=$((max_x % 2))
82             for (( y=0; y<$max_y; y++ )); do
83                 for (( x=0; x<$new_max_x; x++ )); do
84                     x_1=$(($point - $new_max_x + $x))
85                     x_2=$(($max_x - ($new_max_x - $point) - $x - $adj))
86                     offset_1=$((($y * $max_x) + $x_1))
87                     offset_2=$((($y * $max_x) + $x_2))
88                     if [ $x_1 -lt 0 ]; then
89                         offset_1=$offset_2
90                     fi
91                     if [ $x_2 -ge $max_x  ]; then
92                         offset_2=$offset_1
93                     fi
94                     new_map+=("$dot")
95                     new_offset=$((($y * $new_max_x) + $x))
96                     new_map[$new_offset]=$((${map[$offset_1]} | ${map[$offset_2]}))
97                 done
98             done
99             map=("${new_map[@]}")
100             max_x=$new_max_x
101             ;;
102         y)
103             local new_max_y=$(($max_y - $point - 1))
104             if [ $point -gt $new_max_y ]; then
105                 new_max_y=$point
106             fi
107             local adj=$((max_y % 2))
108             for (( y=0; y<$new_max_y; y++ )); do
109                 # do the y offsets here
110                 y_1=$(($point - $new_max_y + $y))
111                 y_2=$(($max_y - ($new_max_y - $point) - $y - $adj))
112                 offset_1=$(($y_1 * $max_x))
113                 offset_2=$(($y_2 * $max_x))
114                 if [ $y_1 -lt 0 ]; then
115                     offset_1=$offset_2
116                 fi
117                 if [ $y_2 -ge $max_y  ]; then
118                     offset_2=$offset_1
119                 fi
120                 for (( x=0; x<$max_x; x++ )); do
121                     off_1=$(($offset_1+$x))
122                     off_2=$(($offset_2+$x))
123                     new_map+=("$dot")
124                     new_offset=$((($y * $max_x) + $x))
125                     new_map[$new_offset]=$((${map[$off_1]} | ${map[$off_2]}))
126                 done
127             done
128             map=("${new_map[@]}")
129             max_y=$new_max_y
130             ;;
131     esac
132 }
133
134 get_points_count() {
135     local count=0
136     for point in "${map[@]}"; do
137         ((count+=$point))
138     done
139
140     echo $count
141 }
142
143 #display_map
144
145 # do first fold
146 fold "${folds[0]}"
147 echo
148 #display_map
149 echo
150 echo "There are $(get_points_count) dots visible after first fold"
151 for (( f=1; f<${#folds[@]}; f++ )); do
152     echo "Doing fold $((f+1)) of ${#folds[@]}"
153     fold "${folds[$f]}"
154 done
155 echo
156 echo "After all folds:"
157 display_map