Reputation: 67
I have been trying to solve this problem for a while now, im supposed to take a given string like "aaabbc" and compress it into a new string that states multiples of a letter in a row in place. So it would output "3a2bc"
So far i managed to print it out except it counts all instances of a letter and im not sure how to get rid of the current repeats:
def compress_str(str)
new_str = []
word = str.split("")
word.each do |char|
count = 0
word.each do |ele|
if ele == char
count += 1
end
end
if count > 1
new_str << count
new_str << char
else
new_str << char
end
end
return new_str.join("")
Example output:
Any suggestions on how I'm supposed to get rid of them?
Upvotes: 0
Views: 437
Reputation: 121010
String#scan
can also be handy here.
uncompressed = %w(aaabbcddaaaaa aaabb 111ddttttabaaacc)
uncompressed.map { |w| w.scan(/(.)(\1*)/).map(&:join) }
#⇒ [["aaa", "bb", "c", "dd", "aaaaa"],
# ["aaa", "bb"],
# ["111", "dd", "tttt", "a", "b", "aaa", "cc"]]
And to get the desired outcome.
uncompressed.map do |w|
w.scan(/(.)(\1*)/).map(&:join).map do |l|
"#{l.length}#{l[0]}"
end.join
end
#⇒ ["3a2b1c2d5a", "3a2b", "312d4t1a1b3a2c"]
Upvotes: 1
Reputation: 11193
You could use String#chars (1), so Enumerable#chunk_while (2), then Enumerable#flat_map (3) into the desired format and finally Array#join:
str = "aaabbcaa"
str.chars.chunk_while { |x, y| x == y }.flat_map { |e| [(e.size unless e.size == 1), e.first] }.join
#=> "3a2bc2a"
# (1)
str.chars#.to_a
#=> ["a", "a", "a", "b", "b", "c", "a", "a"]
so
# (2)
str.chars.chunk_while { |x, y| x == y }#.to_a
#=> [["a", "a", "a"], ["b", "b"], ["c"], ["a", "a"]]
then
# (3)
str.chars.chunk_while { |x, y| x == y }.flat_map { |e| [(e.size unless e.size == 1),e.first] }
#=> [3, "a", 2, "b", nil, "c", 2, "a"]
Upvotes: 1
Reputation: 6572
Using Enumerable#chunk might be a good fit for your needs.
uncompressed = %w(aaabbcddaaaaa aaabb 111ddttttabaaacc)
uncompressed.each do |str|
puts str.chars.chunk{|e| e}.map {|e| "#{e[1].length}#{e[0]}"}.join
end
>>> 3a2b1c2d5a
>>> 3a2b
>>> 312d4t1a1b3a2c
Sure, you can add another check inside map block, so omit 1 before a single element and print as is.
Upvotes: 1