aoc/bash/2023/5/1/solution.sh

83 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
if [[ "${TRACE-0}" == "1" ]]; then
set -o xtrace
fi
cd "$(dirname "$0")"
INPUT_FILE="$1"
get_seeds ()
{
echo -n "$(grep seeds "${INPUT_FILE}" | cut -d ' ' -f 2-)"
}
gen_map ()
{
# Generates files for given index of map in input file.
local paragraph map_name map_content
paragraph=$(($1+1)) # number of paragraph in input file
map_name=$(awk -v RS= "{if(NR == ${paragraph}) print}" "${INPUT_FILE}" | head -n 1 | cut -d ' ' -f 1)
map_content=$(awk -v RS= "{if(NR == ${paragraph}) print}" "${INPUT_FILE}"| tail -n +2)
echo "${map_content}" > "${map_name}.map"
maps+=("${map_name}.map")
}
map_seed ()
{
# Usage: map_seed MAP_FILE SEED_NUMBER
# Prints the mapping of the seed number in the give map.
local map seed dest_start source_start length diff
map="$1"
seed="$2"
while read -r line; do
dest_start=$(cut -d ' ' -f 1 <<< "${line}")
source_start=$(cut -d ' ' -f 2 <<< "${line}")
length=$(cut -d ' ' -f 3 <<< "${line}")
if [[ ${seed} -ge ${source_start} && ${seed} -le $((source_start+length-1)) ]]; then
diff=$((seed-source_start))
echo -n $((dest_start+diff))
return
fi
done < "${map}"
echo -n "${seed}" # no mapping
}
main ()
{
IFS=" " read -r -a seeds <<< "$(get_seeds)"
declare -a maps=()
declare -a destinations=()
local map_count destination lowest
map_count=$(awk -v RS= 'END {print NR}' "${INPUT_FILE}")
map_count=$((map_count-1)) # one of the paragraphs in the file is seeds
for ((i=1; i<=map_count; i++)); do
gen_map "${i}"
done
for seed in "${seeds[@]}"; do
destination=''
for map in "${maps[@]}"; do
if [[ -z ${destination} ]]; then
destination=$(map_seed "${map}" "${seed}")
else
destination=$(map_seed "${map}" "${destination}")
fi
done
destinations+=("${destination}")
done
lowest="${destinations[0]}"
for dest in "${destinations[@]}"; do
if [[ ${dest} -lt ${lowest} ]]; then
lowest="${dest}"
fi
done
echo "${lowest}"
rm -f ./*.map
}
main