|
This thread is locked; no one can reply to it. |
1
2
|
boggle solver |
Matthew Leverton
Supreme Loser
January 1999
|
Attached is a Boggle solver (Windows binary) that I wrote with an official Scrabble wordlist. From a command prompt, just run: boggle 100000 To solve 100000 random boards. The best boards are displayed with their scores. Then the elapsed time is reported. I'm curious to see how fast it is on different CPUs, particularly multi-cores. Report your results! (along with your highest board if you wish) If you are sufficiently bored, I challenge you to write a faster solver than mine. I'm looking at it from a statistical perspective to find most common words, partial words, etc. I know other people have already done it, but it's no fun reading other people's results. Some of the 4x4 boards have over 1,000 words! The Scrabble dictionary is a bit generous and I doubt casual players would allow most of the obscure ones, but it still would be funny to win a "first to 50 points" game in the first round. |
Vanneto
Member #8,643
May 2007
|
I have an Intel Core 2 Duo E4500 @ 2.2GHz. Some results: Solving 100,000 puzzles: Score: 2342 Solved 100000 boards in 8.313000 seconds. <12029.352015/s> Solving 500,000 puzzles: Solving 1,000,000 puzzles: Quite fun and interesting. EDIT: In capitalist America bank robs you. |
Matthew Leverton
Supreme Loser
January 1999
|
The number displayed is the score, not the word count. That is, [1, 1, 2, 3, 5, 11] points for [3, 4, 5, 6, 7, and 8+] letter words. |
OnlineCop
Member #7,919
October 2006
|
Looks like it takes advantage of multiple cores; is it multi-threaded, then? And I guess I'm asking this too late, but it doesn't contain a virus, right? My computer: Dual 2400 processors @ 1.83 GHz, 2 GB RAM
|
Thomas Fjellstrom
Member #476
June 2000
|
I don't really feel like rebooting into windows.. But I could test on my Q6600 if you get source using pthreads.... -- |
Vanneto
Member #8,643
May 2007
|
OK, here is the latest, with 10,000,000.
In capitalist America bank robs you. |
Erikster
Member #9,510
February 2008
|
AMD Turion 64 x2 Mobile Technology TL-60 2.00 GHz 100,000 boards in 11.919 seconds <8389.965832/s> It went nutz at 500,000, what have you done?:o Cat! I'm a kitty cat. And I dance dance dance, and I dance dance dance. |
Todd Cope
Member #998
November 2000
|
Processor: 2.8ghz Pentium 4 w/HT Test 1:
Test 2:
|
Matthew Leverton
Supreme Loser
January 1999
|
I think my C64 could solve faster than some of these computers... I'd have to rewrite the program first though to not use 100MB of RAM on the dictionary. Quote: I don't really feel like rebooting into windows.. But I could test on my Q6600 if you get source using pthreads.... I'll release the source later after I clean it up a bit and add proper support for 'Q' since it's actually 'Qu'. Also right now the scores are erroneously high since I'm not checking for duplicates. The highest known computed score for a 4x4 using the Scrabble word list is around 2,500. And yes, I am using pthreads to concurrently solve boards since they are all independent of each other. |
Thomas Fjellstrom
Member #476
June 2000
|
I figured you'd have used Win32 threads since its a windows program. -- |
wiseguy
Member #44
April 2000
|
wow, 100 percent cpu usage and 70+ Mb of RAM used if you go with too many boards but it's kinda cool
I didn't try for 1,000,000... I have a 2.66 GHz celeron |
OnlineCop
Member #7,919
October 2006
|
My question is, why is the time exponential O(n2) instead of linear O(n) or even O(n log n) ? Are you re-checking things within a tight loop (like variable.size() inside of a for..loop)?
|
Thomas Fjellstrom
Member #476
June 2000
|
Quote: My question is, why is the time exponential O(n2) instead of linear O(n) or even O(n log n) ? Maybe the number of threads has something to do with it? Windows performs fairly badly when you start loading up on threads. -- |
Matthew Leverton
Supreme Loser
January 1999
|
Quote: My question is, why is the time exponential O(n2) instead of linear O(n) or even O(n log n) ? Do you mean a single solution? Because the time per board has the same distribution whether you do 1000 or 1000000. Solving a single solution takes roughly the same time, but it depends on the letters. A board of all Q's will be solved faster than one with good letters. Quote: wow, 100 percent cpu usage and 70+ Mb of RAM used if you go with too many boards If I'm not using 100% then I'm not using enough! It uses more threads depending on the number of boards to solve. If you do fewer than 1000, then it will run in a single thread. So if you only have on CPU/core that may give you best results. I have a dual core system (AMD), but I get best results by running up to 8 threads at once. Obviously the most significant jump for me was from 1 to 2 threads. From 2 to 8 boosted me up to about 11K/s from 8K/s on 2 threads. Same went for my Core 2 Duo laptop. But from some of the numbers here, it doesn't appear to be consistent across all computers. I assume none of the people were taxing their CPUs hard at the same time as running the solver... |
GullRaDriel
Member #3,861
September 2003
|
Edited: I was using some poor power management on my laptop. BTW I have a Core 2 Duo @ 2 GHz with 2 GB of ram. EDIT: Quote: Windows performs fairly badly when you start loading up on threads. Do you have any proof of that ? "Code is like shit - it only smells if it is not yours" |
nonnus29
Member #2,606
August 2002
|
Solved 100000 boards in 7.234000 seconds (13823.610333/s) Solved 500000 boards in 36.609001 seconds (13657.843267/s) Core 2 Duo E6600. I want to see Thomas Q6600 result. Edit: Solved 1000000 boards in 71.359001 seconds (14013.649067/s) Oooh, do I have the high score?!?! I think this is the hardest workout this machine has had in the year I've had it... That's a shame... |
Matthew Leverton
Supreme Loser
January 1999
|
For what it's worth, it works like this: I load the dictionary as a tree. Each node is a letter with 26 children nodes. CAT, CARE, and CAREER would look like: Root | C | A / \ T R * | CAT E----E----R * * CARE CAREER The dictionary is read only and shared among all the threads. Say we have a board like: C E A R I set a node pointer to the dictionary root and check if n->c['c'] exists. It does, so I walk down to it. I check to see if the terminate node (*) exists. It doesn't, so C is not a word. I move to the right on the board, see an e, and therefore check for n->c['e']. It doesn't exist, so no words begin that that combo, and I go back up to the previous node and check the next available letter in the board. I just use an iteration (no recursion) with a static stack of length rows * cols. If a word node is reached, then its pointer added to the static list of word pointers. This is to minimize any unnecessary string copies from the dictionary to the word list. That is, once the dictionary is loaded and the board is created, memory is not created or destroyed or moved around. So if your CPU can handle all of that, then you'll get a nice fast time. The biggest optimization to my current approach would be to try to get stuff in memory stored in as optimal way as possible, but if anyone has any better algorithms than mine please share. |
Timorg
Member #2,028
March 2002
|
Thats the kind of dictionary structure I used for an anagram finder. ____________________________________________________________________________________________ |
nonnus29
Member #2,606
August 2002
|
Quote: but if anyone has any better algorithms than mine please share. That sounds pretty optimal to me. I was thinking that your tree dictionary will probably give you good 'locality of reference' since the most common words in the english language use similar letters (ie will the most used parts of the dictionary stay in cache?). You're not allocating/freeing memory. Are there function calls? A lot of function calls? I'm going to be pissed OFF if this is NOT written in D. |
ks
Member #1,086
March 2001
|
Perhaps the following link is of some value,
|
Matthew Leverton
Supreme Loser
January 1999
|
I wrote it in D and then translated it to C. In a real world application, I would use D because I wouldn't need to solve billions of puzzles. But given I want to optimize it for speed, C is a better choice. This is the type of thing I'd write in C as a library and interface it with D or PHP, etc. [Or use D but write the code by managing my own memory.] All memory allocation is done at initialization. The only function calls are like board_reset() and board_solve() which could really be optimized out. The algorithm itself is just a single for loop. The D version was significantly slower because I made it more friendly to use. For instance, I had a pathfinder() function that could walk every possible path, taking a boolean delegate as a parameter that would determine whether or not to continue following each node. So I could so stuff like:
So it looks nice because you can easily share code, but really you're just wasting a lot of function calls. Obviously a similar thing could be done in C with function pointers, but I wanted to maximized speed. Once I finish it in C, I'll translate it back D in the same form. But it won't really look like a D application. I mostly just want to test out how well the D compiler optimizes. |
Oscar Giner
Member #2,207
April 2002
|
Solved 100000 boards in 5.328000 seconds (18768.768527/s) Core 2 Duo E6750 at 3.2GHz -- |
GullRaDriel
Member #3,861
September 2003
|
Quote: Obviously a similar thing could be done in C with function pointers, but I wanted to maximized speed. And how a call to a function pointer is different from a call to that function itself ? "Code is like shit - it only smells if it is not yours" |
Thomas Fjellstrom
Member #476
June 2000
|
Quote: And how a call to a function pointer is different from a call to that function itself ? The extra pointer indirection adds up if its done a lot. -- |
ImLeftFooted
Member #3,935
October 2003
|
Matthew said: I mostly just want to test out how well the D compiler optimizes. Any details (ie. numbers) on performance differences? |
|
1
2
|