diff --git a/2024/day-9/solution-2.sh b/2024/day-9/solution-2.sh index 5086405..76b72cc 100644 --- a/2024/day-9/solution-2.sh +++ b/2024/day-9/solution-2.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -FILE=input +FILE=$1 # Sparse sequence read -r -a SPARSE_ARRAY <<< "$( INDEX=0 @@ -15,13 +15,13 @@ read -r -a SPARSE_ARRAY <<< "$( else for (( i=1; i<=CHAR; i++ )) do - printf ". " + printf "%s " '-1' done fi (( INDEX++ )) done <<< "$( sed -E 's/(.)/\1\n/g' "$FILE" | grep -v '^$' )" )" -printf "%s" "${SPARSE_ARRAY[@]}" +printf "%s" "${SPARSE_ARRAY[@]}" | fold -w 100 printf "\n" printf "Sparse array len: %s\n" "${#SPARSE_ARRAY[@]}" SHADOW_ARRAY=( "${SPARSE_ARRAY[@]}" ) @@ -29,72 +29,87 @@ SHADOW_ARRAY=( "${SPARSE_ARRAY[@]}" ) # Start by working backwards j=$(( ${#SPARSE_ARRAY[@]} - 1 )) # Moveable index since file blocks jump k=0 # SHADOW_ARRAY cursor +LAST_SKIP=9999 while [[ $j -ge 0 ]] do - if [[ ${SPARSE_ARRAY[j]} != '.' ]] + # Find a file + if [[ ${SPARSE_ARRAY[j]} -eq -1 ]] 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 + # Not a file (( j-- )) + continue + fi + + # Get file size + # j moved to index before file head + 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 + + # Since search space is constantly decreasing + # Contiguous space can only keep getting smaller + if [[ $FILE_SIZE -ge $LAST_SKIP ]] + then + printf "File %s size %s skipped. Last skip: %s\n" "$ID" "$FILE_SIZE" "$LAST_SKIP" + continue + fi + + # Search for available contiguous space + # Search from start until the file itself + k=0 + while [[ $k -le $j ]] && [[ $k -le ${#SHADOW_ARRAY[@]} ]] + do + CONT_SPACE=0 + + # Skip ahead until first match of space + while [[ ${SHADOW_ARRAY[k]} -ne -1 ]] && [[ $k -le ${#SHADOW_ARRAY[@]} ]] + do + (( k++ )) + done + + # Space found, now get contiguous length + while [[ ${SHADOW_ARRAY[k]} -eq -1 ]] && [[ $k -le ${#SHADOW_ARRAY[@]} ]] + do + (( CONT_SPACE++ )) + (( k++ )) + done + + # Space length is ok, can proceed + if [[ $FILE_SIZE -le $CONT_SPACE ]] ;then break; fi + done + + # Space length ok, can proceed + if [[ $FILE_SIZE -le $CONT_SPACE ]] + then + # Move the file to head of contiguous space + (( k-= CONT_SPACE )) + while [[ $FILE_SIZE -gt 0 ]] && \ + [[ ${SHADOW_ARRAY[k]} -eq -1 ]] && \ + [[ ${SHADOW_ARRAY[j+FILE_SIZE]} -ne -1 ]] + do + SHADOW_ARRAY[k]=$ID + SHADOW_ARRAY[j+FILE_SIZE]=-1 + (( k++ )) + (( FILE_SIZE-- )) + done + else + LAST_SKIP=$FILE_SIZE + printf "File %s skipped. File size: %s\n" "$ID" "$FILE_SIZE" + continue fi done -printf "%s" "${SHADOW_ARRAY[@]}" +printf "%s " "${SHADOW_ARRAY[@]}" | fold -w 100 | tee final-result | cat printf "\n" -# Generate checksum for sparse array +# Generate checksum for shadow array CHECKSUM=0 for (( i=0; i<${#SHADOW_ARRAY[@]}; i++ )) do - if [[ ${SHADOW_ARRAY[i]} != "." ]] ;then (( CHECKSUM += i * SHADOW_ARRAY[i] )); fi + if [[ ${SHADOW_ARRAY[i]} -ne -1 ]] ;then (( CHECKSUM += i * SHADOW_ARRAY[i] )); fi done -printf "%s" "$CHECKSUM" +printf "%s\n" "$CHECKSUM"