Code review: recursion in circular array, reduce two functions to one?

Hello,
I think there's an easier way to do this but can't seem to recall but given an array of animals[0...5] and an initial value is a random index in the array, here it's 3.

3,4,5,4,3,2,1,0,1,2,3,4,5,4,3,2,1,0... inifinite repeat

a quick brute force solution i came up with was two functions, i set a limit of 20 so it doesn't become a memory bomb. there would be some kind of other conditional break point.

func fwd()
{
  counter += 1
  while(currentRow < (animals.count - 1))
  { currentRow += 1 }
  if counter < 20 { bk() }
}

func bk()
{
  counter += 1
  while(currentRow > 0)
  { currentRow -= 1 }
  if counter < 20 { fwd () }
}

fwd()

That spec is beyond me. Mayhap others, with some assumptions on e.g. shell and data structure, find a sensible interpratation of what you write.

For an index not to exceed array boundaries the modulo operator has proven quite helpful.

1 Like

Maybe you could have an adjustment value that you would always add. When the counter gets high, you set the adjustment value to -1. When it gets back to zero, you set it to 1. That way, you only have one function plus a decision to make about if you need to change the adjustment value:-

adjval=1
counter=0
currentRow=0

function adjust_it ()
{
 ((counter=$counter+1))
 ((currentRow=$currentRow+$adjval))
 [ $currentRow -le 0 ] && adjval=1                # We set it to count up
 [ $currentRow -ge 5 ] && adjval=-1               # We set it to count down
 echo "Counter is $counter ; CurrentRow is $currentRow ; Adjustment value is $adjval"
}

Then, a simple loop will illustrate it:-

$ while :
> do
> adjust_it
> sleep 1
> done
Counter is 1 ; CurrentRow is 1 ; Adjustment value is 1
Counter is 2 ; CurrentRow is 2 ; Adjustment value is 1
Counter is 3 ; CurrentRow is 3 ; Adjustment value is 1
Counter is 4 ; CurrentRow is 4 ; Adjustment value is 1
Counter is 5 ; CurrentRow is 5 ; Adjustment value is -1
Counter is 6 ; CurrentRow is 4 ; Adjustment value is -1
Counter is 7 ; CurrentRow is 3 ; Adjustment value is -1
Counter is 8 ; CurrentRow is 2 ; Adjustment value is -1
Counter is 9 ; CurrentRow is 1 ; Adjustment value is -1
Counter is 10 ; CurrentRow is 0 ; Adjustment value is 1
Counter is 11 ; CurrentRow is 1 ; Adjustment value is 1
Counter is 12 ; CurrentRow is 2 ; Adjustment value is 1
Counter is 13 ; CurrentRow is 3 ; Adjustment value is 1
Counter is 14 ; CurrentRow is 4 ; Adjustment value is 1
Counter is 15 ; CurrentRow is 5 ; Adjustment value is -1
Counter is 16 ; CurrentRow is 4 ; Adjustment value is -1
Counter is 17 ; CurrentRow is 3 ; Adjustment value is -1
Counter is 18 ; CurrentRow is 2 ; Adjustment value is -1
Counter is 19 ; CurrentRow is 1 ; Adjustment value is -1
Counter is 20 ; CurrentRow is 0 ; Adjustment value is 1
Counter is 21 ; CurrentRow is 1 ; Adjustment value is 1
Counter is 22 ; CurrentRow is 2 ; Adjustment value is 1
Counter is 23 ; CurrentRow is 3 ; Adjustment value is 1
Counter is 24 ; CurrentRow is 4 ; Adjustment value is 1
Counter is 25 ; CurrentRow is 5 ; Adjustment value is -1
Counter is 26 ; CurrentRow is 4 ; Adjustment value is -1
Counter is 27 ; CurrentRow is 3 ; Adjustment value is -1
Counter is 28 ; CurrentRow is 2 ; Adjustment value is -1
Counter is 29 ; CurrentRow is 1 ; Adjustment value is -1

Does that help, or have I missed the point?
Robin

1 Like
#!/bin/bash

max=5

next() {
  [ $counter -eq 0    ] || [ -z "$last" ] && change="1"
  [ $counter -eq $max ]                   && change="-1"
  last=$counter
  ((counter=$counter + $change))
}

counter=$(($RANDOM%($max+1)))
for((i=0;$i<20;i++));do
        echo $counter
        next
done

Remark
Don't use global variables like this in a bigger script!

1 Like

The recursion seems strange.
Better go for an iteration: an outer loop with counter, and two loops inside (one fwd then one bk).
BTW this is not shell code...

1 Like

Hello Robin, that definitely helps. The original code is swift but I don't mind if code is bash, perl... I just need to see some code that works.
Thank you.

---------- Post updated at 03:34 PM ---------- Previous update was at 03:25 PM ----------

Thanks for the input. I gave that a try but couldn't quite work out how to flip the counter to count down negative. I'm not that informed on how to flip the pointer.

---------- Post updated at 03:38 PM ---------- Previous update was at 03:34 PM ----------

Thank you.

Ohhh - got it . . . Try - recent bash ( ksh ) required -

animals=(Lion Tiger Panther Cougar Cheetah Leopard)
DLT=1
IDX=3
for i in {1..20}
  do    echo $IDX: ${animals[IDX]}
        (( IDX % (${#animals[@]}-1) )) || (( DLT *= -1 ))
        (( IDX += DLT))
  done
3: Cougar
4: Cheetah
5: Leopard
4: Cheetah
3: Cougar
2: Panther
1: Tiger
0: Lion
1: Tiger
2: Panther
3: Cougar
4: Cheetah
5: Leopard
4: Cheetah
3: Cougar
2: Panther
1: Tiger
0: Lion
1: Tiger
2: Panther
1 Like