OVSFコードですか?


27

1sと-1sのリストが与えられたら、それが有効なOVSFコードかどうかを判断します(真偽値または偽値を出力します)。

OVSFコードは次のように定義されます。

  • [1] OVSFコードです。

  • 場合はX、次に、OVSFコードであるX ++ XX ++ -Xの両方のOVSFコードです。

    以下++はリストの連結-で、リスト内のすべての要素を否定します。

  • 他のリストは有効なOVSFコードではありません。

あなたは、入力リストにのみ含まれているとして-11していますが、その長さが2のべき乗ではありません空正しくリスト、などのリストを処理する必要があります。

最短コード(バイト単位)が優先されます。

テストケース

[] -> False
[1] -> True
[-1] -> False
[1, 1] -> True
[1, -1] -> True
[1, 1, 1, 1] -> True
[1, 1, 1, 1, 1] -> False
[1, -1, -1, 1, -1, 1, 1, -1] -> True
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1] -> False
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1] -> False
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1] -> True

5
「OVSF」とは何の略ですか?
-NoOneIsHere

5
直交変数拡散係数。これは、それらの使用方法と、それらが持つ有用な特性を指します。これはあまり関連していないように見えましたが、ウィキペディアのリンクですべて説明されています(漠然と)。
リン

回答:


8

ゼリー18 16 14 11バイト

^2/Eam2µḊ¿Ṭ

[1]OVSFコードの出力(真)、[]それ以外の場合(偽)。

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

バックグラウンド

同様LuisMendoのMATLの答え@@ XNORのPythonの答えは、「内側から」この提出検証入力配列。

長さ2以上のOVSFコードの要素のすべての(重複しない)ペアは、本質的に、同じ符号または両方の符号が交換された最初のペアのコピーです。同様に、長さ4以上のOVSFコードのすべての(重複しない)4タプルの要素は、本質的に最初の4タプルのコピーであり、同じ符号または両方の符号が交換されています。同じことが、OVFSコードの長さまでの8タプル、16タプルなどにも当てはまります。

これを検証する1つの方法は、最初にすべてのペアの符号が等しいかどうかをチェックし、次に各ペアの2番目の要素を削除することです(これは冗長な情報です)。このプロセスをもう一度繰り返すと、基本的にすべての4タプルをチェックしています。次の反復では、8タプルなどを比較しています。

最後に、必要な2 kタプルすべてが符号を法として等しく、配列がシングルトンに縮小されている場合、残りの要素が1であるかどうかをチェックするだけで十分です。

使い方

^2/Eam2µḊ¿Ṭ  Main link. Argument: A (array of 1's and -1's)

       µḊ¿   While dequeuing A (removing its first element) yields a non-empty
             array, execute the monadic chain to the left, updating A with the
             return value after each iteration.
^2/            Compute the bitwise XOR of each non-overlapping pair of elements of
               A. Note that 1 ^ 1 = 0 = -1 ^ -1 and 1 ^ -1 = -2 = -1 ^ 1.
               For an array of even length that consists of the same pairs modulo
               the sign, this returns either an array of 0's or an array of -2's.
               If the length is odd, it will also contain the last element, which
               is either a 1 or a -1.
   E           Test the elements of the result for equality. This yields 1 if the
               array consists solely of 0's or solely of -2's, 0 otherwise.
    a          Take the logical AND of the previous result and every element of A.
               This returns A if it passed the previous test, but replaces all of
               its elements with 0's otherwise.
     m2        Modulo 2; select every second element of A, starting with the first.
             At this point, the last return value can be:
               • [  ] if the input was empty
               • [ 1] if the input was a valid OVSF code
               • [-1] if the input was the negative of a valid OVSF code.
               • [ 0] in all other cases.
           Ṭ  Untruth; yield an array with 1's at the specified indices.
              Indexing is 1-based in Jelly, so [1] returns [1], the array with a 1
              at index 1. Since the indices -1 and 0 are non-canonical, the arrays
              [-1] and [0] are mapped to []. The empty array remains empty.

14

Mathematica、52 47 45バイト

バイトカウントはCP-1252エンコードを想定$CharacterEncodingし、WindowsANSI(Windowsインストールのデフォルト)に設定されます。

±___=!(±1=1>0)
a__±b__/;a!==b!||{a}==-{b}:=±a

これは可変引数関数を定義しますPlusMinus。これは入力リストを引数のフラットリストとして受け取り、ブール値、たとえばPlusMinus[1, -1, -1, 1]gives を返しますTrue。理論的には演算子としても使用できます±が、その演算子は単項およびバイナリコンテキストでのみ構文的に有効であるため、呼び出し規約は奇妙になります±##&[1,-1,-1,1]。無視できる大量の警告がスローされます。

これは、無視できるいくつかの警告もスローします。

やや面倒な部分を短くする余地があるかもしれませんa!==b!||{a}==-{b}、私は今何も見つけていません。SubsetQMatrixRankなどのキーワードは長すぎます。:/

説明

このソリューションは基本的にすべてのトリッキーなことをMathematicaのパターンマッチャーに委ねるため、スタイルが非常に宣言的です。最初の行のいくつかのゴルフ練習とは別に、これは実際に演算子に3つの異なる定義を追加するだけ±です。

±___=False;
±1=True;
a__±b__/;a!==b!||{a}==-{b}:=±a

最初の2行は、定義をネストし、Trueとして表現することにより短縮されました1>0

これをさらに分解して、PlusMinus単項演算子表記と二項演算子表記のみを使用して、これが実際にvariadci関数を定義する方法を示す必要があります。キャッチは、すべての演算子が完全な式のための単純な糖衣であるということです。私たちのケースではに±対応しPlusMinusます。次のコードは100%同等です。

PlusMinus[___]=False;
PlusMinus[1]=True;
PlusMinus[a__,b__]/;a!==b!||{a}==-{b}:=PlusMinus[a]

オペランド(他の言語のスプラットのようなもの)をオペランドとして使用することにより、3つ以上の引数で使用できない場合でも±、の任意の数の引数をカバーできます。基本的な理由は、これらのシーケンスのいずれかが展開される前に、構文糖が最初に解決されることです。PlusMinus±

定義について:

最初の定義は、単純にフォールバックです(___引数の任意のリストに一致します)。以下のより具体的な定義と一致しないものはすべて与えられFalseます。

2番目の定義はOVSFの基本ケースで、リストにはのみが含まれ1ます。これをと定義しますTrue

最後に、3番目の定義は、またはに分解できるリストにのみ適用され、の結果を再帰的に使用します。定義は、彼らがサブに分割することができます確保することによって、これらのリストに限定されるととともに、その後の状態を(添付)のいずれかまたは。この奇妙な方法で演算子を介して可変個性関数として定義すると、リストで単項演算子を定義するよりも5バイトも節約できます。X ++ XX ++ -XXaba__±b__/;{a}=={b}{a}==-{b}PlusMinus±

しかし、待ってください、まだあります。のa!==b!代わりに使用しています{a}=={b}。明らかに、2バイト短いのでこれを行っていますが、興味深い質問はなぜ機能するのかということです。上で説明したように、すべての演算子は、頭のある式の単なる構文糖です。{a}ですList[a]。しかし、aあるシーケンスので、もし(私が言ったように、ソート他の言語のスプラット等)aされ1,-1,1、我々が得ますList[1,-1,1]。現在、接尾辞!Factorialです。だから、ここで、我々は得るだろうFactorial[1,-1,1]。ただしFactorial、引数の数が1つと異なる場合はどうすればよいかわからないため、これは単に評価されないままです。==両側のものがリストであるかどうかは実際には気にせず、式を比較するだけで、等しい場合はTrue(この場合、そうでない場合は実際には与えられFalseませんが、条件が以外を返す場合、パターンは一致しませんTrue)。つまり、リストに少なくとも2つの要素がある場合、同等性チェックは引き続き機能します。1つしかない場合はどうなりますか?IFがaある1その後、a!まだです1。の場合a-1a!提供しComplexInfinityます。今で1は、もちろんそれ自体と比較してもうまくいきます。しかしComplexInfinity == ComplexInfinity、評価されていないままで、たとえを与えても真実でありませんa == -1 == b。幸いなことに、これは重要ではありません。これが現れる唯一の状況PlusMinus[-1, -1]は、とにかく有効なOVSFではないからです!(条件が戻ったTrue場合、再帰呼び出しは報告しますFalseすべての後に、それは重要ではありませんので、チェックはうまくいかないこと。)我々はために同じトリックを使用することはできません{a}==-{b}ので、-以上のスレッドではないでしょうFactorial、それだけでオーバースレッドList

パターンマッチャーが残りを処理し、適用する正しい定義を見つけるだけです。


9

Haskell、57バイト

q=length
f l=l==until((>=q l).q)(\s->s++map(*l!!q s)s)[1]

入力リスト所与l、OVSFコードを成長sから出発することによって[1]のいずれかで繰り返し連結sまたは-sそれの最初の要素の一致を行う方、l。次に、結果がl最後にあることを確認します。これはs、少なくともの長さを持つとチェックされlます。

再帰構造のいくつかの選択肢もたまたま57

(s%i)l|length l<=i=s==l|j<-2*i=(s++map(*l!!i)s)%j$l
[1]%1

q=length
s%l|q s>=q l=s==l|r<-s++map(*l!!q s)s=r%l
([1]%)

q=length
g s l|q s<q l=g(s++map(*l!!q s)s)l|1>0=s==l
g[1]

6

MATLAB / オクターブ、94バイト

function a=f(r);n=nnz(r);m=log2(n);a=0;if fix(m)-m==0;for c=hadamard(n);a=a+all(r==c');end;end

これは新しいアプローチを使用しています。長さの許可されたOVSFコードは、基本的に同じ再帰によって定義されるためNlog2(N)-th Walsh-matrixに表示されます。

ウォルシュ行列は、2のべき乗の場合、サイズのアダマール行列の特殊なケースです。(他のサイズのアダマール行列もあります。)MATLABとOctaveには、数値アルゴリズムのプロパティをテストするためのテスト行列を生成するさまざまな組み込み関数があります。幸いなことに、2つのMATLABのpowersがウェールズ行列の正確な構成を使用しています。N x NNhadamard()hadamard()

そのため、この関数は最初に入力の長さが2のべき乗かどうかを確認し、そうであれば、対応するサイズのウェールズ行列の行かどうかを確認します。

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


5

Python、64バイト

f=lambda l:[]<l[1::2]==[x*l[1]for x in l[::2]]*f(l[::2])or[1]==l

リストをスライスを介して偶数インデックスの要素と奇数インデックスの要素に分割します。最初の要素によって強制された符号で1を乗算することにより、結果ベクトルが等しいか負であるかを確認します。次に、偶数インデックスの要素に対して同じ再帰チェックを行います。

基本ケースでは、チェックが失敗した場合、リストがでない限り拒否し[1]ます。空のリストは、無限ループを回避するために特に拒否されます。

私のHaskellの答えのような別の戦略は66バイトを与えます:

f=lambda l,i=1,s=[1]:l[i:]and f(l,i*2,s+[x*l[i]for x in s])or s==l

2

Haskell106 91 87 86バイト

g n|n<1=[[1]]|m<-g(n-1)=foldl(\a b->[b++map(0-)b,b++b]++a)[]m++m
f l=elem l$g$length l

この関数はリストgn反復を生成しますが(比較的非効率的ですが、length $ g n == 3^n重複を削除するとが取得されるため2^n)、fリストがそれらのいずれかに含まれているかどうかをチェックします。いくつかのヒントを提供してくれた@Zgrabに感謝します!

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


最後の2つのテストケースを実行しても、出力が得られませんでした。
オリバー

ためである@obarakonうん、gある非常に非効率的かつ生産トン重複のを。(デバッグセクションを確認してください。時間またはメモリの制限が原因である可能性があります。)
flawr

2

JavaScript(ES6)、130 93 87 85 83バイト

f=a=>(b=a.slice(0,l=a.length/2),c=a.slice(l)+"",a==1||l&&b==c|b.map(i=>-i)==c&f(b))

デモ

f=a=>(b=a.slice(0,l=a.length/2),c=a.slice(l)+"",a==1||l&&b==c|b.map(i=>-i)==c&f(b)),[[],[1],[-1],[1,1],[1,-1],[1,1,1,1],[1,1,1,1,1],[1,-1,-1,1,-1,1,1,-1],[1,1,1,1,-1,-1,-1,-1,1,1,1,1],[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1],[1,1,1,1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1]].map(a=>console.log(`[${a}] -> ${!!f(a)}`))


2

JavaScript(ES6)、85 61バイト

a=>(l=a.length)&&!(l&l-1)&a.every((e,i)=>e==a[j=i&-i]*a[i-j])

1またはを確認するために要素をチェックした以前のバージョン-1

a=>(l=a.length)&&!(l&l-1)&a.every((e,i)=>i?(j=i&-i)<i?e==a[j]*a[i-j]:e==1|e==-1:e==1)

説明:

  • 長さをゼロにすることはできません
  • 長さは2のべき乗でなければなりません
  • 最初の要素は1でなければなりません
  • 2のべき乗の位置にある要素は、1または-1でなければなりません
  • 他の位置の要素は、ビットマスクに対応する位置のすべての要素の積ですa[22] == a[2] * a[4] * a[16]a[20] == a[4] * a[16]すでにチェックされているので、チェックするだけa[22] == a[2] * a[20]です。
  • 上記のチェックではi、少なくとも2ビットが設定されていないため、縮退した結果が得られます。ビットが設定されていない場合は、をチェックします。a[0] == a[0] * a[0]これはに対してfalseですa[0] == -1。一方、ビットが設定されている場合は、をチェックしa[i] == a[0] * a[i]ます。

4バイトを保存する(l=a.length)&&!(l&l-1)よう(l=a.length)&-l==lに変更できます
パトリックロバーツ

@PatrickRobertsそれは本当ではないl==0ですか?
ニール

ああ、あなたは正しい。じゃあ(l=a.length)&&l&-l==l?1バイトを保存するに
パトリックロバーツ

実際のところ、[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1]私の提案がなくても機能は機能しません。
パトリックロバーツ

@PatrickRoberts l&-l==lは、==より優先順位が高いため機能しません&。また、テストケースは、タイプミスにより修正するのに1バイトかかるため、機能しません。
ニール

2

MATL21 20バイト

`2eZ}yy=&=tn1>hh]1X=

オンラインでお試しください!または、すべてのテストケースを確認します

使い方

このコードは、配列を2つの等しい長さの部分に分割します。1つ目は奇数インデックスのエントリ、2つ目は偶数インデックスのエントリです。2つの部分の長さは等しくなり、必要に応じて2番目の部分にゼロが埋め込まれます。次に、コードはそれをチェックします

  1. 2つの部分の対応するエントリは、すべて等しいか、すべて異なります。
  2. 2番目の部分のエントリはゼロではありません。
  3. ピースの長さが1を超えています。

これらの3つの条件が満たされている場合、プロセスは最初のピースに再度適用されます。長さがすでに1だったためにループが終了した場合、入力はOFSVコードです。そうでない場合はそうではありません。

繰り返される条件1は、OVSFコードの定義プロパティの同等バージョンです。たとえば長さ8の配列の場合、簡単な方法は、エントリ1、2、3、4がすべてエントリ5、6、7、8と等しいか、すべて異なることを確認することです(これが定義プロパティです)。ただし、エントリ1、3、5、7がすべてエントリ2、4、6、8と等しいか、すべて異なることを同等にチェックできます。これにより、使用するバイト数が少なくなります。

条件2は、入力長が2の累乗であることを確認します。そうでない場合は、ある段階でパディングゼロが導入されます。

`        % Do...while loop
  2e     %   Reshape as a two-row matrix, with a padding zero if needed
         %   Row 1 contains the original odd-indexed entries, row 2 the
         %   even-indexed
  Z}     %   Split matrix into two vectors, one corresponding to each row
  yy     %   Duplicate those two vectors
  =      %   Check if corresponding entries are equal or not
  &=     %   Matrix of all pairwise comparisons. This will give a matrix
         %   filled with ones if and only if the previous check gave all
         %   true or all false (condition 1)
  tn1>   %   Duplicate and push true if size exceeds 1, or false otherwise
         %   (condition 3)
  hh     %   Concatenate condition 1, condition 3, and the original copy of
         %   the second piece (condition 2). The resulting vector is truthy
         %   if and only if it doesn't contain any zero
]        % End
1X=      % True if top of the stack is a single 1, false otherwise

2

Haskell、66バイト

イェイ、無限リスト!

o=[1]:(o>>= \x->[x++map(0-)x,x++x])
f l=l`elem`take(2*2^length l)o

代替バージョン:

o=[1]:(o<**>map(>>=flip(++))[map(0-),id])
f=Data.List.Ordered.hasBy(comparing length)o

(0-)トリックのおかげで、私はnegate((-1)*)
Bergiで

1

APL、46バイト

{0::0⋄⍵≡,1:1⋄⍬≡⍵:0⋄(∇Z↑⍵)∧(∇Y)∨∇-Y←⍵↓⍨Z←.5×⍴⍵}

かなり簡単です:

  • 基本ケース:
    • 0::0:エラーが発生した場合、0を返します
    • ⍵≡,1:1:入力が正確な場合、[1]1を返します
    • ⍬≡⍵:0:入力が空のリストの場合、0を返します
  • 再帰的な場合:
    • Z←.5×⍴⍵Z入力の半分の長さ
    • Y←⍵↓⍨ZY入力の最後の半分です(⍴⍵不均一な場合は失敗し、例外ハンドラーがトリガーされます)
    • (∇Y)∨∇-Y:リストの後半、またはリストの後半の否定は、OVSFコードである必要があります
    • (∇Z↑⍵)∧:リストの前半はOVSFコードでなければなりません。

1
後半のOVSFのコード性をチェックするだけでは不十分だと思います。前半またはその否定と等しくなければなりません。
-Zgarb

1
彼らはBASICがハイレベルのしおれるで、APLは、苦悩のハイレベルであると言う: ')

彼らはBASICがハイレベルのしおれるで、APLは、苦悩のハイレベルであると言う: ')

1

Haskell、69 68バイト

g x=any(elem x)$scanr(\_->concat.mapM(\y->[y++y,y++map(0-)y]))[[1]]x

使用例:g [-1,1]-> False

@flawrの答えよりもさらに非効率的です。4つの要素リストには時間がかかりすぎ、メモリもかかります。(多くの重複がある)OVSFコードのリストが実際に作成されていることを確認するには、次を試してください。

take 10 $ c $ scanr(\_->concat.mapM(\y->[y++y,y++map(0-)y]))[[1]] [1..4]

返す

[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
 [1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1],
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
 [1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1],
 [1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1],
 [1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1],
 [1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1],
 [1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1],
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
 [1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1]]

つまり、リストは16個すべての要素リストで始まり(のため、4回連結されます[1..4])、8個すべての要素リストで続き、で終わるまで続きます[1]

編集:@xnorはバイトを保存しました。ありがとう!


ああ、私は完全に忘れてしまったscanr
-flawr

を定義するany(elem x)elem x$cではなく、行うことでバイトを削減できると思いますc
xnor


0

JavaScript(ES6)、80

f=(l,k=[1])=>l+l==k+k||l[k.length]&&f(l,k.concat(k))|f(l,k.concat(k.map(v=>-v)))

入力リストの長さまで、各リストを再帰的に作成してチェックし[1]ます。

戻り値は、具体的には、JSのtruthyまたはfalseyである1true、有効な場合、0またはfalseまたはundefined有効でない場合。

テスト

f=(l,k=[1])=>l+l==k+k||l[k.length]&&f(l,k.concat(k))|f(l,k.concat(k.map(v=>-v)))

test=`[] -> False
[1] -> True
[-1] -> False
[1, 1] -> True
[1, -1] -> True
[1, 1, 1, 1] -> True
[1, 1, 1, 1, 1] -> False
[1, -1, -1, 1, -1, 1, 1, -1] -> True
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1] -> False
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1] -> False
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1] -> True`
.split('\n')

test.forEach(r=>{
  input = r.match(/-?1/g)||[]
  check = r.slice(-4) == 'True'
  result = f(input)
  console.log(result, check, '['+input+']')
})


0

Clojure、118バイト

(defn f[C](or(=(count C)1)(let[l(/(count C)2)[a b](split-at l C)](and(> l 0)(=(count b)l)(apply =(map * a b))(f a)))))

入力cを2つに分割ab、要素ごとの積がすべて同一かどうかをチェックします。その場合、前半が有効なシーケンスであることを確認します。

これは142バイトですが、私はそれがより興味深いことがわかりました:

#((set(nth(iterate(fn[I](mapcat(fn[i][(concat i i)(concat i(map - i))])I))[[1][-1]])(loop[l(count %)i 0](if(< l 2)i(recur(/ l 2)(inc i))))))%)

looplog_2入力の長さを計算iterateし、定義に基づいてその数の反復のシーケンスを生成します。入力引数が有効なシーケンスであるnil場合、そうでない場合、これは入力引数を返します。

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