Inconsistent Ruby results with scanned line length
I may not have the whole picture here, but I get inconsistent results with the calculation: I am trying to solve the problem of encoding the length of the run, so if you get an input string like AAABBAAACCCAA, the encoding will be: 3A2B3A3C2A ", so the functions:
def encode(input)
res = ""
input.scan(/(.)\1*/i) do |match|
res << input[/(?<bes>#{match}+)/, "bes"].length.to_s << match[0].to_s
end
res
end
The results I get are as follows:
irb(main):049:0> input = "AAABBBCCCDDD"
=> "AAABBBCCCDDD"
irb(main):050:0> encode(input)
(a) => "3A3B3C3D"
irb(main):051:0> input = "AAABBBCCCAAA"
=> "AAABBBCCCAAA"
irb(main):052:0> encode(input)
(b) => "3A3B3C3A"
irb(main):053:0> input = "AAABBBCCAAA"
=> "AAABBBCCAAA"
irb(main):054:0> encode(input)
(c) => "3A3B2C3A"
irb(main):055:0> input = "AAABBBCCAAAA"
=> "AAABBBCCAAAA"
irb(main):056:0> encode(input)
(d) => "3A3B2C3A"
irb(main):057:0> input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'
=> "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB"
irb(main):058:0> encode(input)
(e) => "12W1B12W1B12W1B"
As you can see, results (a) - (c) are correct, but results (d) and (e) are missing some repetitions, and the resulting code is a few short letters, can you give a hint as to where. Check please? (I am learning to use "pry" right now)
source to share
You only get a match of matched characters repeated in the first place. You need to do the replacement within gsub
and pass the match object to the block, where you can do the necessary manipulations:
def encode(input)
input.gsub(/(.)\1*/) { |m| m.length.to_s << m[0] }
end
See the online Ruby test .
Results:
"AAABBBCCCDDD" => 3A3B3C3D
"AAABBBCCCAAA" => 3A3B3C3A
"AAABBBCCAAA" => 3A3B2C3A
"AAABBBCCAAAA" => 3A3B2C4A
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" => 12W1B12W3B24W1B
source to share
Regular expressions are great, but they are not the golden hammer for every problem.
str = "AAABBAAACCCAA"
str.chars.chunk_while { |i, j| i == j }.map { |a| "#{a.size}#{a.first}" }.join
Breaking what it does:
str = "AAABBAAACCCAA"
str.chars # => ["A", "A", "A", "B", "B", "A", "A", "A", "C", "C", "C", "A", "A"]
.chunk_while { |i, j| i == j } # => #<Enumerator: #<Enumerator::Generator:0x007fc1998ac020>:each>
.to_a # => [["A", "A", "A"], ["B", "B"], ["A", "A", "A"], ["C", "C", "C"], ["A", "A"]]
.map { |a| "#{a.size}#{a.first}" } # => ["3A", "2B", "3A", "3C", "2A"]
.join # => "3A2B3A3C2A"
to_a
there is for illustration, but this is optional:
str = "AAABBAAACCCAA"
str.chars
.chunk_while { |i, j| i == j }
.map { |a| "#{a.size}#{a.first}" }
.join # => "3A2B3A3C2A"
how do you know methods like Array # chunk_while? I am using Ruby 2.3.1 but cannot find it in the API docs, I mean where is the list of lists of all available methods? certainly not here ruby-doc.org/core-2.3.1/Array.html
Well, this is an off-topic question, but its useful information to know:
Remember that the array contains an Enumerable module that contains chunk_while
. Use the search functions of http://ruby-doc.org to find where they live. Also, check out the ri
command line usage and try running gem server
at the command line to get help for all the gems you have installed.
If you look at the Array documentation page , on the left, you can see that the array has a parent object class, so it will have methods from Object and that it also inherits from Enumerable, so it will also use whatever was implemented in Enumerable.
source to share