diff --git a/00_hello/hello.rb b/00_hello/hello.rb new file mode 100644 index 000000000..61626e810 --- /dev/null +++ b/00_hello/hello.rb @@ -0,0 +1,7 @@ +def hello + "Hello!" +end + +def greet(name) + "Hello, #{name}!" +end diff --git a/01_temperature/temperature.rb b/01_temperature/temperature.rb new file mode 100644 index 000000000..160742143 --- /dev/null +++ b/01_temperature/temperature.rb @@ -0,0 +1,7 @@ +def ftoc(f) + (f.to_f - 32.0) * 5.0/9.0 +end + +def ctof(c) + c.to_f * 9.0/5.0 + 32 +end diff --git a/02_calculator/calculator.rb b/02_calculator/calculator.rb new file mode 100644 index 000000000..bb5cea694 --- /dev/null +++ b/02_calculator/calculator.rb @@ -0,0 +1,24 @@ +def add(first, second) + first + second +end + +def subtract(first, second) + first - second +end + +def sum(array) + array.reduce(0) { |a, b| a + b } +end + +def multiply(array) + array.reduce { |a, b| a * b } +end + +def power(base, factor) + base ** factor +end + +def factorial(n) + return 1 if n == 0 + (1..n).to_a.reduce { |a, b| a * b } +end diff --git a/02_calculator/calculator_spec.rb b/02_calculator/calculator_spec.rb index fef7e9d00..31d5b2838 100644 --- a/02_calculator/calculator_spec.rb +++ b/02_calculator/calculator_spec.rb @@ -79,21 +79,37 @@ describe "#multiply" do - it "multiplies two numbers" + it "multiplies two numbers" do + expect(multiply([2,3])).to eq(6) + end + + it "multiplies several numbers" do + expect(multiply([2,3,4])).to eq(24) + end - it "multiplies several numbers" - end describe "#power" do - it "raises one number to the power of another number" + it "raises one number to the power of another number" do + expect(power(2,3)).to eq(8) + end end # http://en.wikipedia.org/wiki/Factorial describe "#factorial" do - it "computes the factorial of 0" - it "computes the factorial of 1" - it "computes the factorial of 2" - it "computes the factorial of 5" - it "computes the factorial of 10" + it "computes the factorial of 0" do + expect(factorial(0)).to eq(1) + end + it "computes the factorial of 1" do + expect(factorial(1)).to eq(1) + end + it "computes the factorial of 2" do + expect(factorial(2)).to eq(2) + end + it "computes the factorial of 5" do + expect(factorial(5)).to eq(120) + end + it "computes the factorial of 10" do + expect(factorial(10)).to eq(3628800) + end end diff --git a/03_simon_says/simon_says.rb b/03_simon_says/simon_says.rb new file mode 100644 index 000000000..5b4ffebc7 --- /dev/null +++ b/03_simon_says/simon_says.rb @@ -0,0 +1,40 @@ +def echo(text) + text +end + +def shout(text) + text.upcase +end + +def repeat(text, times=2) + text + ((" "+text) * (times-1)) +end + +def start_of_word(text, letters) + text[0..letters-1] +end + +def first_word(text) + array = text.split(' ') + array[0] +end + +def capitalize(word) + word[0] = word[0].upcase + word +end + +def titleize(text) + array = text.split(' ') + little_words = ['a', 'an', 'the', 'and', 'or', 'but', 'for', 'by', 'near', 'under', 'over', 'of'] + output = array.map.with_index(0) do |word, index| + if index == 0 + capitalize(word) + elsif little_words.include?(word) + word + else + capitalize(word) + end + end + output = output.join(' ') +end diff --git a/04_pig_latin/pig_latin.rb b/04_pig_latin/pig_latin.rb new file mode 100644 index 000000000..f9138c700 --- /dev/null +++ b/04_pig_latin/pig_latin.rb @@ -0,0 +1,28 @@ +def translate_word(text) + vowels = ['a', 'e', 'i', 'o', 'u', 'y'] + if vowels.include?(text[0]) + output = text + 'ay' + else + array = text.split('') + array.length.times do + current_letter = array.shift + if vowels.include?(current_letter) + array.unshift(current_letter) + break + elsif current_letter == 'q' + current_letter = current_letter + array.shift + array.push(current_letter) + else + array.push(current_letter) + end + end + output = array.join('') + 'ay' + end + output +end + +def translate(text) + words = text.split(' ') + output = words.map { |word| translate_word(word) } + output.join(' ') +end diff --git a/05_silly_blocks/silly_blocks.rb b/05_silly_blocks/silly_blocks.rb new file mode 100644 index 000000000..b2ae784ad --- /dev/null +++ b/05_silly_blocks/silly_blocks.rb @@ -0,0 +1,22 @@ +def word_reverser + input = yield.split('') + output = [] + while input.length > 0 + output.push(input.pop) + end + output.join('') +end + +def reverser + words = yield.split(' ') + output = words.map { |word| word_reverser { word } } + output.join(' ') +end + +def adder(addend=1) + yield + addend +end + +def repeater(multiplicand=1) + multiplicand.times { yield } +end diff --git a/06_performance_monitor/performance_monitor.rb b/06_performance_monitor/performance_monitor.rb new file mode 100644 index 000000000..57f3b7600 --- /dev/null +++ b/06_performance_monitor/performance_monitor.rb @@ -0,0 +1,11 @@ +def measure(count=1) + recorded_times = [] + count.times do + start = Time.now + yield + finish = Time.now + recorded_times.push(finish - start) + end + sum_of_times = recorded_times.reduce(0){|sum, x| sum + x} + sum_of_times / count +end diff --git a/07_hello_friend/friend.rb b/07_hello_friend/friend.rb new file mode 100644 index 000000000..5b2147a57 --- /dev/null +++ b/07_hello_friend/friend.rb @@ -0,0 +1,9 @@ +class Friend + def greeting(name="") + if name.length == 0 + "Hello!" + else + "Hello, #{name}!" + end + end +end diff --git a/08_book_titles/book.rb b/08_book_titles/book.rb new file mode 100644 index 000000000..dd3e6dca3 --- /dev/null +++ b/08_book_titles/book.rb @@ -0,0 +1,29 @@ +class Book + def title=(title) + @title = titleize(title) + end + def title + @title + end + + def capitalize(word) + word[0] = word[0].upcase + word + end + + def titleize(text) + array = text.split(' ') + little_words = ['a', 'an', 'the', 'and', 'or', 'but', 'for', 'by', 'near', 'under', 'over', 'of', 'in'] + output = array.map.with_index(0) do |word, index| + if index == 0 + capitalize(word) + elsif little_words.include?(word) + word + else + capitalize(word) + end + end + output = output.join(' ') + end + +end diff --git a/09_timer/timer.rb b/09_timer/timer.rb new file mode 100644 index 000000000..b847c46a5 --- /dev/null +++ b/09_timer/timer.rb @@ -0,0 +1,21 @@ +class Timer + def initialize + @seconds = 0 + end + def seconds=(seconds=0) + @seconds = seconds + end + def seconds + @seconds + end + def time_string + minutes = @seconds / 60 + seconds = @seconds % 60 + hours = minutes / 60 + minutes = minutes % 60 + "#{format_time_division(hours)}:#{format_time_division(minutes)}:#{format_time_division(seconds)}" + end + def format_time_division(number) + number.to_s.rjust(2, '0') + end +end diff --git a/10_temperature_object/temperature.rb b/10_temperature_object/temperature.rb new file mode 100644 index 000000000..528d0cbef --- /dev/null +++ b/10_temperature_object/temperature.rb @@ -0,0 +1,35 @@ +class Temperature + def initialize(options={}) + @f = options[:f] ||= options[:fahrenheit] + @c = options[:c] ||= options[:celsius] + end + def self.ftoc(f) + (f.to_f - 32.0) * 5.0/9.0 + end + def self.ctof(c) + c.to_f * 9.0/5.0 + 32 + end + def in_fahrenheit + @f || self.class.ctof(@c) + end + def in_celsius + @c || self.class.ftoc(@f) + end + def self.from_celsius(c) + Temperature.new({:c => c}) + end + def self.from_fahrenheit(f) + Temperature.new({:f => f}) + end +end + +class Celsius < Temperature + def initialize(c) + @c = c + end +end +class Fahrenheit < Temperature + def initialize(f) + @f = f + end +end diff --git a/10_temperature_object/temperature_object_spec.rb b/10_temperature_object/temperature_object_spec.rb index 5c0af8685..98802560b 100644 --- a/10_temperature_object/temperature_object_spec.rb +++ b/10_temperature_object/temperature_object_spec.rb @@ -97,7 +97,12 @@ # run *all* the tests during your refactoring, to make sure you did it right # describe "utility class methods" do - + it "ftoc method" do + expect(Temperature.ftoc(32)).to eq(0.0) + end + it "ctof method" do + expect(Temperature.ftoc(212)).to eq(100.0) + end end # Here's another way to solve the problem! diff --git a/11_dictionary/dictionary.rb b/11_dictionary/dictionary.rb new file mode 100644 index 000000000..f7a952390 --- /dev/null +++ b/11_dictionary/dictionary.rb @@ -0,0 +1,37 @@ +class Dictionary + def initialize + @dict = {} + @keywords = [] + end + def entries + @dict + end + def add(pair) + if pair.class == Hash + @dict.merge!(pair) + @keywords.push(pair.keys[0]) + elsif + @dict.merge!(pair => nil) + @keywords.push(pair) + end + end + def keywords + @keywords.sort + end + def include?(query) + @keywords.include?(query) + end + def find(query) + @dict.select { |key, value| key.start_with? query} + end + def printable + @keywords.sort! + output = "" + @keywords.each do |keyword| + output += "[#{keyword}] \"#{@dict[keyword]}\"\n" + end + output = output.slice(0, output.length-1) # remove trailing \n + end +end + +# "" diff --git a/12_rpn_calculator/rpn_calculator.rb b/12_rpn_calculator/rpn_calculator.rb new file mode 100644 index 000000000..d203c2887 --- /dev/null +++ b/12_rpn_calculator/rpn_calculator.rb @@ -0,0 +1,33 @@ +class RPNCalculator + def initialize + @stack = [] + end + def push(n) + @stack.push(n.to_f) + end + def value + @stack[-1] + end + def operation + begin + a = @stack.pop + b = @stack.pop + yield(a,b) + rescue + raise Exception, "calculator is empty" + end + end + def plus + operation { |a,b| @stack.push(a + b) } + end + def minus + operation { |a,b| @stack.push(b - a) } + end + def times + operation { |a,b| @stack.push(a * b) } + end + def divide + operation { |a,b| @stack.push(b / a) } + end + +end diff --git a/13_xml_document/index.html b/13_xml_document/index.html deleted file mode 100644 index 900ff72d5..000000000 --- a/13_xml_document/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - Test-First Teaching: learn_ruby: xml_document - - - -
-

TestFirst.org

-

the home of test-first teaching

-
- -

xml_document

-

Topics

- -
    -
  • method_missing
  • -
  • blocks
  • -
  • strings
  • -
  • hashes
  • -
- - -

Builder

- -

Here we will implement the so-called Builder Pattern: we will make an object, XmlDocument, that builds an XML file, which can contain arbitrary tags.

-
-
-

Tests

-xml_document_spec.rb -
-# Stuff you'll learn:
-# method_missing
-# nested closures
-# "builder pattern"
-
-require "xml_document"
-
-describe XmlDocument do
-  before do
-    @xml = XmlDocument.new
-  end
-
-  it "renders an empty tag" do
-    expect(@xml.hello).to eq("<hello/>")
-  end
-
-  it "renders a tag with attributes" do
-    expect(@xml.hello(:name => 'dolly')).to eq("<hello name='dolly'/>")
-  end
-
-  it "renders a randomly named tag" do
-    tag_name = (1..8).map{|i| ('a'..'z').to_a[rand(26)]}.join
-    expect(@xml.send(tag_name)).to eq("<#{tag_name}/>")
-  end
-
-  it "renders block with text inside" do
-    expect(@xml.hello do
-      "dolly"
-    end).to eq("<hello>dolly</hello>")
-  end
-
-  it "nests one level" do
-    expect(@xml.hello do
-      @xml.goodbye
-    end).to eq("<hello><goodbye/></hello>")
-  end
-
-  it "nests several levels" do
-    xml = XmlDocument.new
-    expect(xml.hello do
-      xml.goodbye do
-        xml.come_back do
-          xml.ok_fine(:be => "that_way")
-        end
-      end
-    end).to eq("<hello><goodbye><come_back><ok_fine be='that_way'/></come_back></goodbye></hello>")
-  end
-
-  it "indents" do
-    @xml = XmlDocument.new(true)
-    expect(@xml.hello do
-      @xml.goodbye do
-        @xml.come_back do
-          @xml.ok_fine(:be => "that_way")
-        end
-      end
-    end).to eq(
-    "<hello>\n" +
-    "  <goodbye>\n" +
-    "    <come_back>\n" +
-    "      <ok_fine be='that_way'/>\n" +
-    "    </come_back>\n" +
-    "  </goodbye>\n" +
-    "</hello>\n")
-  end
-end
-
-
-
- - - diff --git a/13_xml_document/xml_document_spec.rb b/13_xml_document/xml_document_spec.rb deleted file mode 100644 index fa1995818..000000000 --- a/13_xml_document/xml_document_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# # Topics -# -# * method_missing -# * blocks -# * strings -# * hashes -# -# # Builder -# -# Here we will implement the so-called Builder Pattern: we will make an object, XmlDocument, that *builds* an XML file, which can contain arbitrary tags. - -# Stuff you'll learn: -# method_missing -# nested closures -# "builder pattern" - -require "xml_document" - -describe XmlDocument do - before do - @xml = XmlDocument.new - end - - it "renders an empty tag" do - expect(@xml.hello).to eq("") - end - - it "renders a tag with attributes" do - expect(@xml.hello(:name => 'dolly')).to eq("") - end - - it "renders a randomly named tag" do - tag_name = (1..8).map{|i| ('a'..'z').to_a[rand(26)]}.join - expect(@xml.send(tag_name)).to eq("<#{tag_name}/>") - end - - it "renders block with text inside" do - expect(@xml.hello do - "dolly" - end).to eq("dolly") - end - - it "nests one level" do - expect(@xml.hello do - @xml.goodbye - end).to eq("") - end - - it "nests several levels" do - xml = XmlDocument.new - expect(xml.hello do - xml.goodbye do - xml.come_back do - xml.ok_fine(:be => "that_way") - end - end - end).to eq("") - end - - it "indents" do - @xml = XmlDocument.new(true) - expect(@xml.hello do - @xml.goodbye do - @xml.come_back do - @xml.ok_fine(:be => "that_way") - end - end - end).to eq( - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n") - end -end diff --git a/14_array_extensions/array_extensions.rb b/14_array_extensions/array_extensions.rb new file mode 100644 index 000000000..1c30761ed --- /dev/null +++ b/14_array_extensions/array_extensions.rb @@ -0,0 +1,11 @@ +class Array + def sum + self.reduce(0) { |a, b| a + b } + end + def square + self.map { |item| item * item } + end + def square! + self.map! { |item| item * item } + end +end diff --git a/15_in_words/in_words.rb b/15_in_words/in_words.rb new file mode 100644 index 000000000..326b39bb3 --- /dev/null +++ b/15_in_words/in_words.rb @@ -0,0 +1,76 @@ +require 'pry' +require 'pry-byebug' + +class Fixnum + def in_words + string = self.to_s + one_less_digit = string[1..string.length].to_i + first_digit = string[0].to_i + output = "" + orders_of_magnitude = { + 1000000000000 => "trillion", + 1000000000 => "billion", + 1000000 => "million", + 1000 => "thousand", + 100 => "hundred", + } + orders_of_magnitude.each do |magnitude, word| + if self >= magnitude + quantity = self / magnitude + remainder = self - quantity * magnitude + if remainder > 0 + output += quantity.in_words + ' ' + word + ' ' + remainder.in_words + else + output += quantity.in_words + ' ' + word + end + return output + end + end + dictionary = { + 90 => "ninety", + 80 => "eighty", + 70 => "seventy", + 60 => "sixty", + 50 => "fifty", + 40 => "forty", + 30 => "thirty", + 20 => "twenty", + 19 => "nineteen", + 18 => "eighteen", + 17 => "seventeen", + 16 => "sixteen", + 15 => "fifteen", + 14 => "fourteen", + 13 => "thirteen", + 12 => "twelve", + 11 => "eleven", + 10 => "ten", + 9 => "nine", + 8 => "eight", + 7 => "seven", + 6 => "six", + 5 => "five", + 4 => "four", + 3 => "three", + 2 => "two", + 1 => "one" + } + dictionary.each do |match, word| + if self/match > 0 && self > 20 + if one_less_digit == 0 + output += word + else + output += word + ' ' + one_less_digit.in_words + end + output.strip! + break + elsif self == match + output = word + output.strip! + elsif self/10 == 0 && self == 0 + output = "zero" + end + end + output + end +end