#!/usr/bin/env bash declare -a __GRID__PERPENDICULAR_DIRECTIONS=( '1 0' '0 1' '0 -1' '-1 0' ) grid.coord_to_index() { local width="$1" x="$2" y="$3" printf '%d' "$((y * width + x))" } grid.index_to_coord() { local width="$1" index="$2" printf '%d %d\n' "$((index % width))" "$((index / width))" } grid.text_to_grid() { local -n __grid_text_to_grid_grid="$1" local text="$2" width=0 height=0 c=0 __grid_text_to_grid_grid=() while read -r line; do ((height++)) [[ "$width" ]] && width="${#line}" while IFS= read -rd '' -n 1 char; do [[ "$char" == $'\n' ]] && continue __grid_text_to_grid_grid+=(["$c"]="$char") ((c++)) done <<<"$line" done <<<"$text" __grid_text_to_grid_grid+=([width]="$width") __grid_text_to_grid_grid+=([height]="$height") } grid.perpendicular_neighbors() { local -n __grid_perpendicular_neighbors_grid="$1" local x="$2" y="$3" for dir in "${__GRID__PERPENDICULAR_DIRECTIONS[@]}"; do local dx dy nx ny read -r dx dy <<<"$dir" nx="$(( x + dx ))" ny="$(( y + dy ))" (( nx >= 0 && nx < __grid_perpendicular_neighbors_grid[width] && ny >= 0 && ny < __grid_perpendicular_neighbors_grid[height] )) || continue printf '%d %d\n' "$nx" "$ny" done } grid.get() { local -n __grid_get_grid="$1" local x="$2" y="$3" width="${__grid_get_grid[width]}" (( x >= 0 && x < __grid_get_grid[width] && y >= 0 && y < __grid_get_grid[height] )) || { echo "($x,$y) is out of bounds for grid of size (${__grid_get_grid[width]},${__grid_get_grid[height]})" >&2 return 1 } printf '%s\n' "${__grid_get_grid["$((y * width + x))"]}" } grid.set() { local -n __grid_set_grid="$1" local x="$2" y="$3" value="$4" width="${__grid_set_grid[width]}" (( x >= 0 && x < __grid_set_grid[width] && y >= 0 && y < __grid_set_grid[height] )) || { echo "($x,$y) is out of bounds for grid of size (${__grid_set_grid[width]},${__grid_set_grid[height]})" >&2 return 1 } __grid_set_grid["$((y * width + x))"]="$value" }