Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Count up several variables ... 1

Status
Not open for further replies.

TSch

Technical User
Jul 12, 2001
557
DE
Hi folks,

sorry I must be getting a little bit rusty ... :-(

Could you help me out with the following:

I have 5 Variables (A B C D E).
Each Variable is starting with a value of 1 and can count up to 2000.
I want to start with A=1 B=1 C=1 D=1 E=1 and first count up E up to 2000.
As soon as it reaches 2000 the value D shall be increased to 2 and E shall run up from 1 to 2000 again and so on until D also reaches 2000. If so C shall be increased to 2, D back to 1 and E count up from 1 to 2000 again ...

So what I want is to run all possible combinations where A B C D E can become something between 1 and 2000.

For each combination I want to perform some calculations and if the result I'm looking for (Which is: The combination where all my calculations will have the same result) is found the script shall stop and report me the current values for A B C D E ...

I started with the following lines but somehow I got stuck and my mind refuses to think any further even though it's not such a huge programming problem ... :-(

Code:
#!/usr/bin/ksh

A=1
B=1
C=1
D=1
E=1


while [ $A -lt 2000 ];
do
 while [ $B -lt 2000 ];
 do
  while [ $C -lt 2000 ];
  do
   while [ $D -lt 2000 ];
   do
    while [ $E -lt 2000 ];
    do
    RA=$(($A+$B))
    RB=$(($C-$A))
    RC=$(($A*$D))
    RD=$(($A/$E))
    if [ $RA -eq $RB -a $RB -eq $RC -a $RC -eq $RD ];
    then
    echo $A $B $C $D $E
    echo $RA $RB $RC $RD
    echo "That's it !"
    exit 1;
    fi
    E=`expr $E + 1`
    done
   D=`expr $D + 1`
   done
  C=`expr $C + 1`
  done
 B=`expr $B + 1`
 done
A=`expr $A + 1`
done

Could you help me out with that ?

Regards,
Thomas
 
Hi

So you intend to run the inner loops multiple times, but you initialize their counters only once, before everything begins ? Not good. Move [tt]E=1[/tt] immediately before [tt]while [ $E -lt 2000 ];[/tt] and so on.

But that only fixes the logic. To increase its speed better avoid [tt]expr[/tt] and prefer arithmetic evaluation ( without sigils ! ) :
Code:
[gray]#!/usr/bin/ksh[/gray]

A=1
[b]while[/b] (( A < 2000 )); [b]do[/b]
 B=1
 [b]while[/b] (( B < 2000 )); [b]do[/b]
  C=1
  [b]while[/b] (( C < 2000 )); [b]do[/b]
   D=1
   [b]while[/b] (( D < 2000 )); [b]do[/b]
    E=1
    [b]while[/b] (( E < 2000 )); [b]do[/b]
    (( RA = A + B ))
    (( RB = C - A ))
    (( RC = A * D ))
    (( RD = A / E ))
    [b]if[/b] (( RA == RB && RB == RC && RC == RD )); [b]then[/b]
     echo [green][i]"$A $B $C $D $E"[/i][/green]
     echo [green][i]"$RA $RB $RC $RD"[/i][/green]
     echo [green][i]"That's it !"[/i][/green]
     exit 1;
    [b]fi[/b]
    (( E++ ))
    [b]done[/b]
   (( D++ ))
   [b]done[/b]
  (( C++ ))
  [b]done[/b]
 (( B++ ))
 [b]done[/b]
(( A++ ))
[b]done[/b]

But even so, this will take ages to run. Looks like those Project Euler challenges which can not be solved with brute force using computers currently available for civilians. For example, given that C - A must be equal to A + B which will be always positive, you could safely skip all cases when C < A.

Feherke.
feherke.ga
 
Hi feherke,

thanks a lot, it's working perfect now !

However ... Runtime is a good Point. ;-)
I was really hoping it would be running a "little bit" faster.

I tried to Speed it up a bit but I'm afraid that's still far from what I would Need ... ;-(

Code:
#!/usr/bin/ksh

A=1
while (( A < 2000 )); do
 B=1
 while (( B < 2000 )); do
  C=1
  while (( C < 2000 )); do
   D=1
   while (( D < 2000 )); do
    E=1
    while (( E < 2000 )); do
[COLOR=#8AE234]    (( SUM = A + B + C + D + E ))
    if [ $C -ge $A -a $A -ge $E -a $SUM -le 2000 ];
[/color]    then
    (( RA = A + B ))
    (( RB = C - A ))
    (( RC = A * D ))
    (( RD = A / E ))
    if (( RA == RB && RB == RC && RC == RD )); then
     echo "$A $B $C $D $E"
     echo "$RA $RB $RC $RD"
     echo "That's it !"
     exit 1;
    else
    echo "$A $B $C $D $E"
    fi
    else
[COLOR=#8AE234]    if [ $A -lt $E ];
    then
    E=1999
[/color]    fi
    fi
    E=`expr $E + 1`
    done
   D=`expr $D + 1`
   done
  C=`expr $C + 1`
  done
 B=`expr $B + 1`
 done
A=`expr $A + 1`
done

I think I will have to give this some more thought ...

Regards,
Thomas
 
Hi

Well, to speed it up significantly you will have to move some of the [tt]if[/tt]s out from the 5[sup]th[/sup] [tt]while[/tt], so some inner loops can be skipped completely. Is pointless to loop all D's and E's too and only there to check [tt]$C -ge $A[/tt] -- that could be done much earlier in C's block.

By the way, the advice to forget [tt]expr[/tt] is a generic one :
Code:
[blue]$[/blue] time ( A=0; while (( A < 100000 )); do A=`expr $A + 1`; done )             

real    0m32.88s
user    0m3.99s
sys     0m5.34s

[blue]$[/blue] time ( A=0; while (( A < 100000 )); do (( A++ )); done )

real    0m0.05s
user    0m0.06s
sys     0m0.00s


Feherke.
feherke.ga
 
If you define your variables to be Integers, you'll gain a little more speed...

Code:
$ time ( A=0; while (( A < 1000000 )); do (( A++ )); done )           

real    0m0.82s
user    0m0.80s
sys     0m0.00s
$ time ( [u]typeset -i A=0[/u]; while (( A < 1000000 )); do (( A++ )); done )

real    0m0.25s
user    0m0.25s
sys     0m0.00s

So...

Code:
#!/usr/bin/ksh

typeset -i RA
typeset -i RB
typeset -i RC
typeset -i RD

typeset -i A=1
while (( A < 2000 )); do
 typeset -i B=1
 while (( B < 2000 )); do
  typeset -i C=1
  while (( C < 2000 )); do
   typeset -i D=1
   while (( D < 2000 )); do
    typeset -i E=1
    while (( E < 2000 )); do
    (( RA = A + B ))
    (( RB = C - A ))
    (( RC = A * D ))
    (( RD = A / E ))
    if (( RA == RB && RB == RC && RC == RD )); then
     echo "$A $B $C $D $E"
     echo "$RA $RB $RC $RD"
     echo "That's it !"
     exit 1;
    fi
    (( E++ ))
    done
   (( D++ ))
   done
  (( C++ ))
  done
 (( B++ ))
 done
(( A++ ))
done


 
As feherke pointed out, this looks like one of those questions that shouldn't be tackled with a brute force attack.
A little bit of common sense and elementary mathematics should suffice, I think.

SPOILER WARNING!
If you insist on finding a solution with the help of a computer program, stop reading here!

As all your numbers are integers >0, we can see:
i) RC = A * D >= A
ii) RD = A / E <= A

RC = RD implies
iii) RC = A and RD = A
and therefore
iv) D = 1
v) E = 1

and finally
A = RC = RA = A + B will give us
vi) B = 0

As the conditions can only be met with B = 0, in contrast to your requirement B > 0, we gather that there is no solution.

Easy, huh?
[wink]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top