ZAP! Day 10.
authorBrett Parker <iDunno@sommitrealweird.co.uk>
Wed, 9 Dec 2020 01:40:12 +0000 (01:40 +0000)
committerBrett Parker <iDunno@sommitrealweird.co.uk>
Wed, 9 Dec 2020 01:40:12 +0000 (01:40 +0000)
day10/common.sh
day10/zap.sh [new file with mode: 0644]

index 86979ed04963febd2e8fb8a3b503d84591801a75..db5c6b9df6a70d4b4434ed628726f0bd15c0cd1d 100644 (file)
@@ -4,8 +4,8 @@ get_vector() {
     local x2=$3
     local y2=$4
 
     local x2=$3
     local y2=$4
 
-    x_diff=$(($x1 - $x2))
-    y_diff=$(($y1 - $y2))
+    x_diff=$(($x2 - $x1))
+    y_diff=$(($y2 - $y1))
 
     echo "$x_diff,$y_diff"
 }
 
     echo "$x_diff,$y_diff"
 }
diff --git a/day10/zap.sh b/day10/zap.sh
new file mode 100644 (file)
index 0000000..eae98d2
--- /dev/null
@@ -0,0 +1,138 @@
+#!/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."