它是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
正交变量扩展因子,指的是它们的使用方式以及它们具有的有用特性。这似乎并不十分相关,但是Wikipedia链接(含糊地)对此进行了解释。
林恩

Answers:


8

果冻18 16 14 11字节

^2/Eam2µḊ¿Ṭ

[1]OVSF代码的输出(真),[]否则为(假)。

在线尝试!

背景

就像@LuisMendo的MATL答案@xnor的Python答案一样,此提交“从内到外”验证输入数组。

长度为2或更高的OVSF代码的每对(不重叠)元素本质上都是第一对的副本,具有相同符号或两个符号互换。同样,长度为4或更高的OVSF代码的每个(不重叠)4元组本质上是第一个4元组的副本,具有相同的符号或两个符号互换。对于8元组,16元组等,直到OVFS代码的长度也是如此。

验证这一点的一种方法是先检查所有成对对是否等于模,然后删除每对的第二个元素(现在是冗余信息)。如果我们再次重复此过程,则实际上是在检查所有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]givens True。从理论上讲,它也可以用作运算符±,但是该运算符仅在语法上在一元和二进制上下文中有效,因此调用约定会变得很奇怪:±##&[1,-1,-1,1]。它将引发一堆可以忽略的警告。

这还将引发一些可以忽略的警告。

可能在客场缩短有点恼人的a!==b!||{a}==-{b}一部分,但我没有马上找到任何东西。像SubsetQMatrixRank这样的关键字太长了。:/

说明

该解决方案基本上将所有棘手的问题推迟到Mathematica的模式匹配器中,因此在样式上非常声明。除了第一行有些夸张之外,这实际上为操作员添加了三个不同的定义±

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

通过嵌套定义并表示True为,缩短了前两行1>0

我们应该进一步对其进行解构,以显示它实际上如何PlusMinus仅通过使用一元和二进制运算符表示法来定义variadci函数。要注意的是,所有运算符都只是完整表达式的语法糖。在我们的情况下±对应于PlusMinus。以下代码是100%等效的:

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

通过使用序列(其他语言中类似splats)作为操作数,±我们可以覆盖的任意数量的参数PlusMinus,即使±不能用于两个以上的参数。根本原因是在扩展这些序列中的任何一个之前,先解析语法糖。

关于定义:

第一个定义只是后备(___匹配任意参数列表)。以下是与更具体的定义不匹配的所有内容False

第二个定义是OVSF的基本情况,该列表仅包含1。我们将其定义为True

最后,第三个定义适用到可以分解成列表X ++ XX ++ -X和递归使用的结果X。该定义是通过保证它们可以被分成子序列不限于这些列表aba__±b__再附接条件(/;),要么{a}=={b}{a}==-{b}PlusMinus通过操作符以这种怪异的方式定义为可变函数,比在列表上定义一元操作符节省了多达5个字节±

但是等等,还有更多。我们使用a!==b!而不是{a}=={b}。显然,我们这样做是因为它短了两个字节,但是有趣的问题是它为什么起作用。正如我在上面解释的那样,对于某些带有头部的表达,所有运算符都只是语法糖。{a}List[a]。但这a是一个序列(就像我说的那样,有点像其他语言中的splat),所以如果得到a则为。现在postfix 是。所以在这里,我们得到。但是不知道当参数个数与参数个数不同时该怎么办,因此这仍然没有被评估。并不真正在意双方都是列表,它只是比较表达式,如果相等,则给出1,-1,1List[1,-1,1]!FactorialFactorial[1,-1,1]Factorial==True(在这种情况下,如果不是,它实际上不会给出False,但如果条件返回以外的其他值,则模式不匹配True)。因此,如果列表中至少有两个元素,则相等检查仍然有效。如果只有一个怎么办?如果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]

给定输入列表ls通过从或开始[1]并反复串联来增长OVSF代码,以使得第一个元素与匹配。然后,检查结果是否结束。一旦长度至少为,就检查一次。s-sllsl

一些替代方法递归结构也恰好得出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 / Octave,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代码N出现在log2(N)-th Walsh-matrix中,因为它们基本上是由相同的递归定义的:

Walsh矩阵是大小的Hadamard矩阵的特例,N x N如果N是2的幂。(还有其他尺寸的Hadamard矩阵。)MATLAB和Octave具有各种内置函数,可以生成测试矩阵以测试数值算法的属性,其中包括hadamard()。幸运的是,对于两个MATLAB hadamard()usex的幂来说,威尔士矩阵的构造正好如此。

因此,此函数首先检查输入长度是否为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]。空列表也被明确拒绝,以避免无限循环。

我的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

该函数g生成n列表的迭代(效率相对较低,因为length $ g n == 3^n,但是,如果我们删除重复项,则会得到2^n),请f检查列表是否在其中任何一个列表中。感谢@Zgrab的一些提示!

在线尝试!


运行最后两个测试用例对我来说没有输出。
奥利弗

@obarakon是的,这是因为g非常低效的,并且产生重复的。(请检查调试部分,这可能是由于时间或内存限制所致。)
更加糟糕

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没有设置至少两位,以上检查给出了简并的结果。如果设置为零,则检查是否a[0] == a[0] * a[0]为false;a[0] == -1如果设置为1,则检查为a[i] == a[0] * a[i]

您可以更改(l=a.length)&&!(l&l-1)(l=a.length)&-l==l保存4个字节
Patrick Roberts

@PatrickRoberts不是真的l==0吗?
尼尔

哦,对了。那(l=a.length)&&l&-l==l好吗?保存1个字节...
Patrick Roberts

实际上没关系,[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1]即使没有我的建议,您的功能也会失败。
Patrick Roberts

@PatrickRoberts l&-l==l不起作用,因为==它的优先级高于&。而且由于出现错字,测试用例无法正常工作,这会花费我一个字节来修复。
尼尔

2

MATL21 20字节

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

在线尝试!验证所有测试用例

怎么运行的

该代码将数组分为两个等长的片段:第一个具有奇数索引条目,第二个具有偶数索引条目。迫使这两个部分具有相等的长度,如果需要,在第二个中填充零。然后代码检查

  1. 两部分的对应条目要么全部相等,要么全部不同。
  2. 第二部分中没有任何条目为零;
  3. 件的长度超过1。

如果满足这三个条件,则在第一块上再次应用该过程。如果由于长度已经为1而退出循环,则输入为OFSV代码。否则不是。

迭代的条件1是OVSF代码的define属性的等效版本。对于长度为8的数组,直接的方法是检查条目1,2,3,4是否分别等于或完全不同于条目5,6,7,8(这是定义属性)。但是我们可以等效地检查条目1,3,5,7分别等于或全部不同于条目2,4,6,8;原来使用更少的字节。

条件2确保输入长度为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
瑕疵

我认为您可以通过执行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,专门1或者true如果有效,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分为两半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))))))%)

loop计算log_2输入的长度,iterate并根据定义生成多次迭代的序列。如果它是有效序列,nil则返回输入参数,否则返回。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.