Znajdź Array Runs

14

Znajdź przebiegi w tablicy

Przebieg jest zdefiniowany jako trzy lub więcej liczb, które zwiększają się w stosunku do poprzedniego ze stałym krokiem. Na przykład [1,2,3] będzie przebiegiem z krokiem 1, [1,3,5,7] będzie przebiegiem z krokiem 2, a [1,2,4,5] nie będzie biegiem.

Możemy wyrazić te przebiegi poprzez zapis „i do j przez s”, gdzie i to pierwsza liczba przebiegów, j to ostatnia liczba przebiegów, a s to krok. Jednak przebiegi kroku 1 będą wyrażone „i do j”.

Używając wcześniej tablic, otrzymujemy:

  • [1,2,3] -> „1 do 3”

  • [1,3,5,7] -> „1to7by2”

  • [1,2,4,5] -> „1 2 4 5”

W tym wyzwaniu Twoim zadaniem jest zrobienie tego dla tablic, które mogą mieć wiele przebiegów.

Przykładowy kod Pythona z rekurencją:

def arr_comp_rec(a, start_index):
    # Early exit and recursion end point
    if start_index == len(a)-1:
        return str(a[-1])
    elif start_index == len(a):
        return ''

    # Keep track of first delta to compare while searching
    first_delta = a[start_index+1] - a[start_index]
    last = True
    for i in range(start_index, len(a)-1):
        delta = a[i+1] - a[i]
        if delta != first_delta:
            last = False
            break
    # If it ran through the for loop, we need to make sure it gets the last value
    if last: i += 1

    if i - start_index > 1:
        # There is more than 2 numbers between the indexes
        if first_delta == 1:
            # We don't need by if step = 1
            return "{}to{} ".format(a[start_index], a[i]) + arr_comp_rec(a, i+1)
        else:
            return "{}to{}by{} ".format(a[start_index], a[i], first_delta) + arr_comp_rec(a, i+1)
    else:
        # There is only one number we can return
        return "{} ".format(a[start_index]) + arr_comp_rec(a, i)

IO jest elastyczny

Wejście

Tablica posortowanych dodatnich liczb całkowitych (bez duplikatów)

Wynik

Ciąg przebiegów oddzielony spacją lub tablica ciągów przebiegów

Nie musi być chciwy w określonym kierunku

Może mieć końcowe białe znaki

Przypadki testowe

In: [1000, 1002, 1004, 1006, 1008, 1010]
Out: "1000to1010by2"

In: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
Out: "1to3 5 8 13 21 34 55 89 144 233"

In: [10, 20, 30, 40, 60]
Out: "10to40by10 60"

In: [5, 6, 8, 11, 15, 16, 17]
Out: "5 6 8 11 15to17"

In: [1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 30, 45, 50, 60, 70, 80, 90, 91, 93]
Out: "1to7 9to15by2 30 45 50to90by10 91 93"

To jest więc wygrywa najmniej bajtów.

WretchedLout
źródło
1
powiązane
Luis felipe De jesus Munoz
2
Czy musi być chciwy od lewej do prawej? (tzn. [4, 5, 6, 7, 9, 11, 13, 15]nie może być 4to6 7to15by2?)
Jonathan Allan
1
@JonathanAllan Nie, niekoniecznie trzeba być chciwym.
WretchedLout
Przypuszczam, że nie będzie zduplikowanych wpisów?
Shieru Asakoto
1
Tylko dodatnie liczby całkowite. @ Οurous Dopuszczalne końcowe białe znaki.
WretchedLout

Odpowiedzi:

5

Galaretka ,  42  40 bajtów

-2 dzięki Kevinowi Cruijssenowi (odfiltruj dwójki ḟ2zamiast zastępować dwójki zerami 2,0y)

ŒṖIE×LƲ€ḟ2SƊÞṪµ.ịU,Iḟ1ƊQ€Fż“to“by”ṁṖƊ$)K

Pełny program drukujący wynik.
(Jako monadyczny link uzyskana zostanie lista zawierająca mieszaninę liczb całkowitych i znaków)

Wypróbuj online!
(Zbyt mało wydajny, aby największy przypadek testowy mógł zostać ukończony w ciągu 60s, więc usunąłem[1,2,3,4].)

W jaki sposób?

ŒṖIE×LƲ€ḟ2SƊÞṪµ.ịU,Iḟ1ƊQ€Fż“to“by”ṁṖƊ$)K - Main Link: list of numbers
ŒṖ                                       - all partitions
           ƊÞ                            - sort by last three links as a monad:
      Ʋ€                                 -   last four links as a monad for €ach:
  I                                      -     incremental differences (of the part)
   E                                     -     all equal?
     L                                   -     length (of the part)
    ×                                    -     multiply
        ḟ2                               -   filter discard twos
          S                              -   sum
             Ṫ                           - tail (gets us the desired partition of the input)
              µ                       )  - perform this monadic chain for €ach:
               .                         -   literal 0.5
                ị                        -   index into (the part) - getting [tail,head]
                 U                       -   upend - getting [head,tail]
                      Ɗ                  -   last three links as a monad:
                   I                     -     incremental differences (of the part)
                     1                   -     literal one
                    ḟ                    -     filter discard (remove the ones)
                  ,                      -   pair -> [[head,tail],[deltasWithoutOnes]]
                       Q€                -   de-duplicate €ach -> [[head,tail],[delta]] or [[head,tail],[]] or [[loneValue],[]]
                         F               -   flatten -> [head,tail,delta] or [head,tail] or [loneValue]
                                     $   -   last two links as a monad:
                                    Ɗ    -     last three links as a monad:
                           “to“by”       -       literal list [['t', 'o'], ['b', 'y']]
                                   Ṗ     -       pop (get flattened result without rightmost entry)
                                  ṁ      -       mould ["to","by"] like that (i.e. ["to","by"] or ["to"] or [])
                         ż               -     zip together      
                                       K - join with spaces
                                         - implicit print
Jonathan Allan
źródło
„by” nie powinno być stosowane, jeśli krok = 1
WretchedLout
o Gawwwd: p Dzięki za heads-up!
Jonathan Allan
2,0ySƲÞmożna grać w golfa ḟ2SƊÞna -2 bajty.
Kevin Cruijssen
@KevinCruijssen bardzo prawdziwy, fajny golf, dzięki
Jonathan Allan
1
@KevinCruijssen FYI Pamiętam, dlaczego to było teraz - pierwotnie starałem się sortować według produktu P, a nie sumy Si potrzebowałem zer.
Jonathan Allan
6

Szybki, 246 bajtów

func f(_ a:[Int]){
var c=a.count,m=a+a,z=0,r:String=""
for i in 1..<c{m[i]-=a[i-1];if m[i]==m[i-1]{m[i-1]=0}};m[0]=1
for i in 0..<c{if m[i]==0 {z=1}else if z==0{r+=" \(a[i])"}else{r+="to\(a[i])"+(m[i]>1 ? "by\(m[i])":"");z=0;m[i+1]=1}}
print(r)
}

Wypróbuj online!

pociągnięty
źródło
4
Witamy w Programowaniu Puzzle i Code Golf! Bardzo ładna pierwsza odpowiedź. Mam nadzieję, że zostaniesz tutaj, ponieważ społeczność Swift tutaj jest ... naprawdę mała!
Pan Xcoder,
3

JavaScript (ES6), 129 bajtów

Zwraca tablicę ciągów.

a=>(a.map((n,i)=>n+[n-a[i+1]||''])+'').replace(/(\d+)(-\d+)(?:,\d+\2)+,(\d+)/g,(_,a,b,c)=>a+'to'+(~b?c+'by'+-b:c)).split(/-\d+,/)

Wypróbuj online!

W jaki sposób?

Krok 1

Najpierw dołączamy do każdego numeru sufiks składający się z wiodącego, '-'a następnie różnicy z następnym numerem, z wyjątkiem ostatniego wpisu, który pozostaje niezmieniony. Ta nowa tablica jest wymuszana na ciąg.

(a.map((n, i) => n + [n - a[i + 1] || '']) + '')

Przykład:

Input : [ 1, 2, 3, 5, 9, 11, 13, 20 ]
Output: "1-1,2-1,3-2,5-4,9-2,11-2,13-7,20"

Krok 2

Identyfikujemy wszystkie przebiegi w powstałym ciągu i zastępujemy je odpowiednią notacją.

.replace(
  /(\d+)(-\d+)(?:,\d+\2)+,(\d+)/g,
  (_, a, b, c) => a + 'to' + (~b ? c + 'by' + -b : c)
)

Przykład:

Input : "1-1,2-1,3-2,5-4,9-2,11-2,13-7,20"
Output: "1to3-2,5-4,9to13by2-7,20"

Krok 3

Na koniec podzieliliśmy ciąg na pozostałe sufiksy, w tym końcowe przecinki.

.split(/-\d+,/)

Przykład:

Input : "1to3-2,5-4,9to13by2-7,20"
Output: [ '1to3', '5', '9to13by2', '20' ]
Arnauld
źródło
2

Rubin , 125 118 bajtów

->a{i=y=0;a.chunk{|x|-y+y=x}.map{|z,w|2-i<(s=w.size)?"#{w[i*s]}to#{w[~i=0]}"+"by#{z}"*(z<=>1)+' ':' '*i+w*' '*i=1}*''}

Wypróbuj online!

Wyjaśnienie

Ruby's Enumerable ma przydatną chunkmetodę, która robi dokładnie to, czego potrzebujemy tutaj - grupuje elementy według kolejnych serii o tej samej wartości zwracanej z bloku, w naszym przypadku - różnicy między wartością bieżącą ( x) a poprzednią ( y).

Zastrzeżenie polega na tym, że taka strategia nie uchwyci pierwszego elementu przebiegu, np. Tutaj tylko dwa ostatnie elementy są zgrupowane razem:

Input: [5, 6, 8, 11, 15, 16, 17]
Grouped: [[5, [5]], [1, [6]], [2, [8]], [3, [11]], [4, [15]], [1, [16, 17]]]

Dlatego podczas mapowania na poprawnie sformatowane ciągi, gdy napotkamy nowy potencjalny przebieg (porcja z> 1 elementem), musimy śledzić, czy poprzedni element był pojedynczy ( i=1), czy był już używany w innym uruchomieniu ( i=0). Jeśli jest nieużywany pojedynczy element, staje się on punktem początkowym przebiegu i obniża próg wielkości porcji z 3 do 2.

Kirill L.
źródło
2

R , 180 175 bajtów

r=rle(c(0,diff(a<-scan())));for(j in 1:sum(1|r$l)){l=r$l[j];v=r$v[j];i=T+l-1;cat("if"(l>2-F,paste0(a[T][!F],"to",a[i],"by"[v>1],v[v>1]," "),c("",a[T:i])[-3^F]));T=i+1;F=l<3-F}

Wypróbuj online!

Pod względem koncepcyjnym jest to część mojej odpowiedzi Ruby , choć oczywiście nieco inna technicznie.

5 bajtów zapisanych przez JayCe.

Kirill L.
źródło
Chciałem coś z tym zrobić, rleale byłem zbyt leniwy ... możesz zaoszczędzić 1 bajt robiąc sum(1|x)w miejsce length(x): TIO
JayCe
W rzeczywistości możesz mieć tylko 1 cat na 175 bajtów: TIO
JayCe
Ach, świetnie, dzięki!
Kirill L.,
2

R , 238 217 bajtów

Dzięki @digEmAll za -19 bajtów.

function(v,R=rle(diff(v)),L=R$l,S=sum(L|1),Y=0)if(!S)cat(v)else for(i in 1:S){D=R$v[i]
N=L[i]-F
if(N>1){N=N+1
cat(v[Y+1],'to',v[Y+N],'by'[D>1],D[D>1],' ',sep='')
F=1}else{N=N+(i==S)
if(N>0)cat(v[Y+1:N],'')
F=0}
Y=Y+N}

Wypróbuj online!

J.Doe
źródło
użyj Fzamiast njak już jest zainicjowane 0, co powinno zaoszczędzić kilka bajtów, tak myślę.
Giuseppe,
Ten jest frustrujący. Już prawie jesteś przy użyciu split, diffi rle. Niestety, zachłanne poszukiwanie biegów oznacza dużo zabawy.
J.Doe
214 bajtów Prawie tam jedynym problemem jest czasem nieprawidłowe ustawienie odstępów ...
digEmAll
To 'by'[D>1]dobra sztuczka.
J.Doe
Wydaje się, że działa dobrze 217 bajtów
digEmAll
1

JavaScript (Node.js) , 177 173 bajtów

a=>{for(h=t=p=d=0,o=[];(c=a[t])||h<t;p=c,t++)d||!c?c-p!=d?(o.push(...[[a[h]+"to"+p+(d>1?"by"+d:"")],[p],[p-d,p]][t-h<3?t-h:0]),d=0,h=t--):0:!d&&t-h?d=c-p:0;return o.join` `}

Wypróbuj online!

Shieru Asakoto
źródło
1

Czysty , 208 ... 185 bajtów

import StdEnv,Data.List,Text
l=length
$[]=""
$k=last[u<+(if(v>[])("to"<+last v<+if(u<v!!0-1)("by"<+(v!!0-u))"")"")+" "+ $t\\i=:[u:v]<-inits k&t<-tails k|l(nub(zipWith(-)i v))<2&&l i<>2]

Wypróbuj online!

Obrzydliwe
źródło
1

Galaretka , 41 bajtów

ŒṖIE€Ạ$>Ẉ2eƊƲƇṪµ.ịṚj⁾to;IḢ⁾by;ẋ⁻1$ƲƊµḊ¡€K

Wypróbuj online!

Pełny program

Erik the Outgolfer
źródło
1

Python 2 , 170 166 bajtów

def f(a):
 j=len(a)
 while j>2:
	l,r=a[:j:j-1];s=(r-l)/~-j
	if a[:j]==range(l,r+1,s):return[`l`+'to%d'%r+'by%d'%s*(s>1)]+f(a[j:])
	j-=1
 return a and[`a[0]`]+f(a[1:])

Wypróbuj online!

TFeld
źródło
Nie jestem pewien, czy ten format wyjściowy jest prawidłowy; biegi powinny być ciągami, nie?
Erik the Outgolfer
@EriktheOutgolfer Naprawiono
TFeld
1

Python 2 , 138 136 bajtów

-2 bajty dzięki Erikowi Outgolfer .

r=[];d=0
for n in input()+[0]:
 a=n-([n]+r)[-1]
 if(a-d)*d:
	if r[2:]:r=["%dto"%r[0]+`r[-1]`+"by%s"%d*(1%d)]
	print r.pop(0),
 r+=n,;d=a

Wypróbuj online!

ovs
źródło
1

gvm (commit 2612106 ) bytecode, 108 bajtów

Oczekuje rozmiaru tablicy w jednym wierszu, a następnie członków w jednym wierszu.

Hexdump:

> hexdump -C findruns.bin
00000000  e1 0a 00 10 00 e1 0b 00  ff c8 92 00 f4 f7 10 00  |................|
00000010  01 b0 20 03 00 ff 0a 01  a2 01 c8 92 00 f4 01 c0  |.. .............|
00000020  03 00 ff 0a 02 d0 72 01  0a 03 c8 92 00 f4 05 b0  |......r.........|
00000030  20 a2 02 c0 02 02 6a 03  8b 00 ff f6 06 b0 20 a2  | .....j....... .|
00000040  02 f4 ce 0a 02 c8 92 00  f6 07 6a 03 8b 00 ff f6  |..........j.....|
00000050  f2 b9 66 01 a2 02 00 01  8a 03 f6 05 b9 69 01 a2  |..f..........i..|
00000060  03 92 00 f4 ac c0 74 6f  00 62 79 00              |......to.by.|
0000006c

Przebiegi testowe:

> echo -e "7\n5\n6\n8\n11\n15\n16\n17\n" | ./gvm findruns.bin
5 6 8 11 15to17
> echo -e "20\n1\n2\n3\n4\n5\n6\n7\n9\n11\n13\n15\n30\n45\n50\n60\n70\n80\n90\n91\n93\n" | ./gvm findruns.bin
1to7 9to15by2 30 45 50to90by10 91 93

Ręcznie zmontowany z tego:

0100  e1        rud                     ; read length of array
0101  0a 00     sta     $00             ; -> to $00
0103  10 00     ldx     #$00            ; loop counter
                  readloop:
0105  e1        rud                     ; read unsigned number
0106  0b 00 ff  sta     $ff00,x         ; store in array at ff00
0109  c8        inx                     ; next index
010a  92 00     cpx     $00             ; length reached?
010c  f4 f7     bne     readloop        ; no -> read next number
010e  10 00     ldx     #$00            ; loop counter
0110  01                                ; 'lda $20b0', to skip next instruction
                  runloop:
0111  b0 20     wch     #' '            ; write space character
0113  03 00 ff  lda     $ff00,x         ; load next number from array
0116  0a 01     sta     $01             ; -> to $01
0118  a2 01     wud     $01             ; and output
011a  c8        inx                     ; next index
011b  92 00     cpx     $00             ; length reached?
011d  f4 01     bne     compare         ; if not calculate difference
011f  c0        hlt                     ; done
                  compare:
0120  03 00 ff  lda     $ff00,x         ; load next number from array
0123  0a 02     sta     $02             ; -> to $01
0125  d0        sec                     ; calculate ...
0126  72 01     sbc     $01             ; ... difference ...
0128  0a 03     sta     $03             ; ... to $03
012a  c8        inx                     ; next index
012b  92 00     cpx     $00             ; length reached?
012d  f4 05     bne     checkrun        ; if not check whether we have a run
012f  b0 20     wch     #' '            ; output space
0131  a2 02     wud     $02             ; output number
0133  c0        hlt                     ; done
                  checkrun:
0134  02 02     lda     $02             ; calculate next ...
0136  6a 03     adc     $03             ; ... expected number in run
0138  8b 00 ff  cmp     $ff00,x         ; compare with real next number
013b  f6 06     beq     haverun         ; ok -> found a run
013d  b0 20     wch     #' '            ; otherwise output space ...
013f  a2 02     wud     $02             ; ... and number
0141  f4 ce     bne     runloop         ; and repeat searching for runs
                  haverun:
0143  0a 02     sta     $02             ; store number to $02
0145  c8        inx                     ; next index
0146  92 00     cpx     $00             ; length reached?
0148  f6 07     beq     outputrun       ; yes -> output this run
014a  6a 03     adc     $03             ; calculate next expected number
014c  8b 00 ff  cmp     $ff00,x         ; compare with real next number
014f  f6 f2     beq     haverun         ; ok -> continue parsing run
                  outputrun:
0151  b9 66 01  wtx     str_to          ; write "to"
0154  a2 02     wud     $02             ; write end number of run
0156  00 01     lda     #$01            ; compare #1 with ...
0158  8a 03     cmp     $03             ; ... step size
015a  f6 05     beq     skip_by         ; equal, then skip output of "by"
015c  b9 69 01  wtx     str_by          ; output "by"
015f  a2 03     wud     $03             ; output step size
                  skip_by:
0161  92 00     cpx     $00             ; length of array reached?
0163  f4 ac     bne     runloop         ; no -> repeat searching for runs
0165  c0        hlt                     ; done
                  str_to:
0166  74 6f 00                          ; "to"
                  str_by:
0169  62 79 00                          ; "by"
016c
Felix Palmen
źródło
1

05AB1E (starsza wersja) , 49 50 bajtów

.œʒε¥Ë}P}Σ€g2KO>}¤εD©g≠i¬s¤„toý¬®¥0èDU≠i„byX««]˜ðý

Zbyt długo, ale już się cieszę, że to działa. To wyzwanie jest o wiele trudniejsze, niż się wydaje. Można bez wątpienia dalej grać w golfa.
Σ€g2KO>}¤jest port 2,0ySƲÞṪ z odpowiedzi galaretki @JonathanAllan (dzięki!).

Wypróbuj online. (UWAGA: przekroczono limit czasu dla dużych przypadków testowych).

+1 bajt jako rozwiązanie błędu, ponieważ 0podczas sortowania zawsze znajduje się w pozycji końcowej.

Wyjaśnienie:

                       # Get all partions of the (implicit) input-list
                         #  i.e. [1,2,3,11,18,20,22,24,32,33,34]
                         #   → [[[1],[2],[3],[11],[18],[20],[22],[24],[32],[33],[34]],
                         #      [[1],[2],[3],[11],[18],[20],[22],[24],[32],[33,34]],
                         #      [[1],[2],[3],[11],[18],[20],[22],[24],[32,33],[34]],
                         #      ...]
  ʒ     }                # Filter this list by:
   ε  }                  #  Map the current sub-list by:
    ¥Ë                   #   Take the deltas, and check if all are equal
                         #    i.e. [1,2,3] → [1,1] → 1
                         #    i.e. [1,2,3,11] → [1,1,8] → 0
       P                 #  Check if all sub-list have equal deltas
  Σ      }               # Now that we've filtered the list, sort it by:
   g                    #  Take the length of each sub-list
                         #   i.e. [[1,2,3],[11,18],[20,22,24],[32,33],[34]]
                         #    → [3,2,3,2,1]
                         #   i.e. [[1,2,3],[11],[18,20,22,24],[32,33,34]]
                         #    → [3,1,4,3]
     2K                  #  Remove all 2s
                         #   i.e. [3,2,3,2,1] → ['3','3','1']
       O                 #  And take the sum
                         #   i.e. ['3','3','1'] → 7
                         #   i.e. [3,1,4,3] → 11
        >                #  And increase the sum by 1 (0 is always trailing when sorting)
          ¤              # And then take the last item of this sorted list
                         #  i.e. for input [1,2,3,11,18,20,22,24,32,33,34]
                         #   → [[1,2,3],[11],[18,20,22,24],[32,33,34]]
  ε                      # Now map each of the sub-lists to:
   D©                    #  Save the current sub-list in the register
     gi                 #  If its length is not 1:
                         #    i.e. [11] → 1 → 0 (falsey)
                         #    i.e. [18,20,22,24] → 4 → 1 (truthy)
        ¬s¤              #   Take the head and tail of the sub-list
                         #    i.e. [18,20,22,24] → 18 and 24
           toý          #   And join them with "to"
                         #    i.e. 18 and 24 → ['18to24', '18to20to22to24']
               ¬         #   (head to remove some access waste we no longer need)
                         #    i.e. ['18to24', '18to20to22to24'] → '18to24'
        ®                #   Get the sub-list from the register again
         ¥               #   Take its deltas
                         #    i.e. [18,20,22,24] → [2,2,2]
          0è             #   Get the first item (should all be the same delta)
                         #    i.e. [2,2,2] → 2
            DU           #   Save it in variable `X`
              i         #   If the delta is not 1:
                         #     i.e. 2 → 1 (truthy)
                byX«    #    Merge "by" with `X`
                         #     i.e. 2 → 'by2'
                     «   #    And merge it with the earlier "#to#"
                         #     i.e. '18to24' and 'by2' → '18to24by2'
                      ]  # Close the mapping and both if-statements
˜                        # Flatten the list
                         #  i.e. ['1to3',[11],'18to24by2','32to34']
                         #   → ['1to3',11,'18to24by2','32to34']
 ðý                      # And join by spaces (which we implicitly output as result)
                         #  i.e. ['1to3',11,'18to24by2','32to34']
                         #   → '1to3 11 18to24by2 32to34'
Kevin Cruijssen
źródło
0

Perl 5 , 154 bajtów

{my(@r,$r);@r&&(@$r<2||$$r[1]-$$r[0]==$_-$$r[-1])?push@$r,$_:push@r,$r=[$_]for@_;join" ",map@$_<3?@$_:("$$_[0]to$$_[-1]by".($$_[1]-$$_[0]))=~s/by1$//r,@r}

To samo dotyczy spacji, znaków nowej linii, #komentacji i sub by:

sub by {
  my(@r,$r);
  @r &&                               # if at least one run candidate exists and...
   ( @$r<2                            # ...just one elem so far
     || $$r[1]-$$r[0] == $_-$$r[-1] ) # ...or diff is same
    ? push @$r, $_                    # then add elem to curr. run candidate
    : push @r, $r=[$_]                # else start new run cand. with curr elem
        for @_;
  join " ",
    map @$_<3                                         # is it a run?
    ? @$_                                             # no, just output the numbers
    : ("$$_[0]to$$_[-1]by".($$_[1]-$$_[0]))=~s/by1$//r, # yes, make run, delete by1
    @r                                                # loop run candidates
}

Wypróbuj online!

... za zdanie testów z OP.

Kjetil S.
źródło
0

Retina 0.8.2 , 77 bajtów

\d+
$*
(1+)(?= \1(1+))
$1:$2
1:(1+) (1+:\1 )+(1+)
1to$3by$1
:1+|by1\b

1+
$.&

Wypróbuj online! Link zawiera przypadki testowe. Wyjaśnienie:

\d+
$*

Konwertuj na unary.

(1+)(?= \1(1+))
$1:$2

Oblicz kolejne różnice.

1:(1+) (1+:\1 )+(1+)
1to$3by$1

Konwertuj przebiegi do to...byskładni.

:1+|by1\b

Usuń nieprzekształcone różnice i by1.

1+
$.&

Konwertuj na dziesiętny.

Neil
źródło