Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adds some other katas I've tried

  • Loading branch information...
commit e608d56b3acb805111488f19ae734835b94e4d4f 1 parent cc020f9
@MichaelBaker authored
View
19 prime-factors/11/primes.rb
@@ -0,0 +1,19 @@
+class Integer
+ def prime_factors
+ x = self
+ divisor = 2
+ primes = []
+ limit = Math.sqrt x
+ while x >= 2
+ if x % divisor == 0
+ primes << divisor
+ x = x / divisor
+ elsif divisor > limit
+ divisor = x
+ else
+ divisor = divisor + 1
+ end
+ end
+ primes
+ end
+end
View
23 prime-factors/11/primes_spec.rb
@@ -0,0 +1,23 @@
+require 'minitest/autorun'
+require './primes'
+
+class PrimesTest < MiniTest::Unit::TestCase
+ def self.test_cases
+ [[0, []],
+ [1, []],
+ [2, [2]],
+ [3, [3]],
+ [4, [2, 2]],
+ [5, [5]],
+ [7, [7]],
+ [8, [2, 2, 2]],
+ [9, [3, 3]],
+ [10, [2, 5]]]
+ end
+
+ test_cases.each do |number, primes|
+ define_method "test_#{number}" do
+ assert_equal(primes, number.prime_factors)
+ end
+ end
+end
View
4 prime-factors/11/watch_it.rb
@@ -0,0 +1,4 @@
+watch ".*" do |file|
+ system "clear"
+ system "ruby primes_spec.rb"
+end
View
4 string-calculator/00/Watchfile
@@ -0,0 +1,4 @@
+watch ".*" do |filename|
+ system "clear"
+ system "rspec -fdocumentation string_calculator_spec.rb"
+end
View
47 string-calculator/00/string_calculator.rb
@@ -0,0 +1,47 @@
+module StringCalculator
+ DEFAULT_SEPARATOR = /,|\s/
+ MULTI_CHARACTER_SEPARATOR = /\[(.*?)\]/
+ CUSTOM_SEPARATOR_LINE = /^\/\/(.*)\n/
+ VALID_NUMBERS = lambda { |number| 0 <= number && number <= 1000 }
+
+ def self.add(string)
+ numbers = string_to_list string
+ assert_no_negative_numbers numbers
+ numbers.select(&VALID_NUMBERS).reduce &:+
+ end
+
+ private
+
+ def self.string_to_list(string)
+ return [0] if string.empty?
+ string, separator = parse_string_with_separator(string) if contains_custom_separator? string
+ string.split(separator || DEFAULT_SEPARATOR).map &:to_i
+ end
+
+ def self.assert_no_negative_numbers(numbers)
+ negative_numbers = numbers.select { |number| number < 0 }
+ if negative_numbers.any?
+ raise "Negatives not allowed: #{negative_numbers.join(', ')}"
+ end
+ end
+
+ def self.parse_string_with_separator(string)
+ separator = parse_separator string[CUSTOM_SEPARATOR_LINE]
+ [string.sub(CUSTOM_SEPARATOR_LINE, ""), separator]
+ end
+
+ def self.parse_separator(line)
+ if line =~ MULTI_CHARACTER_SEPARATOR
+ Regexp.new line.scan(MULTI_CHARACTER_SEPARATOR)
+ .flatten
+ .map {|separator| Regexp.escape separator}
+ .join("|")
+ else
+ line[2]
+ end
+ end
+
+ def self.contains_custom_separator?(string)
+ string.start_with? "//"
+ end
+end
View
47 string-calculator/00/string_calculator_spec.rb
@@ -0,0 +1,47 @@
+require './string_calculator'
+
+describe StringCalculator do
+ describe ".add" do
+ it "sums a list of numbers separated by commas or newlines" do
+ StringCalculator.add("1,2").should == 3
+ StringCalculator.add("1,2,3").should == 6
+ StringCalculator.add("1,1,1,1").should == 4
+ StringCalculator.add("1,"*100).should == 100
+ StringCalculator.add("1\n2").should == 3
+ StringCalculator.add("1\n2\n2").should == 5
+ StringCalculator.add("1,2\n5").should == 8
+ end
+
+ context "accepts user defined delimiters on the first line of the string" do
+ it "of a single character in the form //<delimiter>" do
+ StringCalculator.add("//;\n1;2").should == 3
+ end
+
+ it "of multiple characters in the form //[<characters>]" do
+ StringCalculator.add("//[***]\n1***2").should == 3
+ end
+
+ it "multiple delimiters in the form //[<delimeter1>][<delimeter2>]" do
+ StringCalculator.add("//[*][%]\n1*2%3").should == 6
+ StringCalculator.add("//[**][%]\n1**2%3").should == 6
+ StringCalculator.add("//[!!!][&*]\n1&*2!!!3").should == 6
+ end
+ end
+
+ it "rejects negative numbers with an exception that includes the offending numbers" do
+ expect { StringCalculator.add("-1").should }.to raise_error /-1/
+ end
+
+ it "ignores numbers greater than 1000" do
+ StringCalculator.add("2,1001").should == 2
+ end
+
+ it "considers the empty string to sum to zero" do
+ StringCalculator.add("").should == 0
+ end
+
+ it "considers a list of one element to sum to itself" do
+ StringCalculator.add("1").should == 1
+ end
+ end
+end
View
4 string-calculator/01/Watchfile
@@ -0,0 +1,4 @@
+watch ".*" do |filename|
+ system "clear"
+ system "rspec -fdocumentation string_calculator_spec.rb"
+end
View
56 string-calculator/01/string_calculator.rb
@@ -0,0 +1,56 @@
+class StringCalculator
+ def initialize(string)
+ self.original_string = string
+ self.string = string.dup
+ extract_separator
+ extract_numbers
+ assert_no_negatives
+ filter_out_large_numbers
+ end
+
+ def add
+ return 0 if string.empty?
+ numbers.reduce &:+
+ end
+
+ private
+
+ attr_accessor :string, :separator, :numbers, :original_string
+
+ def extract_separator
+ self.separator = /,|\n/
+ extract_custom_separator if custom_separator?
+ end
+
+ def extract_custom_separator
+ if string.start_with? "//["
+ self.separator = Regexp.new string.scan(/\[(.+?)\]/)
+ .flatten
+ .map { |separator| Regexp.escape separator }
+ .join("|")
+ else
+ self.separator = string[2]
+ end
+ string.sub!(/\/\/.*\n/, "")
+ end
+
+ def custom_separator?
+ string.start_with? "//"
+ end
+
+ def extract_numbers
+ self.numbers = string.split(separator).map &:to_i
+ end
+
+ def assert_no_negatives
+ raise "No negatives #{negative_numbers.join ', '}" if negative_numbers.any?
+ end
+
+ def filter_out_large_numbers
+ numbers.select! { |number| 0 <= number && number <= 1000 }
+ end
+
+ def negative_numbers
+ numbers.select { |number| number < 0 }
+ end
+end
View
50 string-calculator/01/string_calculator_spec.rb
@@ -0,0 +1,50 @@
+require './string_calculator'
+
+describe StringCalculator do
+ describe "#add sums a stringified list of numbers" do
+ describe "accepts lists separated by" do
+ it "commas" do
+ StringCalculator.new("1,2").add.should == 3
+ StringCalculator.new("1,2,3").add.should == 6
+ StringCalculator.new("1,"*100).add.should == 100
+ end
+
+ it "new-lines" do
+ StringCalculator.new("1\n2").add.should == 3
+ StringCalculator.new("1\n2\n2").add.should == 5
+ StringCalculator.new("1\n"*50).add.should == 50
+ end
+ end
+
+ describe "accepts a custom separator on the first line of the string" do
+ specify "a single character in the form //<separator>" do
+ StringCalculator.new("//;\n1;2").add.should == 3
+ end
+
+ specify "multiple characters in the form //[<characters]" do
+ StringCalculator.new("//[***]\n1***2").add.should == 3
+ end
+
+ specify "multiple separators in the form //[<separator1>][<separator2>]" do
+ StringCalculator.new("//[&][%]\n1&2%3").add.should == 6
+ StringCalculator.new("//[&!][%]\n1&!2%3").add.should == 6
+ end
+ end
+
+ it "ignores numbers greater than 1000" do
+ StringCalculator.new("1,1001").add.should == 1
+ end
+
+ it "raises an error for negative numbers" do
+ expect { StringCalculator.new("-1").add }.to raise_error /-1/
+ end
+
+ it "considers the empty string to be zero" do
+ StringCalculator.new("").add.should == 0
+ end
+
+ it "considers a list of one number to sum to itself" do
+ StringCalculator.new("1").add.should == 1
+ end
+ end
+end
View
4 string-calculator/02/Watchfile
@@ -0,0 +1,4 @@
+watch ".*" do |filename|
+ system "clear"
+ system "rspec -fdocumentation string_calculator_spec.rb"
+end
View
9 string-calculator/02/string_calculator.rb
@@ -0,0 +1,9 @@
+module StringCalculator
+ def self.add(string)
+ return 0 if string.empty?
+ numbers = string.split(/[^-0-9]/).map(&:to_i)
+ negative_numbers = numbers.select {|number| number < 0}
+ raise "No negatives #{negative_numbers.join(", ")}" if negative_numbers.any?
+ numbers.reduce &:+
+ end
+end
View
30 string-calculator/02/string_calculator_spec.rb
@@ -0,0 +1,30 @@
+require './string_calculator'
+
+describe StringCalculator do
+ describe ".add" do
+ context "sums a string of numbers separated by" do
+ it "commas" do
+ StringCalculator.add("1,2").should == 3
+ end
+
+ it "new-lines" do
+ StringCalculator.add("1\n2").should == 3
+ end
+ end
+
+ it "rejects negative numbers with an exception" do
+ expect { StringCalculator.add("-1") }.to raise_error /-1/
+ end
+
+ context "considers" do
+ it "the empty string to be zero" do
+ StringCalculator.add("").should == 0
+ end
+
+ it "a single number to sum to itself" do
+ StringCalculator.add("1").should == 1
+ StringCalculator.add("2").should == 2
+ end
+ end
+ end
+end
View
4 word-transform/00/Watchfile
@@ -0,0 +1,4 @@
+watch ".*" do |file|
+ system "clear"
+ system "ruby word-morph.rb"
+end
View
12 word-transform/00/spec.rb
@@ -0,0 +1,12 @@
+require "rspec"
+require "./word-morph"
+
+describe "returns a set of steps that morphs the receiver into the argument" do
+ specify "a -> I" do
+ "a".morph_into("I").should == ["a", "I"]
+ end
+
+ specify "ann -> ebb" do
+ "ann".morph_into("ebb").should == ["ann", kkkkkk, "ebb"]
+ end
+end
View
47,158 word-transform/00/word-list.txt
47,158 additions, 0 deletions not shown
View
48 word-transform/00/word-morph.rb
@@ -0,0 +1,48 @@
+RubyVM::InstructionSequence.compile_option = {
+ :tailcall_optimization => true,
+ :trace_instruction => false
+}
+
+require "set"
+
+$dict = Set.new
+
+File.open "word-list.txt" do |file|
+ file.each_line do |line|
+ $dict << line.chomp unless line.chomp =~ /\W/
+ end
+end
+
+def tries(word)
+ set = []
+ word.each_char.with_index do |char, index|
+ ("a".."z").each do |sub|
+ next if sub == char
+ new_word = word.dup
+ new_word[index] = sub
+ set << new_word if $dict.include?(new_word)
+ end
+ end
+ set
+end
+
+def successful_match?(attempt, target)
+ attempt.last == target
+end
+
+def next_set(attempts, this_attempt)
+ tries(this_attempt.last).reject do |word|
+ this_attempt.include? word
+ end.each do |next_try|
+ attempts << (this_attempt.clone << next_try)
+ end
+ attempts
+end
+
+def morph(attempts, target)
+ this_attempt = attempts.shift
+ return this_attempt if successful_match?(this_attempt, target)
+ morph(next_set(attempts, this_attempt), target)
+end
+
+p morph([["ruby"]], "code")
View
6 word-wrap/07/watchfile.rb
@@ -0,0 +1,6 @@
+require 'watchr'
+
+watch ".*" do |filename|
+ system "clear"
+ system "ruby word_wrap_spec.rb"
+end
View
9 word-wrap/07/word_wrap.rb
@@ -0,0 +1,9 @@
+module Wrapper
+ def self.wrap(text, max)
+ return text if text.length <= max
+ current_line = text[0...max]
+ whitespace = current_line.rindex /\s/
+ breakpoint = whitespace || max
+ text[0...breakpoint] + "\n" + wrap(text[breakpoint..-1].strip, breakpoint)
+ end
+end
View
32 word-wrap/07/word_wrap_spec.rb
@@ -0,0 +1,32 @@
+require 'minitest/autorun'
+require './word_wrap'
+
+class WrapperTest < MiniTest::Unit::TestCase
+ def test_empty_string
+ assert_equal("", Wrapper.wrap("", 2))
+ end
+
+ def test_string_shorter_than_max
+ assert_equal("word", Wrapper.wrap("word", 10))
+ end
+
+ def test_string_longer_than_max
+ assert_equal("wo\nrd", Wrapper.wrap("word", 2))
+ end
+
+ def test_string_with_space_jusr_after_max
+ assert_equal("word\nword", Wrapper.wrap("word word", 4))
+ end
+
+ def test_string_with_space_before_max
+ assert_equal("word\nword", Wrapper.wrap("word word", 7))
+ end
+
+ def test_string_with_a_space_on_a_line
+ assert_equal("word word\nword", Wrapper.wrap("word word word", 12))
+ end
+
+ def test_string_same_line_as_max
+ assert_equal("word", Wrapper.wrap("word", 4))
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.