126 lines
3.5 KiB
Bash
126 lines
3.5 KiB
Bash
|
#!/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
|