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

108 lines
2.7 KiB
Bash

#!/usr/bin/env bash
declare -A KV_CACHE
read -r -a ROCK_LIST <<< "$( cat input )"
DUMP_KV_CACHE=0
BLINK_NUM=75
# KV Cache provides n depth search,
# but must always be fully divisible by BLINK_NUM
DEPTH=5
if [[ $(( BLINK_NUM % DEPTH )) -gt 0 ]] ;then printf "BLINK_NUM DEPTH mismatch.\n" && exit ; fi
ROCK_RETURN=()
ROCK_NUM=0
blink_rock () {
#printf "Blinking rock : %s\n" "$ROCK_NUM" >&2
# Remove leading zeroes
#ROCK_NUM=$(( 10#$ROCK_NUM ))
# Rule 1 : Convert 0 to 1
if [[ $ROCK_NUM -eq 0 ]]
then
ROCK_RETURN=( 1 )
return
fi
# Rule 2 : If even number of digits, split half half
DIGIT_COUNT=${#ROCK_NUM}
if [[ $(( DIGIT_COUNT % 2 )) -eq 0 ]] && [[ $DIGIT_COUNT -gt 0 ]]
then
HALF=$(( DIGIT_COUNT / 2 ))
read -r -a ROCK_RETURN <<< "$( printf "%s %s " "$(( 10#${ROCK_NUM:0:$HALF} ))" "$(( 10#${ROCK_NUM:$HALF} ))" )"
return
fi
# Rule 3 : Multiply by 2024
ROCK_RETURN=( $(( ROCK_NUM * 2024 )) )
return
}
ROCKS_TO_BLINK=()
BLINKED_ROCKS=()
# Updates the global array
blink_rocks () {
BLINKED_ROCKS=()
for ROCK in "${ROCKS_TO_BLINK[@]}"
do
ROCK_NUM=$ROCK
blink_rock
BLINKED_ROCKS+=( "${ROCK_RETURN[@]}" )
done
#printf "BLINKED_ROCKS: " >&2
#printf "%s " "${BLINKED_ROCKS[@]}" >&2
#printf "\n" >&2
}
read -r -a FINAL_LIST <<< "$( printf "%s " "${ROCK_LIST[@]}" )"
POSITION=0
while [[ $POSITION -lt $BLINK_NUM ]]
do
printf "%s Starting position %s, current len: %s, kv size: %s\n" "$( date )" "$POSITION" "${#FINAL_LIST[@]}" "${#KV_CACHE[@]}"
INTER_LIST_1=()
# Essentially move $DEPTH steps at a time
for ROCK in "${FINAL_LIST[@]}"
do
# Check if this is already cached
if [[ -v KV_CACHE["$ROCK"] ]]
then
# Retrieve cached entry
read -r -a X <<< "${KV_CACHE[$ROCK]}"
INTER_LIST_1+=( "${X[@]}" )
#printf "Cache hit. Key: %s, Value: " "$ROCK"
#printf "%s " "${KV_CACHE[$ROCK]}"
#printf "\n"
else
# Build cache entry
ROCKS_TO_BLINK=( "$ROCK" )
for (( i=0; i<DEPTH; i++ ))
do
blink_rocks
read -r -a ROCKS_TO_BLINK <<< "$( printf "%s " "${BLINKED_ROCKS[@]}" )"
done
KV_CACHE[$ROCK]=$( printf "%s " "${BLINKED_ROCKS[@]}" )
INTER_LIST_1+=( "${BLINKED_ROCKS[@]}" )
fi
done
read -r -a FINAL_LIST <<< "$( printf "%s " "${INTER_LIST_1[@]}" )"
# All rocks are calculated $DEPTH ahead
(( POSITION+=DEPTH ))
done
# Dump KV cache for debugging
if [[ $DUMP_KV_CACHE -eq 0 ]]
then
printf "Number of keys in KV cache: %s\n" "${#KV_CACHE[@]}"
printf "Dumping KV CACHE\n"
for KEY in "${!KV_CACHE[@]}"
do
printf "Key: %s, Value: %s\n" "$KEY" "${KV_CACHE[$KEY]}"
done | sort
fi
#printf "%s " "${FINAL_LIST[@]}"
#printf "\n"
printf "%s\n" "${#FINAL_LIST[@]}"