Here's my solution:

http://www.dave.burt.id.au/ruby/highline.rb

It's inspired a fair bit by OptParse, and I tried to make it very flexible 
and smart in how it accepts options. The code features a little 
meta-programming (so you can do "retries 1" or "validation 1..10" in a block 
passed to the Prompt.new), optional named arguments, and inference of 
arguments' meaning by class somewhat like OptParse#on does.

It's not as easily mockable as EasyPrompt - you would have to do something 
tricky like this:
class Prompt
  def print(*args)
    my_alternate_output_stream.print *args
  end
  def gets
    my_alternate_input_stream.gets
  end
end

I think the code you write to use it is cleaner and more straighforward than 
the examples from the quiz question and the EasyPrompt doco. Here are those 
examples and more:

# Example usage from the Quiz
age = ask("What is your age?", Integer, 0..105 )
num = ask('Enter a binary number.') {|s| not s =~ /[^01]/ }.to_i(2)
if ask("Would you like to continue?", TrueClass) # ...

# Example usage from EasyPrompt documentation

irb(main):003:0> fname = prompt.ask( "What's your first name?" )
What's your first name? John
=> "John"
irb(main):004:0> lname = ask("What's your last name?", "Doe")
What's your last name? [Doe]
=> "Doe"
irb(main):005:0> ok = ask("Is your name #{ fname } #{ lname }?", TrueClass)
Is your name John Doe? [Yn]
=> true

# Extra examples
s = ask
i = ask("How many strikes will be allowed?", 3, 0..(1.0/0.0))
s = ask("Give me a word with "foo" in it:", /foo/)
i = ask("Give me a number divisible by 3:", Integer) {|i| i % 3 == 0 }
a = ask("Give me three or more numbers:", Array) do |x|
    x.each {|n| Float(n) }
    x.size >= 3 or puts "I need more things than that!"
end.map {|n| n.to_f }

# And you can also get a reusable Prompt object:
p = Prompt.new("A word with foo in it?") do
  validation /foo/i
  default "Foo"
end
p = Prompt.new("A word with foo in it?", "Foo", /foo/i)
s = p.ask