隣接する複製を折りたたむ


22

チャレンジ

整数のリストを指定すると、隣接する等しいアイテムのすべてのペアを繰り返し削除した後、これらの整数のリストを返します。

同じ数の奇数長の実行がある場合、ペアの一部ではなく、そのうちの1つが残ることに注意してください。

例:

[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0]

まず、あなたは削除する必要があり0, 04, 4および1, 1取得するには:

[0, 1, 2, 2, 0]

今、あなたは削除する必要があります2, 2

[0, 1, 0]

これが最終結果です。

テストケース

[]-> []
[1]-> [1]
[1、1]-> []
[1、2]-> [1、2]
[11、11、11]-> [11]
[1、22、1]-> [1、22、1]
[-31、46、-31、46]-> [-31、46、-31、46]
[1、0、0、1]-> []
[5、3、10、10、5]-> [5、3、5]
[5、3、3、3、5]-> [5、3、5]
[0、-2、4、4、-2、0]-> []
[0、2、-14、-14、2、0、-1]-> [-1]
[0、0、0、1、2、4、4、2、1、1、0]-> [0、1、0]
[3、5、4、4、8、26、26、8、5]-> [3]
[-89、89、-87、-8、8、88]-> [-89、89、-87、-8、8、88]

得点

これはなので、各言語で最短の答えが勝ちです!


削除された投稿を見ることができる人のためのサンドボックス
-musicman523

関係ありません、それらはすべて平等です。このフレーズの意味は、次のように[14, 14, 14]崩壊することです[14]
musicman523

チャレンジを読み違えました、ごめんなさい。あなたは(1ずつ増加番号のすべてのペアを削除すると思っていた1,211,12など)
スティーブン・

入力を区切り文字列として取得できますか?
シャギー

2
次のようなテストケースを追加できます-89,89,-87,-8,-88か?私の(未投稿の)JaptソリューションとFryのRetinaソリューションの両方がそこで失敗し、出力し--87,8ます。
シャギー

回答:


5

ゼリー、10バイト

Œgœ^/€FµÐL

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

使い方

Œgœ^/€FµÐL  Main link. Argument: A (array)

       µ    Combine all links to the left into a chain.
Œg              Group all adjacent equal items.
    /€          Reduce each group by...
  œ^                symmetric multiset difference.
                In each step, this maps ([], n) to [n] and ([n], n) to [], so the
                group is left with a single item if its length is odd, and no items
                at all if its length if even.
      F         Flatten the resulting array of singleton and empty arrays.
        ÐL  Apply the chain until the results are no longer unique. Return the last
            unique result.

代わりに使用すると、Fリスト内のリストもサポートされます。
エリックアウトゴルファー

いいえ、œ^ここでは整数から配列への昇格に依存しています。1D配列は2D配列に昇格しないため、数値の配列以外では機能しません。
デニス

へえ...私はあなたがちょうど使用できたということですŒgWẎ$œ^/$€ẎµÐL...ああ、それはあまりにも素朴です。:P
エリック・ザ・アウトゴルファー

4

網膜17 15バイト

+m`^(.+)¶\1$¶?

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

NeilとMartinのおかげで2バイト節約されました!

数字の各ペアを何も置き換えません。このプロセスは、変更が行われないまでループします。


これを見つける前に、Japtで同じソリューションを作成しました。残念ながら、のような入力では失敗し-89 89 -87 -88 -88ます--87
シャギー

1
@Shaggyありがとう、_いくつかの言語で一般的であるように、境界チェックを追加し、ネガを示すために使用して修正しました。
FryAmTheEggman

それから、これも失敗して_89 89 _87 _8 _88出力することを発見しました_89 89 _87 8。すみません:\
シャギー

@Shaggyごめんなさい!問題を見つけてくれてありがとう!その場合を修正するために、別の境界チェックを追加しました。
FryAmTheEggman

1
@FryAmTheEggmanそれがニールの意味するものかどうかはわかりませんがm\bsを^and に変えるために使用することもできます$
マーティンエンダー

3

Mathematica 29バイト

これにより、a_,a_残りがなくなるまで、等しい隣接要素のペアが繰り返し削除されます。

#//.{b___,a_,a_,c___}:>{b,c}&

3

Python 2、57バイト

r=[]
for x in input():r+=x,;r[-2:]*=r[-2:-1]!=[x]
print r

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

次の要素を追加して出力リストを繰り返し構築し、追加する要素がその前の要素と等しい場合、末尾を切り取ります。r[-2:-1]!=[x]リストの長さが1のみである可能性があるため、最後から2番目の要素をチェックすると、扱いにくいことがわかります。


素晴らしい答え、よくやった:)
musicman523

2

ゼリー、15バイト

Œr;ṪḂ$$€x/€FµÐL

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

説明

Œr;ṪḂ$$€x/€FµÐL  Main Link
Œr               Run-length encode
  ;              Concatenate (?)
       €         For each element
   ṪḂ$$          Is the last element odd?
          €      For each element    // Non-breaking alternative
        x/       Reduce by repeating // for run-length decode
           F     Flatten
            µ    (New monadic link)
             ÐL  Repeat until results are no longer unique

マイルのおかげで-1バイト、修正済み:)


@FryAmTheEggman修正済み; ありがとう!
ハイパーニュートリノ

エラーをスローして出力を空のままにしておくのが正しい解決策かどうかはわかりません。ValueError: not enough values to unpack (expected 2, got 0)テストケースのスローをプログラムし[1,2,2,1]ます。また、空の出力が異なることに注意して下さい[]2は異なっています[2]

で13バイトŒr;ṪḂ$$€ŒṙµÐL。エラーを回避するには、交換するŒṙx/€F、空のリストが与えられたとき、ランレングスデコードがエラーを投げているからです。出力をリストとしてŒṘ表示するには、タッキングで表示します。
マイル

@ThePirateBay Jellyの空のリストの表現は、空、1つのアイテム、そのアイテムだけ、および複数のアイテム-括弧で囲まれたコンマ区切りのリストです。提出は、リンク(機能)ではない(ラムダはPythonでだろうくらいのような)完全なプログラムである-より多くの「普通の」ビューの場所を参照するためにÇŒṘ、最後のリンクを(呼び出すためのフッターにするÇ)とPython表現を印刷します(ŒṘ) 。ただし、エラーは受け入れられない場合があります。
ジョナサンアラン

@JonathanAllan。わかりました、リストのJellyの文字列表現が受け入れられることに気付きました。最初のコメントの要点は、リストが空になるとエラーがスローされることを言及することです。

2

JavaScript(ES6)、54 53バイト

@ThePirateBayのおかげで1バイト節約

f=a=>1/a.find(q=>q==a[++i],i=-2)?f(a,a.splice(i,2)):a

単純な再帰的ソリューションは、改善可能かもしれません。


あなたが交換できるようにあなたは、現在および以前の要素の代わりに、現在と次のいずれかを確認することができi=0i=-2i-1してi合計である-1バイト。

@ guest44851ありがとう、でも... ...に変更する必要があるということではないでしょうi+1か?(私も前にこれを動かしてみましたが、それを++理解することができませんでしたが、そうするのに約1分しかありませんでした)
ETHproductions

正常に動作することがわかります

@ThePirateBayゴーリーで、あなたは正しい!しかし、どのように?
ETHproductions

2

Python 2、73バイト

コメントするほどの評判がないので、@ officialaimmの答えを変更して、バイトを保存するためにlen(r)ではなくr!= []を使用するようにしました。@officialaimm、あなたにとって非常に賢い解決策です!

r=[]                            # create list that will hold final results. A new list is important because it needs to be removable.
for i in input():               
 if r!=[]and r[-1]==i:r.pop()   # Ensure that we have at least 1 char added to the list (r!=[])... or that the last character of our final result isn't the current character being scanned. If that is, well, remove it from the final list because we do not want it anymore
 else:r+=[i]                    # Shorthand for r.append(i). This adds i to the final result
print r

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

やはり遅すぎる…なぜ私はまだ起きているのか?



2

MATL、7バイト

t"Y'oY"

結果が空の一部のテストケースでは、プログラムはエラーで終了しますが、いずれの場合も正しい(空の)出力を生成します。

オンラインでお試しください!または、空でない出力でテストケースを確認します

説明

t     % Implicit input. Duplicate
"     % For each (i.e. do as many times as input size)
  Y'  %   Run-length encode. Gives array of values and array of run lengths
  o   %   Parity, element-wise. Reduces run-lengths to either 0 or 1
  Y"  %   Run-length decode. Gives array of values appearing 0 or 1 times;
      %   that is, removes pairs of consecutive values
      % Implicit end. Implicit display

入力を検討する

0 0 0 1 2 4 4 2 1 1 0

各反復により、連続するペアのペアが削除されます。最初の反復は配列を

0 1 2 2 0

2現在隣接している2つの値は、初期配列では隣接していませんでした。そのため、2回目の反復が必要になります。

0 1 0

さらに繰り返しても、これは変更されません。必要な反復回数は、入力サイズの上限です。

中間結果が空の場合、ランレングスデコード関数(Y")は現在のバージョンの言語でエラーになります。ただし、必要に応じて出力は空です。


説明を追加してもらえますか?あなたがどうやって私をとても強く打ち負かしたのかを理解したい。:P
デニス

@Dennis確かに!私は忘れていました。完了:-)
ルイスメンドー

1
ああ、RLEは2つの配列をプッシュします。それは便利です。
デニス

2

x86マシンコード(32ビット保護モード)、36バイト

52
8B 12
8D 44 91 FC
8B F9
8D 71 04
3B F0
77 10
A7
75 F9
83 EF 04
4A
4A
A5
3B F8
75 FB
97
EB E7
58
89 10
C3

上記のマシンコードのバイトは、配列を入力として受け取り、隣接する重複をインプレースで折りたたみ、結果を返さずに呼び出し元に戻る関数を定義します。これは__fastcall呼び出し規約に従い、2つのパラメーターをそれぞれECXEDXレジスタに渡します。

最初のパラメーター(ECX)は、32ビット整数の配列の最初の要素へのポインターです(配列が空の場合、メモリ内の任意の場所を指すことができます)。2番目のパラメーター(EDX)は、配列の長さを含む32ビット整数へのポインターです。

この関数は、必要に応じて配列の要素をインプレースで変更し、折りたたみ配列の新しい長さを示すために長さも更新します。これは、入力を受け取って出力を返すためのちょっと変わった方法ですが、実際にはアセンブリ言語で他の選択肢はありません。Cと同様に、配列は実際には言語で最初の要素へのポインターとlengthとして表されます。ここで少し奇妙なのは、参照によってを取得することですが、そうしなかった場合、配列を短くする方法はありません。コードは正常に機能しますが、折りたたまれた配列の要素の出力をどこで停止するかを呼び出し側が知らないため、出力にはゴミが含まれます。

非ゴルフアセンブリニーモニック:

; void __fastcall CollapseAdjacentDuplicates(int * ptrArray, int * ptrLength);
; ECX = ptrArray              ; ECX = fixed ptr to first element
; EDX = ptrLength
   push  edx                  ; save pointer to the length
   mov   edx, [edx]           ; EDX = actual length of the array
   lea   eax, [ecx+edx*4-4]   ; EAX = fixed ptr to last element 

FindAdjacentPairs:
   mov   edi, ecx             ; EDI = ptr to element A
   lea   esi, [ecx+4]         ; ESI = ptr to element B
FindNext:
   cmp   esi, eax             ; is ptr to element B at end?
   ja    Finished             ; if we've reached the end, we're finished
   cmpsd                      ; compare DWORDs at ESI and EDI, set flags, and increment both by 4
   jne   FindNext             ; keep looping if this is not a pair

; Found an adjacent pair, so remove it from the array.
   sub   edi, 4               ; undo increment of EDI so it points at element A
   dec   edx                  ; decrease length of the array by 2
   dec   edx                  ;  (two 1-byte DECs are shorter than one 3-byte SUB)
RemoveAdjacentPair:
   movsd                      ; move DWORD at ESI to EDI, and increment both by 4
   cmp   edi, eax             ; have we reached the end?
   jne   RemoveAdjacentPair   ; keep going until we've reached the end
   xchg  eax, edi             ; set new end by updating fixed ptr to last element
   jmp   FindAdjacentPairs    ; restart search for adjacent pairs from beginning

Finished:
   pop   eax                  ; retrieve pointer to the length
   mov   [eax], edx           ; update length for caller
   ret

実装はC ++ 11の回答に触発されましたが、アセンブリを細かく書き直し、サイズを最適化しました。アセンブリは、はるかに優れたゴルフ言語です。:-)

注:このコードは、文字列命令を使用しているため、ある方向フラグが(明らかであると仮定DF== 0)。ABIは通常DFが明確であることを要求するため、これはほとんどのオペレーティング環境で合理的な仮定です。これを保証できない場合は、コードの先頭に1バイトのCLD命令(0xFC)を挿入する必要があります。

また、前述のように、32ビット保護モード、具体的には、余分なセグメント(ES)がデータセグメント(DS)と同じ「フラット」メモリモデルを想定しています。


1

バッチ、133バイト

@set s=.
:l
@if "%1"=="%2" (shift/1)else set s=%s% %1
@shift/1
@if not "%1"=="" goto l
@if not "%s:~2%"=="%*" %0%s:~1%
@echo(%*

.重複している場合にBatchが混乱するため、sを設定します。また、引数リストを新しい配列とループに設定するshift/1ために使用できるようにする必要%0%s:~1%があります。


私は尋ねなければなりません...なぜですか?良い答え...しかし、なぜですか?
ザカリー

@Zacharýそこにあるから。
ニール

1
@Zacharý一部、非ゴルフ言語でゴルフをする正当な理由は、これが実際に役立つかもしれないからです。これを行うために実際にJellyインタープリターを起動する人はいませんが、バッチファイルで実行する必要があるかもしれません。
コーディグレー

ああ。それは理にかなっている。
ザカリー

1

ゼリー、12 バイト

ŒgṁLḂ$$€ẎµÐL

数字のリストを取得および返すモナドリンク。

オンラインでお試しください!またはテストスイートを見る

どうやって?

ŒgṁLḂ$$€ẎµÐL - Link: list
         µÐL - perform the chain to the left until no changes occur:
Œg           -   group runs (yield a list of lists of non-zero-length equal runs)
      $€     -   last two links as a monad for €ach run:
     $       -     last two links as a monad:
   L         -       length (of the run)
    Ḃ        -       modulo 2 (1 if odd, 0 if even)
  ṁ          -     mould (the run) like (1 or 0) (yields a list of length 1 or 0 lists)
        Ẏ    -   tighten (make the list of lists into a single list)

ṁLḂ$$€同等であるḣLḂ$$€ことと等価であるṫḊ¿€3$あなたと交換することができたṫḊ¿€3ダイアド/ nilad対を形成するためにここに。
エリックアウトゴルファー

これは、たとえば、長さが4の実行では機能しません。whileループの各反復でのデキューへの入力は何ですか?
ジョナサンアラン

0または1要素のリストが残っているはずです。len(x)== 1の場合は戻ります[]が、len(x)== 0の場合は戻りますが0、どちらも偽の値です。もちろん、への入力は現在の値であり、左の引数と3右の引数として現在の値を持ちます。len(x)== 4の場合、それはと同じṫ3ṫ3か、そのṫ5ままになります[]
エリックアウトゴルファー

私はそれが何をすべきかを見ることができますがx、あなたの説明には本当に現在の価値がありますか?試してみてください、このサイズのためにアウト。
ジョナサンアラン

正直に言うと、それがコードなのかバグなのかはわかりません:)
ジョナサンアラン


1

05AB1E、15バイト

[γʒgÉ}€нÐγ‚€gË#

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

説明

[γʒgÉ}€нÐγ‚€gË#
[               # Start infinite loop
 γ              # Group Array into consecutive equal elements
  ʒgÉ}          # Keep the subarrays with an uneven amount of elements
      €н        # Keep only the first element of each subarray
        Ð       # Triplicate the result on the stack
         γ      # Group the top element into consecutive equal elements
          ‚     # Wrap the top two items of the stack in an array
           €g   # Get the length of each subarray
             Ë# # Break if they are equal
                # Implicit print          



1

パイソン274の70 66バイト

  • 4バイトの@SteamyRootに感謝します。r代わりlen(r)に、リスト/スタックの空をチェックするのに十分です。
  • 4バイトの@ovsに感謝:条件が良い場合 [i]==r[-1:]

Python 2、66バイト

r=[]
for i in input():
 if[i]==r[-1:]:r.pop()
 else:r+=[i]
print r

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


1
の目的がlen(r)リストが空かどうかを確認することだけrである場合、ちょうどに置き換えることができるはずです、と思いますか?
SteamyRoot

そうそう、ありがとう。
officialaimm


@ovsどうもありがとう、それは素晴らしい!(y)
officialaimm

1
代替の66バイト長バージョンですが、必要なのは3行だけです。
ジョナサンフレッチ

0

Clojure、100バイト

#(loop[i % j[]](if(= i j)i(recur(mapcat(fn[p](repeat(mod(count p)2)(last p)))(partition-by + i))i)))

これが最短かどうかはわかりません。


0

Bash、82バイト

cat>b
while cat b>a
perl -pe 's/(\d+) \1( |$)//g' a>b
! diff a b>c
do :
done
cat a

おそらくそれらすべてから抜け出す方法はありますcatが、私は知りません。




0

V、10バイト

òͨ.«©î±î*

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

圧縮正規表現::%s/\(.\+\)\n\1\n*。オプションの改行は、ファイルの最後でも機能するようになっています。終了後に改行があると仮定すると、8バイトになります...しかし、それはストレッチのようです


0

dc84 78バイト

[L.ly1-dsy0<A]sA[LtLtS.ly1+sy]sP[dStrdStr!=Pz1<O]sO[0syzdsz1<Oly0<Azlz>M]dsMxf

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

わかりやすくするためにいくつかの試みで、少し順番をずらして展開します。

  • [0syzdsz1<Olydsx0<Alx1+lz>M]dsMxfメインマクロはMカウンターyを0にリセットし、スタック上のアイテムの数を取得し、これをregister zに保存Oし、スタック上に少なくとも2つのアイテムがある場合にマクロを実行します。いったんO終了し、それがカウンタにロードyし、レジスタにコピーし、それをx確認するためにチェックする前に、yゼロ以外は(意味スタックがある.データを持っています)。この場合、macroが実行されAます。最後に、元のスタックサイズが現在のスタックサイズよりも大きいかどうかを確認し、大きい場合は自分自身を再実行します。終了すると、でスタックを印刷しますf
  • [dStrdStr!=Pz1<O]sOマクロOは、スタックの上の2つのアイテムを一時的にstackに保存しますt。次に、上位2つのアイテムを比較し、P等しくない場合はマクロを実行します。最後に、スタック上に少なくとも2つの項目があるかどうかを確認し、ある場合はそれ自体を実行します。
  • [LtLtS.ly1+sy]sPマクロPはスタックから2つのアイテムをt取得し、一番上のアイテムをメインスタックにプッシュし、次のアイテムをスタックにプッシュします.。次に、counterをインクリメントしますy
  • [L.ly1-dsy0<A]sAマクロAはスタック.を取得し、それをプライマリスタックに戻します。yプッシュするものがなくなるまでカウンターをデクリメントします。

説明のために編集し、私は不必要にスタックのサイズを保存していたので、6バイトをオフにゴルフしました。


0

C ++ 11、161バイト

#include<vector>
#include<algorithm>
using V=std::vector<int>;void f(V&v){V::iterator i;while((i=std::adjacent_find(v.begin(),v.end()))!=v.end())v.erase(i,i+2);}

上記のコードは、参照fを取りstd::vector<int>、仕様に従って隣接する重複を折りたたむように修正する関数を定義します。

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

バイトカウントを確認する前に、これはかなりスマートなコードだと思いました。ただし、150バイト以上はあまり良くありません!私はゴルフがあまり得意ではないか、C ++がゴルフのあまり上手ではありません…

ゴルフをしていない:

#include <vector>
#include <algorithm>

using V = std::vector<int>;

void f(V& v)
{
   V::iterator i;

   // Use std::adjacent_find to search the entire vector for adjacent duplicate elements.
   // If an adjacent pair is found, this returns an iterator to the first element of the
   // pair so that we can erase it. Otherwise, it returns v.end(), and we stop.
   while ((i=std::adjacent_find(v.begin(), v.end())) != v.end())
   {
        v.erase(i, i+2);   // erase this adjacent pair
   }
}

C ++は最高のゴルフ言語ではありません。の素敵な使用std::adjacent_find!あなたが削除することができますので、それは、短くなる場合あなたがこの機能を自分で実装した場合、私は疑問#include <algorithm>にも
musicman523

@ musicman523最初の試み手作業で実装しましたが、少し異なるアルゴリズムを使用しました。私はstd::unique必要なことを行うためにの実装を適応させていました。しかし、すべてのロジックを実行するには多くのコードが必要であり、偶然見つけたときstd::adjacent_find、それがコードサイズの面で勝者であることは明らかでした。
コーディグレー

0

PHP、74バイト

function c(&$a){foreach($a as$k=>$v)$a[$k+1]===$v&&array_splice($a,$k,2);}

関数cは、配列を減らすために参照によって呼び出します。オンラインでお試しください

興味深いことに、これはPhp5.6で機能しますが、7では機能しません。





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