Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save foliosus/1442016 to your computer and use it in GitHub Desktop.
Save foliosus/1442016 to your computer and use it in GitHub Desktop.
PDX.rb I Spy 2011-12-06: simple Class-ification
require 'rubygems'
class Board
attr_reader :number
def initialize(n)
@number = n
@array = board(@number)
end
def valid?
xs = @array.flatten.count(1)
os = @array.flatten.count(2)
(xs == os || xs == os+1) && (!wins?(1) || !wins?(2))
end
def wins?(p)
p = case p
when 1, :x, :X then 1
when 2, :o, :O then 2
else nil
end
return false unless p
lines_of_3 = @array + @array.transpose
lines_of_3 << (0...3).collect { |i| @array[i][i] }
lines_of_3 << (0...3).collect { |i| @array[i][2-i] }
lines_of_3.include? [p,p,p]
end
def to_s
@array.collect do |row|
row.collect do |n|
case n
when 0 then ' '
when 1 then 'X'
when 2 then 'O'
end
end.join(' | ')
end.join("\n--+---+--\n")
end
def canonical_number
return @canonical_number if defined?(@canonical_number)
alternatives = [@array, @array.reverse]
alternatives |= alternatives.map { |x| x.collect { |r| r.reverse } }
alternatives |= alternatives.map { |x| x.transpose }
@canonical_number = alternatives.collect {|x| board_number(x) }.min
end
def self.row_number(r)
r[0]+3*r[1]+9*r[2]
end
def self.number(b)
row_number(b[0]) + 27*row_number(b[1]) + 27*27*row_number(b[2])
end
private
def row(i)
[i % 3, (i/3) % 3, (i/9) % 3]
end
def board(i)
[ row(i), row(i/27), row(i/(27*27)) ]
end
end
unique_boards = Hash.new(0)
(0...3**9).each do |i|
board = Board.new(i)
unique_boards[board.canonical_number] += 1 if board.valid?
end
print "There are #{unique_boards.count} unique 3x3 boards.\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment