Problem:
Write a program that generates a "random walk" across a 10 x 10 array. The array
will contain characters (all '.' initially). The program must randomly "walk"
from element to element, always going up, down, left or right by one element.
The elements visited by the program will be labeled with the letters A through
Z, in the order visited. Here's an example of the desired output:
A . . . . . . . . .
B C D . . . . . . .
. F E . . . . . . .
H G . . . . . . . .
I . . . . . . . . .
J . . . . . . . Z .
K . . R S T U V Y .
L M P Q . . . W X .
. N O . . . . . . .
. . . . . . . . . .
Before performing a move, check that (a) it won't go outside the array, and (b) it doesn't take us to an element that already has a letter assigned. If either condition is violated, try moving in another direction. If all four directions are blocked, the program must terminate. Here's an example of premature termination:
A B G H I . . . . .
. C F . J K . . . .
. D E . M L . . . .
. . . . N O . . . .
. . W X Y P Q . . .
. . V U T S R . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
Y is blocked on all four sides, so there's no place to put Z.
expected output:
A . . . . . . . . .
B C D . . . . . . .
. F E . . . . . . .
H G . . . . . . . .
I . . . . . . . . .
J . . . . . . . Z .
K . . R S T U V Y .
L M P Q . . . W X .
. N O . . . . . . .
. . . . . . . . . .
actual output:
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
.abcdefghi
This is C language exercise but I`m trying to write it in bash
my code which doesnt want to work
#!/bin/bash
#set -x
rows=10
cols=10
UP=0
DOWN=1
RIGHT=2
LEFT=3
i=0
b=0
#initialising and filling array with "."
while [ $i -lt $rows ]; do
while [ $b -lt $cols ]; do
my_array[$i,$b]='.'
((b++))
done
b=0
((i++))
done
#initialising array with letters from alphabet in each element in ascending order
abc=({a..z})
b=0
r=0
c=0
#set -x
#core section where movements are done with checking boundaries of array and neighboring elements
while [ "$b" -lt "${#abc[@]}" ]; do
move=$(($RANDOM % 4))
case $move in
$UP) if [ $(($r+1)) -lt $rows ] && [ "${my_array[$r+1,$c]}" == "." ]; then
((r++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($r-1)) -ge 0 ] && [ "${my_array[$r-1,$c]}" == "." ]; then
((r--))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($c+1)) -lt $cols ] && [ "${my_array[$r,$c+1]}" == "." ]; then
((c++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($c-1)) -ge 0 ] && [ "${my_array[$r,$c-1]}" == "." ]; then
((c--))
my_array[$r,$c]=${abc[$b]}
((b++))
else
b=${#abc[@]}
fi;;
$DOWN) if [ $(($r-1)) -ge 0 ] && [ "${my_array[$r-1,$c]}" == "." ]; then
((r--))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($r+1)) -lt $rows ] && [ "${my_array[$r+1,$c]}" == "." ]; then
((r++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($c+1)) -lt $cols ] && [ "${my_array[$r,$c+1]}" == "." ]; then
((c++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($c-1)) -ge 0 ] && [ "${my_array[$r,$c-1]}" == "." ]; then
((c--))
my_array[$r,$c]=${abc[$b]}
((b++))
else
b=${#abc[@]}
fi;;
$RIGHT) if [ $(($c+1)) -lt $cols ] && [ "${my_array[$r,$c+1]}" == "." ]; then
((c++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($c-1)) -ge 0 ] && [ "${my_array[$r,$c-1]}" == "." ]; then
((c--))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($r+1)) -lt $rows ] && [ "${my_array[$r+1,$c]}" == "." ]; then
((r++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($r-1)) -ge 0 ] && [ "${my_array[$r-1,$c]}" == "." ]; then
((r--))
my_array[$r,$c]=${abc[$b]}
((b++))
else
b=${#abc[@]}
fi;;
$LEFT) if [ $(($c-1)) -ge 0 ] && [ "${my_array[$r,$c-1]}" == "." ]; then
((c--))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($c+1)) -lt $cols ] && [ "${my_array[$r,$c+1]}" == "." ]; then
((c++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($r+1)) -lt $rows ] && [ "${my_array[$r+1,$c]}" == "." ]; then
((r++))
my_array[$r,$c]=${abc[$b]}
((b++))
elif [ $(($r-1)) -ge 0 ] && [ "${my_array[$r-1,$c]}" == "." ]; then
((r--))
my_array[$r,$c]=${abc[$b]}
((b++))
else
b=${#abc[@]}
fi;;
*) echo "Something went wrong..."
exit 1;;
esac
done
i=0
b=0
#set -x
#printing whats in the array
while [ $i -lt $rows ]; do
b=0
while [ $b -lt $cols ]; do
echo -n "${my_array[$i,$b]}"
((b++))
done
echo
((i++))
done
exit 0
EDIT: solved the problem forgot to explicitly declare assosiative array "declare -A my_array" forgot to use $(($r+n)) in my_array when checking moves
wouldnt mind to see more efficient code. readability doesnt matter
bash does not have multidimensional arrays.
my_array[$i,$b]='.'behaves likemy_array[$b]='.'; consequently, you only have an array of 10 elements, not 10x10.On bash 4.0+, you have access to associative arrays (basically Python's
dict). You need to declare it beforehand:This is somewhat similar to saying
my_array = {}in Python. With that,my_array[$i,$b]='.'will behave like Python'smy_array[f"{i},{b}"] = '.'.However, this means you no longer have integral indices, so
${my_array[$r-1,$c]}will behave like Python'smy_array[f"{r}-1,{c}"]— i.e. if$r=5and$c=3, it will try to access the element under the key5-1,3instead of4,3. The correct way to do this would be${my_array[$((r-1)),$c]}.Alternately, you can work with a single-dimensional array of strings, such that
${my_array[0]}is"..........". It is still a bit awkward given that bash does not let you change individual characters. This would work on an older bash as well (like the one that comes by default on a Mac OS). Here is a bash 3.2 compatible implementation: