Renversez des dominos!

22

Merci à cette question pour une certaine inspiration

Dans ce défi, nous représenterons une ligne de dominos sous la forme d'une chaîne de |, /et \. Vous recevrez une chaîne de dominos en entrée et vous devez déterminer à quoi ils ressemblent lorsqu'ils se sont installés. Voici les règles de chute des dominos

  • Un domino debout |, à gauche d'un domino tombé à gauche \, deviendra également un domino tombé à gauche.

  • Un domino debout |, à droite d'un domino tombé à droite /, deviendra également un domino tombé à droite.

  • Si un domino debout se trouve entre un domino tombé à gauche \et un /domino tombé à droite , il restera debout.

Ces règles sont appliquées à plusieurs reprises jusqu'à ce que l'arrangement ne change plus.

Voici un exemple de la façon dont une seule entrée peut arriver à sa conclusion

|||||||\/|||||||\||\|||/||||||\|||||

||||||\\//|||||\\|\\|||//||||\\|||||
|||||\\\///|||\\\\\\|||///||\\\|||||
||||\\\\////|\\\\\\\|||////\\\\|||||
|||\\\\\////|\\\\\\\|||////\\\\|||||
||\\\\\\////|\\\\\\\|||////\\\\|||||
|\\\\\\\////|\\\\\\\|||////\\\\|||||

\\\\\\\\////|\\\\\\\|||////\\\\|||||

Votre tâche consiste à écrire du code qui trouve et génère le résultat final d'une entrée. Vous pouvez supposer que l'entrée est toujours valide et contient au moins 2 caractères.

Il s'agit de donc les réponses seront notées en octets, moins d'octets seront meilleurs.

Cas de test

|||/||||  -> |||/////
|||\||||  -> \\\\||||
|/||||\|  -> |///\\\|
||/|||\|  -> ||//|\\|
||\|||/|  -> \\\|||//
Assistant de blé
la source
6
Backslash s'échappant ahoy! (
Arnauld
1
@Arnauld Non, vous devez utiliser les barres obliques.
Wheat Wizard
1
Je ne peux pas ... savoir quoi échapper et quoi ne pas.
2018 totalement humain
L'entrée sera-t-elle jamais la chaîne vide ou un seul caractère?
Poignée de porte
3
Cela me dérange plus qu'il ne devrait que des choses comme `//////// | \ soient considérées comme stables.
MooseBoys

Réponses:

13

Rétine , 32 octets

+`(/.\\)|(/)\||\|(\\)
$1$2$2$3$3

Essayez-le en ligne!

Explication

Le +indique à Retina d'exécuter le remplacement dans une boucle jusqu'à ce qu'il ne parvienne pas à changer la chaîne. Chaque remplacement calcule une étape les dominos tombants. Le remplacement lui-même est en réalité trois remplacements en un, mais cela garantit qu'ils se produisent simultanément:

(/.\\)...
$1

Cela correspond juste /|\(ainsi que /\\et /\\, mais cela n'a pas d'importance) et le réinsère inchangé. Le but de ceci est de sauter |avec des dominos tombés des deux côtés, car cela est plus court que d'exclure ces cas avec des contournements séparés dans les deux autres cas.

...(/)\|...
$2$2

Cela correspond /|et le transforme en //.

...\|(\\)
$3$3

Cela correspond |\et le transforme en \\.

Martin Ender
la source
Je ne peux pas dire que je ne l'ai pas vu venir. La rétine est certainement un bon outil pour le travail.
Wheat Wizard
@WheatWizard C'est facile à résoudre, mais probablement encore trop verbeux avec tous les échappés et ça $1$2$2$3$3pour battre les langues du golf.
Martin Ender
5

Python 2 , 115 114 111 108 98 95 octets

-1 octet grâce aux ovs

a=input()
for i in range(4)*len(a):a=a.replace('//|x||\ \\'[i::4],'/\/x|\/ \\'[3-i::4])
print a

Essayez-le en ligne!

Barre
la source
114 octets utilisant des chaînes r.
ovs
Vous pouvez supprimer b=0;et remplacer les occurrences de bby idpour économiser deux octets!
Lynn
4

V , 23 octets

òÓ¯À<!|¨Ü©ü¨¯©|ÜÀ!/±±²²

Essayez-le en ligne!

Vraiment, c'est très similaire à la réponse de la rétine, juste qu'elle semble plus moche. Utilise la compression regex.

Hexdump:

00000000: f2d3 afc0 3c21 7ca8 dca9 fca8 afa9 7cdc  ....<!|.......|.
00000010: c021 2fb1 b1b2 b2                        .!/....

Explication:

òindique à V de s'exécuter jusqu'à ce que la chaîne ne change pas. Le reste est une expression rationnelle compressée. Convertissons-le en équivalent vim ...

:s/\v\/@<!\|(\\)|(\/)\|\\@!/\1\1\2\2/g

:s/                                     " Substitute...
   \v                                   " Turn on magic (use less escaping)
          \|                            " A bar
            (\\)                        " Followed by a captured backslash
       @<!                              " That is not preceded by
     \/                                 " A forward slash
                |                       " OR...
                 (\/)                   " A captured forward slash
                     \|                 " Followed by a bar
                       \\@!             " That is not followed by a backslash
                           /            " Replace this with
                            \1\1        " Pattern 1 twice (will be empty if we matched the second path)
                                \2\2    " Pattern 2 twice (will be empty if we matched the first path)
                                    /g  " Replace every match on this line
DJMcMayhem
la source
4

SNOBOL4 (CSNOBOL4) , 117 115 112 111 octets

	D =INPUT
S	D '/|\' ='_'	:S(S)
	E =D
	D '/|' ='//'
	D '|\' ='\\'
	D E	:F(S)
R	D '_' ='/|\'	:S(R)
	OUTPUT =D
END

Essayez-le en ligne!

Mention de la réponse de Rod en python pour l'idée de la condition d'arrêt avec une deuxième variable pour voir les changements plutôt que de tester D '/|' | '|\'.

	D =INPUT		;* read input
S	D '/|\' ='_'	:S(S)	;* replace '/|\' with '_', recursively
	E =D			;* set E to D, this is the while loop
	D '/|' ='//'		;* topple right
	D '|\' ='\\'		;* topple left
	D E	:F(S)		;* if D doesn't match E, goto S
R	D '_' ='/|\'	:S(R)	;* replace '_' with '/|\' (inverse of statement S)
	OUTPUT =D		;* output
END
Giuseppe
la source
3

Haskell , 114 107 octets

until=<<((==)=<<)$g
g s=t<$>zip3('|':s)s(tail s++"|")
t(l,'|',r)|l<'0',r/='\\'=l|r=='\\',l>'/'=r
t(_,e,_)=e

Essayez-le en ligne! La première ligne définit une fonction anonyme.

Explication:

  • until=<<((==)=<<)$gest une fonction de point fixe (voir ici pour une explication) qui applique la fonction gà la chaîne d'entrée jusqu'à ce que le résultat ne change plus.
  • zip3('|':s)s(tail s++"|")crée pour chaque domino, c'est-à-dire le caractère de la chaîne s, un triple avec le domino pré- et suivant, le rembourrage avec |sur les bords. Par exemple, /\|devient[(|,/,\),(/,\,|),(\,|,|)] (en ignorant la fuite).
  • Ensuite, la fonction test appliquée à chacun des triplets pour calculer la nouvelle position de la pièce centrale du triplet.
Laikoni
la source
2

Prolog (SWI) , 132 octets

+[]-->[].
+[47,124,92|T]-->"/|\\",+T.
+[47,47|T]-->"/|",+T.
+[92,92|T]-->"|\\",+T.
+[X|T]-->[X],+T.
X+Y:- +(N,X,[]),!,(X=N,Y=N;N+Y).

Essayez-le en ligne!

Ce programme définit un prédicat +/2 qui est vrai si le deuxième argument est la version réglée du premier. Les deux arguments sont des listes de codes de caractères.

Explication

Cette solution utilise un DCG pour déterminer quelle est l'étape suivante, puis calcule à plusieurs reprises l'étape suivante jusqu'à ce que l'étape suivante soit la même que l'étape en cours.

Le DCG

+[]-->[].
+[47,124,92|T]-->"/|\\",+T.
+[47,47|T]-->"/|",+T.
+[92,92|T]-->"|\\",+T.
+[X|T]-->[X],+T.

Ces cinq lignes de code définissent une règle DCG (Definite Clause Grammar) +utilisée dans le programme pour calculer une seule étape de basculement des dominos. Les DCG dans Prolog fonctionnent en trouvant le premier cas de la règle dont le côté droit correspond à la chaîne et en déterminant l'argument de la règle du côté gauche à travers ce processus. Si un cas ne correspond pas, il reviendra en arrière et tentera un cas plus tard.

+[]-->[].

Cette ligne représente le cas de base du + règle. Il indique simplement que s'il n'y a pas de dominos actuellement, à l'étape suivante, il n'y aura toujours pas de dominos.

+[47,124,92|T]-->"/|\\",+T.

Depuis que ce programme traite exclusivement des listes de codes de caractères , il est important de noter que les codes de caractères pour /, \et |sont 47, 92 et 124 respectivement. Ce cas de la +règle gère le/|\ chaîne.

+[47,47|T]-->"/|",+T.

Cet étui gère un domino tombant à droite renversant le domino à sa droite. Puisqu'il vient après le cas pour la manipulation/|\ il ne sera pas utilisé pour cette possibilité.

+[92,92|T]-->"|\\",+T.

Gère le boîtier pour un domino tombant à gauche renversant le domino à sa gauche.

+[X|T]-->[X],+T.

C'est le cas des caractères génériques. Étant donné que rien d'autre ne change en dehors de ce qui est décrit ci-dessus, tant qu'il reste du texte dans la chaîne d'entrée, il le copiera simplement vers la sortie tant qu'il ne correspond à aucun des cas ci-dessus.

Le prédicat

X+Y:- +(N,X,[]),!,(X=N,Y=N;N+Y).

Le prédicat principal prend deux arguments, le premier est la configuration initiale des dominos, le second les dominos installés. Comme il s'agit de Prolog, le second peut être indéterminé et le programme le calculera. Le prédicat en soi est assez simple +(N,X,[])appelle le DCG et calcule la prochaine étape des dominos qui le stockent N. (X=N,Y=N;N+Y)vérifie si la prochaine étape des dominos est la même que l'actuelle et si elle l'est, Ycar les dominos doivent s'être installés et si ce n'est pas le cas, elle se reproduit, en appelant le même prédicat à l'étape suivante des dominos Nau lieu de X.

0 '
la source
1

face , 166 octets

\|/,cm_/o>AvI[IIcP/+PP|m_/m*/Sl*Im1/11:~-_I|'|?_1-_P|?_1`I-III_|+II|'I.C:1-_I|?_C'|-_P|?_C_|'I-_I|`I?_!'I.C:!'|'|-III+II|'I:C_|-PPP+PPI'I?I~_I-PPP+PP|-**1?*~Sl*Iw*I*>

Prend l'entrée en tant qu'argument de ligne de commande et renvoie à STDOUT. Cela ne fonctionne que dans le commit 86494f6 et au-delà en raison d'un bug corrigé dans ce commit.

Enveloppé pour l'esthétique:

\|/,cm_/o>AvI[IIcP/+PP|m_/m*/Sl*Im1/11:~-_I|'|?_1-_P|?_1`I
-III_|+II|'I.C:1-_I|?_C'|-_P|?_C_|'I-_I|`I?_!'I.C:!'|'|-III
+II|'I:C_|-PPP+PPI'I?I~_I-PPP+PP|-**1?*~Sl*Iw*I*>

Et non golfé / commenté:

\|/,cm_/o>              ( setup )

AvI[II                  ( store input into I )
cP/+PP|m_/              ( store 92, ascii for \, into P, meaning prev char )
m*/Sl*Im1/11            ( store length of input into counter variable * )

( main loop: )
:~

    -_I|'|?_1           ( branch to 1 if the character is not \ )
    -_P|?_1             ( also branch to 1 if the previous character wasn't | )
    `I-III_|+II|'I      ( we have a sequence |\ so prev needs to be toppled )
    .C                  ( jump to C, the "continue" label at end of loop )

    :1
    -_I|?_C             ( branch to C if the character is not | )
    '|-_P|?_C           ( also branch to C if the previous character wasn't / )
    _|'I-_I|`I?_!       ( branch to ! if the next character isn't \ )
    'I.C:!              ( otherwise, skip the next \ and branch to continue )
    '|'|-III+II|'I      ( if all conditions hold we have /|| or /|/ so topple )

    :C
    _|                  ( reset pointer to source )
    -PPP+PPI            ( update prev variable )
    'I                  ( step through data )

?I~

_I-PPP+PP|-**1          ( reset input/prev and decrement counter )
?*~                     ( repeat main loop as many times as there are chars )

Sl*Iw*I*>               ( output final string to stdout )

Il y a quelques astuces subtiles ici qui rasent quelques octets supplémentaires, tels que

  • la dénomination des variables | et /, dont les valeurs ASCII sont accessibles via l'introspection plus loin dans le code

  • le '|sur la première ligne de la boucle principale, qui y est appelée au lieu de sur la deuxième ligne afin de définir le | pointeur à utiliser dans la deuxième section de la boucle principale

Poignée de porte
la source
1

Perl 5 , 52 + 1 (-p) = 53 octets

-6 octets grâce à mik

Probablement pas le meilleur possible pour Perl, mais c'est ce que j'ai pu trouver.

0while(s/(?<!\/)\|(?=(\\))|(?<=(\/))\|(?!\\)/$1$2/g)

Explication

while(
  s/
    (?<!\/)\|(?=(//)) # If there's a | that precedes a \ but doesn't follow a /, capture /
      | # Or
    (?<=(\/))\|(?!//)/ # If there's a | that follows a / doesn't precede a \, capture /
  /$1$2/ # Replace all | with capture group 1 or 2, as one of the two will always be empty
  g # Repeat as much as possible for this string
)

Essayez-le en ligne!

Geoffrey H.
la source
-pau lieu d' -aéliminer le besoin de print;; utiliser whilecomme suffixe pour une expression fictive (par exemple 0) permettra d'économiser encore 2 octets
mik
Merci @mik, je ne connaissais pas ces astuces. Je me rends également compte que je pourrais délimiter l'expression régulière avec autre chose pour économiser quelques octets. Pourrait y arriver plus tard.
Geoffrey H.
1

Perl 5 , 44 (code) + 1 ( -p) = 45 octets

1while s,(/)\|(?!\\)|(?<!/)\|(\\),$1$1$2$2,g

Essayez-le en ligne!

Explication

1while s,                        ,        ,g   while anything found substitute globally
         (/)\|(?!\\)              $1$1         /| that is not followed by \ to //
                    |                          or
                     (?<!/)\|(\\)     $2$2     |\ that is not preceded by / to \\
mik
la source
1

Nettoyer , 98 octets

import StdEnv
$['/|':t]=['//': $t]
$['|\\':t]=['\\\\': $t]
$[h:t]=[h: $t]
$e=e
f=until(\e=e== $e)$

Essayez-le en ligne!

Οurous
la source
0

Rubis , 83 octets

Techniquement cheatable avec 9.times, ou même juste 999.timesmais je n'ai pas envie d'être bon marché :)

Possède toujours un énorme potentiel de golf. (Remarque: y while undoneest beaucoup plus long que x.size.times)

->x{x.size.times{x.gsub! /\/\|\\?|\|\\/,'/|\\'=>'/|\\','/|'=>'//','|\\'=>'\\\\'}
x}

Essayez-le en ligne!

Unihedron
la source
0

R , 114 octets

function(d){g=gsub
for(i in 1:nchar(d))d=g("/|","//",g("|\\","\\\\",g("/|\\","_",d,f=T),f=T),f=T)
g("_","/|\\",d)}

Essayez-le en ligne!

Renvoie une chaîne d'échappement.

Giuseppe
la source
0

C (gcc) , 183 octets

D,i;f(char*S){char*s=malloc(-~strlen(S));for(D=1;D--;strcpy(S,s))for(strcpy(s,S),i=0;s[i];i++)s[i]>92&&(S[-~i]==92&&S[~-i]!=47&&(s[i]=92,D=1)||S[~-i]==47&&S[-~i]!=92&&(s[i]=47,D=1));}

Essayez-le en ligne!

Jonathan Frech
la source