Working day 17 part 1

This commit is contained in:
2024-12-17 15:48:25 +08:00
parent f17b7f75d2
commit ac940aad0e
5 changed files with 403 additions and 41 deletions

View File

@ -83,28 +83,33 @@ done
CHECKPOINT_ARRAY[$END_POSITION]=0
printf "%s " "${!CHECKPOINT_ARRAY[@]}"
printf "\n"
CHECKPOINT_ARRAY_LEN=${#CHECKPOINT_ARRAY[@]}
# Iterate over checkpoints and print pairings
declare -A CHECKPOINT_PAIRS
declare -A CHECKPOINT_PAIR_WEIGHTS
PREV_UP=$(( 2 * 5 * 7 ))
PREV_DOWN=$(( 3 * 5 * 7 ))
PREV_LEFT=$(( 2 * 3 * 5 ))
PREV_RIGHT=$(( 2 * 3 * 7 ))
get_weight_change () {
local POSITION=$1
local NEXT_POSITION=$2
local DIRECTION=$3
# For same directions, weight change is 1
if [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_UP ]] && [[ $(( DIRECTION % 2 )) -eq 0 ]]
# Check if next position is moving in line with the previous direction
if [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_UP ]] && [[ $(( DIRECTION % PREV_UP )) -eq 0 ]]
then
printf "1"
return 0
elif [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_DOWN ]] && [[ $(( DIRECTION % 3 )) -eq 0 ]]
elif [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_DOWN ]] && [[ $(( DIRECTION % PREV_DOWN )) -eq 0 ]]
then
printf "1"
return 0
elif [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_LEFT ]] && [[ $(( DIRECTION % 5 )) -eq 0 ]]
elif [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_LEFT ]] && [[ $(( DIRECTION % PREV_LEFT )) -eq 0 ]]
then
printf "1"
return 0
elif [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_RIGHT ]] && [[ $(( DIRECTION % 7 )) -eq 0 ]]
elif [[ $(( NEXT_POSITION - POSITION )) -eq $DIR_RIGHT ]] && [[ $(( DIRECTION % PREV_RIGHT )) -eq 0 ]]
then
printf "1"
return 0
@ -113,45 +118,55 @@ get_weight_change () {
printf "1000"
}
recurse_travel () {
local POSITION=$1
local CHECKPOINT=$2
local DIRECTION=$3
local WEIGHT=$4
local UP=$(( POSITION - MAP_WIDTH ))
local DOWN=$(( POSITION + MAP_WIDTH ))
local LEFT=$(( POSITION - 1 ))
local RIGHT=$(( POSITION + 1 ))
local POSITION=$1 # Current position
local CHECKPOINT=$2 # Previous checkpoint
local DIRECTION=$3 # Allowed adjacent tiles
local WEIGHT=$4 # Weightage so far
# Search adjacent tiles
# Recurse if it's movable
# Add a checkpoint pair and weights if checkpoint found
if [[ $(( DIRECTION % 2 )) -eq 0 ]] && [[ $UP -gt 0 ]]
# 2 : Up
# 3 : Down
# 5 : Left
# 7 : Right
if [[ $(( DIRECTION % 2 )) -eq 0 ]]
then
if [[ ${MAP_ARRAY[$UP]} == "." ]]
local UP=$(( POSITION + DIR_UP ))
if [[ $UP -gt 0 ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$UP" "$DIRECTION" )
recurse_travel "$UP" "$CHECKPOINT" "$(( 2 * 5 * 7 ))" "$(( WEIGHT + WEIGHT_CHANGE ))"
elif [[ -v CHECKPOINT_ARRAY[$UP] ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$UP" "$DIRECTION" )
CHECKPOINT_PAIRS[$UP]=$CHECKPOINT
CHECKPOINT_PAIR_WEIGHTS["$UP-$CHECKPOINT"]=$(( WEIGHT + WEIGHT_CHANGE ))
if [[ ${MAP_ARRAY[$UP]} == "." ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$UP" "$DIRECTION" )
recurse_travel "$UP" "$CHECKPOINT" "$(( 2 * 5 * 7 ))" "$(( WEIGHT + WEIGHT_CHANGE ))"
elif [[ -v CHECKPOINT_ARRAY[$UP] ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$UP" "$DIRECTION" )
CHECKPOINT_PAIRS["$CHECKPOINT-$UP"]=0
CHECKPOINT_PAIR_WEIGHTS["$CHECKPOINT-$UP"]=$(( WEIGHT + WEIGHT_CHANGE ))
fi
fi
fi
if [[ $(( DIRECTION % 3 )) -eq 0 ]] && [[ $DOWN -lt $MAP_LEN ]]
then
if [[ ${MAP_ARRAY[$DOWN]} == "." ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$DOWN" "$DIRECTION" )
recurse_travel "$DOWN" "$CHECKPOINT" "$(( 3 * 5 * 7 ))" "$(( WEIGHT + WEIGHT_CHANGE ))"
elif [[ -v CHECKPOINT_ARRAY[$DOWN] ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$DOWN" "$DIRECTION" )
CHECKPOINT_PAIRS[$DOWN]=$CHECKPOINT
CHECKPOINT_PAIR_WEIGHTS["$DOWN-$CHECKPOINT"]=$(( WEIGHT + WEIGHT_CHANGE ))
local DOWN=$(( POSITION + DIR_DOWN ))
if [[ $DOWN -lt $MAP_LEN ]]
then
if [[ ${MAP_ARRAY[$DOWN]} == "." ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$DOWN" "$DIRECTION" )
recurse_travel "$DOWN" "$CHECKPOINT" "$(( 3 * 5 * 7 ))" "$(( WEIGHT + WEIGHT_CHANGE ))"
elif [[ -v CHECKPOINT_ARRAY[$DOWN] ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$DOWN" "$DIRECTION" )
CHECKPOINT_PAIRS["$CHECKPOINT-$DOWN"]=0
CHECKPOINT_PAIR_WEIGHTS["$CHECKPOINT-$DOWN"]=$(( WEIGHT + WEIGHT_CHANGE ))
fi
fi
fi
if [[ $(( DIRECTION % 5 )) -eq 0 ]]
then
local LEFT=$(( POSITION + DIR_LEFT ))
if [[ ${MAP_ARRAY[$LEFT]} == "." ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$LEFT" "$DIRECTION" )
@ -159,12 +174,13 @@ recurse_travel () {
elif [[ -v CHECKPOINT_ARRAY[$LEFT] ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$LEFT" "$DIRECTION" )
CHECKPOINT_PAIRS[$LEFT]=$CHECKPOINT
CHECKPOINT_PAIR_WEIGHTS["$LEFT-$CHECKPOINT"]=$(( WEIGHT + WEIGHT_CHANGE ))
CHECKPOINT_PAIRS["$CHECKPOINT-$LEFT"]=0
CHECKPOINT_PAIR_WEIGHTS["$CHECKPOINT-$LEFT"]=$(( WEIGHT + WEIGHT_CHANGE ))
fi
fi
if [[ $(( DIRECTION % 7 )) -eq 0 ]]
then
local RIGHT=$(( POSITION + DIR_RIGHT ))
if [[ ${MAP_ARRAY[$RIGHT]} == "." ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$RIGHT" "$DIRECTION" )
@ -172,25 +188,66 @@ recurse_travel () {
elif [[ -v CHECKPOINT_ARRAY[$RIGHT] ]]
then
WEIGHT_CHANGE=$( get_weight_change "$POSITION" "$RIGHT" "$DIRECTION" )
CHECKPOINT_PAIRS[$RIGHT]=$CHECKPOINT
CHECKPOINT_PAIR_WEIGHTS["$RIGHT-$CHECKPOINT"]=$(( WEIGHT + WEIGHT_CHANGE ))
CHECKPOINT_PAIRS["$CHECKPOINT-$RIGHT"]=0
CHECKPOINT_PAIR_WEIGHTS["$CHECKPOINT-$RIGHT"]=$(( WEIGHT + WEIGHT_CHANGE ))
fi
fi
}
ITER=99999
for CHECKPOINT in "${!CHECKPOINT_ARRAY[@]}"
do
recurse_travel "$CHECKPOINT" "$CHECKPOINT" "$CHECKPOINT" "$(( 2 * 3 * 5 * 7 ))" "0"
recurse_travel "$CHECKPOINT" "$CHECKPOINT" "$(( 2 * 3 * 5 * 7 ))" "0"
(( ITER-- ))
if [[ $ITER -eq 0 ]] ; then break ;fi
done
for CHECKPOINT in "${!CHECKPOINT_PAIRS[@]}"
do
printf "DEST %s from checkpoint %s\n" "${CHECKPOINT_PAIRS[$CHECKPOINT]}" "$CHECKPOINT"
done
printf "Dest %s from checkpoint %s\n" "${CHECKPOINT_PAIRS[$CHECKPOINT]}" "$CHECKPOINT"
done | sort
for CHECKPOINT in "${!CHECKPOINT_PAIR_WEIGHTS[@]}"
do
printf "Weight %s for checkpoint pair %s\n" "${CHECKPOINT_PAIR_WEIGHTS[$CHECKPOINT]}" "$CHECKPOINT"
done | sort
if [[ ${#CHECKPOINT_PAIRS[@]} -ne ${#CHECKPOINT_PAIR_WEIGHTS[@]} ]]
then
printf "Checkpoint count with weight counts do not match.\n"
fi
# Map out full paths for calculate final results for it
# Quite akin to BFS
declare -A FINAL_PATH
FINAL_PATH[$START_POSITION]=0
for (( i=0 ; i<CHECKPOINT_ARRAY_LEN ; i+= 1 )) # Start to end should only have these many iterations
do
for PATH in "${!FINAL_PATH[@]}"
do
CHECKPOINT=${PATH##*-}
PATH_SCORE=${FINAL_PATH[$PATH]}
if [[ $CHECKPOINT -eq $END_POSITION ]] # This path has completed
then
continue
fi
for NEXT_CHECKPOINT in "${!CHECKPOINT_ARRAY[@]}" # Check if there is a next mapping
do
if [[ $PATH =~ -$NEXT_CHECKPOINT- ]]; then continue; fi # Prevent loops
PAIR="$CHECKPOINT-$NEXT_CHECKPOINT"
if [[ -v CHECKPOINT_PAIRS[$PAIR] ]]
then
FINAL_PATH["$PATH-$NEXT_CHECKPOINT"]=$(( PATH_SCORE + ${CHECKPOINT_PAIR_WEIGHTS[$PAIR]} ))
unset "FINAL_PATH[$PATH]"
fi
done
done
done
# Score the path
#
for PATH in "${!FINAL_PATH[@]}"
do
END=${PATH##*-}
if [[ $END == "$END_POSITION" ]]
then
printf "Path: %s weight: %s \n" "$PATH" "${FINAL_PATH[$PATH]}"
fi
done
print_map
#print_map