Sudoku Programmers Forum Index

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister   ProfileProfile   Log inLog in          Games  Calendar

Log in to check your private messagesLog in to check your private messages   

How to generate random sudoku array?
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Programming sudoku
View previous topic :: View next topic  
Author Message
popo_john

Joined: 14 Oct 2005
Posts: 2
:
Location: Beijing

Items
PostPosted: Fri Oct 14, 2005 6:55 am    Post subject: How to generate random sudoku array? Reply with quote

HI, every one here, i've seen some topics in the forum, but i cant find some good approach to generate sudoku array. who can help me good idea? thx. Smile
Back to top
View user's profile Send private message
dukuso

Joined: 14 Jul 2005
Posts: 424
:
Location: germany

Items
PostPosted: Fri Oct 14, 2005 12:05 pm    Post subject: Reply with quote

there is a list of 306693 so-called G-classes at
http://magictour.free.fr/sudogan.gz
pick one of these at random, permute the minicolumns randomly,
but such that you get a valid sudoku-grid.
This way you can get a sudokugrid from any of the
~5e9 equivalence classes.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
noeldillabough

Joined: 12 Oct 2005
Posts: 16
:

Items
PostPosted: Sat Oct 15, 2005 1:33 am    Post subject: G-Classes Reply with quote

Cool resource, but where can I read more about these G-Classes and what they are, how they work etc?
Back to top
View user's profile Send private message
dukuso

Joined: 14 Jul 2005
Posts: 424
:
Location: germany

Items
PostPosted: Sat Oct 15, 2005 2:18 am    Post subject: Reply with quote

http://www.setbb.com/phpbb/viewtopic.php?t=194&mforum=sudoku

I could make a program to print one sudokugrid from each
S-class, some few will be printed twice, about 6 billion grids,
requiring a 500GB file to store them and running for
some days.
Or a program which prints all T-classes for a given G-class.
(again some few doublettes may occur)
Back to top
View user's profile Send private message Send e-mail Visit poster's website
mrcl

Joined: 01 Dec 2005
Posts: 3
:

Items
PostPosted: Sat Dec 03, 2005 12:57 am    Post subject: Re: How to generate random sudoku array? Reply with quote

popo_john wrote:
i cant find some good approach to generate sudoku array. who can help me good idea? thx. Smile

i think it is possible by using of the results stated in http://www.sudoku.com/forums/viewtopic.php?t=44&postdays=0&postorder=asc&start=55 to construct truly random sudoku grids.
for box (B1,B2,B4,B5,B3,B7,B6,B8,B9) we have at most (9!,12096,12096,448,3!^3,3!^3,8,8,1) selections. this gives about 7*10^22 possibilities to select a grid of random. there are about 7*10^21 sudoku grids (http://www.sudoku.com/forums/viewtopic.php?t=44&postdays=0&postorder=asc&start=138, http://www.sudoku.com/forums/viewtopic.php?t=44&postdays=0&postorder=asc&start=41) so there is a chance about 1/10 that such a randomly selected grid is a sudoku grid.
_________________
guenter
Back to top
View user's profile Send private message
dukuso

Joined: 14 Jul 2005
Posts: 424
:
Location: germany

Items
PostPosted: Sat Dec 03, 2005 7:55 am    Post subject: Reply with quote

one of these programs which count all sudokugrids can
probably be modified to generate a truly random sudokugrid.

You could also generate about a million random latin squares
with Jacobson-Matthews(sp?) and choose the first of these
which happens to be a sudokugrid

6.67e21 sudokugrids
5.5e27 9*9 latin squares
Back to top
View user's profile Send private message Send e-mail Visit poster's website
dom

Joined: 10 Nov 2005
Posts: 42
:

Items
PostPosted: Mon Dec 05, 2005 10:07 am    Post subject: Reply with quote

Here's a bit of pseudo-code for completely random grid generation. No need to use big memory arrays or anything.

Basically it selects a random number for cell 1, checks the grid is valid (always true), selects a number for cell 2, checks the grid is valid, selects a number for cell 3, checks the grid is valid, etc..

When the grid isn't valid a different random number is tried in that cell.

When all values have been tried in that cell the recursion backs up one, and other values are tried in the previous cell. The algorithm carries on going forwards and backwards like that until it reaches the 81st cell, at which point the grid is complete.

The code is very quick, but there are obviously optimisations to be made. In the interest of readability I haven't included any below. Smile

(edit)in case you were wondering, generation can be <0.5ms per board depending on how you write the BoardValid function.

Code:
PopulateBoard()
{
 PopulateCell(0)
}

bool PopulateCell(index)
{
 if (index==81
  return true; // the board is full!!

 // try setting each possible value in cell
 set cellorder = {1..9} // Note this list contains 1..9 in a *random* order

 for (i=0; i<9; i++)
 {
  // set this test value
  set cell[index] = cellorder[i]

  // is this board still valid?
  if(BoardValid())
  {
   // it is so try to populate next cell
   if (PopulateCell(index+1))
   {
    // if this cell returned true, then the board is valid
    return true;
   }
  }
 }
 // rollback this cell
 return false;
}

bool BoardValid()
{
 // test constraints
 if (constraintsValid)
  return true;
 else
  return false;
}

_________________
Orangeminds Sudoku
http://www.orangeminds.com/sudoku/
Back to top
View user's profile Send private message
tifs

Joined: 19 Dec 2005
Posts: 5
:

Items
PostPosted: Mon Dec 19, 2005 12:49 am    Post subject: Reply with quote

I wrote an implementation of this pseudo-code in pascal, but I'm having trouble with the boardvalidate function. Could you help?

The function starts by checking whether a number is repeated in a row or column, and if so, the function returns false.
However, the program enters an infinite loop because (i think):
When an invalid number is entered for cell[i], ie when no number fits, the algorithm backtracks to cell[i-1] and tries to change that value. However, because cell[i] still contains an invalid number, cell[i-1] becomes invalid.

The 2 possible solutions I can think of:
1) write boardvalid() so it only checks up to cell[i]
2) clear all cells after cell[i] before executing boardvalid()

I had a go at both of these ways with no luck - suggestions appreciated Smile
Back to top
View user's profile Send private message
dom

Joined: 10 Nov 2005
Posts: 42
:

Items
PostPosted: Mon Dec 19, 2005 10:56 am    Post subject: Reply with quote

Hi tifs,

You're on the right lines with rolling that cell back before steping back in the recursion. i.e. where the comment says...

Code:
// rollback this cell


...you want to set the cell's value to null before the function returns in the recursion.

Your two suggestions should also work fine though. Perhaps you could view the algorithm as it goes along and just slow it down with a sleep() to see what it's doing?
_________________
Orangeminds Sudoku
http://www.orangeminds.com/sudoku/
Back to top
View user's profile Send private message
tifs

Joined: 19 Dec 2005
Posts: 5
:

Items
PostPosted: Thu Dec 22, 2005 1:08 am    Post subject: Reply with quote

Thanks for the help!
I did what you suggested but it still went into a loop, so either I put the rollback command in the wrong place, or something else is wrong. I used 'cells[1..81] : integer' for the board, and the following code for the populatecell() function. Note the version of pascal I'm using doesn't support "return" - a boolean function returns true or false based on the setting of the function's name when the function has reached completion. The boardvalid code so far only checks for repetition in a row or column.
Code:

function populatecell(count:integer) : boolean;
begin
  if count <> 82 then begin
   
    //set 1-9 in random order
    triedvals := '';
    for i := 1 to 9 do begin
      repeat
        n := (Random(9)+1);
      //note pos(string1,string2) returns -1 if string2 is not present in string1
      until pos(triedvals,integertostring(n)) = -1;
      vals[i] := n; // vals[1..9] contains 1 to 9 in a random order
      triedvals := triedvals + integertostring(n);
    end;

    k := 1;
    valok := FALSE;
   
    repeat
      cells[count] := 0;
      cells[count] := vals[k]; //try a test value
      if boardvalid = TRUE then if populatecell(count+1) = TRUE then valok := TRUE;
      if valok = FALSE then cells[count] := 0;
      k := k + 1;
    until valok = TRUE;

    count := count + 1;

  end;
populatecell := TRUE;
end;

Making the program show what it's doing once gave this:
385612479
946851732
291478563
514927386
127394851
000000000
000000000
000000000
000000000
As you can see, the algorithm fails on the last number (1), which should be a 6 according to the row, but can't be according to the column. This shows it either isn't backtracking correctly, or setting cells[count] to 0 is misplaced. Note 6 is also present in the 8th column. Did I understand your populatecell code correctly? Confused[/code]
Back to top
View user's profile Send private message
dom

Joined: 10 Nov 2005
Posts: 42
:

Items
PostPosted: Thu Dec 22, 2005 8:25 am    Post subject: Reply with quote

Hi tifs,

I'm no pascal expert, but I don't think your second repeat until loop will ever terminate. What you need to do is to get populatecell to return a false value if none of it's 9 possibilities lead to a valid board.

So somewhere you're going to need

Code:
populatecell := FALSE;


Actually, maybe the following will work better...

Code:

function populatecell(count:integer) : boolean;
begin
  valok := FALSE;
  if count <> 82 then begin
   
    //set 1-9 in random order
    triedvals := '';
    for i := 1 to 9 do begin
      repeat
        n := (Random(9)+1);
      //note pos(string1,string2) returns -1 if string2 is not present in string1
      until pos(triedvals,integertostring(n)) = -1;
      vals[i] := n; // vals[1..9] contains 1 to 9 in a random order
      triedvals := triedvals + integertostring(n);
    end;

    k := 1;
    valok := FALSE;
   
    repeat
      cells[count] := vals[k]; //try a test value
      if boardvalid = TRUE then if populatecell(count+1) = TRUE then valok := TRUE;
      k := k + 1;
    until k > 9 || valok = TRUE;

    if valok = FALSE then cells[count] := 0;

  else
    valok = TRUE; // i.e. if we are at cell 82, the board must be valid
  end;
populatecell := valok;
end;


In this case the second repeat loop will just try the 9 values until a valid board is found (vakok=true). If a valid board isn't found then the loop exits with valok = to false. The current value is then reset to 0 if valok is false. Finally the function returns whether or not this cell has resulted in a valid board (populatecell := valok)

Note that you don't need count := count+1 inside the loop because you already add 1 to count when you call the next recursion of the function.
_________________
Orangeminds Sudoku
http://www.orangeminds.com/sudoku/
Back to top
View user's profile Send private message
Fyska

Joined: 08 Nov 2005
Posts: 10
:

Items
PostPosted: Mon Jan 02, 2006 2:15 pm    Post subject: Reply with quote

I'm also having problems with the BoardValid() function

I split the problem up into validating the 9 grids, rows and columns seperately, in 3 functions.

I've checked each function separately, and they work fine - just checking the grids gives me 9 grids with 1-9 in the same place, just checking the rows gives me 1-9 along the rows.

But when I call all 3 (or indeed, just 2), it completely screws up - the first grid of 3x3 is always full of the last number of cellorder.....

set cellorder = {1..9} // Note this list contains 1..9 in a *random* order

And the second grid has this same number everywhere except the [3,3].

Any ideas? Smile
Back to top
View user's profile Send private message
dom

Joined: 10 Nov 2005
Posts: 42
:

Items
PostPosted: Tue Jan 03, 2006 12:33 pm    Post subject: Reply with quote

Fyska wrote:
set cellorder = {1..9} // Note this list contains 1..9 in a *random* order

And the second grid has this same number everywhere except the [3,3].

Any ideas? Smile


Difficult to say without seeing your code. I think there's two things to check here. Firstly test your boardvalid function by using some input which you already know is a valid board

Code:
123456789
456789123
789123456
234567891
567891234
891234567
345678912
678912345
912345678


Next, make sure that your recursive function is actually recursive. For example, check that it occasionally returns false. The fact that your algorithm completes with an invalid board is not a good sign, because presumably boardvalid is returning false, which means it should never have got past the first cell which created an invalid board.

This algorihtm depends entirely on the ability to backup when it reaches a cell which it can't fill in. So if it's tried all of {1..9} in a cell, and it can't get a valid board, the algorithm then needs to go back to the previous cell and try a different value. To do this the recursive function returns false, which tells the previous cell to try a different value.

If that last paragraph doesn't make sense, keep reading it until it does, because that's the crux of this method. Smile

Good luck, and if you have any problems, feel free to drop me a message or post your code here. Smile
_________________
Orangeminds Sudoku
http://www.orangeminds.com/sudoku/
Back to top
View user's profile Send private message
Fyska

Joined: 08 Nov 2005
Posts: 10
:

Items
PostPosted: Tue Jan 03, 2006 12:54 pm    Post subject: Reply with quote

I checked whether it returns false, and it does.

This is my FillBoard method [C#]:
Code:

        protected bool FillBoard(int index)
        {
            if (index == NUMROWS * NUMCOLUMS)
                return true; //board is full

            int[] randomvalues = GenerateRandomNums();

            //todo: change all numbers to constants
            for (int i = 0; i < NUMROWS; i++)
            {
                _BoardNumbers[index] = randomvalues[i];

                if (BoardIsValid())
                    if (FillBoard(index + 1))
                        return true; //board is valid
            }

            return false;
        }


Having another look at it, I decided to add in a 'return false' here:

Code:

                if (BoardIsValid())
                    if (FillBoard(index + 1))
                        return true; //board is valid
                    else
                        return false;


And the output is slightly better - it looks like:
http://fyska.ireallydontcare.com/images/sudoku%20error.png which is an improvement on it being all the same number, I suppose...

But still, it's a bit borked.
Back to top
View user's profile Send private message
dom

Joined: 10 Nov 2005
Posts: 42
:

Items
PostPosted: Tue Jan 03, 2006 1:13 pm    Post subject: Reply with quote

Fyska wrote:

Code:

                if (BoardIsValid())
                    if (FillBoard(index + 1))
                        return true; //board is valid
                    else
                        return false;



I'd change that to this just to make sure... if if else is a classic case of difficult to compile code...

Code:

                if (BoardIsValid())
                {
                    if (FillBoard(index + 1))
                        return true; //board is valid
                    else
                        return false;
                }


{EDIT}But you shouldn't need the else return false; bit anyway. And actually, I'm certain that'll break the algorithm...{/EDIT}

{EDIT2}Actually, scratch that.

Remove your additional return false;, but before you return false, make sure you do this
Code:

_BoardNumbers[index] = 0;

Otherwise your board will be left with dud values when the algorithm goes backwards, which will definitely stop the algorithm completing.
{/EDIT2}
_________________
Orangeminds Sudoku
http://www.orangeminds.com/sudoku/


Last edited by dom on Tue Jan 03, 2006 1:21 pm; edited 2 times in total
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Programming sudoku All times are GMT
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Sudoku Programmers topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group

Igloo Theme Version 1.0 :: Created By: Andrew Charron