(1)第一个答案是B的问题是哪一个?
A、2 B、3 C、4 D、5 E、6
(2)恰好有两个连续问题的答案是一样的,它们是:
A、2,3 B、3,4 C、4,5 D、5,6 E、6,7
(3)本问题答案和哪一个问题的答案相同?
A、1 B、2 C、4 D、7 E、6
(4)答案是A的问题的个数是:
A、0 B、1 C、2 D、3 E、4
(5)本问题答案和哪一个问题的答案相同?
A、10 B、9 C、8 D、7 E、6
(6)答案是A的问题的个数和答案是什么的问题的个数相同?
A、B B、C C、D D、E E、以上都不是
(7)按照字母顺序,本问题的答案和下一个问题的答案相差几个字母?
A、4 B、3 C、2 D、1 E、0(注:A和B相差一个字母)
(8)答案是元音字母的问题的个数是:
A、2 B、3 C、4 D、5 E、6(注:A和E是元音字母)
(9)答案是辅音字母的问题的个数是:
A、一个质数 B、一个阶乘数 C、一个平方数 D、一个立方数 E、5的倍数
(10)本问题的答案是:
A、A B、B C、C D、D E、E
Ruby语言基于amb的解决方案,本质上,这是一个backtrack search:
# A B C D E
# 0 1 2 3 4
class ConstraintChecker
def initialize
@constraints = [
# each constraint lambda expression should return false
# if the corresponding answer(the "this_answer" param)
# is violated by answers seen so far(the "ans" param),
# and true if the answer is satisfied or can not be judged yet
#~ lambda {|ans, this_answer| #test code
#~ a = [1, 1, 2, 3, 1, 2, 3, 4, 3, 1]
#~ 0.upto(ans.length - 1) {|i|
#~ break false if ans[i] && ans[i]!=a[i]
#~ } != false # true if break not executed
#~ },
#q1
lambda {|ans, this_answer|
firstB = [1,2,3,4,5][this_answer]
ans[firstB] == nil or ans.index(1) == firstB
},
#q2
lambda {|ans, this_answer|
idx = [1,2,3,4,5][this_answer]
# ans[idx] is the same as ans[idx+1]
0.upto(ans.size-2) {|i|
#~ puts "i=#{i}, idx=#{idx}, ans[i]=#{ans[i]}, ans[i+1]=#{ans[i+1]}"
break true if ans[i+1] == nil
break false if ((i==idx) != (ans[i]==ans[i+1]))
} != false
#~ ans[idx]==nil or ans[idx]==ans[idx-1]
},
#q3
lambda {|ans, this_answer|
same = [0, 1, 3, 6, 5][this_answer]
(ans[same] == nil) or (ans[same] == this_answer)
},
#q4
lambda {|ans, this_answer|
numOfA = [0, 1, 2, 4, 5][this_answer]
(ans.last == nil) or (ans.select{|i|i==0}.size == numOfA)
},
#q5
lambda {|ans, this_answer|
same = [9, 8, 7, 6, 5][this_answer]
(ans[same] == nil) or (ans[same] == this_answer)
},
#q6
lambda {|ans, this_answer|
return true if ans.last == nil
# A, B, C, D, E
nums = [0, 0, 0, 0, 0]
[0, 1, 2, 3, 4].each do |i|
ans.each do |j|
nums[i] += 1 if i==j
end
end
idToA =[]
1.upto nums.size-1 do |i|
idToA << i if nums[i] == nums[0]
end
(idToA.empty? and this_answer == 4) || (idToA.size == 1 and idToA[0] == this_answer+1)
},
#q7
lambda {|ans, this_answer|
nextAnswer = ans[7]
return true if nextAnswer == nil
[4, 3, 2, 1, 0][this_answer] == (this_answer - nextAnswer).abs
},
#q8
lambda {|ans, this_answer|
return true if ans.last == nil
ans.select{|i| i==0 or i==4}.size == [2,3,4,5,6][this_answer]
},
#q9
lambda {|ans, this_answer|
return true if ans.last == nil
numCon = ans.select{|i| i==1 or i==2 or i==3}.size
conds = [[2, 3, 5, 7], [1, 2, 6], [1, 4, 9], [1, 8], [0, 5, 10]]
conds.each_index do |i|
break false if (i == this_answer) != (conds[i].include? numCon)
end != false
},
#q10
lambda {|ans, this_answer|
true
}
]
end
def Check(answers, upto=nil)
if (upto!=nil)
(upto+1).upto answers.size-1 do |idx|
answers[idx]=nil
end
end
#~ print "Checking "; dump answers; puts
answers.each_index do |i|
break unless answers[i]
return false unless @constraints[i].call(answers, answers[i])
end
true
end #of method Check
def num_constraint
@constraints.size
end
# exposion for debug purpose
attr_reader :constraints
end #of class ConstraintChecker
class AmbSolver
def initialize
@checker = ConstraintChecker.new
@result = Array.new
end
def solve
require 'amb'
a = Amb.new
begin
answers = Array.new @checker.num_constraint
answers.each_index do |i|
next_answers = (0..4).to_a.collect{|n| answers[i]=n; answers.dup}
answers = a.choose(*next_answers)
a.assert @checker.Check(answers)
end
@result << answers.dup
a.failure
rescue Amb::ExhaustedError
end
@result
end
end #of class AmbSolver
def dump answers
answers.each do |a|
(a==nil)? print('?') : print(('A'..'Z').to_a[a])
print " "
end
end
if __FILE__ == $0
puts "Consistent answers:"
start = Time.now
result = AmbSolver.new.solve
elapsed = Time.now - start
result.each do |a|
dump a
puts
end
puts("time ", elapsed) #0.468
end
# Modified Amb, originally by Jim Weirich
class Amb
class ExhaustedError < RuntimeError; end
def initialize
@fail = proc { fail ExhaustedError, "amb tree exhausted" }
end
def choose(*choices)
prev_fail = @fail
choices.each { |choice|
callcc { |fk|
@fail = proc {
@fail = prev_fail
fk.call(:fail)
}
if choice.respond_to? :call
return choice.call
else
return choice
end
}
}
@fail.call
end
def failure
choose
end
def assert(cond)
failure unless cond
end
end
class Amb
class ExhaustedError < RuntimeError; end
def initialize
@fail = proc { fail ExhaustedError, "amb tree exhausted" }
end
def choose(*choices)
prev_fail = @fail
choices.each { |choice|
callcc { |fk|
@fail = proc {
@fail = prev_fail
fk.call(:fail)
}
if choice.respond_to? :call
return choice.call
else
return choice
end
}
}
@fail.call
end
def failure
choose
end
def assert(cond)
failure unless cond
end
end