Skip to content

Instantly share code, notes, and snippets.

@takehiko
Created July 6, 2014 20:56
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/03c66680606c48344539 to your computer and use it in GitHub Desktop.
Save takehiko/03c66680606c48344539 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# ruby magicsquare.rb
# ruby magicsquare.rb -c
# ruby magicsquare.rb 2
# ruby magicsquare.rb 3
module MagicSquare
class Table
def initialize(t = nil)
@numbers = t || [nil, nil, 6, 3, nil, nil, 0, nil, nil]
end
attr_accessor :numbers
def to_s
s = ""
3.times do |row|
3.times do |col|
s += "[#{@numbers[3 * row + col] || ' '}]"
end
s += "\n"
end
s.strip
end
def print
puts to_s
end
def fill(ary)
i = 0
ary.each do |item|
until @numbers[i].nil?
i += 1
if i == @numbers.length
return self
end
end
@numbers[i] = item
end
self
end
def answer?(opt_msg = false)
if @numbers.compact.length != @numbers.length
return opt_msg ? "not filled" : false
end
if @numbers.uniq.length != @numbers.length
return opt_msg ? "same numbers found" : false
end
if @numbers[2] != 6 || @numbers[3] != 3 || @numbers[6] != 0
return opt_msg ? "initial state changed" : false
end
[@numbers[1], @numbers[3], @numbers[5], @numbers[7]].each do |num|
if num.even?
return opt_msg ? "odd number condition violated" : false
end
end
sums = []
sums << @numbers[0] + @numbers[1] + @numbers[2]
sums << @numbers[3] + @numbers[4] + @numbers[5]
sums << @numbers[6] + @numbers[7] + @numbers[8]
sums << @numbers[0] + @numbers[3] + @numbers[6]
sums << @numbers[1] + @numbers[4] + @numbers[7]
sums << @numbers[2] + @numbers[5] + @numbers[8]
sums << @numbers[0] + @numbers[4] + @numbers[8]
sums << @numbers[2] + @numbers[4] + @numbers[6]
if sums.uniq.length != sums.length
return opt_msg ? "same sums found" : false
end
opt_msg ? "OK" : true
end
end
class Solver
def initialize(opt_c = false)
@table_init = Table.new
@opt_correct_answer_only = opt_c
@trial_count = 0
end
def fill_table(t, ary)
t.fill(ary)
end
def valid_table(t = @table_init, opt_msg = false)
t.answer?(opt_msg)
end
def check_and_print_result(t)
@trial_count += 1
if @opt_correct_answer_only
if t.answer?
t.print
puts
end
else
puts "Trial \##{@trial_count} / Result: #{valid_table(t, true)}"
t.print
puts
end
end
def solve(param = nil)
case param
when "2"
solve_evenodd
when "3"
solve_perm9
else
solve_perm6
end
end
def solve_evenodd
if !@opt_correct_answer_only
Table.new.print
puts
end
ary_odd = "157".split(//).map {|item| item.to_i}
ary_even = "248".split(//).map {|item| item.to_i}
ary_odd.permutation do |perm_odd|
ary_even.permutation do |perm_even|
t = Table.new
t.numbers[1], t.numbers[5], t.numbers[7] = perm_odd
t.numbers[0], t.numbers[4], t.numbers[8] = perm_even
check_and_print_result(t)
end
end
end
def solve_perm9
ary = (0..8).to_a
ary.permutation do |perm|
check_and_print_result(Table.new(perm))
end
end
def solve_perm6
if !@opt_correct_answer_only
Table.new.print
puts
end
ary = "124578".split(//).map {|item| item.to_i}
ary.permutation do |perm|
check_and_print_result(Table.new.fill(perm))
end
end
end
end
if __FILE__ == $0
opt_c = false
if /^-c/ =~ ARGV.first
ARGV.shift
opt_c = true
end
MagicSquare::Solver.new(opt_c).solve(ARGV.first)
end
=begin
http://www.juen.ac.jp/math/journal/files/vol29/29-tsukada.pdf
【問題1】
[ ][_][6]
[3][ ][_]
[0][_][ ]
たて,横,ななめの3つのマス内の数字の和がすべてことなるように0~8を各1個ずつ入れます.灰色の4つのマスには奇数の数字を入れます.いま,0,3,6が図上のように入っています.このとき,残りの1,2,4,5,7,8を入れなさい.
(灰色:[_]および[3])
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment