Files
advent-of-code/2024/day-12/solution-2.sh

113 lines
3.4 KiB
Bash
Raw Normal View History

2024-12-12 22:49:45 +08:00
#!/usr/bin/env bash
FUNCNEST=99999
2024-12-13 16:35:36 +08:00
FILE=test-input-1
2024-12-12 22:49:45 +08:00
read -r -a MAP_ARRAY <<< "$( < "$FILE" paste -s -d "" | sed -E 's/(.)/\1\ /g' )"
MAP_LEN=${#MAP_ARRAY[@]}
MAP_WIDTH=$(( $( head -1 "$FILE" | wc -c ) -1 ))
MAP_WIDTH_INV=$(( 0 - MAP_WIDTH ))
MAP_HEIGHT=$( < "$FILE" wc -l )
printf "Len: %s Width: %s Height: %s\n" "$MAP_LEN" "$MAP_WIDTH" "$MAP_HEIGHT"
# Check if tiles are adjacent and do not violate bounds
check_adjacent () {
# Check for out of map bounds
if [[ $2 -lt 0 ]] || [[ $2 -gt $MAP_LEN ]] ; then return 1 ; fi
DIFF=$(( $2 - $1 ))
# Valid adjacent distances
2024-12-13 16:35:36 +08:00
if [[ $DIFF -eq 1 ]] || [[ $DIFF -eq -1 ]] || [[ $DIFF -eq $MAP_WIDTH ]] || [[ $DIFF -eq $MAP_WIDTH_INV ]] ; then : ; else return 1 ; fi
2024-12-12 22:49:45 +08:00
# Check for left/right bounds
if [[ $DIFF -eq 1 ]] && [[ $(( $2 % MAP_WIDTH )) -eq 0 ]] ; then return 1 ; fi
if [[ $DIFF -eq -1 ]] && [[ $(( $1 % MAP_WIDTH )) -eq 0 ]] ; then return 1 ; fi
}
2024-12-13 16:35:36 +08:00
# Basically recurse over kv and "consume" all adjacent tiles
# All tiles that are consumed are adjacent
2024-12-12 22:49:45 +08:00
check_and_unset () {
local KV_I=${1%% *} # Remove trailing whitespace
(( AREA++ ))
VALUE=${KV_CACHE[$KV_I]}
unset "KV_CACHE[$KV_I]" # "Take" it
2024-12-13 16:35:36 +08:00
2024-12-12 22:49:45 +08:00
printf "max: %s peri: %s area: %s key: %s val: %s\n" "$MAX_PERI" "$PERI_NUM" "$AREA" "$1" "$VALUE" >&2
2024-12-13 16:35:36 +08:00
# As a square, expect width and height to always be preserved
# Recursion should always be in sequence
2024-12-12 22:49:45 +08:00
unset IFS; read -r -a VAL_ARRAY <<< "$VALUE"
# Loop through adjacent tiles and recurse
2024-12-13 16:35:36 +08:00
for VAL in "${VAL_ARRAY[@]}" # VAL_ARRAY is always sorted
2024-12-12 22:49:45 +08:00
do
VAL_IDX=${VAL%% *}
if [[ -v KV_CACHE[$VAL_IDX] ]] # Check if tile has been "taken"
then
check_and_unset "$VAL_IDX"
fi
done
}
while read -r CHAR
do
# Get all indexes for a plant
read -r -a CHAR_ARRAY <<< "$(
for (( i=0; i<MAP_LEN; i++ ))
do
if [[ ${MAP_ARRAY[$i]} == "$CHAR" ]]
then
printf "%s " "$i"
fi
done
)"
#{
# printf "For char %s \n" "$CHAR"
# printf "%s " "${CHAR_ARRAY[@]}"
# printf "\n"
#} >&2
declare -A KV_CACHE
IFS=':'; while read -r VAR1 VAR2
do
2024-12-13 16:35:36 +08:00
#printf "VAR1: %s VAR2: %s\n" "$VAR1" "$VAR2" >&2
2024-12-12 22:49:45 +08:00
KV_CACHE[$VAR1]=$VAR2
done <<< "$(
# Find all adjacent tiles
for (( i=0; i<${#CHAR_ARRAY[@]}; i++ ))
do
NUM_ADJ=0
printf "%s:" "${CHAR_ARRAY[i]}"
MIN=$(( $(( i-MAP_WIDTH )) < 0 ? 0 : $(( i-MAP_WIDTH )) ))
MAX=$(( $(( i+MAP_WIDTH )) < MAP_LEN ? $(( i+MAP_WIDTH )) : $(( MAP_LEN )) ))
for (( j=MIN; j<MAX; j++ )) # There can only be MAP_WIDTH number of elements within valid range
do
if check_adjacent "${CHAR_ARRAY[i]}" "${CHAR_ARRAY[j]}"
then
printf "%s " "${CHAR_ARRAY[j]}"
(( NUM_ADJ++ ))
fi
done
printf "\n"
#printf "Num adj for %s idx %s is %s\n" "$CHAR" "${CHAR_ARRAY[$i]}" "$NUM_ADJ" >&2
done
)"
# Iterate through
for CH in "${CHAR_ARRAY[@]}"
do
CHAR=${CH%% *} # Remove trailing whitespace
if ! [[ -v KV_CACHE[$CHAR] ]]; then continue; fi
2024-12-13 16:35:36 +08:00
PERI_NUM=4 # Number of perimeters of a square
2024-12-12 22:49:45 +08:00
AREA=0
2024-12-13 16:35:36 +08:00
ROW=0
2024-12-12 22:49:45 +08:00
check_and_unset "$CHAR"
printf "char: %s max: %s peri: %s area: %s\n" "$CHAR" "$MAX_PERI" "$PERI_NUM" "$AREA" >&2
printf "%s\n" "$(( PERI_NUM * AREA ))"
done
# Get all plants
#done <<< "$( < "$FILE" grep -o '[A-Z]' | sort -u | grep -o '[A-Z]*' )"
done <<< "$( < "$FILE" grep -o '[A-Z]' | sort -u | grep -o '[A-Z]*' )" |
paste -s -d "+" | bc