#!/usr/bin/env bash FUNCNEST=99999 MAP_FILE=input-map DIRECTIONS_FILE=input-movements MAP_WIDTH=$(( ( $( head -1 "$MAP_FILE" | wc -c ) -1 ) * 2 )) # 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 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" } # Get robot position for (( i=0; i" ]] 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