aoc2024/utils/grid.sh
2024-12-23 19:20:24 +01:00

76 lines
2.0 KiB
Bash

#!/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"
}