+#!/bin/bash
+
+basedir=$(dirname $(readlink -f $BASH_SOURCE))
+. $basedir/common.sh
+
+our_asteroid=26,29
+
+declare -A asteroids
+declare -A asteroid_angles
+
+exec 3<input.txt
+ln=0
+width=0
+while read -u 3 line; do
+ width=${#line}
+ for (( a=0; a<${#line}; a++ )); do
+ char=${line:$a:1}
+ if [ "${char}" == "#" ]; then
+ asteroids[$a,$ln]=0
+ fi
+ done
+ ln=$((ln+1))
+done
+
+get_angle() {
+ local a1=$1
+ local a2=$2
+
+ local vector=$(get_asteroids_vector $a1 $a2)
+ local move_x=${vector%,*}
+ local move_y=${vector#*,}
+
+ val="$(calc -p 'round(((90 + ((180/pi()) * atan2('$move_y','$move_x'))) % 360) * 100000000) / 100000000')"
+ echo "$val"
+}
+
+get_closest_asteroid() {
+ local asteroids=$1
+
+ local IFS="|"
+ local min_dist=-1
+ local nearest_asteroid=
+ local x=0
+ local y=0
+
+ for asteroid in $asteroids; do
+ vector=$(get_asteroids_vector $our_asteroid $asteroid)
+ x=${vector%,*}
+ y=${vector#*,}
+ # use absolute numbers for length calculation!
+ x=${x#-}
+ y=${y#-}
+
+ distance=$((x+y))
+ if [ $distance -lt $min_dist -o $min_dist -eq -1 ]; then
+ min_dist=$distance
+ nearest_asteroid=$asteroid
+ fi
+ done
+
+ echo $nearest_asteroid
+}
+
+remove_asteroid_from_string() {
+ local asteroids=$1
+ local asteroid=$2
+ local new_asteroids=
+ local a
+
+ local IFS="|"
+ local seperator=""
+
+ for a in $asteroids; do
+ if [ "$a" != "$asteroid" ]; then
+ new_asteroids+="${seperator}$a"
+ fi
+ if [ "x$new_asteroids" != "x" ]; then
+ seperator="|"
+ fi
+ done
+
+ echo "$new_asteroids"
+}
+
+# calculate angles to each asteroid from us
+for asteroid in ${!asteroids[@]}; do
+ if [ $asteroid == $our_asteroid ]; then
+ continue
+ fi
+
+ # otherwise, get the angle from us to there
+ angle=$(get_angle $our_asteroid $asteroid)
+
+ # see if we've already got this angle as a key, if so append to it,
+ # otherwise set it
+ if [ ${asteroid_angles[$angle]+a} ]; then
+ asteroid_angles[$angle]+="|$asteroid"
+ else
+ asteroid_angles[$angle]=$asteroid
+ fi
+done
+
+zapped_count=0
+
+get_angles_list() {
+ local OFS=$'\n'
+
+ printf "%s\n" "${!asteroid_angles[@]}" | sort -g
+}
+
+sorted_angles=( "$(get_angles_list)" )
+
+for (( round=0; round<3; round++ )); do
+ for angle in $sorted_angles; do
+ if [ ${asteroid_angles[$angle]+a} ]; then
+ echo "$angle: ${asteroid_angles[$angle]}"
+ closest=$(get_closest_asteroid "${asteroid_angles[$angle]}")
+ #echo " - closest $closest"
+ # blow up the closest!
+ newlist=$(remove_asteroid_from_string ${asteroid_angles[$angle]} $closest)
+ if [ "x$newlist" == "x" ]; then
+ unset asteroid_angles[$angle]
+ else
+ asteroid_angles[$angle]=$newlist
+ fi
+ zapped_count=$((zapped_count+1))
+
+ echo "$zapped_count: $closest"
+
+ if [ $zapped_count -eq 200 ]; then
+ echo "The 200th asteroid to be zapped was $closest"
+ break 2
+ fi
+ fi
+ done
+done
+
+echo "And we're done."