Free polyominoes enumeration: Difference between revisions

Content added Content deleted
(Updated D entry)
(Added Ruby)
Line 644: Line 644:
###
###
# </pre>
# </pre>

=={{header|Ruby}}==
{{trans|Python}}
<lang ruby>require 'set'

def translate2origin(poly)
# Finds the min x and y coordiate of a Polyomino.
minx = poly.map(&:first).min
miny = poly.map(&:last).min
poly.map{|x,y| [x - minx, y - miny]}.sort
end

def rotate90(x,y) [y, -x] end
def reflect(x,y) [-x, y] end

# All the plane symmetries of a rectangular region.
def rotations_and_reflections(poly)
[poly,
poly = poly.map{|x,y| rotate90(x,y)},
poly = poly.map{|x,y| rotate90(x,y)},
poly = poly.map{|x,y| rotate90(x,y)},
poly = poly.map{|x,y| reflect(x,y)},
poly = poly.map{|x,y| rotate90(x,y)},
poly = poly.map{|x,y| rotate90(x,y)},
poly.map{|x,y| rotate90(x,y)} ]
end

def canonical(poly, polyomino, pattern)
polys = rotations_and_reflections(poly).map{|pl| translate2origin(pl)}
polys.each{|pl| pattern << pl}
polyomino << polys.min
end

# All four points in Von Neumann neighborhood.
def contiguous(x,y)
[[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]]
end

# Finds all distinct points that can be added to a Polyomino.
def new_points(poly)
points = []
poly.each{|x,y| contiguous(x,y).each{|i,j| points << [i,j]}}
(points - poly).uniq
end

def new_polys(polys)
polyomino = Set.new
pattern = Set.new
polys.each do |poly|
new_points(poly).each do |point|
pl = translate2origin(poly + [point])
canonical(pl, polyomino, pattern) unless pattern.include?(pl)
end
end
polyomino.sort
end

# Generates polyominoes of rank n recursively.
def rank(n)
case n
when 0 then [[]]
when 1 then [[[0,0]]]
else new_polys(rank(n-1))
end
end

# Generates a textual representation of a Polyomino.
def text_representation(poly)
table = Hash.new(' ')
poly.each{|x,y| table[[x,y]] = '#'}
maxx = poly.map(&:first).max
maxy = poly.map(&:last).max
(0..maxx).map{|x| (0..maxy).map{|y| table[[x,y]]}.join}
end

p (0..10).map{|n| rank(n).size}
n = ARGV[0] ? ARGV[0].to_i : 5
puts "\nAll free polyominoes of rank %d:" % n
rank(n).each{|poly| puts text_representation(poly),""}</lang>

{{out}}
<pre>
[1, 1, 1, 2, 5, 12, 35, 108, 369, 1285, 4655]

All free polyominoes of rank 5:
#####

####
#

####
#

###
##

###
# #

###
#
#

###
#
#

###
##

##
##
#

##
##
#

##
#
##

#
###
#
</pre>