
Paulo,
Yes you are correct. I actually found another way to do it which is similar but not quite as good; I'll paste it in below. The program doesn't do anything useful; I was trying to use it to compare execution times for a compiled Haskell program to a compiled C program. By the time I stopped optimizing it it runs in about 1.5 seconds, so it isn't of much use as a performance test, but I learned a lot coding it. The C++ version is running about 30 times faster, but I suspect that a lot of that difference is startup time and I'll need longer running times to make a valid comparison. Also, the actual printing of the results, which is really irrelevant (to the situation where I'm trying to convince one of my clients to use Haskell), probably takes a lot of the running time. I'm going to change this to just dump the binary results to a file and see what that does to the running times.
If you happen to see any obvious way to get this to run faster, let me know.
Thanks again for your time and efforts.
import System import IO import Data.List
solutionString (a,b,c,d,e,f,g,h,i,j) = concat["sum=", (show (a+d+e)), ", values= ", (show a), ", ", (show d), ", ", (show e), ", ", (show b), ", ", (show f), ", ", (show g), ", ", (show c), ", ", (show h), ", ", (show i), ", ", (show j), "\n" ]
validCorner x y z = cornerSum >= 6 && cornerSum <= 48 && ((cornerSum `mod` 6) == 0) where cornerSum = (x+y+z)*2
solutionList = [(a, b, c, d, e, f, g, h, i, j) | a <- [0..9], b <- [0..9], b /= a, c <- [0..9], c /= b, c /= a, (validCorner a b c), d <- [0..9], d /= a, d /= b, d /= c, e <- [0..9], e < d, e /= c, e /= b, e /= a, f <- [0..9], f /= e, f /= d, f /= c, f /= b, f /= a, g <- [0..9], f < g, g /= e, g /= d, g /= c, g /= b, g /= a, h <- [0..9], h /= g, h /= f, h /= e, h /= d, h /= c, h /= b, h /= a, i <- [0..9], h < i, i /= g, i /= f, i /= e, i /= d, i /= c, i /= b, i /= a, j <- [0..9], i < j, j /= h, j /= g, j /= f, j /= e, j /= d, j /= c, j /= b, j /= a, (a+d+e+b) == (a+f+g+c), (a+d+e+b) == (b+c+h+i+j) ]
main = (putStr . concat . map solutionString) solutionList
On Sunday 25 August 2002 22:38, you wrote:
Seth,
At last, I can have some time to view your question with care. I'm replying to you, and not the list, because I'm not sure to be understanding exactly what is it that you need; this way, we will avoid introducing some noise into the list by posting "Is this what you asked?" mails. Later, we can post a message that summarizes the dialogue and the answer.
----- Original Message ----- From: Seth Kurtzberg
Sent: Tuesday, August 20, 2002 1:45 AM ...
I was trying to follow the basic pattern for coding a recursive function, where you give a pattern for, say, f (x:[]), and you then give a
for
(x:xs) where xs is then used as the argument for a recursive call (as
in
"f xs").
I'm not sure if this is intentional, but there is a case missing here: f [] In case you want to, you can rewrite displaySolutions to cope whith it
way:
displaySolutions [] = return () -- the "do nothing" displaySolutions (x:xs) = displayOneSolution x >> displaySolutions xs
or
displaySolutions [] = return () -- the "do nothing" displaySolutions (x:xs) = do displayOneSolution x; displaySolutions xs
The following is how I now understand it; let me know if this is
fundamentally
incorrect (and thanks for taking the time to read it).
...
The problem is that the examples I was looking at use something like (some calculation with x) * f xs, or + f xs, or some variation where "f xs" is
used
within a single expression.
This pattern looks like the one foldr captures. Indeed, you can rewrite displaySolutions in this way.
displaySolutions xs = foldr ((>>) . displayOneSolution) (return ()) xs
I see, now, that you need the combinator if there is more than one expression, and that this is not related to whether the expression uses monads.
So, is there a way to code this without resorting to the combinator? I
could
have "displayOneSolution" return "displaySolutions", and then do this (I think):
(displayOneSolution x) xs
but that would just move the combinator out of displaySolutions and into displayOneSolution. Or am I looking for something that doesn't exist;
that
is, the combinator is the best way to code this pattern?
What I understand is that you have a list of solutions you want to display, one after another. For this, you should traverse the list, one element after another, applying the displayOneSolution function in order to build an action that do precisely what the name implies.
This can be viewed as having a sequence of actions (display solutions) to be performed, one after another. Declaratively, you can understand this as having a list of actions that you combine using a sequencing operator. The end result is that you have a compound action that is the sequencing of
Seth,
I'm really bad in optimization issues. To be honest, I have almost no
serious experience using Haskell, so I have never faced the task to build an
application for which it was crucial optimization either in space or time.
On the other hand, I have assimilated the idea that you can't put Haskell
programs compete with analogous versions in C++ in space/time usage. I think
that if you try to convince someone that programming in Haskell is better
than doing it in C++ based these metrics, you lost before starting.
Haskell's beauty is somewhere else.
Try to find mundane problems in which Haskell can do better than others
solving them. For example, I participated in some parts of the design and
implementation an n-tier system using, among other things, Visual Basic.
When we came to write the code for the data access components in the data
services tier, we discovered that much of the work was repetitive and
boring: just look at the stored procs' signatures and map them into VB
procedures.
It was clear that what we needed was an utility that could process some
database metadata and produced VB code. I you were considering implementing
it yourself, which language would you choose? (Certainly, I wouldn't pick VB
;) )
Good luck.
Paulo.
----- Original Message -----
From: Seth Kurtzberg
simpler actions of displaing a solution.
If I'm correct in all this, then the answer is that you cannot avoid the use of the combinator: it is the part that allows you to sequence the actions. Anyway, it seems that displaySolutions has a pattern that is captured by sequence_; so, if you ask me, I would code it this way:
displaySolutions xs = sequence_ (map displayOneSolution xs)
which can be transformed also into
displaySolutions = sequence_ . (map displayOneSolution)
Well, we didn't have to use the combinator after all (it is used in sequence_).
I tend to choose the second form, although I'm not sure if it is clear and easily understandable. What do you think?
Paulo.
-- ----------------------------------- Seth Kurtzberg M. I. S. Corp. 1-480-661-1849
participants (1)
-
Paulo Sequeira