Dada uma lista de 1
s e -1
s, determine se é ou não um código OVSF válido (emitindo um valor de verdade ou falsey).
Os códigos OVSF são definidos da seguinte maneira:
[1]
é um código OVSF.Se
X
for um código OVSF, entãoX ++ X
eX ++ -X
são ambos códigos OVSF.Aqui
++
está a concatenação da lista e-
nega todos os elementos da lista.Nenhuma outra lista é um código OVSF válido.
Você pode supor que a lista de entrada contenha apenas -1
e 1
, mas deve manipular a lista vazia corretamente, bem como listas cujo comprimento não seja 2.
O código mais curto (em bytes) vence.
Casos de teste
[] -> 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
Respostas:
Geléia ,
18161411 bytesSaídas
[1]
(verdade) para códigos OVSF,[]
(falsy) caso contrário.Experimente online!
fundo
Como a resposta MATL do @ LuisMendo e a resposta Python do @ xnor , esse envio verifica a matriz de entrada "de dentro para fora".
Todo par de elementos (sem sobreposição) de um código OVSF de comprimento dois ou superior é essencialmente uma cópia do primeiro par, com os mesmos sinais ou com os dois sinais trocados. Da mesma forma, cada 4-tupla (sem sobreposição) de elementos de um código OVSF de comprimento quatro ou superior é essencialmente uma cópia da primeira 4-tupla, com os mesmos sinais ou com os dois sinais trocados. O mesmo vale para 8 tuplas, 16 tuplas, etc., até o comprimento do código OVFS.
Uma maneira de verificar isso é verificar primeiro todos os pares quanto ao módulo de igualdade, e depois remover o segundo elemento de cada par (que agora é uma informação redundante). Se repetirmos esse processo mais uma vez, estamos essencialmente verificando todas as quatro tuplas. Na próxima iteração, comparamos 8 tuplas etc.
Finalmente, se todos os 2 k- tuples exigidos fossem iguais ao módulo e o array fosse reduzido a um singleton, é suficiente verificar se o elemento restante é 1 .
Como funciona
fonte
Mathematica,
524745 bytesA contagem de bytes assume a codificação CP-1252 e
$CharacterEncoding
definida comoWindowsANSI
(o padrão nas instalações do Windows).Isso define uma função variável
PlusMinus
, que pega a lista de entrada como uma lista simples de argumentos e retorna um booleano, por exemplo,PlusMinus[1, -1, -1, 1]
dáTrue
. É teoricamente também pode ser usado como um operador±
, mas esse operador só é sintaticamente válido em contextos unários e binários, de modo a convenção de chamada iria ficar estranho:±##&[1,-1,-1,1]
. Ele lançará vários avisos que podem ser ignorados.Isso também emitirá alguns avisos que podem ser ignorados.
Não pode ser afastado para encurtar a pouco chato
a!==b!||{a}==-{b}
parte, mas eu não estou achando nada agora. Palavras-chave gostamSubsetQ
eMatrixRank
são simplesmente muito longas. : /Explicação
A solução basicamente adia todas as coisas complicadas ao comparador de padrões do Mathematica e, portanto, é muito declarativa em estilo. Além de alguma golfitude na primeira linha, isso realmente apenas adiciona três definições diferentes para o operador
±
:As duas primeiras linhas foram encurtadas, aninhando as definições e expressando
True
como1>0
.Deveríamos desconstruir isso ainda mais para mostrar como isso realmente define uma função variadci
PlusMinus
usando apenas notação de operador unário e binário. O problema é que todos os operadores são simplesmente açúcar sintático para expressões completas. No nosso caso±
corresponde aPlusMinus
. O código a seguir é 100% equivalente:Usando sequências (como splats semelhantes em outras línguas) como operandos
±
, podemos cobrir um número arbitrário de argumentosPlusMinus
, mesmo que±
não seja utilizável com mais de dois argumentos. A razão fundamental é que o açúcar sintático é resolvido primeiro, antes que qualquer uma dessas seqüências seja expandida.Para as definições:
A primeira definição é simplesmente um fallback (
___
corresponde a uma lista arbitrária de argumentos). Tudo o que não corresponder às definições mais específicas abaixo daráFalse
.A segunda definição é o caso base para o OVSF, a lista que contém apenas
1
. Definimos que sejaTrue
.Finalmente, a terceira definição se aplica apenas a listas que podem ser decompostas em
X ++ X
ouX ++ -X
e usa o resultado recursivamente paraX
. A definição está limitado a estas listas, assegurando que pode ser dividida em subsequênciasa
eb
coma__±b__
e, em seguida, fixar a condição (/;
) que seja{a}=={b}
ou{a}==-{b}
. DefinirPlusMinus
uma função variada dessa maneira estranha por meio de um operador economiza 5 bytes em comparação à definição de um operador unário±
nas listas.Mas espere, tem mais. Estamos usando em
a!==b!
vez de{a}=={b}
. Claramente, estamos fazendo isso porque são dois bytes mais curtos, mas a questão interessante é por que isso funciona. Como expliquei acima, todos os operadores são apenas açúcar sintático para alguma expressão com uma cabeça.{a}
éList[a]
. Masa
é uma sequência (como eu disse, mais ou menos como um splat em outras línguas), então, sea
é1,-1,1
assim que chegamosList[1,-1,1]
. Agora o postfix!
éFactorial
. Então aqui nós teríamosFactorial[1,-1,1]
. MasFactorial
não sabe o que fazer quando tem um número diferente de argumentos que um, então isso simplesmente permanece sem avaliação.==
realmente não se importa se a coisa de ambos os lados são listas, apenas compara as expressões e, se são iguais, forneceTrue
(nesse caso, na verdade não daráFalse
se não estiverem, mas os padrões não corresponderão se a condição retornar algo diferente deTrue
). Portanto, a verificação de igualdade ainda funcionará se houver pelo menos dois elementos nas listas. E se houver apenas um? Sea
é1
entãoa!
é ainda1
. Sea
é-1
entãoa!
dáComplexInfinity
. Agora, comparar1
a si mesmo ainda funciona bem, é claro. MasComplexInfinity == ComplexInfinity
permanece não avaliado e, apesar de tudo , não é verdadeiroa == -1 == b
. Felizmente, isso não importa, porque a única situação emPlusMinus[-1, -1]
que aparece é que não é um OVSF válido de qualquer maneira! (Se a condição retornarTrue
, a chamada recursiva informaráFalse
afinal de contas, não importa que a verificação não funcione.) Não podemos usar o mesmo truque{a}==-{b}
porque, porque-
não seria encadeadoFactorial
, apenas encadeavaList
.O correspondente de padrões cuidará do resto e simplesmente encontrará a definição correta a ser aplicada.
fonte
Haskell, 57 bytes
Dada a lista de entradas
l
, cresce um código OVSFs
iniciando[1]
e concatenando repetidamente ums
ou outro-s
, o que faz o primeiro elemento corresponder ao del
. Em seguida, verifica se o resultado estál
no final. Isso é verificado quando os
comprimento for pelo menos igual al
.Algumas estruturas recursivas alternativas também deram 57:
fonte
MATLAB / oitava , 94 bytes
Isso está usando uma nova abordagem: Os códigos de comprimento OVSF permitidos
N
aparecem na matriz de Walsh-log2(N)
th , como são basicamente definidos pela mesma recursão:As matrizes de Walsh são casos especiais das matrizes Hadamard de tamanho,
N x N
seN
for uma potência de duas. (Existem também matrizes Hadamard de outros tamanhos.) MATLAB e Octave têm uma variedade de funções internas que geram matrizes de teste para testar propriedades de algoritmos numéricos, entre elas estáhadamard()
. Felizmente, para poderes de duashadamard()
usinas do MATLAB, exatamente a construção das matrizes galesas.Portanto, essa função primeiro verifica se o comprimento das entradas é uma potência de dois e, se for, verifica se é uma linha do tamanho correspondente da matriz galesa.
Experimente online!
fonte
Python, 64 bytes
Divide a lista em elementos indexados pares e indexados ímpares por meio de fatias. Verifica se os vetores de resultado são iguais ou negativos, multiplicando um pelo sinal forçado pelo seu primeiro elemento. Em seguida, faz a mesma verificação recursiva nos elementos indexados pares.
Para o caso base, se a verificação falhar, será rejeitada, a menos que a lista esteja
[1]
. A lista vazia também é especificamente rejeitada para evitar um loop infinito.Uma estratégia diferente como a minha resposta Haskell fornece 66 bytes:
fonte
Haskell ,
106 91 8786 bytesA função
g
gera an
iteração das listas (de forma relativamente ineficiente, poislength $ g n == 3^n
, no entanto, se excluirmos as duplicatas, obteríamos2^n
),f
verifica se nossa lista está em alguma delas. Obrigado ao @Zgrab por algumas dicas!Experimente online!
fonte
g
é muito ineficiente e produz uma tonelada de duplicatas. (Verifique a depuração seção, é provavelmente devido às limitações de tempo ou de memória.)JavaScript (ES6),
13093878583 bytesDemo
fonte
JavaScript (ES6),
8561 bytesVersão anterior que verificava os elementos para garantir que fossem
1
ou-1
:Explicação:
a[22] == a[2] * a[4] * a[16]
. Comoa[20] == a[4] * a[16]
já foi verificado, sóa[22] == a[2] * a[20]
precisa ser verificado.i
não ter pelo menos dois bits definidos. No caso de zero bits definido, ele verifica sea[0] == a[0] * a[0]
, o que é falsoa[0] == -1
, enquanto no caso de um bit definido, verifica issoa[i] == a[0] * a[i]
.fonte
(l=a.length)&&!(l&l-1)
para(l=a.length)&-l==l
salvar 4 bytesl==0
?(l=a.length)&&l&-l==l
? para salvar 1 byte ...[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1]
mesmo sem minhas sugestões.l&-l==l
não funciona porque==
tem maior precedência que&
. E o caso de teste não funciona por causa de um erro de digitação que me custará um byte para corrigir.MATL ,
2120 bytesExperimente online! Ou verifique todos os casos de teste .
Como funciona
O código divide a matriz em duas partes iguais: a primeira com as entradas indexadas ímpares, a segunda com as entradas indexadas pares. As duas peças são forçadas a ter o mesmo comprimento, com um preenchimento zero no segundo, se necessário. Então o código verifica se
Se essas três condições forem atendidas, o processo será aplicado novamente na primeira peça. Se o loop for encerrado porque o comprimento já era 1, a entrada é um código OFSV. Senão não é.
A condição 1 iterada é uma versão equivalente da propriedade definidora dos códigos OVSF. Para uma matriz de comprimento 8, a abordagem direta seria verificar se as entradas 1,2,3,4 são todas iguais ou diferentes das entradas 5,6,7,8, respectivamente (esta é a propriedade de definição). Mas podemos verificar de forma equivalente que as entradas 1,3,5,7 são todas iguais ou diferentes das entradas 2,4,6,8, respectivamente; e isso acaba usando menos bytes.
A condição 2 garante que o comprimento da entrada seja uma potência de 2: se não for, um zero de preenchimento será introduzido em algum estágio.
fonte
Haskell, 66 bytes
Yay, listas infinitas!
Versões alternativas:
fonte
(0-)
truque, eu estava preso comnegate
ou((-1)*)
APL, 46 bytes
Bastante simples:
0::0
: se ocorrer um erro, retorne 0⍵≡,1:1
: se a entrada for exatamente[1]
, retorne 1⍬≡⍵:0
: se a entrada for a lista vazia, retorne 0Z←.5×⍴⍵
:Z
é metade do comprimento da entradaY←⍵↓⍨Z
:Y
é a última metade da entrada (isso falha se⍴⍵
for desigual, acionando o manipulador de exceções)(∇Y)∨∇-Y
: a última metade da lista ou a negação da última metade da lista devem ser um código OVSF(∇Z↑⍵)∧
: e a primeira metade da lista deve ser um código OVSF.fonte
Haskell,
6968 bytesExemplo de uso:
g [-1,1]
->False
.Ainda mais ineficiente do que a resposta de @ flawr . Leva muito tempo e memória para 4 listas de elementos. Para ver que a lista de códigos OVSF (com muitas duplicatas) é realmente criada, tente:
que retorna
ou seja, a lista começa com todas as 16 listas de elementos (4 vezes concatenadas, por causa de
[1..4]
), continua com todas as 8 listas de elementos e assim sucessivamente até terminar com[1]
.Edit: @xnor salvou um byte. Obrigado!
fonte
scanr
!any(elem x)
vez deelem x$c
e não definindoc
.Python 2 ,
7875 bytesExperimente online!
fonte
JavaScript (ES6), 80
Cria recursivamente e verifica cada lista até o comprimento da lista de entrada, começando com
[1]
.O valor de retorno é JS verdade ou falsey, especificamente
1
outrue
se válido,0
oufalse
ouundefined
se não for válido.Teste
fonte
Clojure, 118 bytes
Entrada de racha
c
em duas metadesa
eb
e verifica se os seus produtos elemento-wise são todos idênticos. Nesse caso, verifica se a primeira metade é uma sequência válida.Este tem 142 bytes, mas achei mais interessante:
loop
calculalog_2
o comprimento da entrada,iterate
gera sequências de muitas iterações com base na definição. Isso retorna o argumento de entrada se for uma sequência válida ounil
não.fonte