Skip to content

Instantly share code, notes, and snippets.

@jimweirich
Forked from st23am/urinal_etiquette.rb
Created February 22, 2012 01:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jimweirich/1880361 to your computer and use it in GitHub Desktop.
Save jimweirich/1880361 to your computer and use it in GitHub Desktop.
Test Problem
class Urinal
def initialize(occupied, line)
@occupied = occupied
@line = line
end
def select
scores = stalls.map { |n| [score(n), n] }
best = scores.sort.last
best.first < 0 ? nil : best.last
end
private
def score(n)
return never_choose_this if occupied?(n)
result = 1000
result += apply_rule1(n)
result += apply_rule2(n) if rule2_upheld?
result += apply_rule3(n) if rule3_upheld?
result
end
def apply_rule1(n)
n
end
def apply_rule2(n)
neighbors?(n) ? neighbor_penalty : 0
end
def rule2_upheld?
@rule2_upheld ||= stalls.all? { |n| !occupied?(n) || !neighbors?(n) }
end
def apply_rule3(n)
double_neighbors?(n) ? double_neighbor_penalty : 0
end
def rule3_upheld?
@rule3_upheld ||= stalls.all? { |n| !occupied?(n) || !double_neighbors?(n) }
end
def neighbor_penalty
line? ? -10 : -10000
end
def double_neighbor_penalty
line? ? -20 : -20000
end
def neighbors?(n)
occupied?(n-1) || occupied?(n+1)
end
def double_neighbors?(n)
occupied?(n-1) && occupied?(n+1)
end
def occupied?(n)
if n < 0 || n > last_stall
nil
else
@occupied[n]
end
end
def stalls
(0..last_stall)
end
def last_stall
@occupied.size-1
end
def line?
@line
end
def never_choose_this
-1_000_000_000_000_000_000
end
end
require 'rspec/given'
require 'urinal'
describe Urinal do
Given(:urinal) { Urinal.new(occupied, has_line) }
Given(:stalls) { "....." }
Given(:has_line) { false }
Given(:occupied) { stalls.split(//).map { |s| s.downcase == 'x' } }
Given(:outcome) { out = stalls.dup; out[selection] = 'o' if selection; out }
When(:selection) { urinal.select }
describe "Rule 1: farthest from the door" do
context "when empty" do
Then { outcome.should == '....o' }
end
context "when some occupied" do
Given(:stalls) { "..x.." }
Then { outcome.should == '..x.o' }
end
end
describe "Rule 2: not next to a dude" do
context "when given a choice" do
Given(:stalls) { "....x" }
Then { outcome.should == '..o.x' }
end
context "when there is not other choice" do
Given(:stalls) { "x.x.x" }
Then { outcome.should == 'x.x.x' }
context "and when there is a line" do
Given(:has_line) { true }
Then { outcome.should == 'x.xox' }
end
context "and when rule 2 is broken" do
Given(:stalls) { ".x.x.xx" }
Then { outcome.should == 'ox.x.xx' }
end
end
end
describe "Rule 3: really don't stand next to two dudes" do
Given(:has_line) { true }
context "when given a choice" do
Given(:stalls) { ".x.x" }
Then { outcome.should == 'ox.x' }
end
context "and when rule 2 is broken" do
Given(:stalls) { ".x.xxx" }
Then { outcome.should == '.xoxxx' }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment