lestrrat has asked for the wisdom of the Perl Monks concerning the following question:
Okay, so a co-worker of mine is telling me that he can solve the classic n-queens problem 200 times faster in Java than using Perl
I looked at his code, and it definitely doesn't look perl. So I just have this gut feeling that, while the perl solution may never completely beat the java solution in speed, that there's a really tight, perl way of solving this problem much faster
I really suck at these optimizations... so far I've tried and tried, and can't come up with anything that's significantly faster
Do you guys happen to have a perl solution ( that preferrably uses all the perl wizardry ) to this problem that's *really* fast?
By the way, I know it almost sounds like homework, but no. it isn't. I'm done with my school years for now :-)
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Efficient N-Queen solution with Perl
by FoxtrotUniform (Prior) on Nov 16, 2001 at 23:32 UTC | |
An AI course that I took a couple years ago had a "fastest N-queens solver" competition as one of the assignments. I took a look around the net and found some papers on N-queens solutions... the best one I found was O(n), on average. IIRC, it had two steps: The point is, if your algorithm is faster (better time complexity) than his, it doesn't matter if you write it in QBasic and he uses hand-tuned assembly... just crank up N until your curve beats his. Fast algorithms are the best kind of optimization, whether you write them in baby-Perl or golf-Perl. --:wq | [reply] |
|
Re: Efficient N-Queen solution with Perl
by clintp (Curate) on Nov 17, 2001 at 07:30 UTC | |
Since I was more interested in writing games, simulations, and comm software than solving logic problems it didn't hold any interest for me. But after a couple of weeks it was apparent that no-one else was making any headway on solving the problem. The instructor gloated. One afternoon I hacked up a pure Brute Force and Ignorance solution. Howzat? All of the arrangements of 8 queens on a chessboard can be represented as a base-8 counter. Initialize it to 00000000 and add one. Check to see if any digits are repeated or any digits are rows+cols offset from each other (diagonal). Lather, rinse, repeat. It took all of an hour to write and debug, most of that fighting the line editor. Unleashing that on our Prime 950 (I think it was running PrimeOS 7?) it immediately ground the entire machine to a slow death. Fearing being tortured by my classmates and having the lab people hunt me down like an animal, I managed to stop the program and sneak out. Before I did, I set the program to run at midnight (a phantom job) that night and dump results (the octal numbers representing successful matches) to a file. The next morning I got the results. 96 matches (which was correct) including rotations and mirrors. The job ran for 1 hour and 10 minutes, and used 1 hour and 3 minutes of CPU time. Thank God this particular University didn't charge students for CPU time. I used Pascal (which I liked better at the time) to take the results and format them according to the instructor's wishes. I had actually used FORTRAN to solve the problem, so I wasn't cheating... </geezer> | [reply] |
|
Re: Efficient N-Queen solution with Perl
by pjf (Curate) on Nov 17, 2001 at 02:25 UTC | |
In sort, place N queens on an N by N chessboard, such that no queen can take any other queen. The N-queen problem has been around for a while, as you probably guessed from the aforementioned page calling a 1977 article "recent".
Cheers,
| [reply] |
|
Re: Efficient N-Queen solution with Perl
by runrig (Abbot) on Nov 20, 2001 at 02:01 UTC | |
The output is simply the column (or row) for each queen in each succeeding row (or column). It's rather brute force, but sped up slighty from blind brute force by using a hash array. I think its very idiomatic perl, it'd be interesting to compare against the java version: This algorithm is exponential, though an 8x8 board takes less than a second, a 10x10 board took about 11 seconds and a 11x11 board took ~55 seconds. For a 30x30 board, I'm still seeing how long it takes to find even the first solution :) (Update2: A chart on this page will give you an idea how long it takes to get the first solutions for brute force algorithms when you change N). | [reply] [d/l] |
by tye (Sage) on Nov 20, 2001 at 05:00 UTC | |
Rather obfuscated and brute force (updated to handle more than 8 queens): - tye (but my friends call me "Tye") | [reply] [d/l] |
|
(code)Re: Efficient N-Queen solution with Perl
by lestrrat (Deacon) on Nov 20, 2001 at 21:50 UTC | |
So here's the code... let me first say that I think this only finds one solution, and that's it. The first two are the original code that was presented to me... Original Perl Code
Java Code
(Somewhat) Optimized Perl CodeAn here's the code with the optimization. It's exactly the same algorithm, just cut the overhead of calling subs and what not. The interesting thing I found about this is that if you use for( 0..$size ) in the outer loop, it seems to slow down things a bit. I thought that was more efficient under perl... hmm.
| [reply] [d/l] [select] |
|
Re: Efficient N-Queen solution with Perl
by lestrrat (Deacon) on Nov 20, 2001 at 00:24 UTC | |
Just for the record, I cut the overhead of calling subroutines and in fact, minimized blocks ( like, if{} for{}, etc ) and gained a 30% increase in speed. I believe what prompted me to do this was somebody's posting on perlmonks, but I forget who at this point... In any case, perl still remains about 100 times slower than Java. ugh. | [reply] |
by dragonchild (Archbishop) on Nov 20, 2001 at 01:52 UTC | |
Post your proposed solution and let us have a try at it. I'm positive that there's a number of optimizations you haven't seen, cause you're the original author. (This applies to everyone, including tilly, tye, and merlyn.) (Only Erudil doesn't need this kind of help ... he needs a completely different form of help. *grins*) ------ Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. | [reply] |
|
(tye)Re2: Efficient N-Queen solution with Perl
by tye (Sage) on Nov 22, 2001 at 02:52 UTC | |
Thanks for posting your original code. It was about 100-times slower than runrig's code (for fairly small numbers of queens and only counting how long it took runrig's code to find the first match). My updated code actually does more than runrig's (checks for duplicates) but runs quite a bit faster. For example, runrig's takes about 28 seconds to find the 2680 solutions for 11 queens while mine takes about 7 seconds (and notes that only 341 solutions are unique). Sorry, I don't feel like running more samples and making more comparisons than those at the moment. So at least a great deal of the speed problem isn't Perl's fault in this case. ;) - tye (but my friends call me "Tye") | [reply] |
|
Re: Efficient N-Queen solution with Perl
by jmcnamara (Monsignor) on Nov 21, 2001 at 15:53 UTC | |
Here is a depth first search solution that was posted to comp.lang.awk group some years ago. The original posting is on my scratchpad. All that I've done is to modify the output of a2p on the original awk code. Coincidentally, the usenet post was comparing the speed of awk and Perl and a prominent Perlmonk gets a mention. The author of the awk program is Mike Brennan who wrote mawk. Ultimately however, these lang versus lang games prove very little. Update: Fixed 2 errors as per blakem's post below.
--
| [reply] [d/l] |
by blakem (Monsignor) on Nov 22, 2001 at 01:04 UTC | |
looks suspicious, I think it should be $ARGV[0]. But even after changing that, I'm not getting any output from the above program.
-Blake | [reply] [d/l] [select] |
|
Re: Efficient N-Queen solution with Perl
by jynx (Priest) on Nov 22, 2001 at 04:24 UTC | |
Here's some optimizations, Unfortunately, i've been having some problems with the code that i can't put a handle on. Usually you'll get a result for 20 queens within 5 seconds. 50 queens? about 20 seconds, usually less than 30 seconds. Unfortunately sometimes it infinite loops, and i have absolutely no idea where. The main problem i have is that the OOP code i originally used gets a huge speed bump when running under Devel::DProf. So much so that it only takes 4 seconds to do 100 queens. It took about 3 minutes to do 1000. But Devel::DProf slows this script version. Can anyone tell me why? NOTE: These times are for a Redhat Linux box using 64Mb of RAM and a Pentium 200MHz. Your times will vary. (Testing under DarwinPerl with 128MB and a 733MHz processor is much faster :) Anyway, here's the script version, reasonably fast. It could still be optimized tremendously, but there's only one algorithmic optimization that i didn't do. It doesn't make a huge difference in speed, so i don't think it's worth the time for now. If you're interested in the OO code i can post that too.
Major Optimizations of Note:
Hope That Helps, jynx
| [reply] [d/l] |