Skip to content

Instantly share code, notes, and snippets.

@clupasq
Last active March 29, 2018 09:54
Show Gist options
  • Save clupasq/c5e2dd46818bb6b8d2c9514be0069250 to your computer and use it in GitHub Desktop.
Save clupasq/c5e2dd46818bb6b8d2c9514be0069250 to your computer and use it in GitHub Desktop.
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 '#play' do
it "guesses correctly" 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 :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 '#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
@AJFaraday
Copy link

Line 39 includes a hard-coded game id. This is why you were seeing the same result every time, and an ever-increasing turn count.
I've updated the SO question to correct this issue.
Thanks for playing (I enjoyed the idea of this challenge so much more than how it's gone)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment