-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Day 12. Advent of bash is getting slow - if you are stupid. My first …
…solution managed to solve part 1, but was horribly slow for part 2. I basically made my own algorithm. Then I implemented BFS since that is apparantly good (haha).. BFS took 20 seconds for part 1, and then for part 2 I created a nice little bug. I did a BFS for each starting point. 20 seconds times about 688 starting points quickly becomes 3 hours of execution time. Then I did a BFS with multiple starting points and solved it in 24 seconds.
- Loading branch information
Showing
4 changed files
with
346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#!/bin/bash | ||
if [ "$#" -gt 0 ]; then | ||
printf '%s\n' "$@" | ||
fi | ||
|
||
declare -A map | ||
|
||
row=0 | ||
startQueue=( ) | ||
|
||
while IFS= read -r string; do | ||
sX=0 | ||
sY=0 | ||
map[$row]=$string | ||
row=$(($row+1)) | ||
tX=0 | ||
|
||
for char in $(echo $string | sed -e 's/\(.\)/\1\n/g'); do | ||
if [[ "$char" == "S" || "$char" == "a" ]]; then | ||
echo "Starting at $tX,$(($row-1))" | ||
startQueue+=("$tX,$(($row-1))") | ||
fi | ||
tX=$(($tX+1)) | ||
done | ||
done | ||
|
||
|
||
function getKeyCode () { | ||
local X=$1 | ||
local Y=$2 | ||
char="${map[$Y]:$X:1}" | ||
if [[ "$char" == "E" ]]; then | ||
echo $(printf %d "'z") | ||
elif [[ "$char" == "S" ]]; then | ||
echo $(printf %d "'a") | ||
else | ||
echo $(printf %d "'${map[$Y]:$X:1}") | ||
fi | ||
} | ||
|
||
function findPossiblePaths () { | ||
local X=$1 | ||
local Y=$2 | ||
|
||
possibilities="" | ||
for x in $(seq $(($X-1)) $(($X+1))); do | ||
for y in $(seq $(($Y-1)) $(($Y+1))); do | ||
#echo " Checking $x $y" >&2 | ||
if ! [[ $X -eq $x && $Y -eq $y ]] && [[ $x -ge 0 && $x -lt ${#map[0]} && $y -ge 0 && $y -lt $row ]] && [[ $x -eq $X || $y -eq $Y ]] ; then | ||
current=$(getKeyCode $X $Y) | ||
next=$(getKeyCode $x $y) | ||
#echo " $x $y passed the coord check, onto keycode $current $next" >&2 | ||
if [[ "$current $(($current+1))" == *"$next"* ]] || [[ $next -lt $current && ! $next -eq 83 ]] || [[ $current -eq 83 ]]; then | ||
#echo " $x $y was valid" >&2 | ||
possibilities="$x,$y $possibilities" | ||
fi | ||
fi | ||
done | ||
done | ||
#echo $possibilities >&2 | ||
echo $possibilities | ||
} | ||
|
||
|
||
declare -A visited | ||
|
||
declare -A distances | ||
|
||
for x in $(seq 0 $((${#map[0]}-1))); do # Mark all as not visited | ||
for y in $(seq 0 $(($row-1))); do | ||
visited["$x,$y"]=0 | ||
done | ||
done | ||
|
||
|
||
queue=( ) | ||
|
||
for point in ${startQueue[@]}; do | ||
visited["$point"]=1 | ||
queue+=("$point") | ||
done | ||
declare -A parents | ||
|
||
target="" | ||
while [ ${#queue[@]} -gt 0 ]; do | ||
elem=${queue[0]} | ||
queue=("${queue[@]:1}") | ||
|
||
IFS="," read -ra coords <<< $elem | ||
#echo "Elem: $elem Pos: ${map[${coords[1]}]:${coords[0]}:1}" | ||
if [[ "${map[${coords[1]}]:${coords[0]}:1}" == "E" ]]; then | ||
echo "FOUND IT! $elem" | ||
target=$elem | ||
fi | ||
|
||
for coord in $(findPossiblePaths ${coords[0]} ${coords[1]}); do | ||
IFS="," read -ra xy <<< $coord | ||
if [[ ${visited["${xy[0]},${xy[1]}"]} -eq 0 ]]; then | ||
queue+=("${xy[0]},${xy[1]}") | ||
visited["${xy[0]},${xy[1]}"]=1 | ||
parents["${xy[0]},${xy[1]}"]="${coords[0]},${coords[1]}" | ||
fi | ||
done | ||
done | ||
par=$target | ||
#echo " TARGET: $target" | ||
steps=1 | ||
while [[ 1 -eq 1 ]]; do | ||
IFS="," read -ra coords <<< $par | ||
parent=${parents[$par]} | ||
#echo " par: $par Parent: $parent" | ||
for elem in ${startQueue[@]}; do | ||
if [[ "$elem" == "$parent" ]]; then | ||
echo "Steps to find: $steps" | ||
distances["$startX,$startY"]=$steps | ||
exit | ||
fi | ||
done | ||
par=$parent | ||
steps=$(($steps+1)) | ||
done | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#!/bin/bash | ||
if [ "$#" -gt 0 ]; then | ||
printf '%s\n' "$@" | ||
fi | ||
|
||
declare -A map | ||
|
||
row=0 | ||
startX=0 | ||
startY=0 | ||
while IFS= read -r string; do | ||
map[$row]=$string | ||
row=$(($row+1)) | ||
if [[ "$string" == *"S"* ]]; then | ||
rest=${string#*"S"} | ||
startX=$(( ${#string} - ${#rest} - 1 )) | ||
startY=$(($row-1)) | ||
fi | ||
done | ||
|
||
numSpots=$(($row*${#map[0]})) | ||
echo "Starting point: $startX $startY numSpots: $numSpots" | ||
|
||
|
||
function getKeyCode () { | ||
local X=$1 | ||
local Y=$2 | ||
char="${map[$Y]:$X:1}" | ||
if [[ "$char" == "E" ]]; then | ||
echo $(printf %d "'z") | ||
else | ||
echo $(printf %d "'${map[$Y]:$X:1}") | ||
fi | ||
} | ||
|
||
function findPossiblePaths () { | ||
local X=$1 | ||
local Y=$2 | ||
local fromX=$3 | ||
local fromY=$4 | ||
|
||
possibilities="" | ||
for x in $(seq $(($X-1)) $(($X+1))); do | ||
for y in $(seq $(($Y-1)) $(($Y+1))); do | ||
#echo " Checking $x $y" >&2 | ||
if ! [[ $fromX -eq $x && $fromY -eq $y ]] && ! [[ $X -eq $x && $Y -eq $y ]] && [[ $x -ge 0 && $x -lt ${#map[0]} && $y -ge 0 && $y -lt $row ]] && [[ $x -eq $X || $y -eq $Y ]] ; then | ||
current=$(getKeyCode $X $Y) | ||
next=$(getKeyCode $x $y) | ||
#echo " $x $y passed the coord check, onto keycode $current $next" >&2 | ||
if [[ "$current $(($current+1))" == *"$next"* ]] || [[ $next -lt $current && ! $next -eq 83 ]] || [[ $current -eq 83 ]]; then | ||
#echo " $x $y was valid" >&2 | ||
if [[ $next -ge $current ]]; then | ||
possibilities="$x,$y $possibilities" | ||
else | ||
possibilities="$possibilities $x,$y " | ||
fi | ||
fi | ||
fi | ||
done | ||
done | ||
#echo $possibilities >&2 | ||
echo $possibilities | ||
} | ||
|
||
function tryPath () { | ||
local distance=$1 | ||
local X=$2 | ||
local Y=$3 | ||
local lastX=$4 | ||
local lastY=$5 | ||
|
||
distance=$(($distance+1)) | ||
echo "X: $X Y: $Y Row: ${map[$Y]} Current char: ${map[$Y]:$X:1} Distance: $distance" >&2 | ||
|
||
if [[ "${map[$Y]:$X:1}" == "E" ]]; then | ||
#I am at the target, return | ||
echo "Found it at $X $Y, distance $(($distance-1))!" >&2 | ||
echo $(($distance-1)) | ||
sleep 5 | ||
elif [[ $distance -le $numSpots ]]; then | ||
|
||
declare -A paths | ||
counter=0 | ||
for coord in $(findPossiblePaths $X $Y $lastX $lastY); do | ||
counter=$(($counter+1)) | ||
IFS="," read -ra xy <<< $coord | ||
#sleep 1 | ||
paths[$counter]=$(tryPath $distance ${xy[0]} ${xy[1]} $X $Y) | ||
done | ||
|
||
#sleep 1 | ||
if [[ $counter -eq 0 ]]; then #No paths could be tried | ||
echo " No goal" >&2 | ||
echo "-" | ||
else | ||
IFS=$'\n' sorted=($(sort -n <<<"${paths[*]}")) | ||
echo " Returning ${sorted[0]}" | ||
echo ${sorted[0]} | ||
fi | ||
else | ||
echo " Too great distance" >&2 | ||
echo "-" | ||
fi | ||
} | ||
|
||
|
||
|
||
echo "Shortest path? $(tryPath 0 $startX $startY $startX $startY)" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#!/bin/bash | ||
if [ "$#" -gt 0 ]; then | ||
printf '%s\n' "$@" | ||
fi | ||
|
||
declare -A map | ||
declare -A visited | ||
|
||
row=0 | ||
startX=0 | ||
startY=0 | ||
while IFS= read -r string; do | ||
map[$row]=$string | ||
row=$(($row+1)) | ||
if [[ "$string" == *"S"* ]]; then | ||
rest=${string#*"S"} | ||
startX=$(( ${#string} - ${#rest} - 1 )) | ||
startY=$(($row-1)) | ||
fi | ||
done | ||
|
||
numSpots=$(($row*${#map[0]})) | ||
echo "Starting point: $startX $startY numSpots: $numSpots" | ||
|
||
for x in $(seq 0 $((${#map[0]}-1))); do # Mark all as not visited | ||
for y in $(seq 0 $(($row-1))); do | ||
visited["$x,$y"]=0 | ||
done | ||
done | ||
|
||
|
||
|
||
function getKeyCode () { | ||
local X=$1 | ||
local Y=$2 | ||
char="${map[$Y]:$X:1}" | ||
if [[ "$char" == "E" ]]; then | ||
echo $(printf %d "'z") | ||
else | ||
echo $(printf %d "'${map[$Y]:$X:1}") | ||
fi | ||
} | ||
|
||
function findPossiblePaths () { | ||
local X=$1 | ||
local Y=$2 | ||
|
||
possibilities="" | ||
for x in $(seq $(($X-1)) $(($X+1))); do | ||
for y in $(seq $(($Y-1)) $(($Y+1))); do | ||
#echo " Checking $x $y" >&2 | ||
if ! [[ $X -eq $x && $Y -eq $y ]] && [[ $x -ge 0 && $x -lt ${#map[0]} && $y -ge 0 && $y -lt $row ]] && [[ $x -eq $X || $y -eq $Y ]] ; then | ||
current=$(getKeyCode $X $Y) | ||
next=$(getKeyCode $x $y) | ||
#echo " $x $y passed the coord check, onto keycode $current $next" >&2 | ||
if [[ "$current $(($current+1))" == *"$next"* ]] || [[ $next -lt $current && ! $next -eq 83 ]] || [[ $current -eq 83 ]]; then | ||
#echo " $x $y was valid" >&2 | ||
possibilities="$x,$y $possibilities" | ||
fi | ||
fi | ||
done | ||
done | ||
echo $possibilities >&2 | ||
echo $possibilities | ||
} | ||
|
||
|
||
|
||
|
||
visited["$startX,$startY"]=1 | ||
|
||
queue=( ) | ||
|
||
|
||
declare -A parents | ||
|
||
target="" | ||
queue+=("$startX,$startY") | ||
while [ ${#queue[@]} -gt 0 ]; do | ||
elem=${queue[0]} | ||
queue=("${queue[@]:1}") | ||
|
||
IFS="," read -ra coords <<< $elem | ||
echo "Elem: $elem Pos: ${map[${coords[1]}]:${coords[0]}:1}" | ||
if [[ "${map[${coords[1]}]:${coords[0]}:1}" == "E" ]]; then | ||
echo "FOUND IT! $elem" | ||
target=$elem | ||
fi | ||
|
||
for coord in $(findPossiblePaths ${coords[0]} ${coords[1]}); do | ||
IFS="," read -ra xy <<< $coord | ||
if [[ ${visited["${xy[0]},${xy[1]}"]} -eq 0 ]]; then | ||
queue+=("${xy[0]},${xy[1]}") | ||
visited["${xy[0]},${xy[1]}"]=1 | ||
parents["${xy[0]},${xy[1]}"]="${coords[0]},${coords[1]}" | ||
fi | ||
done | ||
done | ||
par=$target | ||
steps=1 | ||
while [[ 1 -eq 1 ]]; do | ||
IFS="," read -ra coords <<< $par | ||
parent=${parents[$par]} | ||
echo "par: $par Parent: $parent" | ||
if [[ "$parent" == "$startX,$startY" ]]; then | ||
echo "Steps to find: $steps" | ||
exit | ||
fi | ||
par=$parent | ||
steps=$(($steps+1)) | ||
done |