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