[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Fwd: [SOLUTION] Sudoku

James Gray

12/30/2005 2:17:00 PM

Begin forwarded message:

> From: NILSSON Christer <christer.nilsson@nordicsolution.com>
> Date: December 30, 2005 4:09:59 AM CST
> To: James Edward Gray II <james@grayproductions.net>
> Subject: Re: Ruby Quiz Suggestion
> Reply-To: NILSSON Christer <christer.nilsson@nordicsolution.com>
>
> Hello James!

[snip]

> I found a short solution for Sudoku. It was originally written by
> Kevin Greer in JavaScript, but Ruby makes it look even nicer. I
> haven't seen the use of this data structure in Sudoku before.

[snip]

> regards
> Christer
>
> class Sudoku
> def initialize s
> @s=s
> end
>
> def solve a, b, c, d
> return true if a==3
> return solve(a+1, 0, c, d) if b==3
> return solve(a, b+1, 0, d) if c==3
> return solve(a, b, c+1, 0) if d==3
> return solve(a, b, c, d+1) if @s[a][b][c][d]!=0
>
> for digit in 1..9
> if not occupied?(a, b, c, d, digit) then
> @s[a][b][c][d] = digit
> return true if solve(a, b, c, d+1)
> @s[a][b][c][d] = 0
> end
> end
> false
> end
>
> def occupied? a, b, c, d, digit
> for x in 0..2
> for y in 0..2
> return true if @s[a][b][x][y]==digit # block
> return true if @s[a][x][c][y]==digit # row
> return true if @s[x][b][y][d]==digit # column
> end
> end
> false
> end
> end
>
> s = [[[[0,0,0],[0,7,1],[0,0,5]], [[5,0,0],[0,6,9],[0,7,1]],
> [[0,7,1],[8,5,3],[4,2,0]]],
> [[[0,1,0],[0,0,2],[0,0,0]], [[7,8,0],[1,5,4],[0,9,2]],
> [[0,4,0],[3,6,0],[1,8,0]]],
> [[[0,6,4],[0,2,3],[0,5,0]], [[9,0,5],[0,1,0],[0,0,0]],
> [[7,0,0],[5,9,0],[0,0,0]]]]
> sudoku = Sudoku.new(s)
> sudoku.solve(0,0,0,0)
>
>



11 Answers

Craig Demyanovich

12/30/2005 3:17:00 PM

0

Greetings,

While it may be true that the Sudoku program below looks nicer in
Ruby than JavaScript, I don't find it very readable. Sure, it's
concise, but that doesn't help me understand it. The variable names
are horrible. As I learn Ruby, I'm seeing more and more of this poor
naming, favoring conciseness so much over clarity that some code
samples are outright frustrating to read for this "nuby." I hope that
I'm just stumbling on some bad examples and not the norm. I hope that
the more Ruby code I read, the more I'll find a pragmatic compromise
between conciseness and clarity.

Regards,
Craig

On Dec 30, 2005, at 9:17 AM, James Edward Gray II wrote:

> Begin forwarded message:
>
>> From: NILSSON Christer <christer.nilsson@nordicsolution.com>
>> Date: December 30, 2005 4:09:59 AM CST
>> To: James Edward Gray II <james@grayproductions.net>
>> Subject: Re: Ruby Quiz Suggestion
>> Reply-To: NILSSON Christer <christer.nilsson@nordicsolution.com>
>>
>> Hello James!
>
> [snip]
>
>> I found a short solution for Sudoku. It was originally written by
>> Kevin Greer in JavaScript, but Ruby makes it look even nicer. I
>> haven't seen the use of this data structure in Sudoku before.
>
> [snip]
>
>> regards
>> Christer
>>
>> class Sudoku
>> def initialize s
>> @s=s
>> end
>>
>> def solve a, b, c, d
>> return true if a==3
>> return solve(a+1, 0, c, d) if b==3
>> return solve(a, b+1, 0, d) if c==3
>> return solve(a, b, c+1, 0) if d==3
>> return solve(a, b, c, d+1) if @s[a][b][c][d]!=0
>>
>> for digit in 1..9
>> if not occupied?(a, b, c, d, digit) then
>> @s[a][b][c][d] = digit
>> return true if solve(a, b, c, d+1)
>> @s[a][b][c][d] = 0
>> end
>> end
>> false
>> end
>>
>> def occupied? a, b, c, d, digit
>> for x in 0..2
>> for y in 0..2
>> return true if @s[a][b][x][y]==digit # block
>> return true if @s[a][x][c][y]==digit # row
>> return true if @s[x][b][y][d]==digit # column
>> end
>> end
>> false
>> end
>> end
>>
>> s = [[[[0,0,0],[0,7,1],[0,0,5]], [[5,0,0],[0,6,9],[0,7,1]],
>> [[0,7,1],[8,5,3],[4,2,0]]],
>> [[[0,1,0],[0,0,2],[0,0,0]], [[7,8,0],[1,5,4],[0,9,2]],
>> [[0,4,0],[3,6,0],[1,8,0]]],
>> [[[0,6,4],[0,2,3],[0,5,0]], [[9,0,5],[0,1,0],[0,0,0]],
>> [[7,0,0],[5,9,0],[0,0,0]]]]
>> sudoku = Sudoku.new(s)
>> sudoku.solve(0,0,0,0)
>>
>>
>
>



Christer Nilsson

12/30/2005 4:20:00 PM

0

Craig Demyanovich wrote:
> The variable names are horrible.

Yes, you are correct. This is puzzle code, not production code. So part
of this is being puzzled! :-)

Joke aside, I considered using better variable names instead of a,b,c
and d, but did not find good candidates. Let me explain:

a, c = row.divmod(3) # row in 0..8
b, d = col.divmod(3) # col in 0..8

Maybe a=rowMajor, c=rowMinor, b=colMajor and d=colMinor would be more
helpful.

Fixing rowMajor and colMajor gives a 3x3 block:
s[rowMajor][colMajor][x][y], x in 0..2, y in 0..2
Fixing rowMajor and rowMinor gives a row
s[rowMajor][x][rowMinor][y]
Fixing colMajor and colMinor gives a column
s[x][colMajor][y][colMinor]

I hope this clarifies the code.

Christer


--
Posted via http://www.ruby-....


Dirk Meijer

12/30/2005 7:17:00 PM

0

2005/12/30, Craig Demyanovich demmer12@fastmail.us:
>
> While it may be true that the Sudoku program below looks nicer in
> Ruby than JavaScript, I don't find it very readable. Sure, it's
> concise, but that doesn't help me understand it.


i wouldn't call it concise, it simply doesn't work.. probably an error in
porting to Ruby..
the idea of simply going through every number and checking possibility is
nice, but not enough, because a lot of numbers might fit, though only one
will get you the proper solution.

Christer Nilsson

12/30/2005 7:29:00 PM

0

Dirk Meijer wrote:
> i wouldn't call it concise, it simply doesn't work.. probably an error
> in porting to Ruby..

It works. This is the complete code.
Christer

# Author: Kevin Greer (JavaScript), Date: Dec 25, 2005 -- Copyright
2005, All Rights Reserved
# Rewritten in Ruby by Christer Nilsson 2005-12-29

class Sudoku

def initialize s
@s=s
end

def display
for a in 0..2
for b in 0..2
for c in 0..2
for d in 0..2
print " " + @s[a][b][c][d].to_s
end
print " |" if c<2
end
print "\n"
end
print "-------+-------+-------\n" if a<2
end
end

def solve a, b, c, d
return true if a==3
return solve(a+1, 0, c, d) if b==3
return solve(a, b+1, 0, d) if c==3
return solve(a, b, c+1, 0) if d==3
return solve(a, b, c, d+1) if @s[a][b][c][d]!=0

for digit in 1..9
if not occupied?(a, b, c, d, digit) then
@s[a][b][c][d] = digit
return true if solve(a, b, c, d+1)
@s[a][b][c][d] = 0
end
end
false
end

def occupied? a, b, c, d, digit
for x in 0..2
for y in 0..2
return true if @s[a][b][x][y]==digit # block
return true if @s[a][x][c][y]==digit # row
return true if @s[x][b][y][d]==digit # column
end
end
false
end
end

s =
[[[[0,0,0],[0,7,1],[0,0,5]],
[[5,0,0],[0,6,9],[0,7,1]],
[[0,7,1],[8,5,3],[4,2,0]]],
[[[0,1,0],[0,0,2],[0,0,0]],
[[7,8,0],[1,5,4],[0,9,2]],
[[0,4,0],[3,6,0],[1,8,0]]],
[[[0,6,4],[0,2,3],[0,5,0]],
[[9,0,5],[0,1,0],[0,0,0]],
[[7,0,0],[5,9,0],[0,0,0]]]]
sudoku = Sudoku.new(s)
sudoku.display
print "\nsolving...\n\n"
if sudoku.solve(0,0,0,0) then
sudoku.display
end


0 0 0 | 0 7 1 | 0 0 5
5 0 0 | 0 6 9 | 0 7 1
0 7 1 | 8 5 3 | 4 2 0
-------+-------+-------
0 1 0 | 0 0 2 | 0 0 0
7 8 0 | 1 5 4 | 0 9 2
0 4 0 | 3 6 0 | 1 8 0
-------+-------+-------
0 6 4 | 0 2 3 | 0 5 0
9 0 5 | 0 1 0 | 0 0 0
7 0 0 | 5 9 0 | 0 0 0

solving...

2 3 9 | 4 7 1 | 6 8 5
5 4 8 | 2 6 9 | 3 7 1
6 7 1 | 8 5 3 | 4 2 9
-------+-------+-------
5 1 6 | 8 9 2 | 3 4 7
7 8 3 | 1 5 4 | 6 9 2
9 4 2 | 3 6 7 | 1 8 5
-------+-------+-------
1 6 4 | 7 2 3 | 9 5 8
9 2 5 | 8 1 6 | 4 3 7
7 3 8 | 5 9 4 | 2 1 6

Program exited with code 0

--
Posted via http://www.ruby-....


Christer Nilsson

12/30/2005 7:32:00 PM

0

Link to the original Javascript code by Kevin Greer:

http://www.peerbox.com:8668/space/start/2005-12-5/1#Soduko_Solver_in_...

Christer

--
Posted via http://www.ruby-....


Christer Nilsson

12/30/2005 7:33:00 PM

0

Simon Kröger

12/30/2005 7:50:00 PM

0

Christer Nilsson wrote:
> Dirk Meijer wrote:
>
>>i wouldn't call it concise, it simply doesn't work.. probably an error
>>in porting to Ruby..
>
>
> It works. This is the complete code.
> Christer
>
> # Author: Kevin Greer (JavaScript), Date: Dec 25, 2005 -- Copyright
> 2005, All Rights Reserved
> # Rewritten in Ruby by Christer Nilsson 2005-12-29
>
> class Sudoku
>
> def initialize s
> @s=s
> end
>
> def display
> for a in 0..2
> for b in 0..2
> for c in 0..2
> for d in 0..2
> print " " + @s[a][b][c][d].to_s
> end
> print " |" if c<2
> end
> print "\n"
> end
> print "-------+-------+-------\n" if a<2
> end
> end
>
> def solve a, b, c, d
> return true if a==3
> return solve(a+1, 0, c, d) if b==3
> return solve(a, b+1, 0, d) if c==3
> return solve(a, b, c+1, 0) if d==3
> return solve(a, b, c, d+1) if @s[a][b][c][d]!=0
>
> for digit in 1..9
> if not occupied?(a, b, c, d, digit) then
> @s[a][b][c][d] = digit
> return true if solve(a, b, c, d+1)
> @s[a][b][c][d] = 0
> end
> end
> false
> end
>
> def occupied? a, b, c, d, digit
> for x in 0..2
> for y in 0..2
> return true if @s[a][b][x][y]==digit # block
> return true if @s[a][x][c][y]==digit # row
> return true if @s[x][b][y][d]==digit # column
> end
> end
> false
> end
> end
>
> s =
> [[[[0,0,0],[0,7,1],[0,0,5]],
> [[5,0,0],[0,6,9],[0,7,1]],
> [[0,7,1],[8,5,3],[4,2,0]]],
> [[[0,1,0],[0,0,2],[0,0,0]],
> [[7,8,0],[1,5,4],[0,9,2]],
> [[0,4,0],[3,6,0],[1,8,0]]],
> [[[0,6,4],[0,2,3],[0,5,0]],
> [[9,0,5],[0,1,0],[0,0,0]],
> [[7,0,0],[5,9,0],[0,0,0]]]]
> sudoku = Sudoku.new(s)
> sudoku.display
> print "\nsolving...\n\n"
> if sudoku.solve(0,0,0,0) then
> sudoku.display
> end
>
>
> 0 0 0 | 0 7 1 | 0 0 5
> 5 0 0 | 0 6 9 | 0 7 1
> 0 7 1 | 8 5 3 | 4 2 0
> -------+-------+-------
> 0 1 0 | 0 0 2 | 0 0 0
> 7 8 0 | 1 5 4 | 0 9 2
> 0 4 0 | 3 6 0 | 1 8 0
> -------+-------+-------
> 0 6 4 | 0 2 3 | 0 5 0
> 9 0 5 | 0 1 0 | 0 0 0
> 7 0 0 | 5 9 0 | 0 0 0
>
> solving...
>
> 2 3 9 | 4 7 1 | 6 8 5
> 5 4 8 | 2 6 9 | 3 7 1
> 6 7 1 | 8 5 3 | 4 2 9
> -------+-------+-------
> 5 1 6 | 8 9 2 | 3 4 7
> 7 8 3 | 1 5 4 | 6 9 2
> 9 4 2 | 3 6 7 | 1 8 5
> -------+-------+-------
> 1 6 4 | 7 2 3 | 9 5 8
> 9 2 5 | 8 1 6 | 4 3 7
> 7 3 8 | 5 9 4 | 2 1 6
>
> Program exited with code 0

First Column has two 9's !

cheers

Simon


Dirk Meijer

12/30/2005 8:26:00 PM

0

>
> First Column has two 9's !


and it leaves my tests with zero's..
greetings, Dirk.

Christer Nilsson

12/30/2005 8:38:00 PM

0

> First Column has two 9's !
> cheers
> Simon

Excellent observation, Simon!

The error is in the display definition:
- print " " + @s[a][b][c][d].to_s
+ print " " + @s[a][c][b][d].to_s

New output:

2 3 9 | 5 4 8 | 6 7 1
4 7 1 | 2 6 9 | 8 5 3
6 8 5 | 3 7 1 | 4 2 9
-------+-------+-------
5 1 6 | 7 8 3 | 9 4 2
8 9 2 | 1 5 4 | 3 6 7
3 4 7 | 6 9 2 | 1 8 5
-------+-------+-------
1 6 4 | 9 2 5 | 7 3 8
7 2 3 | 8 1 6 | 5 9 4
9 5 8 | 4 3 7 | 2 1 6

Sorry, I shouldn't have opened that bottle of champagne yet!

Christer

--
Posted via http://www.ruby-....


Christer Nilsson

12/30/2005 8:41:00 PM

0

Dirk Meijer wrote:
> and it leaves my tests with zero's..
> greetings, Dirk.

Would you mind sending me your input, Dirk?

Christer

--
Posted via http://www.ruby-....