Ma boîte à musique à 4 notes peut-elle jouer cette chanson?

51

J'ai une boîte à musique à manivelle pouvant jouer une série de quatre notes. Lorsque je tourne la manivelle, une des quatre cordes est pincée, en fonction de la position de la manivelle et de la direction du virage. Lorsque la manivelle est tournée plein nord, la boîte (avec ses chaînes numérotées de 1 à 4) ressemble à ceci:

1  |  2
   |
   O   

4     3

À partir de là, je peux tourner la manivelle dans le sens des aiguilles d'une montre pour pincer la ficelle n ° 2 et pointer la manivelle vers l'est:

1     2

   O---   

4     3

Alternativement, j'aurais aussi pu tourner la manivelle dans le sens antihoraire depuis le nord pour jouer la corde n ° 1 et se terminer par une manivelle pointant vers l'ouest:

1     2

---O   

4     3

La boîte peut alors jouer à tout moment l'une des deux notes suivantes: la note suivante disponible dans le sens des aiguilles d'une montre ou la note suivante dans le sens inverse des aiguilles d'une montre.

Défi

Votre défi consiste à écrire un programme ou une fonction qui accepte une chaîne de valeurs de note non vides (c.-à-d. Des chiffres à 1travers 4) et à déterminer s'il est toujours possible de jouer cette séquence de notes sur la boîte à musique. Produisez un résultat de vérité ou de falsification pour indiquer la possibilité de jouer ou non de l'entrée.

Quelques notes:

  • L'entrée ne fait aucune hypothèse sur la position de départ initiale. Les entrées 214(en partant de l’est et en se déplaçant dans le sens contraire des aiguilles d’une montre) et 234(en partant du nord et en se déplaçant dans le sens des aiguilles d’une montre) et valables.

  • La manivelle peut se déplacer librement dans les deux sens après chaque note. Une série de la même note est possible (par exemple 33333) en se déplaçant d'avant en arrière sur une chaîne. La série 1221441est parfaitement jouable (en partant de l’ouest, en effectuant deux pas dans le sens horaire, puis trois pas dans le sens inverse des aiguilles d’une montre, puis deux pas dans le sens horaire).

Des échantillons

Quelques truecas:

1
1234
1221
3333
143332
22234
2234
22214
1221441
41233

Quelques falsecas:

13     (note 3 is never available after note 1)
1224   (after `122`, the crank must be north, so 4 is not playable)
121    (after `12` the crank is east; 1 is not playable)
12221  (as above, after `1222` the crank is east)
43221  
apsillers
la source
L'entrée peut-elle être la chaîne avec des guillemets?
Luis Mendo
@LuisMendo Bien sûr, je le permettrai - votre algorithme m'intéresse, mais ne vous oblige pas à sauter entre les cerceaux pour obtenir l'entrée. Quoi qu'il en soit, il existe un consensus non officiel dans la communauté selon lequel tout va bien: entrée de chaîne avec ou sans “”?
apsillers
1
Je ne savais pas ça. Merci pour le lien!
Luis Mendo
1
@AJMansfield Non, les solutions devraient permettre un nombre arbitraire de cycles. Bien sûr, si certaines entrées entraînent un dépassement de la limite de votre code dans l'interpréteur de votre langue ou dans la mémoire de votre ordinateur, c'est très bien (car il est simplement limité par la quantité de mémoire que vous avez physiquement ou que votre interprète permet.), Mais votre solution ne doit pas imposer de limitations supplémentaires. sur quelle distance ou combien de fois la manivelle se déplace.
apsillers
1
Ce défi a remporté la catégorie Pas aussi simple que ça en a l'air dans Best of PPCG 2016. Malheureusement, nous ne pouvons pas donner de primes aux défis, mais Zgarb a écrit un défi en votre honneur . Toutes nos félicitations!
Martin Ender

Réponses:

9

Pyth, 30 27 octets

f!-aVJ.u%-ysYN8zTtJ,1 7cR2T

Voici l'idée:

 1.5  1  0.5

  2       0

 2.5  3  3.5

La manivelle est toujours à un demi-entier c. À chaque étape, nous réfléchissons sur une note de position entière npar réglage c = 2*n-c. Si nest valide, cchange de ± 1 mod 8. Si nest invalide, cde ± 3 mod 8. Nous réduisons de manière cumulative sur l'entrée pour collecter toutes les valeurs de c, puis voir si toutes les notes sont valides. Nous faisons cela pour chaque valeur de départ de c, parce que c'est plus court que de cocher juste celles adjacentes à la première note.

Formaté:

f
  ! -
      aV J .u
              % -
                  y s Y
                  N
                8
              z
              T
         t J
      ,
        1 
        7
  cR2 T

Suite de test .

lirtosiast
la source
18

CJam, 34 à 31 octets

8,q{~2*f{_@-_zF8b&,@@+8,=*}0-}/

Je l'ai fait sur mon téléphone, alors je vais devoir donner une explication plus tard. La sortie est non vide si et seulement la vérité.

Essayez-le en ligne | Suite de tests

Explication

Le nouveau code modifie légèrement la mise en page:

2    3    4

1    .    5

0/8  7    6

Les nombres pairs correspondent aux positions des cordes et les nombres impairs correspondent aux positions des manivelles.

Voici ce qui se passe:

8,           Create the range [0 1 .. 7] of possible starting positions
             We can leave the string positions [0 2 4 6] in since it doesn't matter
q{ ... }/    For each character in the input...
  ~2*          Evaluate as integer and double, mapping "1234" -> [2 4 6 8]
  f{ ... }     Map over our possible current crank positions with the string
               position as an extra parameter
    _@-          Calculate (string - crank), giving some number in [-7 ... 7]
    _z           Duplicate and absolute value
    F8b          Push 15 base 8, or [1 7]
    &,           Setwise intersection and get length. If (string - crank) was in
                 [-7 -1 1 7] then the move was valid and this evaluates to 1, otherwise 0
    @@+          Calculate ((string - crank) + string)
    8,=          Take modulo 8, giving the new crank position. x%y in Java matches the
                 sign of x, so we need to do ,= (range + index) to get a number in [0 .. 7]
    *            Multiply the new crank position by our previous 0 or 1
  0-           Remove all 0s, which correspond to invalid positions

La pile est alors automatiquement imprimée à la fin. Toutes les positions possibles de fin seront dans la sortie, par exemple pour l'entrée , 1la sortie est 31, ce qui signifie que la manivelle peut se terminer face à gauche ou vers le haut.

Si seulement CJam avait un filtre avec paramètre supplémentaire ...


Edit: Revenir temporairement en arrière pendant que je me persuade que ce 29 octets fonctionne:

8,q{~2*f{_@-_7b1#@@+8,=|}W-}/
Sp3000
la source
37
Chaque fois que quelqu'un répond avec un langage difficile comme cjam et dit "cela a été fait sur mon téléphone", je meurs un peu à l'intérieur
Dennis van Gils
2
Il voulait probablement dire que le texte avait été écrit à l'aide d'un téléphone, mais c'était dans sa tête.
Nelson
7

Haskell, 93 88 87 octets

any(all(\(a,b:c)->1>mod(a!!1-b)4).(zip=<<tail)).mapM((\a->[[a,a+1],[a+1,a]]).read.pure)

Cela donne une fonction anonyme qui prend une chaîne et retourne un booléen. Suite de test ici.

Explication

L'idée est que le lambda sur la droite mappe un nombre asur [[a,a+1],[a+1,a]], les deux "mouvements" possibles qui prennent la manivelle sur ce nombre, selon le schéma suivant:

  1 (2) 2

(1/5)  (3)

  4 (4) 3

Dans la fonction principale anonyme, nous réalisons d’abord mapM((...).read.pure), qui convertit chaque caractère en un entier, lui applique le lambda ci-dessus et choisit l’un des deux mouvements, en renvoyant la liste de toutes les séquences de mouvements obtenues. Ensuite, nous vérifions si l’une de ces séquences a la propriété que le deuxième nombre de chaque déplacement est égal au premier nombre du prochain modulo 4, ce qui signifie qu’il s’agit d’une séquence physiquement possible. Pour ce faire, nous zipdéplaçons chacun une séquence avec la sienne tail, vérifions la condition alldes paires et voyons si la anyséquence est évaluée True.

Zgarb
la source
7

Rétine, 50 octets

A`13|31|24|42|(.)(?!\1)(.)(\2\2)*(\1|\2(?!\1|\2).)

Je pense que ça marche?

Essayez ici.

jimmy23013
la source
6

Rétine , 127 109 octets

^((1|2)|(2|3)|(3|4)|(4|1))((?<2-5>1)|(?<5-2>1)|(?<3-2>2)|(?<2-3>2)|(?<4-3>3)|(?<3-4>3)|(?<5-4>4)|(?<4-5>4))*$

Cela imprime 0ou 1, en conséquence.

Essayez-le en ligne! (Ceci est une version légèrement modifiée qui marque toutes les correspondances dans l’entrée au lieu d’être imprimées 0ou 1.)

J'ai essayé de concevoir un algorithme élégant, mais mes premières tentatives n'ont pas réussi à contourner le retour en arrière ... et implémenter le retour en arrière est ennuyant ... solution valable. Malheureusement, le codage est assez détaillé et assez redondant ... Je suis sûr que cela peut être raccourci.

Pendant que j'essaie de trouver quelque chose de plus ordonné, si quelqu'un veut comprendre comment cela fonctionne, voici une version un peu plus lisible:

^
(
    (?<a>1|2)
  | (?<b>2|3)
  | (?<c>3|4)
  | (?<d>4|1)
)
(
    (?<a-d>1) | (?<d-a>1)
  | (?<b-a>2) | (?<a-b>2)
  | (?<c-b>3) | (?<b-c>3)
  | (?<d-c>4) | (?<c-d>4)
)*
$

Et voici un indice:

1  a  2

d  O  b

4  c  3
Martin Ender
la source
6

MATL , 57 55 octets

1t_hjnZ^!t1tL3$)2_/wvG1)UGnl2$Ov+Ys.5tv3X53$Y+4X\G!U=Aa

Ceci utilise la version actuelle (10.2.1) , qui est antérieure à ce défi.

EDIT (17 janvier 2017): en raison de changements de langue,v doit être remplacé par &v, et tL3$)par Y)(d'autres améliorations pourraient en outre être apportées ). Le lien suivant inclut ces deux modifications

Essayez-le en ligne!

Explication

Ceci est basé sur deux de mes outils préférés pour le golf de code: force brute et convolution .

Le code définit le chemin suivi par la manivelle en termes de coordonnées 0.5, 1.5etc. Chaque nombre indique la position de la manivelle entre les notes. Le code crée d'abord un tableau de chemins avec tous les chemins possibles commençant par la première note de la chaîne d'entrée. Chaque chemin est une colonne de ce tableau. C'est la composante de la force brute .

À partir de ce tableau de chemins, un tableau de notes est obtenu, où chaque colonne est une séquence réalisable de notes jouées. Par exemple, le déplacement d'une position 0.5à 1.5une autre produit 1. Cela consiste à prendre la moyenne entre les positions puis à appliquer une opération modulo 4. La moyenne courante sur chaque colonne est réalisée avec une convolution 2D .

Enfin, le programme vérifie si une colonne du tableau de notes coïncide avec l'entrée.

1t_h        % row array [1, -1]
j           % input string
nZ^!        % Cartesian power of [1, -1] raised to N, where "N" is length of string
t           % duplicate
1tL3$)      % extract first row
2_/         % divide by -2
wv          % attach that modified row to the top of Cartesian power array
G1)U        % first character of input string converted to number, "x"
Gnl2$O      % column array of N-1 zeros, where N is length of input
v           % concat vertically into column array [x;0;0...;0]
+           % add with singleton expansion
Ys          % cumulative sum along each column. Each column if this array is a path
.5tv        % column array [.5;.5]
3X5         % predefined string 'same' (for convolution)
3$Y+        % 2D convolution of path array with [.5;.5]
4X\         % modified modulo operation. This gives note array with values 1,2,3,4
G!U         % column array of input string characters converted to numbers
=Aa         % true if any column of the note array equals this
Luis Mendo
la source
5

Pyth, 43

Km-R2sMdc`M%R4-VJjQTtJ`0|Fm!s-VKdCm_B^_1dlK

Suite de tests

C’est probablement très golfable, et ce n’est pas l’algorithme optimal pour jouer au golf (je pense que tous les chemins seront énumérés plus courts?) ... Quoi qu’il en soit, si vous trouvez une erreur dans l’algorithme, faites-le-moi savoir. 'ai eu tort avant!

Je vais expliquer mon algorithme en utilisant l'exemple de saisie de 1221. Ce premier programme associe les chiffres contre leurs successeurs, comme suit: [[1,2],[2,2],[2,1]]. Ensuite , il obtient leurs différences mod 4(Pyth obtient le résultat qui correspond au signe de l'argument de droit %, donc ce qui est toujours positif): [3,0,1]. Ensuite , les résultats sont divisés sur 0et ont 2soustrait de chacun d'eux: [[1],[-1]].

Maintenant que la configuration est terminée, nous créons une liste de [-1,1,-1...]et sa négation [1,-1,...], les deux ayant la même longueur que le tableau résultant précédent. Ensuite, pour chacune de ces listes, effectuez une soustraction succincte entre les éléments de la liste et la liste générée à l'étape précédente. Ensuite, si l'un des résultats ne contient que des listes vides, nous produisons true.

FryAmTheEggman
la source
Qu'entendez-vous par "les résultats sont répartis sur 0"? En particulier, qu'obtenez-vous pour 1221221et 1221441?
Neil
1
@Neil 1221221est false et 1221441donne true dans l'ensemble, mais si je comprends bien, vous voulez le résultat après cette étape de l'algorithme? Si tel est le cas, cela donne: de [3, 0, 1, 3, 0, 1]à [[3], [1, 3], [1]]et [3, 0, 1, 1, 0, 3]à [[3], [1, 1], [3]]. Faites-moi savoir si vous voulez quelque chose d'autre expliqué :)
FryAmTheEggman
Je pense que je suis plus confus qu'auparavant, pouvez-vous donc terminer ces deux exemples pour expliquer comment les résultats (corrects) sont obtenus?
Neil
1
@Neil Bien sûr, pas de problème :) À partir de là, nous faisons la soustraction pour obtenir: [[1], [-1, 1], [-1]]et à [[1], [-1, -1], [1]]partir de là, vous pouvez voir que la première ne contient pas de listes alternant entre -1et 1tandis que l'autre liste le fait, donnant le résultat final. L'algorithme est un peu obtus, mais en gros, il mappe les changements de 0direction en sens +/-1puis, en vérifiant qu'aucun saut n'est effectué et que les sens ont un sens.
FryAmTheEggman
Oh, donc le peu qui me manquait était que chaque liste scindée devait contenir la même valeur, et que ces valeurs devaient alterner. Merci!
Neil
4

Matlab, 279 180 octets

o=eye(4);a=input('')-'0';M=[o,o(:,[4,1:3]);o(:,[2:4,1:4,1])];x=2;for p=[a(1),mod(a(1),4)+1];for k=a;i=find(M*[o(:,k);o(:,p)]>1);if i;p=mod(i-1,4)+1;else;x=x-1;break;end;end;end;x>0

Une solution assez paresseuse, mais la plus courte que j'ai pu trouver. J'ai créé matrice spéciale: Lorsque vous codez l'état de la plumeuse et la dernière chaîne qui doit être cueilli, il retourne un vecteur, qui code pour la nouvelle position de la plumeuse, et si la précédente plumer était possible du tout. Nous allons maintenant parcourir toutes les notes des deux positions de départ possibles et voir si l’une d’elles produit une mélodie jouable. Peut probablement être joué au golf beaucoup plus.

Source étendue et expliquée:

o=eye(4);
a=input('')-'0';

% encoding of plucker/notes
%      1
%   1     2
%4           2
%   4     3
%      3
%

M=[...
%12 3 4 1 2 3 4 <
1,0,0,0,0,1,0,0; %1  k = current note
0,1,0,0,0,0,1,0; %2  
0,0,1,0,0,0,0,1; %3  
0,0,0,1,1,0,0,0; %4  
0,0,0,1,0,0,0,1; %1  p = current position of plucker
1,0,0,0,1,0,0,0; %2
0,1,0,0,0,1,0,0; %3
0,0,1,0,0,0,1,0];%4
% the vector we multiply with this matrix has following structure,
% the k-th and the p+4 th entries are 1, the rest 0
% when we multiply this vecotr with this matrix, we get a vector with an
% entry of value 2 IF this is a valid move ( mod(positionOfThe2 -1,4)+1 is
% the position of the plucker now)
% or only entries less than 2 it is impossible
x=2;  %number of "chances" to get it right
for p=[a(1),mod(a(1),4)+1] %check both starting values;
    for k=a;                %loop throu the notes
        size(M);

        c = M * [o(:,k);o(:,p)];
        i=find(c>1);               %did we find a 2?
        if i;
           p=mod(i-1,4)+1;         %if yes, valid move
        else;
            x=x-1;                 %if no, invalid, 
            break;
        end 
    end
end
x=x>0 %if we failed more than once, it is not possible
flawr
la source
4

ES6, 104 à 100 octets

s=>!/13|24|31|42|3[24]{2}1|4[13]{2}2|1[24]{2}3|2[13]{2}4|(.).\1/.test(s.replace(/(.)(\1\1)+/g,"$1"))

Edit: 4 octets enregistrés grâce à @DigitalTrauma.

C'est une réécriture complète car mon approche précédente était imparfaite.

Je commence par réduire tous les nombres de chiffres à 1 ou 2, selon qu’il s’agisse d’un nombre impair ou pair. Je cherche alors toutes les combinaisons illégales:

  • 13|24|31|42 (côtés opposés)
  • 3[24]{2}1comme 3221et 3441sont illégaux
  • de même pour 4xx2, 1xx3et 2xx4xest l'un des chiffres manquants
  • (.).\1comme des choses comme 121sont illégales ( 111a été réduit à 1plus tôt)

S'il n'y a pas de paires ou de "triples" illégaux, alors toute la chaîne est légale (la preuve par induction est laissée à titre d'exercice, car il fait tard ici).

J'ai essayé de simplifier en 3[24]{2}1|1[24]{2}3utilisant une affirmation d'anticipation négative, mais elle s'est avérée être plus longue de cette façon.

Neil
la source
f("1122") => true@DigitalTrauma
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Je ne vois rien de mal à cela. D'un autre côté, j'ai compris que f("1221221")la mauvaise réponse était renvoyée. Je vais donc devoir repenser.
Neil
Il est toujours agréable d'inclure une suite de tests. '43221' échoue: jsbin.com/vafitotequ/1/edit?js,console
Pavlo
@Pavlo Whoops, je joué au golf [24][24]à (2|4)\1mais je ne l' avais pas testé de manière adéquate. Désolé pour ça.
Neil
Pouvez-vous jouer [24][24]au golf [24]{2}?
Digital Trauma
2

JavaScript (ES6), 80 octets

s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r

Explication

i%4 est la position actuelle du vilebrequin:

    1 (i%4 == 1) 2   

(i%4 == 0) (i%4 == 2)

    4 (i%4 == 3) 3   

Indenté et commenté

s=>
  [r=0,1,2,3].map(i=> // i = crank position, test for i starting at 0 to 3, r = result
    [...s].map(n=>    // for each note n
      n-1-i%4?        // if n is not at the position after i
        n%4-i%4?      // if n is not at the position before i
          v=0         // set the result of this test to invalid
        :i+=3         // else i-- (+3 used because i%4 would break for negative values)
      :i++,           // else i++
      v=1             // v = result of test, initialise to 1 (valid)
    )
    |v?r=1:0          // if the test returned true, set the result to true
  )
  |r                  // return the result

Tester

var solution = s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r
<input type="text" value="1221441" oninput="result.textContent=solution(this.value)" />
<pre id="result"></pre>

utilisateur81655
la source
Bien fait. Souhaitez-vous expliquer comment |fonctionne dans ce cas?
Pavlo
1
@pavlo Merci. C'est une façon d'écrire plus courte (x.map(...),v). Cela fonctionne parce que le tableau dans lequel les mapretours retournent 0et 0|v == v.
user81655
2

Lua , 146 142 108 162 159 149 144 135 132 118 113 octets

z,q,s=0,0,io.read()for i in s:gmatch'.'do t=i-z if 2==math.abs(t)or t==q then return''end q=-t z=i end return 2>1

Renvoie true ou false pour une chaîne de nombres comprise entre 1 et 4. (Ne gère pas les données inexistantes ou hors limites.

Suit simplement ce qui était le dernier mouvement et vérifie si ce mouvement est une inversion du dernier mouvement (IE, 121 ou 12221) ou si la distance parcourue est plus que possible.

EDIT 1 :

Enregistré 6 octets. J'ai oublié que if (int) thenrenvoie vrai si int est non nul.

Ainsi:

if t~=0 then

changements à:

if t then

Également enregistré quelques octets en restructurant.

EDIT 2 :

Je suis en train de comprendre cela lentement. J'ai lu la documentation ici: http://www.lua.org/pil/ Et l'une des pages les plus utiles pour le golf est http://www.lua.org/pil/3.3.html

En particulier, cela est très utile:

Comme pour les structures de contrôle, tous les opérateurs logiques considèrent false et nil comme faux et toute autre chose comme vraie.

Cela signifie pour moi que je peux retirer ma déclaration pour q ( initialement définie sur 0 ), car elle sera considérée comme "fausse" jusqu'à ce qu'elle soit définie. Donc, je sauve quelques octets supplémentaires à travers cela.

Une autre chose à noter, bien que je ne l'utilise pas, est que si vous voulez échanger des valeurs dans Lua, vous pouvez simplement vous a,b=b,a passer de la nécessité d'une variable temporaire.

EDIT 3

Donc, grâce à une reconstruction intelligente ainsi qu’à une nouvelle fonction, le décompte d’octets a diminué de 9 de plus.

Meilleur mode de réception des entrées

Si vous avez besoin de lire une liste de nombres et d’opérer les opérations l’un après l’autre, vous pouvez utiliser:

for x in string:gmatch('.') do
    print(x) --This is our number
end

Par rapport à votre alternative en utilisant string: sub, vous pouvez voir la valeur pour le golf (ou l’utilisation générale):

for x=1,string:len() do
    print(string:sub(x,x)) --This is our number
end

Restructurer des fonctions ou des chaînes

Deuxièmement, si vous avez plusieurs déclarations sur une ligne et que l’une des valeurs est une fonction ou si vous avez une condition dans laquelle vous comparez un nombre au résultat d’une fonction comme celle-ci:

x,y,z=io.read(),0,0 print('test')

if math.abs(x)==2 then

en le restructurant de sorte que les parenthèses fermantes constituent le dernier caractère de la condition ou de la déclaration, vous pouvez supprimer un caractère comme suit:

y,z,x=0,0,io.read()print('test') --Notice no space

if 2==math.abs(x)then --If we put the '2' first in the conditional statement, we can now remove a space character

Renvoie des conditions équivalentes à Vrai ou à Faux au lieu de "Vrai" ou "Faux"

J'ai trouvé un moyen assez amusant de réduire mon décompte d'octets encore plus loin. Si vous devez renvoyer true ou false, vous pouvez renvoyer une instruction équivalente à true ou false contenant moins de caractères que "true" ou "false".

Par exemple, comparez:

return true
return false

À:

return 2>1
return 1>2
Skyl3r
la source
121devrait produire faux.
lirtosiast
Ah laisse tomber. Je vois.
Réparera sous
Vous pourriez être intéressé par l'ajout de certains de ces conseils Lua à Conseils pour le golf à Lua si vous ne les voyez pas déjà répertoriés.
apsillers
2

MATL, 49 octets (non concurrentes 1 )

1. La réponse (ab) utilise l'indexation moins stricte des nouvelles versions de MATL et n'aurait pas fonctionné au moment où ce défi a été posté.

dt~aX`tt~f1)q:)w3MQJh)_ht~a]tT-3hX|n2=wT_3hX|n2=+

Essayez-le en ligne! .

J'ai vu ce défi au Best of PPCG 2016 et j'ai pensé que cela pourrait utiliser mon opérateur préféré :

d

Ou bien, diffdans MATLAB / Octave (je vais utiliser librement la terminologie MATLAB / Octave dans mon explication, car elle est plus facile à lire pour les humains). Cette commande calcule la différence entre les éléments dans un vecteur ou, dans ce cas, dans un tableau de caractères.

Pour ce problème, les différences présentent un schéma intéressant. Notez que

Un changement de direction doit signifier qu'une note est jouée deux fois .

Pour le motif de différence (ignorer la 1-4transition pour le moment), cela signifie que

Un changement de connexion diff(input)doit comporter un nombre impair de zéros entre les deux. Inversement, le signe n'est pas autorisé à changer après un nombre pair de zéros.


J'ai implémenté cela en trouvant, pour chaque tableau, le premier zéro. Je coupe le zéro et multiplie tous les éléments après -1. Pour le résultat final, cela signifie que tous les éléments doivent avoir le même signe. Bien sûr, il y a le petit problème de l' -3égalisation +1, et du fait d' 2être interdit en général. J'ai résolu ce problème en prenant l'union d'ensemble du résultat avec [1 -3]et en vérifiant si elle est de taille 2 (c'est-à-dire qu'aucun élément non autorisé n'a été entré dans l'ensemble par l'intermédiaire de l'union). Répétez l'opération pour [-1 3]et vérifiez si (ou les deux, dans le cas d'une entrée de 1 longueur) est vraie.

d                                % Difference of input
 t~a                             % Check if any element equals 0
    X`                     t~a]  % Start while loop, ending in the same check
       t~                           % Get a new vector, logical negated to find zeroes.
          f1)                       % Find the position of the first zero. 
      t         q:)                 % Decrement by 1, to index all elements before that zero.
                   w3MQJh)          % Push the result of 'find', but increment to get all elements after.
                         _h         % Multiply the second half by -1, and concatenate horizontally.

  T-3hX|n2=                      % Check if set union with [1 -3] is size 2
 t        wT_3hX|n2=             % Check if set union with [-1 3] is size 2
                    +            % Logical OR. 
Sanchises
la source
@LuisMendo Merci. J'ai vraiment besoin de lire M, la dernière fois que j'ai essayé, cela a fonctionné différemment que prévu, donc je l'ai simplement ignoré pour le moment. Est-il correct de dire que cela doit être 3Mparce qu'alors je reçois l'entrée de not ), not :mais de q(sauter wcar ce n'est pas une fonction normale )?
Sanchises
Oui, exactement. west sauté parce que ce n'est pas une fonction normale. Les fonctions normales ne nécessitant aucune entrée seraient également ignorées
Luis Mendo, le
2

Python (3.5) 160 151 150 octets

Une solution récursive

def f(s):g=lambda s,c:s==''or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])if s==''or s[0]in c[:2]else 0;return any([g(s,"1234123"[i:])for i in range(4)])

Ungolfed sans lambda

def f(s):
    def g(s,c):
        if s=='' or s[0] in c[:2] :
            return s=='' or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])
        else:
            return False
    return any([g(s,"1234123"[i:]) for i in range(4)])

Je tourne toute la boîte au lieu de la manivelle. La position du vilebrequin se situe entre le premier et le deuxième caractère de la chaîne c. Je dois tester toutes les positions de départ de la manivelle.

Astuce utiliser pour faire pivoter la chaîne

La manière habituelle de faire pivoter une chaîne en python ( s[i:]+s[:i]) nécessite également de répéter index et chaîne. Dans ce cas, je duplique la chaîne et découpe les premiers caractères.

(c*2)                        # duplicate the string
     [(s[0]==c[0])*2+1       # test that return 1 if firsts characters match 3 instead 
                      :]     
                        [:4] # crop again to have a 4 characters string

Cas de test

[f(i) for i in ["1", "1234", "1221", "3333", "143332", "22234", "2234", "22214", "1221441", "41233", "13", "1224", "121", "12221", "43221"]]
[True, True, True, True, True, True, True, True, True, True, False, False, False, False, False]
Erwan
la source
1
Vous pouvez supprimer l'espace à l'adresse 3"[i:]) for.
Erik l'Outgolfer
@EriktheOutgolfer merci je l'enlève.
Erwan
1

JavaScript (ES2015), 110 95

p=(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))

15 octets sauvés par Neil! Version originale non-golfée:

p = (s, d) => {
  h = s[0]
  t = s.substr(1)

  if (!t[0]) return true
  if (!d) return p(s, 1) || p(s, -1)
  if (t[0] == h) return p(t, d*-1)
  if (t[0] == (h-d > 4 ? 1 : h-d || 4)) return p(t, d)

  return false
}

Tests: https://jsbin.com/cuqicajuko/1/edit?js,console

Pavlo
la source
1
17 octets vous ont été sauvés:(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))
Neil
Toujours pas aussi court que la réponse de @ user81655.
Neil
1

Code machine de Turing, 395 octets

0 1 _ r a
0 2 _ r b
0 3 _ r c
0 4 _ r d
a 1 _ r a
a 2 _ r E
a 3 _ r h
a 4 _ r S
b 1 _ r W
b 2 _ r b
b 3 _ r S
b 4 _ r h
c 1 _ r h
c 2 _ r N
c 3 _ r c
c 4 _ r W
d 1 _ r N
d 2 _ r h
d 3 _ r E
d 4 _ r d
N 1 _ r W
N 2 _ r E
N _ _ r r
N * _ r h
E 2 _ r N
E 3 _ r S
E _ _ r r
E * _ r h
S 3 _ r E
S 4 _ r W
S _ _ r r
S * _ r h
W 4 _ r S
W 1 _ r N
W _ _ r r
W * _ r h
h _ 0 r halt
h * _ r h
r _ 1 r halt

Essayez-le en ligne!

Ceci est essentiellement une approche basée sur les états:

  • L'état initial est 0.
  • a, b, cEt dsont des « états indécis » qui se produisent seulement au début
  • N, E, SEt Wsont les "états décidés", debout évidemment pour NOrth, East, South et West.
Fuite, nonne
la source
1

Jeudi, 203 octets

Je ne vois pas comment jouer au golf aussi loin.

0::=:::
>11::=>1
>22::=>2
>33::=>3
>44::=>4
>12::=b
>21::=d
>14::=c
>41::=a
>23::=c
>32::=a
>34::=d
>43::=b
a1::=d
a2::=b
b2::=a
b3::=c
c3::=b
c4::=d
d4::=c
d1::=a
a<::=~n
b<::=~e
c<::=~s
d<::=~w
::=
>0<

Si la séquence de notes est possible, la direction de la sortie sera indiquée, sinon la sortie sera vide.

MegaTom
la source
1

Prolog (SWI) , 117 octets

a(N,P):-P=N;N=1,P=4,!;P is N-1.
m([A,B|C],[X,Y|Z]):-a(A,X),a(B,X),a(B,Y),X\=Y,m([B|C],[Y|Z]).
m([_],_).
p(N):-m(N,_).

Définit un prédicat pqui réussit sur les entrées lisibles (donné comme une liste d’entiers) et échoue sur celles qui ne sont pas jouables. Essayez-le en ligne!

Explication

adéfinit une relation de contiguïté entre la note Net la position du pédalier P. Nous définissons la position p comme étant entre les notes p et p + 1 . Ainsi, une position est adjacente à la noteN ssi

  • il est égal à N( P=N); ou
  • la note est 1 et la position est 4 ( N=1,P=4); ou
  • le cas ci-dessus n'est pas vrai ( !) et la position est égale à N-1( P is N-1).

mprend une liste de notes et tente de générer une liste de positions qui joueront ces notes. Aest la note qui vient d'être jouée, Best la note sur le point d'être jouée; Xest la position actuelle du vilebrequin, Yest la position suivante du vilebrequin. Un déménagement est valable si et seulement

  • la note que vous venez de jouer est adjacente à la position actuelle de la manivelle ( a(A,X));
  • la note sur le point d'être jouée est également adjacente à la position actuelle de la manivelle ( a(B,X));
  • la note sur le point de jouer est adjacente à la position de vilebrequin suivante ( a(B,Y)); et
  • les deux positions de manivelle ne sont pas égales ( X\=Y).

Si tout cela tient, recurse. Si nous arrivons à une note ( m([_],_)), la séquence de notes est jouable.

Pour cette question, nous ne nous soucions que de l'existence d'une séquence de mouvements. Nous définissons pdonc appeler met ignorer la liste générée des positions de manivelle.

Voir une version non golfée et vérifier tous les cas de test ici .

DLosc
la source