On Tue, 01 Aug 2006 17:48:41 +0900, Peter H. wrote:
The source code is available from
http://peterhi.dyndns.org/write_it_in_c/index.html
Here is another version in Ruby. It uses a more clever algorithm.
It makes use of the fact that permuting the rows or the columns of
a latin square still gives a latin square. It also passes a constraint
on the columns that the given number can be in, to reduce the
backtracking
even more.
It runs in 15 seconds on my machine, which I find quite acceptable.
I am sure that this algorithm coded in a compiled functional or logic
language would be about as fast, or faster than your C code, but with
the
advantages of a higher level language.
I still think you benchmark is flawed, because
- the C program works only for squares of size 5
- It shows totally no relevance to the kind of problems that you
would use Ruby for. If you want raw speed for numerical
applications,
then I would suggest to use a functional language (i.e. ocaml).
- If your application runs slowly, it is probably better to think
first
about why it is slow, if you can improve the code with faster
algorithms or removing bottlenecks.
Kristof B.
---------------- latin2.rb --------------------
require ‘permutation’
$size = (ARGV.shift || 5).to_i
MaxVal = $size-1
RowPermutations = Permutation.new($size).map{|p| p.value}
BaseStr = (2…$size).to_a.join
StrPermutations = Permutation.new($size-1).map{|p| p.project(BaseStr)}
StartColumns = (1…MaxVal).to_a
def init_columns(el)
a = StartColumns.dup
a.delete_at(el-1)
return a
end
def insert(sqr, num, row, columns)
insert(sqr, num, row+1, columns) if (row == num)
columns.each do |col|
next if sqr[row][col] != ?.
sqr[row][col] = num + ?1
if (row == MaxVal)
insert(sqr, num+1, 1, init_columns(num+1))
elsif (num == MaxVal && row == MaxVal - 1)
print_solution(sqr)
else
insert(sqr, num, row+1, columns - [col])
end
sqr[row][col] = ?.
end
end
def print_solution(sqr)
RowPermutations.each do |rp|
StrPermutations.each do |sp|
0.upto(MaxVal) do |r|
print sqr[rp[r]].tr(BaseStr, sp)
print “:”
end
puts
end
end
end
$square = [(“1” + BaseStr)] +
Array.new($size-1) { |i| (i+2).to_s + “.” * ($size - 1) }
insert($square, 0, 1, StartColumns)