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