8

I'm trying to find groups of repeated digits in a number, e.g. 12334555611 becomes (1 2 33 4 555 6 11).

This works:

$n.comb(/ 0+ | 1+ | 2+ | 3+ | 4+ | 5+ | 6+ | 7+ | 8+ | 9+ /)

but is not very elegant.

Is there a better way to do this?

Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
mscha
  • 6,509
  • 3
  • 24
  • 40
  • 1
    Just to check `11223311` should become `(11 22 33 11)` and not `(1111 22 33)`? – Scimon Proctor Dec 04 '19 at 09:02
  • @Scimon: correct. – mscha Dec 04 '19 at 09:03
  • 1
    @Elizabeth Mattijsen: I know Perl 6 has been renamed, but must you really erase all traces of the name? That prevents people from finding this question by searching on [perl6 repeated digits], for instance. – mscha Dec 04 '19 at 09:08
  • See https://meta.stackoverflow.com/questions/391656/why-are-no-more-perl-6-questions-asked-on-stack-overflow for evidence that this may be a bad idea, – mscha Dec 04 '19 at 09:37
  • 2
    @mscha: I propose that *if* the op mentions Perl 6 in the title, we change this to "Raku (née Perl 6)". – Elizabeth Mattijsen Dec 04 '19 at 16:57
  • @Elizabeth Mattijsen: yes, something like that makes sense. I had “Perl 6 (Raku)” originally. But in the tags I had both `perl6` and `raku`, is it really necessary to _remove_ the `perl6` tag? (Now people that follow the `perl6` tag but not (yet) the `raku` tag won't see my post.) – mscha Dec 05 '19 at 11:32

3 Answers3

10
'12334555611'.comb(/\d+ % <same>/)

Please check the answer of the first task of Perl Weekly Challenge

chenyf
  • 5,048
  • 1
  • 12
  • 35
6

You may use

$n.comb(/(.) $0*/)

The (.) creates a capturing group and captures any char into Group 1, then there is a backreference to Group 1 that is $0 in Perl6 regex. The * quantifier matches zero or more occurrences of the same char as in Group 1.

Replace the . with \d to match any digit if you need to only match repeated digits.

See a Perl6 demo online.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks. The elegance of this is debatable but it is a better solution than my original one. – mscha Dec 04 '19 at 09:10
  • Beats my attempt `( $n ~~ m/@=((<[0..9]>)$0+)*/ )..map( *.Str )` – Scimon Proctor Dec 04 '19 at 09:16
  • @Wiktor, it's the `{}` that makes me find the elegance debatable. But to my surprise, it doesn't seem to be necessary, `$n.comb(/(.) $0*/)` works as well (at least on my Rakudo Star 2019.03.1). – mscha Dec 04 '19 at 09:27
  • @mscha OK, when I first tried it, it did not work. Good, let me change the link and the code. – Wiktor Stribiżew Dec 04 '19 at 10:05
  • 2
    @mscha "to my surprise, it [`{}`] doesn't seem to be necessary" My discussion of related issues in the first couple sections of [**"Publication" of match variables by Rakudo**](https://stackoverflow.com/questions/51408141/perl6-grammar-not-sure-about-some-syntax-in-an-example/51410261#51410261) may help clear up why. (Perhaps in the sense that some folk use mud to try clear up acne, but I thought I'd comment anyway.) – raiph Dec 04 '19 at 13:12
0

In case someone navigates here wanting to remove singleton digits (Raku REPL code below):

  1. Returning only the longest run(s) of repeated digits, while removing singleton digits (uses m:g adverb combo):

    > put $/ if m:g/ \d**2..* % <same> / given '12334555611';
    33 555 11

  1. Alternatively, depending on how you interpret the original question, returning the overlapping runs of repeated digits (uses m:ov adverb combo):

    > put $/ if m:ov/ \d**2..* % <same> / given '12334555611';
    33 555 55 11

The difference between the two versions is particularly dramatic as repeated runs get longer:


    > given '122333444455555666666' {put $/ if m:g/ \d**2..* % <same> /};
    22 333 4444 55555 666666

    > given '122333444455555666666' {put $/ if m:ov/ \d**2..* % <same> /};
    22 333 33 4444 444 44 55555 5555 555 55 666666 66666 6666 666 66

jubilatious1
  • 1,999
  • 10
  • 18