--- /dev/null
+#!/bin/bash
+
+filename=${1:-17E_8S_25.txt}
+
+declare -a possible_directions=("E" "S" "W" "N")
+
+read_file() {
+ local filename="${1}"
+ unset instructions
+ declare -g -a instructions
+ exec 3<"$filename"
+ while read -u 3 line; do
+ instructions+=( $line )
+ done
+}
+
+read_file "$filename"
+
+ship_direction="E"
+
+ship_east=0
+ship_north=0
+
+go_north() {
+ amount=$1
+ ship_north=$((ship_north+$amount))
+}
+
+go_south() {
+ amount=$1
+ go_north $((amount*-1))
+}
+
+go_east() {
+ amount=$1
+ ship_east=$((ship_east+$amount))
+}
+go_west() {
+ amount=$1
+ go_east $((amount*-1))
+}
+
+do_move() {
+ direction=$1
+ amount=$2
+
+ case $direction in
+ N)
+ go_north $count
+ ;;
+ S)
+ go_south $count
+ ;;
+ E)
+ go_east $count
+ ;;
+ W)
+ go_west $count
+ ;;
+ esac
+}
+
+do_turn() {
+ local amount=$1
+ local mult=$2
+ local dir_pos
+ local a
+
+ # well, we want amount to be done
+ # in 90° blocks, so
+ amount=$((amount / 90))
+ amount=$((amount*mult))
+
+ dir_pos=0
+
+ # find where current direction is in the array
+ for a in ${!possible_directions[@]}; do
+ if [ ${possible_directions[$a]} == $ship_direction ]; then
+ dir_pos=$a
+ break
+ fi
+ done
+
+ dir_pos=$((dir_pos+$amount))
+ dir_pos=$((dir_pos % ${#possible_directions[@]}))
+ ship_direction=${possible_directions[$dir_pos]}
+}
+
+do_waypoint_move() {
+ direction=$1
+ amount=$2
+
+ case $direction in
+ N)
+ waypoint_north=$((waypoint_north+$amount))
+ ;;
+ S)
+ waypoint_north=$((waypoint_north-$amount))
+ ;;
+ E)
+ waypoint_east=$((waypoint_east+$amount))
+ ;;
+ W)
+ waypoint_east=$((waypoint_east-$amount))
+ ;;
+ esac
+}
+
+do_waypoint_turn() {
+ local degrees=$1
+ local steps=$((degrees/90))
+ local temp
+
+ if [ $steps -lt 0 ]; then
+ steps=4+$steps
+ fi
+
+ for (( a=0; a<steps; a++ )); do
+ temp=$waypoint_north
+ waypoint_north=$((waypoint_east*-1))
+ waypoint_east=$temp
+ done
+}
+
+do_move_ship_to_waypoint() {
+ local times=$1
+ ship_east=$((ship_east+($times*$waypoint_east)))
+ ship_north=$((ship_north+($times*$waypoint_north)))
+}
+
+echo "Part 1:"
+
+for instruction in "${instructions[@]}"; do
+ direction=${instruction:0:1}
+ count=${instruction:1}
+
+ case $direction in
+ E|S|N|W)
+ do_move $direction $count
+ ;;
+ F)
+ do_move $ship_direction $count
+ ;;
+ L)
+ do_turn $count -1
+ ;;
+ R)
+ do_turn $count 1
+ ;;
+ esac
+done
+
+echo " Ship ended at $ship_east E, $ship_north N"
+e=${ship_east#-}
+n=${ship_north#-}
+md=$((e+$n))
+echo " Manhatten distance: $md"
+
+echo "Part 2:"
+
+waypoint_east=10
+waypoint_north=1
+ship_east=0
+ship_north=0
+
+for instruction in "${instructions[@]}"; do
+ direction=${instruction:0:1}
+ count=${instruction:1}
+
+ case $direction in
+ E|S|N|W)
+ do_waypoint_move $direction $count
+ ;;
+ F)
+ do_move_ship_to_waypoint $count
+ ;;
+ L)
+ do_waypoint_turn $((count*-1))
+ ;;
+ R)
+ do_waypoint_turn $((count))
+ ;;
+ esac
+done
+
+echo " Ship ended at $ship_east E, $ship_north N"
+e=${ship_east#-}
+n=${ship_north#-}
+md=$((e+$n))
+echo " Manhatten distance: $md"