Szybko przegrupuj listy

17

Grupowanie pobiera listę i dzieli ją na nowe listy równych sąsiadujących elementów. Na przykład

[1,1,2,1,1] -> [[1,1],[2],[1,1]]

Jeśli następnie weźmiesz długość tych grup, otrzymasz nową listę liczb całkowitych

[1,1,2,1,1] -> [2,1,2]

Twoim zadaniem jest napisanie programu, który pobierze listę dodatnich liczb całkowitych i znajdzie liczbę razy, którą możesz pogrupować i długość, zanim wynikowa lista będzie miała jeden element. Na przykład listę [1,2,3,3,2,1]można przegrupować 4 razy

[1,2,3,3,2,1]
[1,1,2,1,1]
[2,1,2]
[1,1,1]
[3]

To jest więc odpowiedzi będą liczone w bajtach, przy czym mniej bajtów będzie lepszych.

Przypadki testowe

[1,2,3,3,2,1] -> 4
[1,2,3,4,5,6,7] -> 2
[1,1,1,1,1,1] -> 1
[2] -> 0
[1,2,4] -> 2
[1,2,2,1,1,2] -> 4
[1,2,2,1,1,2,1,2,2] -> 5
[1] -> 0
Post Rock Garf Hunter
źródło
3
Zasadniczo jest to kodowanie przebiegające bez przechowywania wartości.
12Me21
[1]jest prawidłowym danymi wejściowymi i powinien dać 0, prawda?
ETHprodukcje
@ETHproductions Tak, dodam to, ponieważ jest to trochę trudny przypadek.
Post Rock Garf Hunter

Odpowiedzi:

3

Japt , 12 bajtów

ÊÉ©1+ßUò¦ ml

Przetestuj online!

Wyjaśnienie

 Ê É © 1+ßUò¦  ml
Ul -1&&1+ßUò!= ml    Ungolfed
                     Implicit: U = input array
Ul -1                Take U.length - 1.
     &&              If this is non-zero:
          Uò!=         Split U between non-equal elements.
               ml      Take the length of each run of equal elements.
         ß             Run the entire program again on the resulting array.
       1+              Add one to the return value.

Rekurencja jest naprawdę niekonwencjonalnym podejściem dla Japt, ale wydaje się być o 4 bajty krótsza niż kolejna alternatywa ...

ETHprodukcje
źródło
@Shaggy Moja 16-bajtowa wersja z F.a()jest nadal dostępna w historii zmian. Chciałbym zobaczyć twój 14-bajter!
ETHprodukcje
3

Brachylog , 12 bajtów

;.{ḅlᵐ}ⁱ⁾l1∧

Wypróbuj online!

Wyjaśnienie

;.{   }ⁱ⁾        Iterate Output times the following predicate on the input:
   ḅ               Group consecutive equal elements together
    lᵐ             Map length
         l1∧     The result of this iteration must have length 1
Fatalizować
źródło
2

C (gcc) , 108 bajtów

j,k,n;f(A,l)int*A;{for(j=k=n=0;j<l;j++)if(n++,A[j]-A[k])A[k++]=--n,A[k]=A[j],n=1;A=l>1?-~f(A,k,A[k++]=n):0;}

Wypróbuj online!

Wyjaśnienie

j,k,n;                // array pos, group pos, group val
f(A,l)int*A;{         // function takes array and length
 for(j=k=n=0;j<l;j++) // initialize, loop through array
  if(n++,             // increase n (*), check if group ended
  A[j]-A[k])          // group ended
   A[k++]=--n,        // advance group pos, decrease n, counteracting (*)
   A[k]=A[j],         // store new group type
   n=1;               // group is at least one long
 A=l>1?               // check if array length is larger than one
  -~f(A,k,A[k++]=n)   // fix last group length, enter recursion
  :0;}                // array length is less than two, return zero

Wypróbuj online!

Jonathan Frech
źródło
2

JavaScript (ES6), 67 65 63 bajtów

f=a=>a[1]?1+f(q=j=i=[],a.map(x=>x^a[++i]?j=!q.push(++j):++j)):0

Co dziwne, JavaScript i Japt wydają się mieć ten sam najkrótszy algorytm raz ...

ETHprodukcje
źródło
2

K (oK) , 20 19 bajtów

Rozwiązanie:

#2_{#:'(&~~':x)_x}\

Wypróbuj online!

Przykłady:

#2_{#:'(&~~':x)_x}\1 2 3 3 2 1
4
#2_{#:'(&~~':x)_x}\1 2 3 4 5 6 7
2
#2_{#:'(&~~':x)_x}\1 1 1 1 1 1
1
#2_{#:'(&~~':x)_x}\1#2
0
#2_{#:'(&~~':x)_x}\1 2 4
2

Wyjaśnienie:

Ten jest dość prosty, zastanawiam się, czy jest jeszcze lepsze podejście ... Znajdź wskaźniki, w których dane wejściowe różnią się, podziel na te wskaźniki, a następnie policz długość każdej podlisty. Iteruj, aż wyniki zbiegną się do 1.

#2_{#:'(&~~':x)_x}\ / the solution
   {             }\ / scan over lambda until results converge
                x   / implicit input
               _    / cut at indices
       (      )     / do this together
         ~~':x      / differ... not (~) match (~) each-previous (':) x)
        &           / indices where true
    #:'             / count (#:) each (')
 2_                 / drop first two results
#                   / count result

Uwagi:

Następujące 14-bajtowe rozwiązanie działa dla wszystkich oprócz listy pojedynczych elementów:

#1_(-':&~~':)\

Wypróbuj online!

streetster
źródło
2

J , 25 23 bajtów

1 bajt zapisany dzięki Streetster

1 bajt zapisany dzięki FrownyFrog

2#@}.#;.1@(0,2=/\])^:a:

Wypróbuj online!

Wstępne rozwiązanie:

_2+[:#(#;.1~1,2~:/\])^:a:

Wypróbuj online!

Wyjaśnienie

      (               )^:a: - repeat until result stops changing, store each iteration
        ;.1~                - cut the input (args swapped)              
            1,2~:/\]      - where the items are no longer the same
       #                    - and take the length of the sublists
 2+[:#                      - finally subtract 2 from the number of steps
Galen Iwanow
źródło
1
Czy potrafisz „upuścić dwa”, a następnie „policzyć”, a nie _2+zapisać bajt?
streetster
1
Myślę, że #;.1@(0,2=/\])oszczędza 1 bajt.
FrownyFrog
@ FrownyFrog Tak, robi. Dziękuję Ci!
Galen Iwanow
@streetster Tak, pomaga zaoszczędzić bajt. Dziękuję Ci!
Galen Iwanow
2

Stax , 9 bajtów

ÆÑfá╒]`*Ä

Uruchom i debuguj online

Jest to reprezentacja ascii tego samego programu.

{D}{|RMHgf%

Wykorzystuje to funkcję stax zwaną generatorem, który wytwarza wartość zgodnie z blokami transformacji i filtrów.

{ }            the filter for the generator
 D             tail of array; this is truthy for length >= 2
   {    gf     generator block - termination condition is when the filter fails
    |R         run-length encode into pairs [element, count]
      M        transpose matrix
       H       last element
          %    length of final generated array
rekurencyjny
źródło
2

Python 2 , 84 bajtów

f=lambda a:len(a)>1and-~f(eval(''.join('1'+',+'[x==y]for x,y in zip(a,a[1:]))+'1,'))

Wypróbuj online!

W jaki sposób?

fjest funkcją rekurencyjną, która, jeśli na wejściu, ama długość 2 lub więcej ( len(a)>1) zwraca 1+f(x)* gdzie xjest długość grupy a; podczas gdy jeśli jego wejście ma długość 1 lub 0 zwraca False(równa 0 w Pythonie) - dzieje się tak, ponieważ prawa strona plikuand dzieje się tak, nie jest oceniana, gdy lewą jest falsey.

* -~f(x)jest, -(-1 - f(x))ale może stykać się w andprzeciwieństwie do 1+f(x)lubf(x)+1 )

Długości grup są obliczane przez utworzenie kodu, który jest następnie oceniany za pomocą eval(...). Utworzony kod jest czymś podobnym 1,1,1+1+1,1,1+1,1,do krotki (1,1,3,1,2,1).

Kod jest tworzony przez spakowanie ai abez jego nagłówka ( ...for x, y in zip(a,a[1:])tworzenie xi ykażda z sąsiednich par w a. Jeśli pary są równe, x==yocenia się na True(1) w przeciwnym razie False(0) - ten wynik jest używany do indeksowania ,+ uzyskując ciąg +i ,odpowiednio i dla każdej z nich wynikowy znak jest poprzedzony znakiem 1( '1'+...) - do całości 1,dołącza się końcowy, końcowy znak końcowy . Na przykład, gdyby abyły, [5,5,2,9,9,9]wówczas x,ypary byłyby (5,5)(5,2)(2,9)(9,9)(9,9)równe, 10011to znaki byłyby +,,++, które z poprzedzającymi 1s staje 1+1,1,1+1+i końcowy znak końcowy,1, wyrób1+1,1,1+1+1,który ocenia (2,1,3)zgodnie z wymaganiami.

Zauważ, że trailing ,zapewnia, że ​​dane wejściowe z pojedynczą grupą są oceniane jako krotka, a nie liczba całkowita (tj. [3,3]-> 1+1,-> (2)zamiast [3,3]-> 1+1-> 2)

Jonathan Allan
źródło
1

Perl 5 , 53 50 49 45 bajtów

Obejmuje +3 dla-p

Podaj listę liczb jako jedną linię na STDIN

#!/usr/bin/perl -p
s%%$\+=1<s:\d+:$.++x($'-$&and$.=1):eg%eg}{

Wypróbuj online!

Ton Hospel
źródło
1

Łuska , 8 bajtów

-1 bajt dzięki @Zgarb!

←Vε¡(mLg

Wypróbuj online!

Wyjaśnienie

←Vε¡(mLg)  -- example input: [1,2,3,3,2,1]
   ¡(   )  -- repeatedly apply the function & collect results
    (  g)  -- | group: [[1],[2],[3,3],[2],[1]]
    (mL )  -- | map length: [1,1,2,1,1]
           -- : [[1,2,3,3,2,1],[1,1,2,1,1],[2,1,2],[1,1,1],[3],[1],[1],...
 V         -- index where
  ε        -- | length is <= 1: [0,0,0,0,1,1...
           -- : 5
←          -- decrement: 4
ბიმო
źródło
1
←Vεjest krótszym sprawdzeniem znalezienia indeksu listy singletonów.
Zgarb
1

Galaretka , 10 bajtów

ŒgL€$ḊпL’

Wypróbuj online!

Dennis
źródło
To się nie udaje[1] . Powinieneś być w stanie to naprawić za pomocą dwóch dequeues / pop zamiast_2
Mr. Xcoder
ÐĿnie był to dobry wybór ... Zastąpiłem go pętlą while.
Dennis
1

05AB1E , 9 bajtów

[Dg#γ€g]N

Wypróbuj online!

Wyjaśnienie

[Dg#   ]     # loop until the length of the current value is 1
    γ        # split into groups of consecutive equal elements
     €g      # get length of each
        N    # push the iteration variable N
Emigna
źródło
1

Wolfram Language (Mathematica) , 32 bajty

Zaoszczędzono 2 bajty dzięki Martinowi Enderowi. Korzystanie z kodowania CP-1252, gdzie ±jest jeden bajt.

±{_}=0;±x_:=1+±(Length/@Split@x)

Wypróbuj online!

alephalpha
źródło
1
Zdefiniowanie operatora pozwala zaoszczędzić dwa bajty: ±{_}=0;±x_:=1+±(Length/@Split@x)(przy założeniu WindowsANSIkodowania)
Martin Ender
1

Rubinowy , 54 56 55 54 bajtów

g=->l,d=0{l[1]?g[l.chunk(&:i).map{|i,j|j.size},d+1]:d}

Wypróbuj online!

Asone Tuhid
źródło
1

SmileBASIC, 110 108 bajtów

DEF R L,J
K=LEN(L)FOR I=1TO K
N=POP(L)IF O-N THEN UNSHIFT L,0
INC L[0]O=N
NEXT
IF I<3THEN?J ELSE R L,J+1
END

Funkcja wywołania jako R list,0; dane wyjściowe są drukowane na konsoli.

12Me21
źródło
0

Python 2 , 85 bajtów

from itertools import*
f=lambda a:~-len(a)and-~f([len(list(v))for k,v in groupby(a)])

Wypróbuj online!

Lynn
źródło
0

R , 51 45 bajtów

f=function(a)"if"(sum(a|1)>1,f(rle(a)$l)+1,0)

Wypróbuj online!

Rekurencyjnie bierz długość kodowania długości przebiegu i zwiększaj licznik.

Giuseppe
źródło
0

Retina 0.8.2 , 31 bajtów

,.*
$&_
}`(\b\d+)(,\1)*\b
$#2
_

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

,.*
$&_

Jeśli występuje przecinek, wykonamy kolejną iterację, więc dołącz znak licznika.

}`(\b\d+)(,\1)*\b
$#2

Zastąp każdy bieg jego zmniejszoną długością. Powyższe etapy powtarzają się, dopóki nie pozostaną przecinki.

_

Policz liczbę iteracji.

Neil
źródło
0

Perl 6 , 52 bajtów

{+($_,*.comb(/(\d+)[" "$0»]*/).map(+*.words)...^1)}

Sprawdź to

Rozszerzony:

{  # bare block lambda with implicit parameter 「$_」

  + (              # turn the following into a Numeric (get the count)


      $_,          # seed the sequence with the input

      *.comb(      # turn into a string, and grab things that match:

        /          # regex
          ( \d+ )  # a run of digits (number)
          [
            " "    # a space
                   # (gets inserted between elements of list when stringified)

            $0     # another instance of that number
            »      # make sure it isn't in the middle of a number

          ]*       # get as many as possible
        /
      ).map(
        +*.words  # turn each into a count of numbers
      )

      ...^        # keep doing that until (and throw away last value)

      1           # it gives a value that smart-matches with 1
                  # (single element list)
  )
}
Brad Gilbert b2gills
źródło
0

Kotlin , 123 bajty

Akceptuje List<Int>.

{var a=it;var b=0;while(a.size>1){var c=a[0];var d=0;with(a){a=listOf();forEach{if(it!=c){a+=d;d=0};d++;c=it};a+=d};b++};b}

Bardziej czytelny:

{ l ->
    var input = l
    var result = 0
    while (input.size > 1) {
        var last = input[0]
        var runSize = 0
        with(input) {
            input = listOf()
            forEach { current ->
                if (current != last) {
                    input += runSize
                    runSize = 0
                }
                runSize++
                last = current
            }
            input += runSize
        }
        result++
    }
    result
}

Wypróbuj online!


131 bajtów, TIO

{l->var a=l;var b=0;while(a.size>1){var c=a[0];var d=0;a.let{a=arrayListOf();for(e in it){if(e!=c){a+=d;d=0};d++;c=e};a+=d};b++};b}

181 bajtów, TIO

Obejmuje 39 dla import kotlin.coroutines.experimental.*.

{l->var a=l;var b=0;while(a.size>1){var c=a[0];var d=0;a=buildSequence{for(e in a){if(e!=c){yield(d);d=0;};d++;c=e};yield(d)}.toList();b++};b}
Moira
źródło
0

Czerwony , 140 bajtów

func[b][n: 0 while[(length? b)> 1][l: copy[]parse split form b" "[any[copy s[set t string! thru any t](append l length? s)]]b: l n: n + 1]n]

Wypróbuj online!

Chciałem tylko dać dialekt Red's Parse jeszcze jedną próbę.

Bez golfa

f: func [b] [
    n: 0
    while [(length? b) > 1][
        l: copy []
        parse split form b " " [
            any [copy s [set t string! thru any t]
                (append l length? s)]
        ]
        b: l
        n: n + 1
    ]
    n
]
Galen Iwanow
źródło