Day 12
[advent-of-code-2020.git] / day12 / ship.sh
1 #!/bin/bash
2
3 filename=${1:-17E_8S_25.txt}
4
5 declare -a possible_directions=("E" "S" "W" "N")
6
7 read_file() {
8     local filename="${1}"
9     unset instructions
10     declare -g -a instructions
11     exec 3<"$filename"
12     while read -u 3 line; do
13         instructions+=( $line )
14     done
15 }
16
17 read_file "$filename"
18
19 ship_direction="E"
20
21 ship_east=0
22 ship_north=0
23
24 go_north() {
25     amount=$1
26     ship_north=$((ship_north+$amount))
27 }
28
29 go_south() {
30     amount=$1
31     go_north $((amount*-1))
32 }
33
34 go_east() {
35     amount=$1
36     ship_east=$((ship_east+$amount))
37 }
38 go_west() {
39     amount=$1
40     go_east $((amount*-1))
41 }
42
43 do_move() {
44     direction=$1
45     amount=$2
46
47     case $direction in
48         N)
49             go_north $count
50             ;;
51         S)
52             go_south $count
53             ;;
54         E)
55             go_east $count
56             ;;
57         W)
58             go_west $count
59             ;;
60     esac
61 }
62
63 do_turn() {
64     local amount=$1
65     local mult=$2
66     local dir_pos
67     local a
68
69     # well, we want amount to be done
70     # in 90° blocks, so
71     amount=$((amount / 90))
72     amount=$((amount*mult))
73
74     dir_pos=0
75
76     # find where current direction is in the array
77     for a in ${!possible_directions[@]}; do
78         if [ ${possible_directions[$a]} == $ship_direction ]; then
79             dir_pos=$a
80             break
81         fi
82     done
83
84     dir_pos=$((dir_pos+$amount))
85     dir_pos=$((dir_pos % ${#possible_directions[@]}))
86     ship_direction=${possible_directions[$dir_pos]}
87 }
88
89 do_waypoint_move() {
90     direction=$1
91     amount=$2
92
93     case $direction in
94         N)
95             waypoint_north=$((waypoint_north+$amount))
96             ;;
97         S)
98             waypoint_north=$((waypoint_north-$amount))
99             ;;
100         E)
101             waypoint_east=$((waypoint_east+$amount))
102             ;;
103         W)
104             waypoint_east=$((waypoint_east-$amount))
105             ;;
106     esac
107 }
108
109 do_waypoint_turn() {
110     local degrees=$1
111     local steps=$((degrees/90))
112     local temp
113
114     if [ $steps -lt 0 ]; then
115         steps=4+$steps
116     fi
117
118     for (( a=0; a<steps; a++ )); do
119         temp=$waypoint_north
120         waypoint_north=$((waypoint_east*-1))
121         waypoint_east=$temp
122     done
123 }
124
125 do_move_ship_to_waypoint() {
126     local times=$1
127     ship_east=$((ship_east+($times*$waypoint_east)))
128     ship_north=$((ship_north+($times*$waypoint_north)))
129 }
130
131 echo "Part 1:"
132
133 for instruction in "${instructions[@]}"; do
134     direction=${instruction:0:1}
135     count=${instruction:1}
136
137     case $direction in
138         E|S|N|W)
139             do_move $direction $count
140             ;;
141         F)
142             do_move $ship_direction $count
143             ;;
144         L)
145             do_turn $count -1
146             ;;
147         R)
148             do_turn $count 1
149             ;;
150     esac
151 done
152
153 echo "  Ship ended at $ship_east E, $ship_north N"
154 e=${ship_east#-}
155 n=${ship_north#-}
156 md=$((e+$n))
157 echo "  Manhatten distance: $md"
158
159 echo "Part 2:"
160
161 waypoint_east=10
162 waypoint_north=1
163 ship_east=0
164 ship_north=0
165
166 for instruction in "${instructions[@]}"; do
167     direction=${instruction:0:1}
168     count=${instruction:1}
169
170     case $direction in
171         E|S|N|W)
172             do_waypoint_move $direction $count
173             ;;
174         F)
175             do_move_ship_to_waypoint $count
176             ;;
177         L)
178             do_waypoint_turn $((count*-1))
179             ;;
180         R)
181             do_waypoint_turn $((count))
182             ;;
183     esac
184 done
185
186 echo "  Ship ended at $ship_east E, $ship_north N"
187 e=${ship_east#-}
188 n=${ship_north#-}
189 md=$((e+$n))
190 echo "  Manhatten distance: $md"