Step 1 Specs
require 'rails_helper'
describe String do describe "#look_spammy?" do it "should return false for a non-spam input" do expect("Jason".looks_spammy?).to be(false) expect("Fleetwood-Boldt".looks_spammy?).to be(false) expect("FLEETWOOD-BOLDT".looks_spammy?).to be(false) expect("fleetwood-boldt".looks_spammy?).to be(false) expect("John".looks_spammy?).to be(false) end
it "should return true for a spam input" do expect("EpkWSQnhmoXdYCa".looks_spammy?).to be(true) expect("inRYGlPocamIVW".looks_spammy?).to be(true) expect("njOyZPVC".looks_spammy?).to be(true) expect("PwbpKimWe".looks_spammy?).to be(true) end end end
Step 1 Implementation
class String
def looks_spammy?
last_case = nil; switches = -1
self.chars.each do |c|
if last_case != :upper && /[[:upper:]]/.match(c)
switches += 1
last_case = :upper
elsif last_case != :lower && /[[:lower:]]/.match(c)
switches += 1
last_case = :lower
end
end
switches > 2
end
end
But this implementation doesn’t work for both my name “Fleetwood-Boldt” and the garbage string “njOyZPVC”
So we need to build a smarter mousetrap.
Step 2 Specs
describe "#count_upper" do it "should return 0 for an empty string" do expect("".count_upper).to eq(0) end it "should return 0 for a string with only lowercase characters" do expect("abcdefghijk".count_upper).to eq(0) end it "should return 1 for a string with 1 uppercase character" do expect("jshjXsdkfh".count_upper).to be(1) end it "should return 3 for a string with 3 uppercase character" do expect("yahoo ABC xyz".count_upper).to be(3) end end
Step 2 Implementation
class String def looks_spammy? switches = -1 last_case = nil self.chars.each do |char| if last_case != :upper && /[[:upper:]]/.match(char) switches += 1 last_case = :upper elsif last_case != :lower && /[[:lower:]]/.match(char) switches += 1 last_case = :lower end end return (switches > 3) || count_upper > 2 end def count_upper self.gsub(/[^A-Z]/, '').length || 0 end end
Step 3 Specs
Let’s simply abstract the ‘switches’ out into its own method and call that new method count_switches
require 'rails_helper' describe String do describe "#looks_spammy?" do it "should return false for a non-spam input" do expect("Jason".looks_spammy?).to be(false) expect("Fleetwood-Boldt".looks_spammy?).to be(false) expect("FLEETWOOD-BOLDT".looks_spammy?).to be(false) expect("fleetwood-boldt".looks_spammy?).to be(false) expect("John".looks_spammy?).to be(false) end it "should return true for a spam input" do expect("EpkWSQnhmoXdYCa".looks_spammy?).to eq(true) expect("inRYGlPocamIVW".looks_spammy?).to eq(true) expect("njOyZPVC".looks_spammy?).to eq(true) expect("PwbpKimWe".looks_spammy?).to eq(true) end end describe "#count_switches" do it "should return 0 for an empty string" do expect("".count_switches).to eq(0) end it "should return 0 for all lowercase" do expect("avcdefgh".count_switches).to eq(0) end it "should return 0 for FLEETWOOD-BOLDT" do expect("FLEETWOOD-BOLDT".count_switches).to eq(0) end it "should return 3 for a string that switches 3 times" do expect("aBcD".count_switches).to eq(3) end end describe "#count_upper" do it "should return 0 for an empty string" do expect("".count_upper).to eq(0) end it "should return 0 for a string with only lowercase characters" do expect("abcdefghijk".count_upper).to eq(0) end it "should return 1 for a string with 1 uppercase character" do expect("jshjXsdkfh".count_upper).to be(1) end it "should return 3 for a string with 3 uppercase character" do expect("yahoo ABC xyz".count_upper).to be(3) end end end
Step 3 Implementation
class String def looks_spammy? return (count_switches > 3) || (count_upper > 2) end def count_switches switches = -1 last_case = nil self.chars.each do |char| if last_case != :upper && /[[:upper:]]/.match(char) switches += 1 last_case = :upper elsif last_case != :lower && /[[:lower:]]/.match(char) switches += 1 last_case = :lower end end return [0,switches].max end def count_upper self.gsub(/[^A-Z]/, '').length || 0 end end
Step 4
Now I’ve inadvertantly trapped people who type their name in all uppercase, like the alternate me who types his name FLEETWOOD-BOLDT.
So our final challenge is to fix this an allow a name if it is all uppercase.
Step 4 Specs
require 'rails_helper' describe String do describe "#looks_spammy?" do it "should return false for a non-spam input" do expect("Jason".looks_spammy?).to be(false) expect("Fleetwood-Boldt".looks_spammy?).to be(false) expect("FLEETWOOD-BOLDT".looks_spammy?).to be(false) expect("fleetwood-boldt".looks_spammy?).to be(false) expect("John".looks_spammy?).to be(false) end it "should return true for a spam input" do expect("EpkWSQnhmoXdYCa".looks_spammy?).to eq(true) expect("inRYGlPocamIVW".looks_spammy?).to eq(true) expect("njOyZPVC".looks_spammy?).to eq(true) expect("PwbpKimWe".looks_spammy?).to eq(true) end end describe "#count_switches" do it "should return 0 for an empty string" do expect("".count_switches).to eq(0) end it "should return 0 for all lowercase" do expect("avcdefgh".count_switches).to eq(0) end it "should return 0 for FLEETWOOD-BOLDT" do expect("FLEETWOOD-BOLDT".count_switches).to eq(0) end it "should return 3 for a string that switches 3 times" do expect("aBcD".count_switches).to eq(3) end end describe "#count_upper" do it "should return 0 for an empty string" do expect("".count_upper).to eq(0) end it "should return 0 for a string with only lowercase characters" do expect("abcdefghijk".count_upper).to eq(0) end it "should return 1 for a string with 1 uppercase character" do expect("jshjXsdkfh".count_upper).to be(1) end it "should return 3 for a string with 3 uppercase character" do expect("yahoo ABC xyz".count_upper).to be(3) end end describe "#all_uppercase?" do it "should return a true of the string is all uppercase" do expect("FLEETWOOD-BOLDT".all_uppercase?).to eq(true) expect("JOHNSON".all_uppercase?).to eq(true) expect("AB CD EF..G".all_uppercase?).to eq(true) end it "should return false if the string has any lowercase characters" do expect("fleetwood-boldt".all_uppercase?).to eq(false) expect("SDHFJKHDJF k".all_uppercase?).to eq(false) end end end
Step 4 Implementation
class String
def looks_spammy?
return (count_switches > 3) || (count_upper > 2 && !all_uppercase?)
end
def count_switches
switches = -1
last_case = nil
self.chars.each do |char|
if last_case != :upper && /[[:upper:]]/.match(char)
switches += 1
last_case = :upper
elsif last_case != :lower && /[[:lower:]]/.match(char)
switches += 1
last_case = :lower
end
end
return [0,switches].max
end
def count_upper
self.gsub(/[^A-Z]/, '').length || 0
end
def all_uppercase?
self.upcase == self
end
end