From 44d5ab719ef264ad32dc07246d90b60987051359 Mon Sep 17 00:00:00 2001 From: Eric Lubin Date: Fri, 13 Sep 2013 19:41:27 -0400 Subject: [PATCH 1/3] initial --- .gitignore | 1 + Gemfile | 2 ++ Gemfile.lock | 12 ++++++++++++ macbeth_analyzer.rb | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 macbeth_analyzer.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..90b7d0d --- /dev/null +++ b/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'nokogiri', '~> 1.6.0' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..9869fbd --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,12 @@ +GEM + remote: https://rubygems.org/ + specs: + mini_portile (0.5.0) + nokogiri (1.6.0) + mini_portile (~> 0.5.0) + +PLATFORMS + ruby + +DEPENDENCIES + nokogiri (~> 1.6.0) diff --git a/macbeth_analyzer.rb b/macbeth_analyzer.rb new file mode 100644 index 0000000..86a97d2 --- /dev/null +++ b/macbeth_analyzer.rb @@ -0,0 +1,41 @@ + +class Macbeth_Analyzer + require 'net/http' + require 'open-uri' + require 'nokogiri' + + def run + line_counts = parse_counts(load_file) + display(line_counts) + end + + def load_file + Nokogiri::HTML(open('http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml')) + end + + def parse_counts(xml_doc) + line_count = {} + speeches = xml_doc.css('speech') + speeches.each do |speech| + speaker = speech.css('speaker').text + count = speech.css('line').count + + if speaker == 'ALL' + #line_count.each_key { |k| line_count[k] += 1 } + elsif line_count.has_key?(speaker) + line_count[speaker] += count + else + line_count[speaker] = count + end + end + line_count + end + + def display(line_counts) + line_counts.sort_by{|_key, value| value}.reverse.each do |v| + puts "#{v[1]} #{v[0]}" + end + end +end + +Macbeth_Analyzer.new.run From 3913e30a489686f9485a2a32556fe0a91f6140d0 Mon Sep 17 00:00:00 2001 From: Eric Lubin Date: Tue, 17 Sep 2013 21:07:29 -0400 Subject: [PATCH 2/3] test cleanup, code changes --- Gemfile | 5 ++++ Gemfile.lock | 2 ++ lib/macbeth_analyzer.rb | 34 ++++++++++++++++++++++ macbeth_analyzer.rb | 42 ++------------------------- macbeth_analyzer_spec.rb | 61 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 40 deletions(-) create mode 100644 lib/macbeth_analyzer.rb create mode 100644 macbeth_analyzer_spec.rb diff --git a/Gemfile b/Gemfile index 90b7d0d..e0230a6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,7 @@ source 'https://rubygems.org' + gem 'nokogiri', '~> 1.6.0' + +group :development, :test do + gem "minitest", "~> 5.0.7" +end diff --git a/Gemfile.lock b/Gemfile.lock index 9869fbd..39905c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,6 +2,7 @@ GEM remote: https://rubygems.org/ specs: mini_portile (0.5.0) + minitest (5.0.7) nokogiri (1.6.0) mini_portile (~> 0.5.0) @@ -9,4 +10,5 @@ PLATFORMS ruby DEPENDENCIES + minitest (~> 5.0.7) nokogiri (~> 1.6.0) diff --git a/lib/macbeth_analyzer.rb b/lib/macbeth_analyzer.rb new file mode 100644 index 0000000..3c85c68 --- /dev/null +++ b/lib/macbeth_analyzer.rb @@ -0,0 +1,34 @@ + +class MacbethAnalyzer + require 'net/http' + require 'open-uri' + require 'nokogiri' + + def run + line_counts = parse_counts(load_file) + display(line_counts) + end + + def load_file + Nokogiri::HTML(open('http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml')) + end + + def parse_counts(xml_doc) + line_count = Hash.new(0) + speeches = xml_doc.css('speech') + speeches.each do |speech| + speaker = speech.css('speaker').text + count = speech.css('line').count + line_count[speaker] += count if speaker != 'ALL' + end + line_count + end + + def display(line_counts) + line_counts.sort_by{|_key, value| value}.reverse.each do |v| + puts "#{v[1]} #{v[0]}" + end + end +end + +#MacbethAnalyzer.new.run diff --git a/macbeth_analyzer.rb b/macbeth_analyzer.rb index 86a97d2..ad2b0fc 100644 --- a/macbeth_analyzer.rb +++ b/macbeth_analyzer.rb @@ -1,41 +1,3 @@ -class Macbeth_Analyzer - require 'net/http' - require 'open-uri' - require 'nokogiri' - - def run - line_counts = parse_counts(load_file) - display(line_counts) - end - - def load_file - Nokogiri::HTML(open('http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml')) - end - - def parse_counts(xml_doc) - line_count = {} - speeches = xml_doc.css('speech') - speeches.each do |speech| - speaker = speech.css('speaker').text - count = speech.css('line').count - - if speaker == 'ALL' - #line_count.each_key { |k| line_count[k] += 1 } - elsif line_count.has_key?(speaker) - line_count[speaker] += count - else - line_count[speaker] = count - end - end - line_count - end - - def display(line_counts) - line_counts.sort_by{|_key, value| value}.reverse.each do |v| - puts "#{v[1]} #{v[0]}" - end - end -end - -Macbeth_Analyzer.new.run +require_relative 'lib/macbeth_analyzer' +MacbethAnalyzer.new.run diff --git a/macbeth_analyzer_spec.rb b/macbeth_analyzer_spec.rb new file mode 100644 index 0000000..65b0f7d --- /dev/null +++ b/macbeth_analyzer_spec.rb @@ -0,0 +1,61 @@ +require 'minitest' +require 'minitest/autorun' +require_relative 'lib/macbeth_analyzer' + +class TestMacbethAnalyzer < MiniTest::Test + + describe '#load_file' do + def setup + @ma = MacbethAnalyzer.new + end + def test_load_file + xml_doc = @ma.load_file + refute_nil(xml_doc) + end + def test_load_file_2 + xml_doc = @ma.load_file + assert xml_doc.instance_of?(Nokogiri::HTML::Document), "Expected #{xml_doc.inspect} to be an instance of #{Nokogiri::HTML::Document}, not #{xml_doc.class}" + end + end + + describe "#parse_counts" do + def setup + @ma = MacbethAnalyzer.new + end + def test_parse_returns_one_speaker + line_count = @ma.parse_counts(Nokogiri::XML("AB")) + assert_equal( line_count.count, 1 ) + end + def test_parse_returns_one_speaker_one_line + line_count = @ma.parse_counts(Nokogiri::XML("AB")) + assert_equal( line_count["A"], 1 ) + end + def test_parse_returns_one_speaker_two_lines + line_count = @ma.parse_counts(Nokogiri::XML("ABC")) + assert_equal( line_count["A"], 2 ) + end + def test_parse_returns_two_speakers + line_count = @ma.parse_counts(Nokogiri::XML("ABCD")) + assert_equal( line_count.count, 2 ) + end + end + + describe "#display" do + def setup + @ma = MacbethAnalyzer.new + end + def test_display + output = capture_io do + @ma.display({'A' => 1}) + end + assert_equal ["1 A\n",""], output + end + def test_display_sort + output = capture_io do + @ma.display({'A' => 1, 'B' => 2}) + end + assert_equal ["2 B\n1 A\n", ""], output + end + end +end + From 07ec5254f432c2ba4ce6f25d259175424c6525b6 Mon Sep 17 00:00:00 2001 From: Eric Lubin Date: Tue, 17 Sep 2013 21:09:36 -0400 Subject: [PATCH 3/3] adding output file --- README.md | 35 ++++------------------------------- output.txt | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 31 deletions(-) create mode 100644 output.txt diff --git a/README.md b/README.md index 11daf64..baab9aa 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,6 @@ -***An exercise for Prime subscribers. Visit http://learn.thoughtbot.com/prime to learn more.*** -### Difficulty level: intermediate. +

Run

+ruby macbeth_analyzer.rb +

Run Tests

+ruby macbeth_analyzer_spec.rb -## Your Task - -As a Shakespeare buff, statistics junkie, and unix lover, Ben finds himself wanting a command-line tool for analyzing Macbeth. - -Write a command-line program that prints the number of lines spoken by each character in the play. - -Sample usage/output (using made-up numbers): - - $ ruby macbeth_analyzer.rb - 543 Macbeth - 345 Banquo - 220 Duncan - (etc.) - -You can find an XML-encoded version of Macbeth here: http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml. Your program should download and parse this file at runtime. - -Your solution must be tested, preferably via TDD. - -## Working/Submitting - -1. To work on this exercise, fork the repo and begin implementing your solution. -2. When you are done, copy the output of your program into a file in this repository. -3. Create a pull request so your code can be reviewed. -4. Perform a code review on at least one other person's solution. Your comments should follow our code review guidelines: https://github.com/thoughtbot/guides/tree/master/code-review. Most important: be friendly. Make suggestions, not demands. -5. Improve your solution based on the comments you've received and approaches you've learned from reviewing others' attempts. - -## Bounty - -While knowledge and skill improvement are their own rewards, the author with the best solution (as judged by thoughtbot) will receive a cool thoughtbot t-shirt. diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..c565301 --- /dev/null +++ b/output.txt @@ -0,0 +1,41 @@ +718 MACBETH +265 LADY MACBETH +212 MALCOLM +180 MACDUFF +135 ROSS +113 BANQUO +73 LENNOX +70 DUNCAN +62 First Witch +46 Porter +45 Doctor +41 LADY MACDUFF +39 HECATE +35 Sergeant +30 First Murderer +30 SIWARD +27 Third Witch +27 Second Witch +23 Gentlewoman +23 Messenger +21 Lord +21 ANGUS +20 Son +15 Second Murderer +12 MENTEITH +11 Old Man +11 CAITHNESS +10 DONALBAIN +8 Third Murderer +7 YOUNG SIWARD +5 Third Apparition +5 Servant +5 SEYTON +4 Second Apparition +3 Lords +2 First Apparition +2 Both Murderers +2 FLEANCE +1 ATTENDANT +1 MACBETHLENNOX +1 Soldiers