リストをすばやく再グループ化する


17

グループ化はリストを取り、それを等しい隣接要素の新しいリストに分割します。例えば

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

これらのグループの長さを取得すると、整数の新しいリストが取得されます

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

あなたの仕事は、正の整数のリストを受け取るプログラムを作成し、結果のリストに単一の要素が含まれる前にグループ化および長さ化できる回数を見つけることです。たとえば、リスト[1,2,3,3,2,1]を4回再グループ化できます

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

これはため、回答はバイト単位でスコアリングされ、バイト数は少ない方が良いでしょう。

テストケース

[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

3
これは基本的に、値を保存しないランレングスエンコーディングです。
12Me21

[1]有効な入力であり0、正しいものを与える必要がありますか?
ETHproductions

@ETHproductionsはい、少し難しいケースだから追加します。
小麦ウィザード

回答:




3

Japt、12バイト

ÊÉ©1+ßUò¦ ml

オンラインでテストしてください!

説明

 Ê É © 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.

再帰はJaptにとって実際には型破りなアプローチですが、次の選択肢よりも4バイト短いようです...


@Shaggyの私の16バイトバージョンF.a()は、改訂履歴から引き続きアクセスできます。あなたの14-byterを見たいです!
ETHproductions


2

C(gcc)、108バイト

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;}

オンラインでお試しください!

説明

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

オンラインでお試しください!


2

JavaScript(ES6)、67 65 63バイト

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

奇妙なことに、JavaScriptとJaptは同じ最短のアルゴリズムを一度しか持っていないようです...


2

K(oK)20 19バイト

解決:

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

オンラインでお試しください!

例:

#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

説明:

これは非常に簡単ですが、さらに良いアプローチがあるかどうか疑問に思っています...入力が異なるインデックスを見つけ、それらのインデックスで分割し、各サブリストの長さを数えます。結果が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

ノート:

次の14バイトのソリューションは、単一アイテムのリストを除くすべてに対して機能します。

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

オンラインでお試しください!


2

J25 23バイト

ストリートスターのおかげで1バイト節約

FrownyFrogのおかげで1バイト節約

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

オンラインでお試しください!

初期ソリューション:

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

オンラインでお試しください!

説明

      (               )^: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

1
_2+バイトを保存するのではなく、「2つドロップ」してから「カウント」することはできますか?
ストリートスター

1
#;.1@(0,2=/\])1バイト節約できると思います。
FrownyFrog

@ FrownyFrogはい、そうです。ありがとうございました!
ガレンイワノフ

@streetsterはい、バイトを節約するのに役立ちます。ありがとうございました!
ガレンイワノフ

2

スタックス、9 バイト

ÆÑfá╒]`*Ä

オンラインで実行してデバッグする

同じプログラムのASCII表現はこれです。

{D}{|RMHgf%

これは、変換ブロックとフィルターブロックに従って値を生成するジェネレーターと呼ばれるスタック機能を使用します。

{ }            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

2

Python 2、84バイト

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

オンラインでお試しください!

どうやって?

f、その入力場合、再帰関数でありa、長さが2以上(有するlen(a)>1)戻り1+f(x)* xのグループの長さであるがa。一方、入力が長さ1または0のFalse場合(Pythonでは0に等しい)-これはand、左側が偽の場合に右側が評価されないためです。

* -~f(x)である-(-1 - f(x))が、当接することが可能andと違っ1+f(x)たりしますf(x)+1

グループの長さは、コードを作成することで計算され、次にコードで評価されeval(...)ます。作成されるコードは、のような1,1,1+1+1,1,1+1,1,タプルに評価されるようなもの(1,1,3,1,2,1)です。

コードを介してzip圧縮することによって作成されるaa(その頭なしで...for x, y in zip(a,a[1:])作るxyにおける隣接する対の各a対が等しい場合x==yに評価True(1)そうでなければFalse(0) -この結果は文字列へのインデックスに使用され,++、および,各それぞれと得られた文字が先行する1'1'+...) -全部は、その後、最終的なトレーリングしている1,。添付たとえばa[5,5,2,9,9,9]、次いでx,y対がされる(5,5)(5,2)(2,9)(9,9)(9,9)等式を作る10011次に文字があろう+,,++先行有するいる、1となるS 1+1,1,1+1+および最終後続1,作成1+1,1,1+1+1,(2,1,3)必要に応じて評価します。

末尾,は、単一のグループを持つ入力が整数ではなくタプルとして評価されることを保証することに注意してください(つまり[3,3]-> 1+1,-> (2)ではなく[3,3]-> 1+1-> 2





1

、8バイト

@Zgarbのおかげで-1バイト!

←Vε¡(mLg

オンラインでお試しください!

説明

←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

1
←Vεシングルトンリストのインデックスを見つけるための短いチェックです。
ズガルブ





1

SmileBASIC、110の 108バイト

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

関数を呼び出すR list,0; 出力はコンソールに出力されます。




0

Retina 0.8.2、31バイト

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

オンラインでお試しください!リンクにはテストケースが含まれます。説明:

,.*
$&_

コンマがある場合は、別の反復を行うため、カウント文字を追加します。

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

各ランをそのデクリメントされた長さに置き換えます。上記の段階は、カンマがなくなるまで繰り返されます。

_

反復回数をカウントします。


0

Perl 6、52バイト

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

試して

拡張:

{  # 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)
  )
}



0

Kotlin、123バイト

受け入れ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}

より読みやすい:

{ 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
}

オンラインでお試しください!


131バイト、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バイト、TIO

の39が含まれてい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}

0

、140バイト

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]

オンラインでお試しください!

RedのParse方言をもう一度試してみたかっただけです。

非ゴルフ

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
]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.