2024-12-09 15:13:49 -05:00

79 lines
2.4 KiB
Bash

transpose () {
transpose_file=$(mktemp)
while read line; do
transpose_col=$( echo $line | sed 's/./& /g' | xargs -n 1 )
echo "$(echo "$transpose_col" | paste $transpose_file - -d '')" > $transpose_file
done <<< $(cat $1)
echo "$(cat $transpose_file)"
}
lower_triangular_diagonals () {
# Takes a file containing a matrix of letters and prints
# the diagonals of the lower triangle, starting with the major diagonal,
# each on a new line.
diagonal_file=$(mktemp)
# Use awk because wc -l undercounts by 1 if the file does not end with a blank line.
local i=$(awk 'END { print NR }' < $1)
while [ $i -gt 0 ]; do
tail -n $i $1 | awk -F '' '{++f; print $(f + 0)}' | xargs | tr -d ' ' >> $diagonal_file
i=$((i-1))
done
cat $diagonal_file
}
word_search () {
input=$1
tupni=$(echo $1 | sed 's/./&\n/g' | tac | xargs | sed 's/ //g')
# Transpose the grid, both for searching top-to-bottom, and so
# the lower_triangular_diagonals function can get the upper triangular diagonals
# via the transpose.
transposed=$(mktemp)
transpose $2 > $transposed
# Reverse the grid to get the lower-right triangle, and transpose the reverse
# to get the upper-right triangle.
reversed=$(mktemp)
rev $2 > $reversed
transposed_reversed=$(mktemp)
transpose $reversed > $transposed_reversed
diagonals=$(mktemp)
# Lower-left.
lower_triangular_diagonals $2 > $diagonals
# Upper-left; Use tail -n +2 to avoid saving the major diagonal again.
lower_triangular_diagonals $transposed | tail -n +2 >> $diagonals
# Lower-right.
lower_triangular_diagonals $reversed >> $diagonals
# Upper-right; Use tail -n +2 to avoid saving the major diagonal again.
lower_triangular_diagonals $transposed_reversed | tail -n +2 >> $diagonals
# Search for the word both forward and backward along all orthogonal
# and diagonal slices.
forward=$(cat $2 | grep -o -e "$input" | wc -l)
backward=$(cat $2 | grep -o -e "$tupni" | wc -l)
down=$(cat $transposed | grep -o -e "$input" | wc -l)
up=$(cat $transposed | grep -o -e "$tupni" | wc -l)
criss=$(cat $diagonals | grep -o -e "$input" | wc -l)
cross=$(cat $diagonals | grep -o -e "$tupni" | wc -l)
echo $((forward + backward + down + up + criss + cross))
}
word_search XMAS input.txt