[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Who likes Sudoku?

studlee2@gmail.com

7/15/2006 2:58:00 PM

Here is the smallest Ruby Sudoku solver I could come up with. I've
seen a bunch that are really big, but this is the most simplistic. I'd
like to shrink it a bit more, but it works well for now. Things like
reading in the ARGV line as Integers could remove all the ".to_i" tags.
Another line could be removed if the hash is declared within the loop
instead of the top of the subroutine. Is there are way to loop through
numbers 1..9 using the 10.times notation so I don't have to skip '0' --
it'd be nice to remove that line too? Can we GOLF this anymore? I'm
going to keep refining it, so I'll post any updates later on. This was
a fun problem - Ruby Rocks!

/----------------------------------------------------------------------------------------------------/
# A ruby script to solve sudoku puzzle
# USAGE: ruby sudoku.rb <Sudoku puzzle on one line/no spaces with 0's
being the blanks>
# Example:ruby sudoku.rb 000201600.....09605000
#
# Written by: Studlee2 at Gmail dot com
# algorithm by http://www.ecclest...

$puzzle = ARGV.shift.split(//)

def sudoku_solver
hash = Hash.new()
80.times do |j|
next if $puzzle[j].to_i != 0
80.times {|k| hash[k.to_i / 9 == j / 9 ||k.to_i%9 == j%9 || k.to_i
/ 27 == j / 27 && k.to_i%9/3 == j%9/3 ?$puzzle[k.to_i]:0] = 1}
10.times {|v| next if v==0 || hash.has_key?(v.to_s); $puzzle[j] =
v.to_s; sudoku_solver}
return $puzzle[j] = 0;
end
return puts "The solution is:#{$puzzle}"
end

sudoku_solver
/----------------------------------------------------------------------------------------------------/


Enjoy,
_Steve

15 Answers

dblack

7/15/2006 3:54:00 PM

0

studlee2@gmail.com

7/15/2006 4:04:00 PM

0

I'm not really sure about the whole "GOLF" vs. "golf". We'll say
'GOLF'.downcase and call it even. I think 'golf' is the right way to
refer to squeezing code.

_Steve


dblack@wobblini.net wrote:
> Hi --
>
> On Sun, 16 Jul 2006, studlee2@gmail.com wrote:
>
> > Here is the smallest Ruby Sudoku solver I could come up with. I've
> > seen a bunch that are really big, but this is the most simplistic. I'd
> > like to shrink it a bit more, but it works well for now. Things like
> > reading in the ARGV line as Integers could remove all the ".to_i" tags.
> > Another line could be removed if the hash is declared within the loop
> > instead of the top of the subroutine. Is there are way to loop through
> > numbers 1..9 using the 10.times notation so I don't have to skip '0' --
> > it'd be nice to remove that line too? Can we GOLF this anymore? I'm
>
> Has GOLF become a "backronym"? I thought it was just "golf", but I
> keep seeing it in uppercase.
>
> > going to keep refining it, so I'll post any updates later on. This was
> > a fun problem - Ruby Rocks!
>
> Anyway -- sure you can reduce it a bit. Change $puzzle to $p, to
> start with, and get rid of a bunch of spaces :-) (I haven't looked at
> the logic yet so my suggestions are pretty cosmetic.)
>
>
> David
>
> --
> http://www.rubypoweran... => Ruby/Rails training & consultancy
> http://www.manning... => RUBY FOR RAILS (reviewed on
> Slashdot, 7/12/2006!)
> http://dablog.r... => D[avid ]A[. ]B[lack's][ Web]log
> dblack@wobblini.net => me

Daniel Schierbeck

7/15/2006 5:09:00 PM

0

studlee2@gmail.com wrote:
> Is there are way to loop through
> numbers 1..9 using the 10.times notation so I don't have to skip '0' --
> it'd be nice to remove that line too?

1.upto(10){|i| ... }


Cheers,
Daniel

studlee2@gmail.com

7/15/2006 5:10:00 PM

0

This is a little smaller.

$p = ARGV.shift.split(//)

def s
h = Hash.new()
80.times do |j|
next if $p[j].to_i != 0
80.times {|k| h[k.to_i / 9 == j / 9 ||k.to_i%9 == j%9 || k.to_i /
27 == j / 27 && k.to_i%9/3 == j%9/3 ?$p[k.to_i]:0] = 1}
10.times {|v| next if v==0 || h.has_key?(v.to_s); $p[j] = v.to_s;
s}
return $p[j] = 0;
end
return (puts "\nSolution:#{$p}" )
end

s

studlee2@gmail.com

7/15/2006 5:21:00 PM

0

Smaller still. Thanks David/Daniel:

$p = ARGV.shift.split(//)

def s
h=Hash.new()
80.times do |j|
next if $p[j].to_i!=0

80.times{|k|h[k.to_i/9==j/9||k.to_i%9==j%9||k.to_i/27==j/27&&k.to_i%9/3==j%9/3?$p[k.to_i]:0]=1}
1.upto(9){|v|next if h.has_key?(v.to_s);$p[j]=v.to_s;s}
return $p[j]=0;
end
return (puts "\nSolution:#{$p}")
end

s

rubyfan

7/15/2006 5:35:00 PM

0

On 7/15/06, studlee2@gmail.com <studlee2@gmail.com> wrote:
> Smaller still. Thanks David/Daniel:
>
> $p = ARGV.shift.split(//)
>
> def s
> h=Hash.new()
> 80.times do |j|
> next if $p[j].to_i!=0
>
> 80.times{|k|h[k.to_i/9==j/9||k.to_i%9==j%9||k.to_i/27==j/27&&k.to_i%9/3==j%9/3?$p[k.to_i]:0]=1}
> 1.upto(9){|v|next if h.has_key?(v.to_s);$p[j]=v.to_s;s}
> return $p[j]=0;
> end
> return (puts "\nSolution:#{$p}")
> end
>
> s
>
change h=Hash.new() to h={}

Phil

Marcin Mielzynski

7/15/2006 7:42:00 PM

0

studlee2@gmail.com wrote:
> Smaller still. Thanks David/Daniel:
>
> $p = ARGV.shift.split(//)
>
> def s
> h=Hash.new()
> 80.times do |j|
> next if $p[j].to_i!=0
>
> 80.times{|k|h[k.to_i/9==j/9||k.to_i%9==j%9||k.to_i/27==j/27&&k.to_i%9/3==j%9/3?$p[k.to_i]:0]=1}
> 1.upto(9){|v|next if h.has_key?(v.to_s);$p[j]=v.to_s;s}
> return $p[j]=0;
> end
> return (puts "\nSolution:#{$p}")
> end
>
> s
>

Other cosmetic suggestions:
change:
ARGV to $*
h=Hash.new to h={}
next if $p[j].to_i!=0 to $p[j].to_i!=0&&next
all do..end to {..}
get rid of new lines ;)

lopex

Adam Shelly

7/15/2006 8:34:00 PM

0

On 7/15/06, Joey <rubytalk@eachmapinject.com> wrote:
> Sorry, mine doesnt work. would you mind giving us an input and an output to
> test with?
>
Yes, before we golf this further, does it even work?
I gave the original version the input
003020600900305001001806400008102900700000008006708200002609500800203009005010300
which should solve to
483921657967345821251876493548132976729564138136798245372689514814253769695417382
but it just kept running and running and printing variations on strings like
The solution is:
21345678945678912378912345612436589736589721489721436554163297867894153293257864
which is one digit too short, and has incorrect numbers in many places...
It's possible I didn't wait long enough, but most solvers can finds
that answer in under a second.
-Adam

Daniel Schierbeck

7/15/2006 9:10:00 PM

0

Marcin MielżyÅ?ski wrote:
> all do..end to {..}
> get rid of new lines ;)

Personally, I'd much rather have more do..end and more lines. Terseness
cannot be measured in mere character counts.


Daniel

Just Another Victim of the Ambient Morality

7/15/2006 9:11:00 PM

0


"Adam Shelly" <adam.shelly@gmail.com> wrote in message
news:491107790607151333y2028ceccna66da5abb46a9ad4@mail.gmail.com...
> On 7/15/06, Joey <rubytalk@eachmapinject.com> wrote:
>> Sorry, mine doesnt work. would you mind giving us an input and an output
>> to
>> test with?
>>
> Yes, before we golf this further, does it even work?
> I gave the original version the input
> 003020600900305001001806400008102900700000008006708200002609500800203009005010300
> which should solve to
> 483921657967345821251876493548132976729564138136798245372689514814253769695417382
> but it just kept running and running and printing variations on strings
> like
> The solution is:
> 21345678945678912378912345612436589736589721489721436554163297867894153293257864
> which is one digit too short, and has incorrect numbers in many places...
> It's possible I didn't wait long enough, but most solvers can finds
> that answer in under a second.

Well, I've seen someone else on this newsgroup (or the mailing list)
write a sudoku solver in Ruby and their execution time was more than 30
seconds! This is quite understandable if the goal of the script was
minimizing lines of code rather than minimizing execution time...

However, if someone else finds the script to be broken then I think it
likely is...