-
-
Save jimweirich/1880361 to your computer and use it in GitHub Desktop.
Test Problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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