0

I am trying to find the longest consecutive digits from a string of digits. For example, given:

"12233344445"

I expect to return:

"4444"

I can find that using iteration, but I think that using regex would be cool although it's not efficient. It should be simple but I can't do it. Please enlighten me. I use Ruby, but any language will do.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Sam Kong
  • 5,472
  • 8
  • 51
  • 87
  • Regex can't decipher length. Or, do length comparisons. –  Sep 26 '18 at 00:29
  • Possible duplicate of [Longest recurring cycle of digits](https://stackoverflow.com/questions/30289341/longest-recurring-cycle-of-digits) – Martin Sep 26 '18 at 00:42
  • @Martin, this problem is to find the longest substring in a string of digits of the form `d*n`, where `d` is one of the 10 digits (e.g., '4'*5 #=> "44444"`), whereas the problem you referenced concerns infinitely repeating digits in the decimal representation of a rational number. – Cary Swoveland Sep 26 '18 at 01:35
  • Nuckle dragger method: `s.scan(/1+|2+|3+|4+|5+|6+|7+|8+|9+|0+/).max_by(&:length)` – dawg Sep 26 '18 at 05:58
  • 2
    What if there's a tie? – Sagar Pandya Sep 26 '18 at 06:40

3 Answers3

5

Regardless of the regular expression you use, subsequent iteration will be required. Here's one way.

str = "12233344445"

str.gsub(/(\d)\1*/).max_by(&:size)
  #=> "4444"

We have

enum = str.gsub(/(\d)\1*/)
  #=> #<Enumerator: "12233344445":gsub(/(\d)\1*/)>

We can convert this to an array to see the elements that will be generated by this enumerator.

enum.to_a
  #=> ["1", "22", "333", "4444", "5"]

The regular expression reads, "Match a digit in capture group 1, followed by zero or more characters that equal the contents of capture group 1."

This uses the form of String#gsub where no block is given. (Here the method has nothing to do with character substitution, which can be a bit confusing.)

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
2

You can use a scanner to find all matches then flatten to find the longest match:

> "12233344445".scan(/((\d)\2*)/).flatten.max_by(&:length)
=> "4444"
dawg
  • 98,345
  • 23
  • 131
  • 206
1

Another option is convert the string to an array and use Enuberable chunk_while on it:

num.each_char.chunk_while {|i, j| j == i }.to_a
#=> [["1"], ["2", "2"], ["3", "3", "3"], ["4", "4", "4", "4"], ["5"]]

So you can get for example:

num.each_char.chunk_while {|i, j| j == i }.map(&:join) #=> ["1", "22", "333", "4444", "5"]

Or just get the longest string, for example in this way:

num.each_char.chunk_while {|i, j| j == i }.max_by(&:length).join() #=> "4444"
iGian
  • 11,023
  • 3
  • 21
  • 36