Skip to content

Instantly share code, notes, and snippets.

@takehiko
Created October 30, 2011 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takehiko/1326406 to your computer and use it in GitHub Desktop.
Save takehiko/1326406 to your computer and use it in GitHub Desktop.
Four fives: Method B
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
class Rot90b
def initialize
@field_s = <<EOS
**
**
******
******
**
**
EOS
init_field
end
def start
print_field
@qstar = count_star / 4
@stack = [] # array of [x, y]
@num_answer = 0
search
end
def search(pos_start = 0)
pos_start.upto(@width * @height - 1) do |i|
x = i % @width
y = i / @width
if @field[y][x] == "*"
@stack << [x, y]
if @stack.length == @qstar
if examine_field
@num_answer += 1
puts "Answer No.#{@num_answer}"
print_field
end
reset_field
else
search(i + 1)
end
@stack.pop
end
end
end
def examine_field
reset_field
@stack.each do |x, y|
@field[y][x] = "1"
end
rotate_superpose("1", "2")
rotate_superpose("2", "3")
rotate_superpose("3", "4")
# If there is no "*" in the field, then that is a solution!
count_star == 0
end
def reset_field
@field = []
s = @field_s.split(/\n/)
s.each do |line|
@field << line.split(//)
end
end
def init_field
reset_field
@width = @field.map {|line_a| line_a.length}.max
@height = @field.length
if @width == 0 || @width != @height
puts "The field is not square. Abort."
exit(1)
end
if @width % 2 == 1 || @height % 2 == 1
puts "The width and/or the height is odd. Abort."
exit(1)
end
s = count_star
if s == 0 || s % 4 > 0
puts "The number of asterisk is #{s} and wrong. Abort."
exit(1)
end
@x_center = (@width - 1) * 0.5
@y_center = (@height - 1) * 0.5
end
def count_star
@field.map {|line_a| line_a.join}.join.scan(/\*/).length
end
def print_field
print *(@field.map {|line_a| line_a.join + "\n"})
end
def xy_rot90(x_from, y_from)
x1 = x_from - @x_center
y1 = y_from - @y_center
x2 = y1
y2 = -x1
x_to = (x2 + @x_center).to_i
y_to = (y2 + @y_center).to_i
[x_to, y_to]
end
def rotate_superpose(c_from, c_to)
@height.times do |y|
@width.times do |x|
if @field[y][x] == c_from
x_to, y_to = xy_rot90(x, y)
@field[y_to][x_to] = c_to
end
end
end
end
end
if __FILE__ == $0
Rot90b.new.start
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment