Ruby Quiz #1 - Bonus - Three More Difficulty Levels (2, 3, 4) - Commas Inside Quotes and Double Up Quotes in Quotes, ...


(Gerald Bauer) #1

Hello,

    Thanks for the first three entries - all passing the level 1 test. Yay!

    If that was too easy :slight_smile: I added three more difficulty levels
  to the challenge.[1]
.

### Level 2 - Commas Inside Quotes and Double Up Quotes in Quotes

Let's turn Shakespeare's "literal" Hamlet quote:

Hamlet says, "Seems," madam! Nay it is; I know not "seems."

into

1, "Hamlet says, ""Seems,"" madam! Nay it is; I know not ""seems."""

And the test reads:

def test_parse_level2
  records = [["1", "Hamlet says, \"Seems,\" madam! Nay it is; I know
not \"seems.\""]]

  assert_equal records, parse( <<TXT )
1, "Hamlet says, ""Seems,"" madam! Nay it is; I know not ""seems."""
TXT
end

### Level 3 - Unix/Ruby-Style Backslash Escapes

Lets add the "unix-style" escaping with backslashes (e.g. `\"` for `""`)
used by Ruby :-), PostgreSQL, MySQL and others
(when exporting database tables in CSV, for example):

1, "Hamlet says, \"Seems,\" madam! Nay it is; I know not \"seems.\""

And the test reads:

def test_parse_level3
  records = [["1", "Hamlet says, \"Seems,\" madam! Nay it is; I know
not \"seems.\""]]

  assert_equal records, parse( <<TXT )
1, "Hamlet says, \\"Seems,\\" madam! Nay it is; I know not \\"seems.\\""
TXT
end

### Level 4 - Single or Double? Mixed Quotes

Let's again get inspired by Ruby :slight_smile: -
see 210 Ways to Rome [2] and lets add single or double quotes.

1, "Hamlet says, 'Seems,' madam! Nay it is; I know not 'seems.'"
2, 'Hamlet says, "Seems," madam! Nay it is; I know not "seems."'

And the test reads:

def test_parse_level4
  records = [[1, "Hamlet says, 'Seems,' madam! Nay it is; I know not 'seems.'"],
             [2, 'Hamlet says, "Seems," madam! Nay it is; I know not "seems."']]

  assert_equal records, parse( <<TXT )
1, "Hamlet says, 'Seems,' madam! Nay it is; I know not 'seems.'"
2, 'Hamlet says, "Seems," madam! Nay it is; I know not "seems."'
TXT
end

Happy hacking and data wrangling with Ruby.

[1] https://github.com/planetruby/quiz
[2] https://idiosyncratic-ruby.com/15-207-ways-to-rome.html


(Frank J. Cameron) #2

Gerald Bauer wrote:

    Thanks for the first three entries - all passing the level 1 test.
Yay!
    If that was too easy :slight_smile: I added three more difficulty levels
  to the challenge.[1]

$ ruby lib/001.rb
Run options: --seed 639
# Running:
.F..
Finished in 0.007014s, 570.3056 runs/s, 570.3056 assertions/s.
  1) Failure:
RubyQuizTest#test_parse_level4 [/home/fjc/ruby-quiz/001/test.rb:68]:
--- expected
+++ actual
@@ -1 +1 @@
-[[1, "Hamlet says, 'Seems,' madam! Nay it is; I know not 'seems.'"], [2,
"Hamlet says, \"Seems,\" madam! Nay it is; I know not \"seems.\""]]
+[["1", "Hamlet says, 'Seems,' madam! Nay it is; I know not 'seems.'"],
["2", "Hamlet says, \"Seems,\" madam! Nay it is; I know not \"seems.\""]]
4 runs, 4 assertions, 1 failures, 0 errors, 0 skips

$ cat lib/001.rb
require_relative '../001/test.rb'
class RubyQuizTest
  def parse(text)
    text.lines.map do |line|
      next if line.match(/^\s*$|#/)
      line
      .strip
      .gsub(/"(([^"\\]|"")*(\\.([^"\\]|"")*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/){
        "\000#{
          Regexp.last_match
          .to_a[1..-1]
          .compact[0]
          .gsub(/,/, "\001")
          .gsub(/\\"|""/, '"')
        }\000"
      }
      .split(/\s*,\s*/, -1)
    end.compact.map do |cells|
      cells.map do |cell|
        cell
        .gsub(/\001/, ',')
        .gsub(/\000/, '')
      end
    end
  end
end
RubyQuizTest.new('fjc')