Skip to content

Instantly share code, notes, and snippets.

@takehiko
Last active December 23, 2015 09:09
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/6613014 to your computer and use it in GitHub Desktop.
Save takehiko/6613014 to your computer and use it in GitHub Desktop.
Parity Problem Generator
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# ppg.rb : Parity Problem Generator
# by takehikom (http://d.hatena.ne.jp/takehikom/)
# Usage:
# ruby ppg.rb
# ruby ppg.rb 3
# 遊び方
# どの行・どの列も,すべて偶数または奇数となるよう,
# 反転させるべき場所(1箇所だけ)を見つけてください.
# 偶数か奇数かは,問題ごとにランダムです.
# 引数なしで実行した場合,最初に問題が表示されます.Enterのみを押せば
# 解答,そして次の問題に移り(無限ループ),qとEnterを押せば終了します.
# 引数(整数値)をつけて実行した場合,その数だけ,問題と解答を出力します.
module ParityProblem
class Board
def initialize(h = nil)
if h.nil?
h = {
:width => 6 + rand(3),
:height => 4 + rand(3),
:even => rand(2) == 0,
}
end
@width = h[:width] || 6
@height = h[:height] || 6
@even = h[:even] || false
@invert = [rand(@width), rand(@height)]
init_table_for_output
generate_board
end
def to_s(aa = [@board])
aa.map! {|ary| ary.map {|item| bin_to_str(item)}}
if aa.size == 1
aa.first.join("\n") + "\n"
else
aa1 = aa.shift
aa1.zip(*aa).map {|item| item.join(@s[:to])}.join("\n") + "\n"
end
end
def print_question
print to_s([create_corrupt_board])
end
def print_question_answer
print to_s([create_corrupt_board, create_corrupt_board(2), @board])
end
private
def init_table_for_output
if /jp/i =~ ENV["LANG"]
@s = {
0 => '□',
1 => '■',
2 => '*',
:to => ' → '
}
else
@s = {
0 => '0',
1 => '1',
2 => '*',
:to => ' => '
}
end
end
def generate_board
@board = Array.new(@height - 1) do
Array.new(@width - 1) do
rand(2)
end
end
if $DEBUG
puts "#### step 1 ####"
print to_s([@board])
end
@board.map! do |item|
item + [(item.reduce(:+) + (@even ? 0 : 1)) % 2]
end
if $DEBUG
puts "#### step 2 ####"
print to_s([@board])
end
@board << @board.transpose.map do |item|
(item.reduce(:+) + (@even ? 0 : 1)) % 2
end
if $DEBUG
puts "#### step 3 ####"
print to_s([@board])
puts
end
@board
end
def bin_to_str(ary)
ary.map {|c| @s[c]}.join("")
end
def create_corrupt_board(val = nil)
ary = Marshal.load(Marshal.dump(@board))
ary[@invert[1]][@invert[0]] = val || (1 - ary[@invert[1]][@invert[0]])
ary
end
end
class Manager
def self.print_question_answer
board = ParityProblem::Board.new
board.print_question_answer
end
def self.start
loop do
board = ParityProblem::Board.new
print("\033[2J\033[0;0H")
board.print_question
break if /^q/i =~ gets
print("\033[2J\033[0;0H")
board.print_question_answer
break if /^q/i =~ gets
end
end
end
end
if __FILE__ == $0
if ARGV.empty?
ParityProblem::Manager.start
else
ARGV.shift.to_i.times do
ParityProblem::Manager.print_question_answer
puts
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment