Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
799 views
in Technique[技术] by (71.8m points)

math - javascript : create for loops into for loops

I had to solve the following problem:

problem

9 values, from 1 to 9 (0 and 10 not accepted) and all numbers need to be different.

To solve the probem, I made those horrible for loops inside for loops.
(I added 2 more conditions to check if i had one of the solutions)
It is working, but I was wondering how to create those for loops inside for loops in a better way?

Also, each number can't be equal to another. How can you accomplish this another way than I did? (Again, 2 first conditions can be deleted)

Here is code:

var a = 1, b = 1, c = 1, d = 1, e = 1, f = 1, g = 1, h = 1, i = 1;

var x = 0;

var result = [];

function calc(){

  x = a + 13 * b / c + d + 12 * e - f - 11 + g * h / i - 10;

  if(x == 66){
     result.push([a, b , c , d , e, f, g, h, i] );
  }
}

for(a = 1; a < 10; a++){
    calc();
    for(b = 1; b < 10; b++){
        calc();
        for(c = 1; c < 10; c++){
            calc();
            for(d = 1; d < 10; d++){
                calc();
                for(e = 1; e < 10; e++){
                    calc();
                    for(f = 1; f < 10; f++){
                        calc();
                        for(g = 1; g < 10; g++){
                            calc();
                            for(h = 1; h < 10; h++){
                                calc();
                                for(i = 1; i < 10; i++){
                                    calc();
                                }
                            }
                        }
                    }
                }
            }
        }
    }

}

console.log(result);

var result2 = result.filter(function(el){

    return el[0] == 5 && el[1] == 9 && el[0] != el[1] &&  el[0] != el[2] && el[0] != el[3] && el[0] != el[4] &&   el[0] != el[5] &&   el[0] != el[6] &&   el[0] != el[7] &&   el[0] != el[8] && el[1] != el[0] && el[1] != el[2] && el[1] != el[3] && el[1] != el[4] &&   el[1] != el[5] &&   el[1] != el[6] &&   el[1] != el[7] && el[1] != el[8] &&  el[2] != el[0] && el[2] != el[1] && el[2] != el[3] && el[2] != el[4] && el[2] != el[5] && el[2] != el[6] &&  el[2] != el[7] && el[2] != el[8] && el[3] != el[0] && el[3] != el[1] && el[3] != el[2] && el[3] != el[4] && el[3] != el[5] && el[3] != el[6] && el[3] != el[7] &&  el[3] != el[8] &&  el[4] != el[0] && el[4] != el[1] && el[4] != el[2] && el[4] != el[3] && el[4] != el[5] && el[4] != el[6] && el[4] != el[7] && el[4] != el[8] && el[5] != el[0] && el[5] != el[1] && el[5] != el[2] && el[5] != el[3] && el[5] != el[4] && el[5] != el[6] && el[5] != el[7] && el[5] != el[8] && el[6] != el[1] && el[6] != el[2] && el[6] != el[3] && el[6] != el[4] && el[6] != el[5] && el[6] != el[7] && el[6] != el[8] && el[7] != el[0] && el[7] != el[1] && [7] != el[2] && el[7] != el[3] && el[7] != el[4] && el[7] != el[5] && el[7] != el[6] && el[7] != el[8] && el[8] != el[0] && el[8] != el[1] && el[8] != el[2] && el[8] != el[3] && el[8] != el[4] && el[8] != el[5] && el[8] != el[6] && el[8] != el[7];

});

console.log(result2);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

for starters you can make N x nested for loops like this

You can handle your problem as a 9 digit number generation

As your digits are not repeating you can discard many iterations. If encoded in the above manner (like nested for) you will came up with something like this:

Generalized Permutation (without repetitions) in C++:

//---------------------------------------------------------------------------
//--- permutation class ver 0.00 --------------------------------------------
//---------------------------------------------------------------------------
#ifndef _permutation_h
#define _permutation_h
/*---------------------------------------------------------------------------
    // usage:
    permutation per;
    per.alloc(N);

    per.first();
    for (;;)
        {
        ... here per.i[0..N-1] contains actual permutation
        ... N! permutations
        if (!per.next()) break;
        }
//-------------------------------------------------------------------------*/
class permutation
    {
public:
    int  *i;    // i[N] permutation
    BYTE *a;    // a[N] item not used yet ?
    int   N;    // items
    int  ix;    // actual permutation layer
    permutation()   { N=0; i=NULL; a=NULL; ix=0; }
    permutation(permutation& b) { *this=b; }
    ~permutation()  { free(); }
    permutation* operator = (const permutation *b) { *this=*b; return this; }
    permutation* operator = (const permutation &b) { alloc(b.N); for (int j=0;j<N;j++) { i[j]=b.i[j]; a[j]=b.a[j]; } ix=b.ix; return this; }

    void alloc(int _N)
        {
        free();
        i=new  int[_N];
        if (i==NULL) return;
        a=new BYTE[_N];
        if (a==NULL) { free(); return; }
        N=_N;
        }
    void free ()
        {
        N=0; ix=0;
        if (i!=NULL) delete i; i=NULL;
        if (a!=NULL) delete a; a=NULL;
        }
    void first()                                        // init permutation
        {
        for (ix=0;ix<N;ix++)
            {
            i[ix]=ix;
            a[ix]=0;
            } ix--;
        }
    bool next()                                         // next permutation return if it is not last
        {
        int *ii=&i[ix];
        for (;;)
            {
            if (*ii>=0) a[*ii]=1;
            for ((*ii)++;*ii<N;(*ii)++) if (a[*ii]) { a[*ii]=0; break; }
            if (*ii>=N)
                {
                if (ix==  0) return false;
                *ii=-1; ix--; ii=&i[ix];
                }
            else{
                if (ix==N-1) return true;
                ix++; ii=&i[ix];
                }
            }
        }
    };
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

The important stuff is in first() and next() members, each permutation is stored in the i[] array as index so set N=9 and your output numbers will be (per.i[0]+1),(per.i[1]+1),...,(per.i[9]+1)

it works in following manner:

  1. first() initialize permutation to state i[9]=(0,1,2,...8) and a[9]=(0,0,0,...0)

    I will write this for simplicity like this: i=012345678,a=000000000 where

    • ix points to last digit
    • i is the actual permutation
    • a flags if digit is unused(1) or used(0) (to avoid O(N^N) operation)
  2. next() increment to next valid permutation

    Increase the last digit to next unused value. If no unused value set it as unused and increment previous digit. The same goes for overflow. The first iteration will be like this:

    i=012345678,a=000000000 // starting iteration
    i=01234567? a=000000001 // unset (no unused values)
    i=01234568? a=000000010 // increment 8th digit
    i=012345687 a=000000000 // set the last digit result
    

    next iteration:

    i=012345687 a=000000000 // starting iteration
    i=01234568? a=000000010 // unset (no unused values)
    i=0123456?? a=000000011 // unset (8->9 overflow)
    i=0123457?? a=000000101 // increment 7th digit
    i=01234576? a=000000001 // after overflow digit set to lowest free value
    i=012345768 a=000000000 // after overflow digit set to lowest free value
    

    I hope it is clear enough.

Of coarse if you use recursion instead of iteration the code will look much nicer but in most languages will run also slower due to stack/heap trashing

As @NikolaDimitroff pointed out this is in C++ instead of javascript so:

  • ignore new,delete and class members other then first(),next()
  • set N=9; and arrays i,a can be static like: int i[9]; BYTE a[9];

Here the solution O(N!) for the task in C++:

int a,b,c,d,e,f,g,h,i;
permutation per;
per.alloc(9);
per.first();
for (;;)
    {
    if ((per.i[0]+1)
        +(13*(per.i[1]+1)/(per.i[2]+1))+(per.i[3]+1)
        +(12*(per.i[4]+1))
        -(per.i[5]+1)-11
        +((per.i[6]+1)*(per.i[7]+1)/(per.i[8]+1))-10
        ==66)
        {
        a=per.i[0]+'1';
        b=per.i[1]+'1';
        c=per.i[2]+'1';
        d=per.i[3]+'1';
        e=per.i[4]+'1';
        f=per.i[5]+'1';
        g=per.i[6]+'1';
        h=per.i[7]+'1';
        i=per.i[8]+'1';
        // here a,b,c,d,e,f,g,h,i holds the solution
        break;
        }
    if (!per.next()) break;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...