diff --git a/2024/day-9/solution-2.sh b/2024/day-9/solution-2.sh new file mode 100644 index 0000000..5086405 --- /dev/null +++ b/2024/day-9/solution-2.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +FILE=input +# Sparse sequence +read -r -a SPARSE_ARRAY <<< "$( + INDEX=0 + FILE_ID=0 + while read -r CHAR + do + if [[ $(( INDEX % 2 )) -eq 0 ]] + then + for (( i=1; i<=CHAR; i++ )) do printf "%s " "$FILE_ID" + done + (( FILE_ID++ )) + else + for (( i=1; i<=CHAR; i++ )) + do + printf ". " + done + fi + (( INDEX++ )) + done <<< "$( sed -E 's/(.)/\1\n/g' "$FILE" | grep -v '^$' )" +)" +printf "%s" "${SPARSE_ARRAY[@]}" +printf "\n" +printf "Sparse array len: %s\n" "${#SPARSE_ARRAY[@]}" +SHADOW_ARRAY=( "${SPARSE_ARRAY[@]}" ) + +# Start by working backwards +j=$(( ${#SPARSE_ARRAY[@]} - 1 )) # Moveable index since file blocks jump +k=0 # SHADOW_ARRAY cursor +while [[ $j -ge 0 ]] +do + if [[ ${SPARSE_ARRAY[j]} != '.' ]] + then + + # Get file size + FILE_SIZE=0 + ID=${SPARSE_ARRAY[j]} + while [[ ${SPARSE_ARRAY[j]} == "$ID" ]] + do + (( FILE_SIZE++ )) + (( j-- )) + done + printf "File ID: %s, File size: %s\n" "$ID" "$FILE_SIZE" 2>&1 + + # Search for available contiguous space + # Search from start until the file itself + k=0 + while [[ $k -lt $(( j - FILE_SIZE )) ]] + do + CONT_SPACE=0 + + # Skip ahead until first match of space + while [[ ${SHADOW_ARRAY[k]} != "." ]] + do + (( k++ )) + done + + # Space found, now get contiguous length + while [[ ${SHADOW_ARRAY[k]} == '.' ]] + do + (( CONT_SPACE++ )) + (( k++ )) + done + + # Space length is ok, can proceed + if [[ $FILE_SIZE -le $CONT_SPACE ]] ;then break; fi + done + + # Can proceed + if [[ $FILE_SIZE -le $CONT_SPACE ]] + then + # Move the file to the contiguous space + (( k-= CONT_SPACE )) + while [[ $FILE_SIZE -gt 0 ]] + do + SHADOW_ARRAY[k]=$ID + SHADOW_ARRAY[j+FILE_SIZE]='.' + (( k++ )) + (( FILE_SIZE-- )) + done + else + # Skip the file + continue + fi + else + (( j-- )) + fi +done +printf "%s" "${SHADOW_ARRAY[@]}" +printf "\n" + +# Generate checksum for sparse array +CHECKSUM=0 +for (( i=0; i<${#SHADOW_ARRAY[@]}; i++ )) +do + if [[ ${SHADOW_ARRAY[i]} != "." ]] ;then (( CHECKSUM += i * SHADOW_ARRAY[i] )); fi +done +printf "%s" "$CHECKSUM"