Ruby(+ JSON,HTTParty)-得分:40(6 + 7 + 7 + 7 + 7 + 6)
这是一个有趣的挑战。我使用二进制搜索找到了鸡蛋,并得到了以下结果:
[{:x=>34, :y=>17, :game_id=>"mgpbmdqbnklcqrdjpyrr", :count=>7},
{:x=>99, :y=>17, :game_id=>"mhrsqfzmrrlcqxtcfgnw", :count=>7},
{:x=>23, :y=>86, :game_id=>"zgmsrjpqvdtmqmmglstn", :count=>6},
{:x=>24, :y=>55, :game_id=>"vkpjffyyltplztwhdsft", :count=>7},
{:x=>12, :y=>94, :game_id=>"pxrzjvqfjrjsptvtvnfw", :count=>4},
{:x=>83, :y=>59, :game_id=>"bdxljxkcnqmsqgnvggql", :count=>7},
{:x=>45, :y=>40, :game_id=>"mqrsbrhbldcqwgbnmymc", :count=>7},
{:x=>13, :y=> 9, :game_id=>"bphxkdgfcyyrvwxnfvkx", :count=>6},
{:x=> 8, :y=>80, :game_id=>"qzdstksdwnwrhxqrczpc", :count=>7},
{:x=>56, :y=>92, :game_id=>"ypqkfvmvwrcvvmjccvxg", :count=>6}]
这是代码:
require 'rspec/autorun'
require 'json'
require 'httparty'
require 'pp'
GuessResult = Struct.new :x, :y, :count
class FakeGame
def initialize(x=random_num, y=random_num)
@x = x
@y = y
@count = 0
end
@@results = [:right, :higher, :lower]
def guess(x, y)
@count += 1
GuessResult.new(@@results[@x <=> x], @@results[@y <=> y], @count)
end
def id
:fake
end
def random_num
rand(100) + 1
end
end
class RealGame
def initialize
response = HTTParty.get('http://easter_egg_hunt.andrewfaraday.com/new_game')
j = JSON.parse(response.body)
@id = j['game_id']
end
def guess(x, y)
response = HTTParty.get("http://easter_egg_hunt.andrewfaraday.com/guess/#{id}/#{x}/#{y}")
j = JSON.parse(response.body)
x_result = j['x'].to_sym
y_result = j['y'].to_sym
count = (j['turns']||0).to_i
GuessResult.new(x_result, y_result, count)
end
def id
@id
end
end
class BinarySearch
def initialize(min, max)
@min = min
@max = max
@guessed = false
update_next_guess
end
attr_reader :next_guess, :guessed
def go(result)
return if @guessed
case result
when :right
@guessed = true
when :lower
@max = @next_guess - 1
update_next_guess
when :higher
@min = @next_guess + 1
update_next_guess
end
end
private
def update_next_guess
@next_guess = (@max + @min) / 2
end
end
def play(game)
x_search = BinarySearch.new(1, 100)
y_search = BinarySearch.new(1, 100)
until x_search.guessed && y_search.guessed
puts ?.
result = game.guess(x_search.next_guess, y_search.next_guess)
x_search.go(result.x)
y_search.go(result.y)
end
{
x: x_search.next_guess,
y: y_search.next_guess,
game_id: game.id,
count: result.count
}
end
def game_controller(game_constructor, game_count)
(1..game_count).map do |i|
game = game_constructor.call
puts "Starting game #{game.id}..."
play(game)
end
end
def main
# pp game_controller(->{ FakeGame.new }, 10)
pp game_controller(->{ RealGame.new }, 10)
end
main
# tests
describe :FakeGame do
it "returns right results" do
game = FakeGame.new 4, 4
result = game.guess(2, 5)
expect(result.x).to eql :higher
expect(result.y).to eql :lower
expect(result.count).to eql 1
result = game.guess(5, 3)
expect(result.x).to eql :lower
expect(result.y).to eql :higher
expect(result.count).to eql 2
result = game.guess(4, 4)
expect(result.x).to eql :right
expect(result.y).to eql :right
expect(result.count).to eql 3
end
end
describe :binary_search do
let(:search) { BinarySearch.new 1, 100 }
it "makes optimal guesses" do
# aiming for 34
expect(search.next_guess).to eql 50
expect(search.guessed).to be_falsey
search.go(:lower)
expect(search.next_guess).to eql 25
search.go(:higher)
expect(search.next_guess).to eql 37
search.go(:lower)
expect(search.next_guess).to eql 31
search.go(:higher)
expect(search.next_guess).to eql 34
search.go(:right)
expect(search.next_guess).to eql 34
expect(search.guessed).to be_truthy
end
end
describe :fake_game do
it "correctly responds to guesses" do
game = FakeGame.new(34, 77)
result = play(game)
expect(result.y).to eql :lower
expect(result.count).to eql 1
result = game.guess(5, 3)
expect(result.x).to eql :lower
expect(result.y).to eql :higher
expect(result.count).to eql 2
result = game.guess(4, 4)
expect(result.x).to eql :right
expect(result.y).to eql :right
expect(result.count).to eql 3
end
end
describe '#play' do
it "guesses correctly" do
game = FakeGame.new(34, 77)
result = play(game)
expect(result[:x]).to eql 34
expect(result[:y]).to eql 77
expect(result[:count]).to eql 7
expect(result[:game_id]).to eql :fake
end
end