Étant donné une liste de 1
s et de -1
s, déterminez s'il s'agit ou non d'un code OVSF valide (en émettant une valeur true ou falsey).
Les codes OVSF sont définis comme suit:
[1]
est un code OVSF.Si
X
est un code OVSF, alorsX ++ X
etX ++ -X
sont tous les deux des codes OVSF.Voici la
++
concaténation de liste et-
annule chaque élément de la liste.Aucune autre liste n'est un code OVSF valide.
Vous pouvez supposer que la liste d'entrée contient uniquement -1
et 1
, mais vous devez gérer correctement la liste vide, ainsi que les listes dont la longueur n'est pas une puissance de 2.
Le code le plus court (en octets) gagne.
Cas de 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
Réponses:
Gelée ,
18161411 octetsSorties
[1]
(véridiques) pour les codes OVSF,[]
(fausses) sinon.Essayez-le en ligne!
Contexte
Comme @ réponse de MATL de LuisMendo et réponse Python @ xnor , cette soumission vérifie le tableau d'entrée de « de l'out à l' intérieur ».
Chaque paire (sans chevauchement) d'éléments d'un code OVSF de longueur deux ou plus est essentiellement une copie de la première paire, soit avec les mêmes signes, soit avec les deux signes échangés. De même, chaque 4-tuple (sans chevauchement) d'éléments d'un code OVSF de longueur quatre ou plus est essentiellement une copie du premier 4-tuple, soit avec les mêmes signes, soit avec les deux signes échangés. Il en va de même pour 8-tuples, 16-tuples, etc., jusqu'à la longueur du code OVFS.
Une façon de vérifier cela consiste à vérifier d'abord toutes les paires pour modulo l'égalité du signe, puis supprimer le deuxième élément de chaque paire (qui est maintenant une information redondante). Si nous répétons ce processus une fois de plus, nous vérifions essentiellement tous les 4-tuples. Dans la prochaine itération, nous comparons 8 tuples, etc.
Enfin, si tous les 2 k -uplets requis étaient égaux modulo le signe et le tableau a été réduit à un singleton, il suffit de vérifier si l'élément restant est un 1 .
Comment ça marche
la source
Mathematica,
524745 octetsLe nombre d'octets suppose le codage CP-1252 et
$CharacterEncoding
défini surWindowsANSI
(la valeur par défaut sur les installations Windows).Ceci définit une fonction variadique
PlusMinus
, qui prend la liste d'entrée comme une liste plate d'arguments et retourne un booléen, par exemplePlusMinus[1, -1, -1, 1]
donneTrue
. Il est théoriquement aussi utilisable comme un opérateur±
, mais que l' opérateur n'est syntaxiquement valide dans des contextes unaires et binaires, de sorte que la convention d'appel obtiendrait bizarre:±##&[1,-1,-1,1]
. Il lancera un tas d'avertissements qui peuvent être ignorés.Cela lancera également quelques avertissements qui peuvent être ignorés.
Il pourrait y avoir un raccourci pour raccourcir la
a!==b!||{a}==-{b}
partie quelque peu ennuyeuse , mais je ne trouve rien pour l'instant. Les mots clés aimentSubsetQ
etMatrixRank
sont tout simplement trop longs. : /Explication
La solution reporte fondamentalement toutes les choses délicates à l'assortiment de motifs de Mathematica et est donc très déclarative dans le style. Mis à part une certaine golfitude sur la première ligne, cela ajoute simplement trois définitions différentes pour l'opérateur
±
:Les deux premières lignes ont été raccourcies en imbriquant les définitions et en exprimant
True
comme1>0
.Nous devrions déconstruire cela davantage pour montrer comment cela définit réellement une fonction variadci
PlusMinus
en utilisant uniquement la notation d'opérateur unaire et binaire. Le hic, c'est que tous les opérateurs sont simplement du sucre syntaxique pour les expressions complètes. Dans notre cas±
correspond àPlusMinus
. Le code suivant est 100% équivalent:En utilisant des séquences (un peu comme des splats similaires dans d'autres langages) comme opérandes de,
±
nous pouvons couvrir un nombre arbitraire d'argumentsPlusMinus
, même s'il±
n'est pas utilisable avec plus de deux arguments. La raison fondamentale est que le sucre syntaxique est résolu en premier, avant que l'une de ces séquences ne soit développée.Passons aux définitions:
La première définition est simplement une solution de repli (
___
correspond à une liste arbitraire d'arguments). Tout ce qui ne correspond pas aux définitions plus spécifiques ci-dessous donneraFalse
.La deuxième définition est le cas de base pour l'OVSF, la liste ne contenant que
1
. Nous définissons cela comme étantTrue
.Enfin, la troisième définition s'applique uniquement aux listes qui peuvent être décomposées en
X ++ X
ouX ++ -X
, et utilise récursivement le résultat pourX
. La définition est limitée à ces listes en garantissant qu'elles peuvent être divisées en sous-séquencesa
etb
aveca__±b__
puis en attachant la condition (/;
) qui soit{a}=={b}
ou{a}==-{b}
. DéfinirPlusMinus
comme une fonction variadique de cette manière étrange via un opérateur économise un énorme 5 octets sur la définition d'un opérateur unaire±
sur les listes.Mais attendez, il y a plus. Nous utilisons
a!==b!
au lieu de{a}=={b}
. De toute évidence, nous le faisons parce qu'il est de deux octets plus court, mais la question intéressante est de savoir pourquoi cela fonctionne. Comme je l'ai expliqué ci-dessus, tous les opérateurs ne sont que du sucre syntaxique pour une expression avec une tête.{a}
estList[a]
. Maisa
c'est une séquence (comme je l'ai dit, un peu comme un splat dans d'autres langues) donc sia
c'est1,-1,1
alors nous obtenonsList[1,-1,1]
. Maintenant, le suffixe!
estFactorial
. Alors ici, nous aurionsFactorial[1,-1,1]
. MaisFactorial
ne sait pas quoi faire quand il a un nombre d'arguments différent d'un seul, donc cela reste simplement non évalué.==
ne se soucie pas vraiment si la chose des deux côtés sont des listes, il compare simplement les expressions, et si elles sont égales, cela donneTrue
(dans ce cas, il ne donnera pas réellementFalse
s'ils ne le sont pas, mais les motifs ne correspondent pas si la condition renvoie autre chose queTrue
). Cela signifie donc que le contrôle d'égalité fonctionne toujours s'il y a au moins deux éléments dans les listes. Et s'il n'y en a qu'un? Sia
c'est1
alorsa!
c'est encore1
. Sia
est-1
alorsa!
donneComplexInfinity
. Maintenant, la comparaison1
avec elle-même fonctionne bien, bien sûr. MaisComplexInfinity == ComplexInfinity
reste non évalué, et ne donne pas vrai même sia == -1 == b
. Heureusement, cela n'a pas d'importance, car la seule situation dansPlusMinus[-1, -1]
laquelle cela se produit est de ne pas être un OVSF valide de toute façon! (Si la condition revenaitTrue
, l'appel récursif signaleraitFalse
après tout, il n'a donc pas d'importance que la vérification ne fonctionne pas.) Nous ne pouvons pas utiliser la même astuce pour{a}==-{b}
parce que le-
fil ne déborderait pasFactorial
, il ne ferait que filerList
.Le patcher matcher prendra soin du reste et trouvera simplement la bonne définition à appliquer.
la source
Haskell, 57 octets
Étant donné la liste d'entrée
l
, développe un code OVSFs
en commençant[1]
et en concaténant à plusieurs reprises soits
ou-s
, selon ce qui fait que le premier élément correspond à celui del
. Ensuite, vérifie que le résultat estl
à la fin. Ceci est vérifié une foiss
sa longueur au moins égale àl
.Certaines structures récursives alternatives se sont également avérées donner 57:
la source
MATLAB / Octave , 94 octets
Ceci utilise une nouvelle approche: les codes de longueur OVSF autorisés
N
apparaissent dans lalog2(N)
-ème matrice de Walsh , car ils sont essentiellement définis par la même récursivité:Les matrices de Walsh sont des cas particuliers des matrices de Hadamard de taille
N x N
ifN
est une puissance de deux. (Il existe également des matrices Hadamard d'autres tailles.) MATLAB et Octave ont une variété de fonctions intégrées qui génèrent des matrices de test pour tester les propriétés des algorithmes numériques, entre autreshadamard()
. Heureusement pour les pouvoirs de deuxhadamard()
usex de MATLAB exactement la construction des matrices galloises.Donc, cette fonction vérifie d'abord si la longueur des entrées est une puissance de deux, et si c'est le cas, elle vérifie s'il s'agit d'une ligne de la matrice galloise de taille correspondante.
Essayez-le en ligne!
la source
Python, 64 octets
Divise la liste en éléments pairs et en éléments impairs indexés via des tranches. Vérifie si les vecteurs de résultat sont égaux ou négatifs en multipliant un par le signe forcé par son premier élément. Effectue ensuite la même vérification récursive sur les éléments pairs.
Pour le cas de base, si la vérification échoue, rejette sauf si la liste l'est
[1]
. La liste vide est également spécifiquement rejetée pour éviter une boucle infinie.Une stratégie différente comme ma réponse Haskell donne 66 octets:
la source
Haskell ,
106 91 8786 octetsLa fonction
g
génère l'n
itération des listes (relativement inefficace, carlength $ g n == 3^n
, si nous supprimions les doublons, nous l'obtiendrions2^n
),f
vérifie si notre liste est dans l'un d'eux. Merci à @Zgrab pour quelques conseils!Essayez-le en ligne!
la source
g
est très inefficace et produit une tonne de doublons. (Consultez la section de débogage , c'est probablement en raison du temps ou des limitations de mémoire.)JavaScript (ES6),
13093878583 octetsDémo
la source
JavaScript (ES6),
8561 octetsVersion précédente qui vérifiait les éléments pour s'assurer qu'ils étaient
1
ou-1
:Explication:
a[22] == a[2] * a[4] * a[16]
. Commea[20] == a[4] * a[16]
a déjà été vérifié, il suffita[22] == a[2] * a[20]
de le vérifier.i
ne pas avoir défini au moins deux bits. Dans le cas d'un jeu de bits zéro, il vérifie quea[0] == a[0] * a[0]
, ce qui est fauxa[0] == -1
, tandis que dans le cas d'un jeu de bits, il vérifie celaa[i] == a[0] * a[i]
.la source
(l=a.length)&&!(l&l-1)
pour(l=a.length)&-l==l
enregistrer 4 octetsl==0
?(l=a.length)&&l&-l==l
? pour économiser 1 octet ...[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1]
même sans mes suggestions.l&-l==l
ne fonctionne pas car==
a une priorité plus élevée que&
. Et le cas de test ne fonctionne pas à cause d'une faute de frappe qui va me coûter un octet à corriger.MATL ,
2120 octetsEssayez-le en ligne! Ou vérifiez tous les cas de test .
Comment ça marche
Le code divise le tableau en deux morceaux de longueur égale: le premier avec les entrées indexées impaires, le second avec les entrées indexées paires. Les deux pièces sont obligées d'avoir une longueur égale, avec un rembourrage nul dans la seconde si besoin. Ensuite, le code vérifie que
Si ces trois conditions sont remplies, le processus est appliqué à nouveau sur la première pièce. Si la boucle est quittée car la longueur était déjà 1, l'entrée est un code OFSV. Sinon, ce n'est pas le cas.
La condition 1 itérée est une version équivalente de la propriété de définition des codes OVSF. Pour un tableau de longueur disons 8, l'approche simple serait de vérifier que les entrées 1, 2, 3, 4 sont toutes égales ou toutes différentes des entrées 5, 6, 7, 8 respectivement (c'est la propriété qui définit). Mais nous pouvons vérifier de manière équivalente que les entrées 1,3,5,7 sont toutes égales ou toutes différentes des entrées 2,4,6,8 respectivement; et cela s'avère utiliser moins d'octets.
La condition 2 garantit que la longueur d'entrée est une puissance de 2: si ce n'est pas le cas, un zéro de remplissage sera introduit à un moment donné.
la source
Haskell, 66 octets
Oui, des listes infinies!
Versions alternatives:
la source
(0-)
astuce, j'étais coincé avecnegate
ou((-1)*)
APL, 46 octets
Assez simple:
0::0
: si une erreur se produit, retourne 0⍵≡,1:1
: si l'entrée est exactement[1]
, retourne 1⍬≡⍵:0
: si l'entrée est la liste vide, retourne 0Z←.5×⍴⍵
:Z
est la moitié de la longueur de l'entréeY←⍵↓⍨Z
:Y
est la dernière moitié de l'entrée (cela échoue si elle⍴⍵
est inégale, déclenchant le gestionnaire d'exceptions)(∇Y)∨∇-Y
: soit la dernière moitié de la liste, soit la négation de la dernière moitié de la liste, doit être un code OVSF(∇Z↑⍵)∧
: et la première moitié de la liste doit être un code OVSF.la source
Haskell,
6968 octetsExemple d'utilisation:
g [-1,1]
->False
.Encore plus inefficace que la réponse de @ flawr . Cela prend trop de temps et de mémoire pour 4 listes d'éléments. Pour voir que la liste des codes OVSF (avec beaucoup de doublons) est réellement créée, essayez:
qui revient
c'est-à-dire que la liste commence avec les 16 listes d'éléments (4 fois concaténées, à cause de
[1..4]
), continue avec les 8 listes d'éléments et ainsi de suite jusqu'à ce qu'elle se termine par[1]
.Modifier: @xnor a enregistré un octet. Merci!
la source
scanr
!any(elem x)
au lieu deelem x$c
ne pas définirc
.Python 2 ,
7875 octetsEssayez-le en ligne!
la source
JavaScript (ES6), 80
Construit récursivement et vérifie chaque liste jusqu'à la longueur de la liste d'entrée, en commençant par
[1]
.La valeur de retour est JS véridique ou falsey, spécifiquement
1
outrue
si valide,0
oufalse
ouundefined
si non valide.Tester
la source
Clojure, 118 octets
Divise l'entrée
c
en deux moitiésa
etb
vérifie si leurs produits par élément sont tous identiques. Si c'est le cas, vérifie que la première moitié est une séquence valide.Celui-ci fait 142 octets mais je l'ai trouvé plus intéressant:
loop
calculelog_2
la longueur de l'entrée,iterate
génère des séquences de ce nombre d'itérations en fonction de la définition. Cela renvoie l'argument d'entrée s'il s'agit d'une séquence valide etnil
sinon.la source