Working part 2
This commit is contained in:
290
2024/day-15/solution-2.sh
Normal file
290
2024/day-15/solution-2.sh
Normal file
@ -0,0 +1,290 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
FUNCNEST=99999
|
||||
MAP_FILE=input-map
|
||||
DIRECTIONS_FILE=input-movements
|
||||
MAP_WIDTH=$(( ( $( head -1 "$MAP_FILE" | wc -c ) -1 ) * 2 ))
|
||||
MAP_HEIGHT=$( < "$MAP_FILE" wc -l )
|
||||
|
||||
# Move the robot
|
||||
move_robot() {
|
||||
MAP_ARRAY[ROBOT_POSITION]=.
|
||||
ROBOT_POSITION=$NEXT_POSITION
|
||||
MAP_ARRAY[ROBOT_POSITION]=@
|
||||
}
|
||||
|
||||
# Function to move box in n direction
|
||||
vertical_move_box () {
|
||||
local BOX_COORDINATE=$1
|
||||
local BOX_MOVE_DIRECTION=$2
|
||||
|
||||
# Normalise coordinates
|
||||
if [[ ${MAP_ARRAY[$BOX_COORDINATE]} == "[" ]]
|
||||
then
|
||||
local L_SIDE=$BOX_COORDINATE
|
||||
local R_SIDE=$(( BOX_COORDINATE +1 ))
|
||||
elif [[ ${MAP_ARRAY[$BOX_COORDINATE]} == "]" ]]
|
||||
then
|
||||
local L_SIDE=$(( BOX_COORDINATE -1 ))
|
||||
local R_SIDE=$BOX_COORDINATE
|
||||
fi
|
||||
local L_SIDE_MOVE_COORDINATE=$(( L_SIDE + BOX_MOVE_DIRECTION ))
|
||||
local R_SIDE_MOVE_COORDINATE=$(( R_SIDE + BOX_MOVE_DIRECTION ))
|
||||
|
||||
# Recurse if there are more boxes
|
||||
if [[ ${MAP_ARRAY[L_SIDE_MOVE_COORDINATE]} == "[" ]] || \
|
||||
[[ ${MAP_ARRAY[L_SIDE_MOVE_COORDINATE]} == "]" ]]
|
||||
then
|
||||
vertical_move_box "$L_SIDE_MOVE_COORDINATE" "$BOX_MOVE_DIRECTION"
|
||||
fi
|
||||
if [[ ${MAP_ARRAY[R_SIDE_MOVE_COORDINATE]} == "[" ]] || \
|
||||
[[ ${MAP_ARRAY[R_SIDE_MOVE_COORDINATE]} == "]" ]]
|
||||
then
|
||||
vertical_move_box "$R_SIDE_MOVE_COORDINATE" "$BOX_MOVE_DIRECTION"
|
||||
fi
|
||||
|
||||
MAP_ARRAY[L_SIDE_MOVE_COORDINATE]="["
|
||||
MAP_ARRAY[R_SIDE_MOVE_COORDINATE]="]"
|
||||
MAP_ARRAY[L_SIDE]="."
|
||||
MAP_ARRAY[R_SIDE]="."
|
||||
}
|
||||
|
||||
|
||||
# Function to check if box can be moved in n direction
|
||||
vertical_check_move_box () {
|
||||
local BOX_COORDINATE=$1
|
||||
local BOX_MOVE_DIRECTION=$2
|
||||
|
||||
# Normalise coordinates
|
||||
if [[ ${MAP_ARRAY[$BOX_COORDINATE]} == "[" ]]
|
||||
then
|
||||
local L_SIDE=$BOX_COORDINATE
|
||||
local R_SIDE=$(( BOX_COORDINATE +1 ))
|
||||
elif [[ ${MAP_ARRAY[$BOX_COORDINATE]} == "]" ]]
|
||||
then
|
||||
L_SIDE=$(( BOX_COORDINATE -1 ))
|
||||
R_SIDE=$BOX_COORDINATE
|
||||
fi
|
||||
|
||||
# Check if boxes are movable
|
||||
local L_SIDE_MOVE_COORDINATE=$(( L_SIDE + BOX_MOVE_DIRECTION ))
|
||||
local R_SIDE_MOVE_COORDINATE=$(( R_SIDE + BOX_MOVE_DIRECTION ))
|
||||
if [[ ${MAP_ARRAY[$L_SIDE_MOVE_COORDINATE]} == '.' ]] && \
|
||||
[[ ${MAP_ARRAY[$R_SIDE_MOVE_COORDINATE]} == '.' ]] # Can move
|
||||
then
|
||||
return 0
|
||||
elif [[ ${MAP_ARRAY[$L_SIDE_MOVE_COORDINATE]} == '#' ]] || \
|
||||
[[ ${MAP_ARRAY[$R_SIDE_MOVE_COORDINATE]} == '#' ]] # Blocked by wall
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Recurse if there are more boxes
|
||||
if [[ ${MAP_ARRAY[L_SIDE_MOVE_COORDINATE]} == "[" ]] || \
|
||||
[[ ${MAP_ARRAY[L_SIDE_MOVE_COORDINATE]} == "]" ]]
|
||||
then
|
||||
vertical_check_move_box "$L_SIDE_MOVE_COORDINATE" "$BOX_MOVE_DIRECTION"
|
||||
if [[ $? -eq 1 ]]
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if [[ ${MAP_ARRAY[R_SIDE_MOVE_COORDINATE]} == "[" ]] || \
|
||||
[[ ${MAP_ARRAY[R_SIDE_MOVE_COORDINATE]} == "]" ]]
|
||||
then
|
||||
vertical_check_move_box "$R_SIDE_MOVE_COORDINATE" "$BOX_MOVE_DIRECTION"
|
||||
if [[ $? -eq 1 ]]
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
horizontal_move_box () {
|
||||
|
||||
local BOX_COOR=$1
|
||||
local BOX_MOVE_DIRECTION=$2
|
||||
|
||||
local NEXT_SPOT=$(( BOX_COOR + BOX_MOVE_DIRECTION * 2 ))
|
||||
if [[ ${MAP_ARRAY[$NEXT_SPOT]} == "#" ]]
|
||||
then
|
||||
return 1 # Failed to move box
|
||||
elif [[ ${MAP_ARRAY[$NEXT_SPOT]} == "[" ]] || \
|
||||
[[ ${MAP_ARRAY[$NEXT_SPOT]} == "]" ]]
|
||||
then
|
||||
horizontal_move_box "$NEXT_SPOT" "$BOX_MOVE_DIRECTION"
|
||||
if [[ $? -eq 1 ]] ; then return 1 ; fi
|
||||
elif [[ ${MAP_ARRAY[$NEXT_SPOT]} != "." ]]
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Move the box
|
||||
if [[ $NEXT_SPOT -lt $(( BOX_COOR + BOX_MOVE_DIRECTION )) ]]
|
||||
then
|
||||
MAP_ARRAY[NEXT_SPOT]="["
|
||||
MAP_ARRAY[BOX_COOR + BOX_MOVE_DIRECTION]="]"
|
||||
else
|
||||
MAP_ARRAY[BOX_COOR + BOX_MOVE_DIRECTION]="["
|
||||
MAP_ARRAY[NEXT_SPOT]="]"
|
||||
fi
|
||||
MAP_ARRAY[BOX_COOR]="."
|
||||
}
|
||||
|
||||
# Load map
|
||||
read -r -a TEST_ARRAY <<< "$(
|
||||
< "$MAP_FILE" paste -s -d "" |
|
||||
sed -E '
|
||||
s/#/##/g;
|
||||
s/\./../g;
|
||||
s/@/@./g;
|
||||
s/O/[]/g;
|
||||
s/(.)(.)/\1 \2 /g'
|
||||
)"
|
||||
read -r -a MAP_ARRAY <<< "$(
|
||||
< "$MAP_FILE" paste -s -d "" |
|
||||
sed -E '
|
||||
s/#/##/g;
|
||||
s/\./../g;
|
||||
s/@/@./g;
|
||||
s/O/[]/g;
|
||||
s/(.)(.)/\1 \2 /g'
|
||||
)"
|
||||
MAP_LEN=${#MAP_ARRAY[@]}
|
||||
|
||||
print_map () {
|
||||
printf "%s " "${MAP_ARRAY[@]}" |
|
||||
fold -w $(( MAP_WIDTH * 2 ))
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
# Count boxes
|
||||
#BOX_COUNT=0
|
||||
#for (( i=0; i<MAP_LEN; i++ ))
|
||||
#do
|
||||
# if [[ ${MAP_ARRAY[$i]} == "[" ]]
|
||||
# then
|
||||
# (( BOX_COUNT++ ))
|
||||
# fi
|
||||
#done
|
||||
#printf "Box count: %s\n" "$BOX_COUNT"
|
||||
|
||||
# Get robot position
|
||||
for (( i=0; i<MAP_LEN; i++ ))
|
||||
do
|
||||
if [[ ${MAP_ARRAY[$i]} == "@" ]]
|
||||
then
|
||||
ROBOT_POSITION=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
printf "Robot position : %s\n" "$ROBOT_POSITION"
|
||||
|
||||
# Hardcode direction values
|
||||
UP=$(( - MAP_WIDTH ))
|
||||
DOWN=$MAP_WIDTH
|
||||
LEFT=-1
|
||||
RIGHT=1
|
||||
|
||||
# Iterate through directions
|
||||
MOVES=0
|
||||
print_map
|
||||
while read -r DIRECTION
|
||||
do
|
||||
|
||||
# Interpret directions
|
||||
if [[ $DIRECTION == "^" ]]
|
||||
then
|
||||
DIRECTION_VALUE=$UP
|
||||
elif [[ $DIRECTION == "v" ]]
|
||||
then
|
||||
DIRECTION_VALUE=$DOWN
|
||||
elif [[ $DIRECTION == "<" ]]
|
||||
then
|
||||
DIRECTION_VALUE=$LEFT
|
||||
elif [[ $DIRECTION == ">" ]]
|
||||
then
|
||||
DIRECTION_VALUE=$RIGHT
|
||||
fi
|
||||
|
||||
NEXT_POSITION=$(( ROBOT_POSITION + DIRECTION_VALUE ))
|
||||
|
||||
# Box in front
|
||||
if [[ ${MAP_ARRAY[$NEXT_POSITION]} == "[" ]] || \
|
||||
[[ ${MAP_ARRAY[$NEXT_POSITION]} == "]" ]]
|
||||
then
|
||||
#printf "Hit box.\n"
|
||||
if [[ $DIRECTION_VALUE -eq $LEFT ]] || \
|
||||
[[ $DIRECTION_VALUE -eq $RIGHT ]]
|
||||
then
|
||||
#printf "Left right box movement.\n"
|
||||
if horizontal_move_box "$NEXT_POSITION" "$DIRECTION_VALUE"
|
||||
then
|
||||
move_robot
|
||||
fi
|
||||
elif [[ $DIRECTION_VALUE -eq $UP ]] || \
|
||||
[[ $DIRECTION_VALUE -eq $DOWN ]]
|
||||
then
|
||||
#printf "Up down box movement.\n"
|
||||
if vertical_check_move_box "$NEXT_POSITION" "$DIRECTION_VALUE"
|
||||
then
|
||||
vertical_move_box "$NEXT_POSITION" "$DIRECTION_VALUE"
|
||||
move_robot
|
||||
fi
|
||||
fi
|
||||
|
||||
# Wall in front, do nothing
|
||||
elif [[ ${MAP_ARRAY[$NEXT_POSITION]} == "#" ]]
|
||||
then
|
||||
#printf "Next: %s Skipping\n" "${MAP_ARRAY[$NEXT_POSITION]}"
|
||||
:
|
||||
# Empty space, move forward
|
||||
elif [[ ${MAP_ARRAY[$NEXT_POSITION]} == "." ]]
|
||||
then
|
||||
#printf "Next: %s Move robot forward\n" "${MAP_ARRAY[$NEXT_POSITION]}"
|
||||
move_robot
|
||||
fi
|
||||
(( MOVES++ ))
|
||||
|
||||
#print_map
|
||||
done <<< "$( < "$DIRECTIONS_FILE" paste -s -d "" | sed -E 's/(.)(.)/\1 \2 /g' | tr ' ' '\n' )"
|
||||
printf "Moves: %s\n" "$MOVES"
|
||||
|
||||
print_map
|
||||
|
||||
# Calculate GPS values for boxes
|
||||
SUM=0
|
||||
BOX_COUNT=0
|
||||
for (( i=0; i<MAP_LEN; i++ ))
|
||||
do
|
||||
if [[ ${MAP_ARRAY[i]} == "[" ]]
|
||||
then
|
||||
(( BOX_COUNT++ ))
|
||||
#X_L=$(( i % MAP_WIDTH ))
|
||||
#X_R=$(( MAP_WIDTH - (i % MAP_WIDTH ) -1 ))
|
||||
#Y_T=$(( i / MAP_WIDTH * 100 ))
|
||||
#Y_B=$(( ( MAP_HEIGHT - i / MAP_WIDTH ) * 100 ))
|
||||
#X=$(( X_R > X_L ? X_L : X_R ))
|
||||
#Y=$(( Y_T > Y_B ? Y_B : Y_T ))
|
||||
X=$(( i % MAP_WIDTH ))
|
||||
Y=$(( i / MAP_WIDTH * 100 ))
|
||||
GPS=$(( X + Y ))
|
||||
#printf "Box %s X: %s Y: %s GPS: %s\n" "$i" "$X" "$Y" "$GPS"
|
||||
#if [[ $GPS -lt 0 ]] ; then printf "Negative GPS: %s for box %s\n" "$GPS" "$i"; continue; fi
|
||||
(( SUM+=GPS ))
|
||||
fi
|
||||
done
|
||||
printf "Sum: %s\n" "$SUM"
|
||||
printf "Box count: %s\n" "$BOX_COUNT"
|
||||
|
||||
# Compare and test if walls have moved
|
||||
for (( i=0; i<MAP_LEN; i++ ))
|
||||
do
|
||||
if [[ ${TEST_ARRAY[i]} == "#" ]]
|
||||
then
|
||||
if [[ ${TEST_ARRAY[i]} != "${MAP_ARRAY[i]}" ]]
|
||||
then
|
||||
printf "Index %s Wall changed.\n" "$i"
|
||||
fi
|
||||
fi
|
||||
done
|
Reference in New Issue
Block a user