Guest User

Untitled

a guest
Jul 19th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.86 KB | None | 0 0
  1. # StringCalculator in Ruby 1.8.x
  2.  
  3. class StringCalculator
  4. DEFAULT_DELIMITER_DETECTOR = /\,|\n/
  5. CUSTOM_DELIMITER_PARSERS = [/^\/\/(.)\n/, /^\/\/((?:\[[^\]]+\])+)\n/]
  6.  
  7. def initialize(numbers)
  8. @numbers=numbers
  9. @result=nil
  10. @errors=''
  11. @delimiterDetectorRegExp=DEFAULT_DELIMITER_DETECTOR
  12. detect_and_consume_custom_delimiter_if_any
  13. end
  14.  
  15. def total_sum
  16. calculate_sum unless @result
  17. raise "Negative numbers detected: #{@errors}" unless @errors.empty?
  18. @result
  19. end
  20.  
  21. private
  22.  
  23. def calculate_sum
  24. @result = 0
  25. @numbers.split(@delimiterDetectorRegExp).each do |currentNumber|
  26. currentNumber = currentNumber.to_i
  27. @errors << " #{currentNumber}" if currentNumber < 0
  28. @result += currentNumber if currentNumber <= 1000
  29. end
  30. end
  31.  
  32. def detect_and_consume_custom_delimiter_if_any
  33. CUSTOM_DELIMITER_PARSERS.detect do |customDelimiterDetectorRegExp|
  34. if customDelimiterMatch = customDelimiterDetectorRegExp.match(@numbers)
  35. extractAllDelimiters(customDelimiterMatch[1])
  36. @numbers = @numbers[customDelimiterMatch.end(0)..-1]
  37. end
  38. end
  39. end
  40.  
  41. def extractAllDelimiters(delimiterExpression)
  42. return @delimiterDetectorRegExp = Regexp.union(@delimiterDetectorRegExp, Regexp.new(Regexp.escape(delimiterExpression))) if delimiterExpression.length == 1
  43. delimiterExpression.scan(/\[([^\]]+)\]/) do |delimiter|
  44. @delimiterDetectorRegExp = Regexp.union(@delimiterDetectorRegExp, Regexp.new(Regexp.escape(delimiter[0])))
  45. end
  46. end
  47. end
  48.  
  49. describe StringCalculator do
  50. context "Sums 0, 1 or 2 numbers" do
  51. it "returns 0 when passed an empty string" do
  52. StringCalculator.new('').total_sum.should == 0
  53. end
  54. it "returns the number when passed only one number" do
  55. StringCalculator.new('1').total_sum.should == 1
  56. StringCalculator.new('12').total_sum.should == 12
  57. StringCalculator.new('24').total_sum.should == 24
  58. StringCalculator.new('35').total_sum.should == 35
  59. end
  60. it "returns the sum of two numbers separated by commas" do
  61. StringCalculator.new('1,2').total_sum.should == 3
  62. StringCalculator.new('12,34').total_sum.should == 46
  63. StringCalculator.new('24,10').total_sum.should == 34
  64. StringCalculator.new('46,34').total_sum.should == 80
  65. end
  66. end
  67.  
  68. context "Sums any number of integers" do
  69. it "returns 13 when passed '1,10,2'" do
  70. StringCalculator.new("1,10,2").total_sum.should == 13
  71. end
  72. it "returns 254 when passed '21,1,232'" do
  73. StringCalculator.new("21,1,232").total_sum.should == 254
  74. end
  75. it "returns 112 when passed '100,5,6,1'" do
  76. StringCalculator.new("100,5,6,1").total_sum.should == 112
  77. end
  78. it "returns 153 when passed '10,11,102,30'" do
  79. StringCalculator.new("10,11,102,30").total_sum.should == 153
  80. end
  81. end
  82.  
  83. context "It deals with \\n as a delimiter" do
  84. it "returns 46 when passed '12\\n34'" do
  85. StringCalculator.new("12\n34").total_sum.should == 46
  86. end
  87. it "returns 13 when passed '1,10\\n2'" do
  88. StringCalculator.new("1,10\n2").total_sum.should == 13
  89. end
  90. it "returns 254 when passed '21\\n1,232'" do
  91. StringCalculator.new("21\n1,232").total_sum.should == 254
  92. end
  93. it "returns 112 when passed '100\\n5\\n6\\n1'" do
  94. StringCalculator.new("100\n5\n6\n1").total_sum.should == 112
  95. end
  96. it "returns 153 when passed '10,11\\n102\\n30'" do
  97. StringCalculator.new("10,11\n102\n30").total_sum.should == 153
  98. end
  99. it "returns 112 when passed '100\\n5\\n6,1'" do
  100. StringCalculator.new("100\n5\n6,1").total_sum.should == 112
  101. end
  102. it "returns 153 when passed '10\\n11,102\\n30'" do
  103. StringCalculator.new("10\n11,102\n30").total_sum.should == 153
  104. end
  105. end
  106.  
  107. context "It deals with an arbitrary delimiter specified with '//delimiter\\n'" do
  108. it "returns 46 when passed '//;\\n12;34'" do
  109. StringCalculator.new("//;\n12;34").total_sum.should == 46
  110. end
  111. it "returns 13 when passed '//*\\n1*10\\n2'" do
  112. StringCalculator.new("//*\n1*10\n2").total_sum.should == 13
  113. end
  114. it "returns 13 when passed '//*\\n1\\n10*2'" do
  115. StringCalculator.new("//*\n1\n10*2").total_sum.should == 13
  116. end
  117. it "returns 153 when passed '//-\\n10-11\\n102-30'" do
  118. StringCalculator.new("//-\n10-11\n102-30").total_sum.should == 153
  119. end
  120. end
  121.  
  122. context "It raises an error when passed negative numbers including the offending numbers" do
  123. it "raises an error containing -22 when passed '1,-22'" do
  124. lambda { StringCalculator.new("1,-22").total_sum }.should raise_error { |error| error.message.should include("-22") }
  125. end
  126. it "raises an error containing -22,-2 and -15 when passed '1,-22,33,-2,44,-15'" do
  127. lambda { StringCalculator.new("1,-22,33,-2,44,-15").total_sum }.should raise_error { |error| error.message.should include("-22","-2","-15") }
  128. end
  129. end
  130.  
  131. context "Ignores numbers above 1000" do
  132. it "returns 35 when passed '1,1002,34'" do
  133. StringCalculator.new("1,1002,34").total_sum.should == 35
  134. end
  135. it "returns 135 when passed '1,1002,34,50,2353,50'" do
  136. StringCalculator.new("1,1002,34,50,2353,50").total_sum.should == 135
  137. end
  138. end
  139.  
  140. context "It deals with a custom delimiter of variable length specified with '//[delimiter]\\n'" do
  141. it "returns 46 when passed '//[;**]\\n12;**34'" do
  142. StringCalculator.new("//[;**]\n12;**34").total_sum.should == 46
  143. end
  144. it "returns 13 when passed '//[*-*]\\n1*-*10\\n2'" do
  145. StringCalculator.new("//[*-*]\n1*-*10\n2").total_sum.should == 13
  146. end
  147. it "returns 13 when passed '//[iop]\\n1\\n10iop2'" do
  148. StringCalculator.new("//[iop]\n1\n10iop2").total_sum.should == 13
  149. end
  150. it "returns 153 when passed '//[-99-]\\n10-99-11\\n102-99-30'" do
  151. StringCalculator.new("//[-99-]\n10-99-11\n102-99-30").total_sum.should == 153
  152. end
  153. end
  154.  
  155. context "It deals with a several custom delimiter '//[delimiter1][delimiter2]\\n'" do
  156. it "returns 76 when passed '//[;**][%]\\n12;**34%10\n20'" do
  157. StringCalculator.new("//[;**][%]\n12;**34%10\n20").total_sum.should == 76
  158. end
  159. it "returns 53 when passed '//[*-][$$][&]\\n1*-*10\\n2$$15&25'" do
  160. StringCalculator.new("//[*-*][$$][&]\n1*-*10\n2$$15&25").total_sum.should == 53
  161. end
  162. end
  163. end
Add Comment
Please, Sign In to add comment