Link to home
Start Free TrialLog in
Avatar of nakoutra
nakoutra

asked on

C to VB/VBA

Hello all,


This is another combinatorial question from C to VB/VBA.

I found this code and since I'm illetatate with C
I would like your help translating the code.

How I understand this code is as follows:

1. Given a file that holds some sets of size 6, like:
   {1,2,3,6,9,15}
   {4,23,24,34,45}
   
2. The code below shall count how many sets from a parent set
   {1,2,3...49}, are covered in such a way that at least
   3plets, 4plets, 5plets and 6plets are included within
   the sets of the given file.
 
3. It makes use of the Binomial Table c(49,6)

I do not understand how it accomplishes that count.
Any help/explanation or code will be greatly appreciated


Thanks,



/*
un programme qui prends un fichier input.dat contenant les
combinaisons a raison de 1 par ligne.
et qui a en argument le nombre de boules 6<= MAX <= 49

Cela permet de tester toutes les combinaisons sur des jeux reduits.

*/

#include <stdio.h>

#define LIM6 49
#define LIM5 (LIM6-1)
#define LIM4 (LIM6-2)
#define LIM3 (LIM6-3)
#define LIM2 (LIM6-4)
#define LIM1 (LIM6-5)

#define PRIVATE static
#define PROC void

#define EOT3 ((LIM6*LIM5*LIM4)/6)
#define EOT4 ((EOT3)*LIM3/4)
#define EOT5 ((EOT3)*(LIM3*LIM2)/20)
#define COMBIP2 ((LIM3*LIM2*LIM1)/6)
#define EOT  ((EOT3*COMBIP2)/20)   /* C(LIM6,6) */

#define ROLL(a0,a1,a2,a3,a4,a5,l) for (a5=5 ; a5 < l  ; a5++) \
                                   for (a4=4 ; a4 < a5 ; a4++) \
                                    for (a3=3 ; a3 < a4 ; a3++) \
                                     for (a2=2 ; a2 < a3 ; a2++) \
                                      for (a1=1 ; a1 < a2 ; a1++) \
                                       for (a0=0 ; a0 < a1 ; a0++)

PRIVATE int base1[49] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48 } ;

PRIVATE int base2[49] = { 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55,
66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325,
351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820,
861, 903, 946, 990, 1035, 1081, 1128 } ;

PRIVATE int base3[49] = { 0, 0, 0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220,
286, 364, 455, 560, 680, 816, 969, 1140, 1330, 1540, 1771, 2024, 2300, 2600,
2925, 3276, 3654, 4060, 4495, 4960, 5456, 5984, 6545, 7140, 7770, 8436, 9139,
9880, 10660, 11480, 12341, 13244, 14190, 15180, 16215, 17296 } ;

PRIVATE int base4[49] = { 0, 0, 0, 0, 1, 5, 15, 35, 70, 126, 210, 330, 495,
715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855, 10626, 12650,
14950, 17550, 20475, 23751, 27405, 31465, 35960, 40920, 46376, 52360, 58905,
66045, 73815, 82251, 91390, 101270, 111930, 123410, 135751, 148995, 163185,
178365, 194580 } ;

PRIVATE int base5[49] = { 0, 0, 0, 0, 0, 1, 6, 21, 56, 126, 252, 462, 792,
1287, 2002, 3003, 4368, 6188, 8568, 11628, 15504, 20349, 26334, 33649, 42504,
53130, 65780, 80730, 98280, 118755, 142506, 169911, 201376, 237336, 278256,
324632, 376992, 435897, 501942, 575757, 658008, 749398, 850668, 962598, 1086008,
1221759, 1370754, 1533939, 1712304 } ;

PRIVATE int base6[49] = { 0, 0, 0, 0, 0, 0, 1, 7, 28, 84, 210, 462, 924, 1716,
3003, 5005, 8008, 12376, 18564, 27132, 38760, 54264, 74613, 100947, 134596, 177100,
230230, 296010, 376740, 475020, 593775, 736281, 906192, 1107568, 1344904, 1623160,
1947792, 2324784, 2760681, 3262623, 3838380, 4496388, 5245786, 6096454, 7059052,
8145060, 9366819, 10737573, 12271512 } ;

PRIVATE int sol [EOT3] ;
#define ACCESOL(a,b,c) sol[base1[a]+base2[b]+base3[c] ]
#define SETSOL(a,b,c,d,e,f) ACCESOL(a,b,c)=1,ACCESOL(a,b,d)=1,ACCESOL(a,b,e)=1, \
                            ACCESOL(a,b,f)=1,ACCESOL(a,c,d)=1,ACCESOL(a,c,e)=1, \
                            ACCESOL(a,c,f)=1,ACCESOL(a,d,e)=1,ACCESOL(a,d,f)=1, \
                            ACCESOL(a,e,f)=1,ACCESOL(b,c,d)=1,ACCESOL(b,c,e)=1, \
                            ACCESOL(b,c,f)=1,ACCESOL(b,d,e)=1,ACCESOL(b,d,f)=1, \
                            ACCESOL(b,e,f)=1,ACCESOL(c,d,e)=1,ACCESOL(c,d,f)=1, \
                            ACCESOL(c,e,f)=1,ACCESOL(d,e,f)=1


#define SOLVED(a,b,c,d,e,f) ACCESOL(a,b,c)+ACCESOL(a,b,d)+ACCESOL(a,b,e)+\
                            ACCESOL(a,b,f)+ACCESOL(a,c,d)+ACCESOL(a,c,e)+\
                            ACCESOL(a,c,f)+ACCESOL(a,d,e)+ACCESOL(a,d,f)+\
                            ACCESOL(a,e,f)+ACCESOL(b,c,d)+ACCESOL(b,c,e)+\
                            ACCESOL(b,c,f)+ACCESOL(b,d,e)+ACCESOL(b,d,f)+\
                            ACCESOL(b,e,f)+ACCESOL(c,d,e)+ACCESOL(c,d,f)+\
                            ACCESOL(c,e,f)+ACCESOL(d,e,f)



main( argc, argv)
int argc;
char **argv;
{
 register int t0,t1,t2,t3,t4,t5 ;
 int n[6] ;
 int res, num ;
 char buffer[256] ;

 FILE  *f;

 int MAX ;

 sscanf(argv[1],"%d",&MAX);
 memset(sol,0,sizeof(sol)) ;

 /* ouverture du fichier d'entree */
 f = fopen("input.dat","r");

 
 while (fgets(buffer,sizeof(buffer),f)) {
    sscanf(buffer,"%d %d %d %d %d %d",&n[0],&n[1],&n[2],&n[3],&n[4],&n[5]) ;
    for (t0=1;t0<6;t0++){
          if (n[t0-1]>=n[t0]) {
             printf (" combinaison incorrecte") ;
             printf (" %2d %2d %2d %2d %2d %2d\n",n[0],n[1],n[2],n[3],n[4],n[5]);
             exit(2) ;
          }  
       }  
    SETSOL((n[0]-1),(n[1]-1),(n[2]-1),(n[3]-1),(n[4]-1),(n[5]-1)) ;
  }
 fclose(f);

 /* verification ... */
 num = 0 ;
 ROLL(t0,t1,t2,t3,t4,t5,MAX) {
    res=SOLVED(t0,t1,t2,t3,t4,t5) ;
    if (!res) {
        num++ ;
        if (num <= 20)
            printf("non verifiee : %2d %2d %2d %2d %2d %2d\n",
                                  t0+1,t1+1,t2+1,t3+1,t4+1,t5+1) ;

    }
 }
 printf (" **** non verifiee(s) : %d ****\n",num);
 exit (0);
}
Avatar of abel
abel
Flag of Netherlands image

I can translate sentence for sentence for you, though I do not understand what the whole program is about.

Do you mean with Binom. Table (49,6) the binomial coefficient, like (49,6) = 49! / (6! * (49 - 6)!) = 13983816?

For starters, you can declare baseX as fixed arrays from 0 to 49 and fill them with the data.
For the #defines we can work out some functions
Every int is a long in VB, you can ignore the term "register". This way you get statements like this:

"register int t0,t1,t2,t3,t4,t5;" becomes:
Dim t0 As Long, t1 As Long, t2 As Long etc.

If you see something like n[6], then this is a fixed 0-based array:
Dim n(0 To 6) As Long


Use VB's Open statement for "input.dat" and read each line, filled with (as you stated) six numbers, into n. The for-loop you find there checks if any number is indeed lower then the previous number. In VB this looks like this:

For i = 1 To 5
    If n(i - 1) <= n(i) Then
        MsgBox "Error"
    End If
Next i

If you're still with me and you want me to help you further I'll continue with translating the macro SETSOL.

A final notice, the code you posted contains errors. For example, the main() statement is incorrect. Do you have the correct URL where to find this code including a sample input.dat? With a correct version I can more easily translate it.

Regards,
Abel
Btw, it is not a compact C++ program. The writer could have used arrays much more and much smarter, making it overall easier to read.
Avatar of nakoutra
nakoutra

ASKER

Hi abel,

The web page is : http://membres.lycos.fr/coustaux/lotto-prg.html

The link to the code is: " Un programme de test de couverture a 3 "

or directly to the code : http://membres.lycos.fr/coustaux/prg/cov3.c


The table is the Binomial Coefficients for the given parameters.
This is easy to generate:

For I = 0 To 49: BinTab(I, 1) = I: Next
   For J = 1 To 5
      For I = J To V
         BinTab(I, J) = BinTab(I - 1, J) + BinTab(I - 1, J - 1)
      Next
   Next

What the program does:
This program shall identify how many sets from the total of  49c6  ~14 mil
are "covered" by the sets in the file "input.dat" in at least 3 points
By "covered" I mean the following:

Each set in the file can "cover" from the total field
at least in 3 points:= 6c3 * 43c3=20*12341=246,820 combinations from 49c6
at least in 4 points:= 6c4 * 43c2=15*903=13545 combinations
at least in 5 points:= 6c5 * 43c1=6*43=258
and       in 6 points:= 6c6 *43c0=1*1=1
For a total of  260,624 combinations
So each set covers so many combinations (260,624) in at least 3 points.
But the collection of sets in the file, how many total combinations "cover"?

This program can calculate that faster than going through a "brute force" procedure.

The program can be used to rank combinations (sets) according to their "covering" properties.

I'm trying to understand how this is accomplished.

Any help is very much appreciated.


nakoutra
Hi abel,

The web page is : http://membres.lycos.fr/coustaux/lotto-prg.html

The link to the code is: " Un programme de test de couverture a 3 "

or directly to the code : http://membres.lycos.fr/coustaux/prg/cov3.c


The table is the Binomial Coefficients for the given parameters.
This is easy to generate:

For I = 0 To 49: BinTab(I, 1) = I: Next
   For J = 1 To 5
      For I = J To V
         BinTab(I, J) = BinTab(I - 1, J) + BinTab(I - 1, J - 1)
      Next
   Next

What the program does:
This program shall identify how many sets from the total of  49c6  ~14 mil
are "covered" by the sets in the file "input.dat" in at least 3 points
By "covered" I mean the following:

Each set in the file can "cover" from the total field
at least in 3 points:= 6c3 * 43c3=20*12341=246,820 combinations from 49c6
at least in 4 points:= 6c4 * 43c2=15*903=13545 combinations
at least in 5 points:= 6c5 * 43c1=6*43=258
and       in 6 points:= 6c6 *43c0=1*1=1
For a total of  260,624 combinations
So each set covers so many combinations (260,624) in at least 3 points.
But the collection of sets in the file, how many total combinations "cover"?

This program can calculate that faster than going through a "brute force" procedure.

The program can be used to rank combinations (sets) according to their "covering" properties.

I'm trying to understand how this is accomplished.

Any help is very much appreciated.


nakoutra
I see now that you copied it correctly and the source is correct as well. I just didn't see that is was a C file. I just assumed it was a C++ file.

I understand now what you mean and basically what the program does. I'll update quickly after this.
Hmmm, do not refresh your browser, just hit "Reload Question" on top-right of the page. That way you won't see your comments copied more then once into the thread.
Before I continue, do you understand the basic structure of the program and how to translate? Or do you want me to just give you a fully working VB program based on this C-program?

If there are only certain parts that you don't understand and want translated it will of course be quicker to go through it all.
I continue anyway:


The first #defines are just constants. In VB that looks like this:

Const LIM6 As Long = 49
Const LIM5 As Long = LIM6 - 1
...etc.

You can ignore the #defines PRIVATE and PROC (odd use of the word PRIVATE here, but that's another story).
The #defines EOT3...EOT are again constants:

Const EOT3 As Long = ((LIM6 * LIM5 * LIM4) /6)
....etc.

Here's an interesting thing. The programmer creates floating point variables here, maybe without knowing. He does nothing to prevent the overhead of doubles, though at other points he tries to instruct the compiler to optimize for speed.

Now we come to the first "functional" #define, called a macro in C-terms. We also come to our first problem here, because this one is not directly convertable to a function or sub in VB. That is, because this macro only expands to the start of a complex loop (you see al these for-statements, that's six loops in one). Usually programmers don't create this kind of macros, simply because they confuse reading the code. I'll come back to this ROLL-macro when we'll need it.


Next you see a lot of PRIVATEs, which basically aren't private, but public. Hence my remark earlier on. Create arrays of these like I said before:
Dim base1(0 To 49) As Long

If you have no Option Base 1, you can ignore the "0 To"-part. Do the same for base2 to base6. Also, use your regular VB-skills to fill the arrays with the data. You may want to put the data (between brackets in the .c file) in files and then read it in, otherwise it may become quite long using VB statements.
You may consider using the Array-statement. But beware, if this becomes quite a computational program, you must know that accessing a variant array is much-much slower then accessing a normal array. And the Array()-statement can only return a variant-array! One way to workaround this issue is to copy the results of the Array-statement into the normal array using a loop. But that's up to you.

The last one, that array sol can be declared without initializing it (I won't be using the "0 To" from now on, ok?)
Dim sol(EOT3) As Long

Again, we come across some functional macros. The first one now, the latter is for the next posting. I don't like too long postings, those are often too hard to read.
Now, this ACCESOL macro just "returns" (it doesn't really do that, but let's pretend it does, otherwise this will end up being a course in C) a calculated value based on three input integers. In VB this looks like this:

Function ACCESOL(a as Long, b As Long, c As Long)
     ACCESOL = sol(base1(a) + base2(b) + base3(c))
End Function


Hope this is what you want,

Regards,
Abel
Hello Abel,

Firstly I will increase the points to 600
Your work into teaching me the conversion is worth it.
300 extra points will be rewarded to you as "points for Abel"

The main purpose of this exercise shall be:
- To understand how this program works to accomplish the task.
- To understand the requirements for translating some  C code  to VB

It is not clear to me yet how it accomplishes the count.
This is my priority.  If you have recognized this I'll be very glad if you
can explain it to me.

I will follow all the notes you provided.
I'll work on this tonight.

Thanks,
nakoutra





ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Richie_Simonetti
Interesting...
I heard that the emailing system was down, so just to let you know there was an update in this thread (hope emailing works again): ping :)
Hello Abel,

Yes I couldn't connect yesterday.

The final word about the program is that it does not
do what I was wishing for.

It only finds the 3plets covered by the file "input.dat"
and not "at least 3 if 6".

There are better was to accomplish what the author was trying to.

Thank you very much.

I'll accept your answer and award you the extra points too.

Thanks again,
nakoutra
Maybe you remember my remark about the unused arrays? If you utilize them, and if you look carefull through the code, it will go through all six! But it will of course take much more processing time, it probably increases exponentially. And that might also have been the reason why the author did not include those arrays: too slow. Or he just found it too tedious to work through all the combinations in the SETSOL macro.

Hopefully you have at least gained a better understanding on how things work in this algorithm. And if you still have questions, I'm still around :)

Cheers,
Abel
Btw, thanks for the grade and the points, it was fun working with you :)