aoc/3/2/solution.sh

126 lines
3.5 KiB
Bash
Raw Normal View History

2023-12-03 21:25:24 +01:00
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
if [[ "${TRACE-0}" == "1" ]]; then
set -o xtrace
fi
LINES=$(wc -l < "$1")
COLUMNS=140
mapfile -t -O 1 INPUT < "$1"
declare -a gear_ratios
find_gears ()
{
# Find and append gear ratios to array.
for ((line=1; line<=LINES; line++)); do
for ((column=1; column<=COLUMNS; column++)); do
if [[ $(arr "${line}" "${column}") =~ ^\*$ ]]; then
declare -i ratio=1
declare -a adjacent=()
for ((i=column-1; i<=column+1; i++)); do # check above
if [[ $(arr $((line-1)) "${i}") =~ ^[0-9]$ ]]; then
number="$(arr $((line-1)) "${i}")"
for ((j=i-1; j>i-3; j--)); do # check before i, numbers are max 3-digit
if [[ $(arr $((line-1)) "${j}") =~ ^[0-9]$ ]]; then
number="$(arr $((line-1)) "${j}")${number}"
else
break
fi
done
add_to_i=0
for ((k=i+1; k<i+3; k++)); do # check after i
if [[ $(arr $((line-1)) "${k}") =~ ^[0-9]$ ]]; then
number="${number}$(arr $((line-1)) "${k}")"
add_to_i=$((add_to_i+1))
else
break
fi
done
i=$((i+add_to_i))
adjacent+=("${number}")
fi
done
for ((i=column-1; i<=column+1; i++)); do # check below
if [[ $(arr $((line+1)) "${i}") =~ ^[0-9]$ ]]; then
number="$(arr $((line+1)) "${i}")"
for ((j=i-1; j>i-3; j--)); do # check before i
if [[ $(arr $((line+1)) "${j}") =~ ^[0-9]$ ]]; then
number="$(arr $((line+1)) "${j}")${number}"
else
break
fi
done
add_to_i=0
for ((k=i+1; k<i+3; k++)); do # check after i
if [[ $(arr $((line+1)) "${k}") =~ ^[0-9]$ ]]; then
number="${number}$(arr $((line+1)) "${k}")"
add_to_i=$((add_to_i+1))
else
break
fi
done
i=$((i+add_to_i))
adjacent+=("${number}")
fi
done
if [[ $(arr "${line}" $((column-1))) =~ ^[0-9]$ ]]; then # check before gear
number="$(arr "${line}" $((column-1)))"
for ((i=column-2; i>column-4; i--)); do # search for beginning
if [[ $(arr "${line}" "${i}") =~ ^[0-9]$ ]]; then
number="$(arr "${line}" "${i}")${number}"
else
break
fi
done
adjacent+=("${number}")
fi
if [[ $(arr "${line}" $((column+1))) =~ ^[0-9]$ ]]; then # check after gear
number="$(arr "${line}" $((column+1)))"
for ((i=column+2; i<column+4; i++)); do # search for end
if [[ $(arr "${line}" "${i}") =~ ^[0-9]$ ]]; then
number="${number}$(arr "${line}" "${i}")"
else
break
fi
done
adjacent+=("${number}")
fi
if [[ ${#adjacent[@]} -gt 1 ]]; then
for number in "${adjacent[@]}"; do
ratio=$((ratio*number))
done
gear_ratios+=("${ratio}")
fi
fi
done
done
}
arr ()
{
# Usage: arr LINE COLUMN
line="$1"
column=$(($2-1))
if ((line<=0)) || ((line>LINES)) || ((column<0)); then
echo -n ''
else
echo -n "${INPUT[${line}]:${column}:1}"
fi
}
main ()
{
find_gears
sum=0
for number in "${gear_ratios[@]}"; do
sum=$((sum+number))
done
echo "${sum}"
}
main