Описание проблемы:
Я хочу перебирать массив (сплющенный 2D -> 1D массив прямо сейчас) и продолжать проверять его ближайших соседей. Из этого я хочу определить, мертвы ли они/живы («X» или «.») И изменить свое состояние в соответствии с моими правилами (упрощенным конвейером).Проверка соседних элементов в плоском массиве
Моя сетка выглядит следующим образом .: например
...............
...........X...
.X.......X...X.
...............
....X..........
....X..........
...............
.....XX........
..........X....
...............
Cells alive: 9
Но у меня есть этот массив сплющенный в 1D массив для перебора над ним. Таким образом, в основном это превращается в нечто вроде этого: ....X...X....X.
и т.д. После записи его на бумаге, я думаю, есть несколько случаев, чтобы проверить в этой «сетки»:
- TopLeft элемент (я = 0) - первый элемент , 3 соседей/случаи, чтобы проверить
- TopRight элемент (I = NCOLUMNS - 1), как указано выше
- BottomLeft элементов (I = NCOLUMNS * Nrows - NCOLUMNS), как указано выше
- BottomRight элементов (I = NCOLUMNS * Nrows - 1) - последний элемент, как указано выше
- Элементы «границы» (5 nei ghbours каждый без угловых элементов)
- Средних элементов с 8 соседями
Но это, кажется, совершенно глупо, чтобы проверить его с некоторыми, если это и заявлением случае. Если бы я мог использовать реальные 2D-массивы, я бы мог просто создать массив смещений (-1, 1), (0, 1) ... и так далее. Но я не могу придумать, как обращаться с этим кодом. Я буду очень рад за любые советы/примеры и так далее.
Мой код до сих пор:
cellsAlive=0
#STDIN variables
geneFile=$1
nRows=$2
nColumns=$3
let "cells = $nRows * $nColumns"
declare -i tick_rate # instead maybe use watch or sleep
readarray -t geneArr < $geneFile # -t removes a trailing newline from each line read.
elementsCounts=${#geneArr[@]}
echo -e "--- Coordinates ---"
for ((i = 0; i < $elementsCounts; i++)); do
echo "${geneArr[$i]}" #| cut -d' ' -f2 $geneFile | head -2
done
echo -e "\n--- Grid ---"
#file must end with a newline
[[ $geneFile && -f $geneFile && -r $geneFile ]] || { printf >&2 'arg must be readable file.\n'; exit; }
array=()
for ((i=0; i<nRows*nColumns; ++i)); do
array+=('.')
done
printf "\n"
while read -r x y; do
[[ $x && $y ]] || continue
[[ $x = +([[:digit:]]) && $y = +([[:digit:]]) ]] || continue
((x=10#$x,y=10#$y)) #10 digit base
((x<nRows && y<nColumns)) || continue
array[x+y*nRows]='X'
if [[ ${array[x+y*nRows]} == 'X' ]]; then
let "cellsAlive += 1"
fi
done < "$geneFile"
# print to stdout and to file
for((i=0;i<nColumns;++i)); do
printf '%s' "${array[@]:i*nRows:nRows}" $'\n'
done | tee currentState
arrayCopy=("${array[@]}")
printf "Cells alive: %d" $cellsAlive ; printf "\n"
# printf "\n"
for ((i = 0; i < ${#arrayCopy[@]}; i++)); do
#neighboursCount=0
case $i in
"0") if [[ ${arrayCopy[$(($i - 1))]} == 'X' ]] || [[ ${arrayCopy[$(($i + $nColumns))]} == 'X' ]] || [[ ${arrayCopy[$(($i + $nColumns + 1))]} == 'X' ]] ; then #TopLeft
echo "That is just ridiculous way to check it..."
fi ;;
"$(($nColumns - 1))") printf "${arrayCopy[$i]}" ;; #TopRight
"$(($nColumns*$nRows-1))") printf "${arrayCopy[$i]}" ;; #BottomRight
"$(($nColumns*$nRows-$nColumns))") printf "${arrayCopy[$i]}" ;; #BottomLeft
*) ;; #Middle elements with 8 neighbours
esac
done
printf "\n"
Заранее спасибо за помощь.
Пример geneFile.txt (добавить пустым, как в конце):
1 2
4 5
6 7
13 2
5 7
4 4
9 2
11 1
10 8
звучит для меня как вы хотите реализовать как версию для игры life :) –
Спасибо за исправление сетки. Да, я просто буду рад за какую-то подсказку прямо сейчас, я собираюсь в кругах и думаю об изменении того, как я подошел к проблеме, - но, возможно, это не обязательно, и кто-то даст хороший совет ^^. Если вопрос слишком общий, я могу попытаться сузить его до определенной проблемы (хотя мне действительно нужно больше общего совета). – learningHappily