To my letter on the Cryptarithm test
(proposed by  Mark Engelberg <[EMAIL PROTECTED]> )

>> [..]
>> As to me, i still agree to pay 17 times for the functionality.
>> But is the test all right, what people think?
>> And he compared the Haskell program with the C++ program that uses
>> the  next_permutation  function.
>> [..]


Manuel M. T. Chakravarty  <[EMAIL PROTECTED]>  writes

> If you don't know the implementation of next_permutation,
> how can you ensure that both programs actually go through
> the same sequence of permutations.  Depending on the two
> algorithms involved one program may do a single permutation
> to reach the goal and the other program 1000 permutations.
> This has nothing to do with the programming languages
> involved.


No.
There are  10! = 3628800  permutations on [0..9].
Both the C++ program and the Haskell one start with  p0 = [0..9]
- this is tested by inserting of printing into C++ program.
Then, i inserted the counter, and it shows that the permutation
No 3628800 (the last one) is  reverse [0..9].
The Haskell program acts the same.
So, there is no need to investigate further this  next_permutation
(unless it is written by hand in assembly! - hardly so).
It is hard to imagine   next_permutation  so treacherous as to 
generate in the middle a great number of wrong permutations.

Both programs go through the same list of permutations.

Only i improved the test now to more fair (to my mind).

Now it shows the ratio  * 6 *.

I wonder, what might this all mean. There remain minor questions.
The test is:
    generate all the permutations starting from  p0 = [0..9]  and 
    ending with  pLast = reverse [0..9],  and find the first 
    permutation  p  among them satisfying `condition',
    condition p =  all (< 20) p  &&  p==pLast

`condition' is set so that only the last permutation would suffice
it.
Also for each  p  it runs testing  p(i) < 20  for  i <- [0..9], 
and only then proceeds with  p==pLast.
This aims to deminish the relative cost of  `(ao ks)++'.
For the latter costs 5 operations on average, while  p==pLast
costs 1-2 operations on average
(and i do not know how to get free of this `++', neither how to
measure its cost by experiment).
This makes the program to do something with the permutation that 
costs near the same as to generate the next permutation.

I think this example is a more real one.

In the C program, the functions  condition1(x), condition2(x)
are introduced for the vector  x,  which correspond to  
`all (< 20) p', `p==pLast'  respectively.
These functions are programmed explicitly, as the cycles for i
from 0 to 9.  This is to uniform it with the Haskell program.

Compilation:   g++       -O3                       t.cc
               ghc-4.04  -c -fvia-C -O2 -O2-for-C  t.hs

RESULT:        C++  is  6 times faster.
 
Platform:      PC i-586,  Linux Debian
g++  version:  
  g++ -v  says
            `gcc version egcs-2.90.29 980515 (egcs-1.0.3 release)'

But this mess with platforms and versions, is not, probably, so 
important, because people can compile and run this program in their
own environments - and correct the performance result.

What do you think of it?

------------------
Sergey Mechveliani
[EMAIL PROTECTED]



-- Haskell ---------------------------------------------------------
import List (find)

permutations :: [Int] -> [[Int]]
            -- build the full permutation list given an ordered list

permutations []     = [[]]
permutations (j:js) = addOne $ permutations js
                             where
                             addOne []       = []
                             addOne (ks:pms) = (ao ks)++(addOne pms)

                             ao []     = [[j]]
                             ao (k:ks) = (j:k:ks):(map (k:) $ ao ks)

main = putStr $ shows (find condition $ permutations p0) "\n"
         where
         (p0, pLast) = ([0..9], reverse [0..9])
         condition p = all (< 20) p  &&  p==pLast


-- C++ -------------------------------------------------------------
#include <vector>
#include <algorithm>
#include <iostream.h>

using namespace std;

int condition1 (vector<long> x)
{int i = 0;
 while  (i < 10  &  x[i] < 10)  i++;
 return (i > 9);
}
int condition2 (vector<long> x)
{int i = 0;
 while  ( i < 20  &  x[i]==9-i )  i++;
 return (i > 9);
}
void main()
{long t,h,i,r,y,w,e,l,v,n;
 long temp[10] = {0,1,2,3,4,5,6,7,8,9};
 vector<long> x(temp,temp+10);

 while (!(condition1(x) & condition2(x)))
 {
  next_permutation(x.begin(), x.end());
 }
 cout << x[0] << x[1] << x[2] << x[3] << x[4] << x[5] << x[6] <<
         x[7] << x[8] << x[9] << '\n';
}










Reply via email to