一意に削除可能なサブシーケンス


25

前書き

整数のシーケンスとそのサブシーケンスの1つ、たとえばA = [4 2 2 4 4 6 5]およびB = [2 4 5]を考えます。AからBの要素を順番に削除したいのですが、いくつかの方法があります。

A = 4 2 2 4 4 6 5
B =   2   4     5
 -> 4   2   4 6

A = 4 2 2 4 4 6 5
B =     2 4     5
 -> 4 2     4 6

A = 4 2 2 4 4 6 5
B =   2     4   5
 -> 4   2 4   6

A = 4 2 2 4 4 6 5
B =     2   4   5
 -> 4 2   4   6

すべての場合において、残りのシーケンスは同じ[4 2 4 6]です。これが発生した場合、BA から一意に削除可能である と言います。

タスク

入力は、非負整数の2つのシーケンスABです。ここで、BAのサブシーケンスであることが保証されています。入力は等しくても、空でもかまいません。必要な順序で、適切な形式でそれらを使用できます。

BAから一意に削除可能な場合、出力は真の値になり、そうでない場合は偽の値になります。

ルールとスコアリング

完全なプログラムまたは関数を作成できます。最も低いバイトカウントが優先されます。

テストケース

[] [] -> True
[0,3] [] -> True
[1,0,1] [1] -> False
[0,2] [0,2] -> True
[2,2,1,1,2,2,2] [2,1] -> True
[4,2,2,4,4,6,5] [4,5] -> False
[10,5,10,10,5,10] [10,5,10] -> False
[4,2,2,4,4,6,5] [2,4,5] -> True
[1,1,1,0,0,0,1,1,1,0] [1,0,1,1] -> True
[0,1,0,0,0,0,1,1,0,1] [1,0,1,1] -> False
[0,4,0,0,4,1,4,2,2] [0,0,0,1,4] -> True
[0,2,2,25,0,2,2,26,0,0,2] [2,0,0,0,2] -> True
[1,1,1,3,2,1,3,2,2,3,3,2] [1,1,2,3,2] -> False
[0,3,2,0,1,3,2,0,0,0,3,2] [0,1,2,0,3] -> False
[5,7,2,7,7,1,7,7,5,2,7,7,5,2,2,7,5] [2,7,5,7,7,2] -> False
[5,4,0,5,4,5,4,1,0,4,2,1,1,2,4,4,0,2,2,1] [4,0,1,1,2,1] -> False
[0,1,4,0,1,4,0,1,5,1,4,4,2,0,0,1,1,1,2,4] [0,1,0,0,2,0,1,4] -> True

回答:


6

Haskell、90 84バイト

a%[]=[a]
(t:z)%x@(s:y)=[a|a<-z%y,t==s]++[t:s|s<-z%x]
_%_=[]
((all=<<(==).head).).(%)

すべての可能な減算されたシーケンスのリストを非決定的に構築し、それらがすべて等しいかどうかをチェックします。

使用法:

*Main> mapM_(\(a,b)->let r=(((all=<<(==).head).).(%)) a b in putStrLn$concat[show a," ",show b," -> ",show r]) [([],[]), ([0,3],[]), ([1,0,1],[1]), ([0,2],[0,2]), ([2,2,1,1,2,2,2],[2,1]), ([4,2,2,4,4,6,5],[4,5]), ([10,5,10,10,5,10],[10,5,10]), ([4,2,2,4,4,6,5],[2,4,5]), ([1,1,1,0,0,0,1,1,1,0],[1,0,1,1]), ([0,1,0,0,0,0,1,1,0,1],[1,0,1,1]), ([0,4,0,0,4,1,4,2,2],[0,0,0,1,4]), ([0,2,2,25,0,2,2,26,0,0,2],[2,0,0,0,2]), ([1,1,1,3,2,1,3,2,2,3,3,2],[1,1,2,3,2]), ([0,3,2,0,1,3,2,0,0,0,3,2],[0,1,2,0,3]), ([5,7,2,7,7,1,7,7,5,2,7,7,5,2,2,7,5],[2,7,5,7,7,2]), ([5,4,0,5,4,5,4,1,0,4,2,1,1,2,4,4,0,2,2,1],[4,0,1,1,2,1]), ([0,1,4,0,1,4,0,1,5,1,4,4,2,0,0,1,1,1,2,4],[0,1,0,0,2,0,1,4])]
[] [] -> True
[0,3] [] -> True
[1,0,1] [1] -> False
[0,2] [0,2] -> True
[2,2,1,1,2,2,2] [2,1] -> True
[4,2,2,4,4,6,5] [4,5] -> False
[10,5,10,10,5,10] [10,5,10] -> False
[4,2,2,4,4,6,5] [2,4,5] -> True
[1,1,1,0,0,0,1,1,1,0] [1,0,1,1] -> True
[0,1,0,0,0,0,1,1,0,1] [1,0,1,1] -> False
[0,4,0,0,4,1,4,2,2] [0,0,0,1,4] -> True
[0,2,2,25,0,2,2,26,0,0,2] [2,0,0,0,2] -> True
[1,1,1,3,2,1,3,2,2,3,3,2] [1,1,2,3,2] -> False
[0,3,2,0,1,3,2,0,0,0,3,2] [0,1,2,0,3] -> False
[5,7,2,7,7,1,7,7,5,2,7,7,5,2,2,7,5] [2,7,5,7,7,2] -> False
[5,4,0,5,4,5,4,1,0,4,2,1,1,2,4,4,0,2,2,1] [4,0,1,1,2,1] -> False
[0,1,4,0,1,4,0,1,5,1,4,4,2,0,0,1,1,1,2,4] [0,1,0,0,2,0,1,4] -> True

6バイトを節約してくれた@Zgarbに感謝します!


あなたは物事を再配置してx%_=x、の2番目のケースのために持つことができ%ます。また、主な機能は、ポイントフルな形式では短くなると思います。
ズガルブ16

@Zgarb x%_=xタイプは一致しませんが_%_=[]、バイトを保存するため、は機能しません。
アンス16

4

JavaScript(ES6)、141 152 156 159

再帰関数-かなり長い

f=(a,b,i=0,j=0,r=a,S=new Set)=>(1/b[j]?1/a[i]&&f(a,b,i+1,j,r,S,a[i]-b[j]||f(a,b,i+1,j+1,r=[...r],r[i]=S)):S.add(0+r.filter(x=>1/x)),S.size<2)

少ないゴルフ

f=(a, b, 
   i = 0, // current position to match in a
   j = 0, // current position to match in b
   r = a, // current result so far, A with elements of B removed - start == A
   S = new Set // set of possible "A removed B"
) => (
    1 / b[j] // check if j is still inside B
    ? 1 / a[i] // if i is inside A
      && (
        // in any case try to find current element of B in the remaining part of A
        f(a, b, i+1, j, r, S),
        a[i] == b[j] // if match was found between A and B
        && 
          // mark current element in a copy of r and 
          // look for the next element of B in the remaining part of A
          f(a, b, i+1, j+1, r=[...r], r[i]=S),
      )
    // else - j is not inside B, we have a solution in r
    // use filter to get a copy without the marked elements
    //  (note: 1/any_number == number_not_0, 1/Object == NaN)
    // then convert to string, to use as a key in S
    : S.add(0+a.filter(x=>1/x)),
    S.size<2 // return true if S has only 1 element
)  

テスト

f=(a,b,i=0,j=0,r=a,S=new Set)=>(1/b[j]?1/a[i]&&f(a,b,i+1,j,r,S,a[i]-b[j]||f(a,b,i+1,j+1,r=[...r],r[i]=S)):S.add(0+r.filter(x=>1/x)),S.size<2)


out=(...x)=>O.textContent+=x.join` `+'\n'
;`[] [] -> True
[0,3] [] -> True
[1,0,1] [1] -> False
[0,2] [0,2] -> True
[2,2,1,1,2,2,2] [2,1] -> True
[4,2,2,4,4,6,5] [4,5] -> False
[10,5,10,10,5,10] [10,5,10] -> False
[4,2,2,4,4,6,5] [2,4,5] -> True
[1,1,1,0,0,0,1,1,1,0] [1,0,1,1] -> True
[0,1,0,0,0,0,1,1,0,1] [1,0,1,1] -> False
[0,4,0,0,4,1,4,2,2] [0,0,0,1,4] -> True
[0,2,2,25,0,2,2,26,0,0,2] [2,0,0,0,2] -> True
[1,1,1,3,2,1,3,2,2,3,3,2] [1,1,2,3,2] -> False
[0,3,2,0,1,3,2,0,0,0,3,2] [0,1,2,0,3] -> False
[5,7,2,7,7,1,7,7,5,2,7,7,5,2,2,7,5] [2,7,5,7,7,2] -> False
[5,4,0,5,4,5,4,1,0,4,2,1,1,2,4,4,0,2,2,1] [4,0,1,1,2,1] -> False
[0,1,4,0,1,4,0,1,5,1,4,4,2,0,0,1,1,1,2,4] [0,1,0,0,2,0,1,4] -> True`
.split('\n').forEach(t=>{
  var [a,b,_,k]=t.match(/\S+/g)
  var r=f(eval(a),eval(b))
  out(r==(k[0]=='T')?'OK':'KO',a,b,r,k)
})
<pre id=O></pre>



3

JavaScript(ES6)、116 114 113バイト

falseまたはを返しますtrue

(a,b,p)=>((F=(a,i,m)=>1/b[i]?a.map((n,j)=>m>j|n-b[i]||F(a.filter((_,k)=>j-k),i+1,j)):p?r|=p!=a:p=a+'')(a,r=0),!r)

書式設定およびコメント化

(                                     // given:
  a, b,                               // - a, b = input arrays
  p                                   // - p = reference pattern, initially undefined
) => (                                //
  (F = (                              // F is our recursive search function, with:
    a,                                // - a = current working copy of the main array
    i,                                // - i = index in 'b'
    m                                 // - m = minimum index of matching values in 'a'
  ) =>                                //
    1 / b[i] ?                        // if we haven't reached the end of 'b':
      a.map((n, j) =>                 //   for each element 'n' at index 'j' in 'a':
        m > j | n - b[i] ||           //     if 'n' is a valid matching value,
        F(                            //     do a recursive call to F(), using:
          a.filter((_, k) => j - k),  //     - a copy of 'a' without the current element
          i + 1,                      //     - the next index in 'b'
          j                           //     - 'j' as the new minimum index in 'a'
        )                             //
      )                               //
    :                                 // else:
      p ?                             //   if the reference pattern is already set:
        r |= p != a                   //     check if it's matching the current 'a'
      :                               //   else:
        p = a + ''                    //     set the current 'a' as the reference pattern
  )(a, r = 0),                        //  initial call to F() + initialization of 'r'
  !r                                  //  yields the final result
)                                     //

テストケース


うわー!私はAの減少コピーで再帰的にする方法を見つけることを試みたが、ない成功
edc65


1

JavaScript(Firefox 30 +)、159 147バイト

f=(a,b,i=f(a,b,0))=>i?i.every(x=>x+""==i[0]):b+b?a+a&&[for(n of a)if(a[i++]==b[0])for(x of f(a.slice(i),b.slice(1),0))[...a.slice(0,i-1),...x]]:[a]

匿名関数の両方の代替アプローチを次に示します。

(a,b,f=(a,b,i=0)=>b+b?a+a&&[for(n of a)if(a[i++]==b[0])for(x of f(a.slice(i),b.slice(1)))[...a.slice(0,i-1),...x]]:[a],c=f(a,b))=>c.every(x=>x+""==c[0])
(a,b,f=(a,b,i=0)=>b+b?a+a&&[for(n of a)if(a[i++]==b[0])for(x of f(a.slice(i),b.slice(1)))[...a.slice(0,i-1),...x]]:[a])=>new Set(f(a,b).map(btoa)).size<2

テストスニペット


Iすぎスニペットのような
edc65

1

Mathematica、128バイト

h=Length;n=ToExpression;g=ToString;y=Array;h@Union@ReplaceList[#2,n@Riffle[y["a"<>g@#<>"___"&,t=h@#+1],#]->n@y["a"<>g@#&,t]]==1&

2つのリスト引数を取る名前のない関数。1つ目はサブシーケンスで、2つ目は完全なシーケンスです。出力TrueまたはFalse

コア部分は次のシーケンスで、読みやすくするために変更されていません。

ReplaceList[#2, ToExpression @
  Riffle[
    Array["a" <> ToString@# <> "___" &, Length@# + 1]
    , #
  ] -> ToExpression @ 
    Array["a" <> ToString@#& , Length@# + 1 ]
]

これ#はサブシーケンスを表し{2,4,5}ます。たとえば、。最初のArrayコマンドは次のような文字列のリストを作成し{"a1___","a2___","a3___","a4___"}、その後され、Riffle一緒にdの#ような奇妙なリストを生成するために{"a1___",2,"a2___",4,"a3___",5,"a4___"}、その後、このリストは実際のMathematica式にキャストされます。例{2,4,5}では、このコアコードの部分評価は

ReplaceList[#2, {a1___,2,a2___,4,a3___,5,a4___} -> {a1,a2,a3,a4}]

これは正確にサブシーケンスを除去するためのすべての可能な方法のリスト与え{2,4,5}から#2単独で、リストの残りの部分を残しています。

このリストが生成された後、使用Unionして重複を削除し、結果の出力の長さが1かどうかをテストします。

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