> <> Hors de l'eau

20

Le poisson bien-aimé qui nage à travers le code de > <> (un langage de programmation ésotérique) a été retiré de son environnement naturel. Ce changement l'a rendu incapable de se déplacer comme d'habitude: ce qui était autrefois un mouvement toroïdal a été limité à un simple mouvement de gauche à droite. Mais> <> les programmes sont toujours écrits comme si le poisson était capable de se déplacer à travers eux. C'est votre tâche, cher programmeur, d'écrire un programme pour linéariser un programme> <>. Et faites-le en aussi peu d'octets que possible; les poissons n'ont pas de très grands souvenirs.

Mouvement dans> <>

Dans> <>, le mouvement est toroïdal et un caractère à la fois. Cela signifie que le poisson (le pointeur) peut «s'enrouler» de la fin d'une ligne jusqu'au début. Dans> <>, le poisson est également capable de se déplacer de haut en bas, de bas en haut et de droite à gauche, contrairement à la façon dont la plupart des pointeurs se déplacent. Donc, ce modèle de mouvement serait valide:

>>>^  >>>v
   >>>^  v

et il se terminerait sur une boucle infinie (rebouclant sur la ligne supérieure une fois qu'il franchit infiniment le bas).

Le poisson se déplace dans une grille de longueur égale à max (longueur de ligne) et de hauteur égale au nombre de lignes.

Comment déterminez-vous dans quelle direction le poisson se déplace? Ces commandes modifient le vecteur de direction du mouvement (par exemple (-1,0), de droite à gauche):

Command | Direction Change
---------------------------
   >    | (1,0) (default)
   <    | (-1,0)
   ^    | (0,1)
   v    | (0,-1)
   /    | (x,y) -> (y,x)
   \    | (x,y) -> (-y,-x)
   |    | (x,y) -> (-x,y)
   _    | (x,y) -> (x,-y)
   #    | (x,y) -> (-x,-y)
   ;    | (0,0)

Comme indiqué, le poisson commence à se déplacer de gauche à droite, c'est-à-dire avec un vecteur de direction (1,0). Le poisson commence à analyser les commandes en commençant par la première commande qu'il voit et change de direction si une commande correspond à l'un des changeurs de direction susmentionnés.

Le poisson cesse de bouger lorsqu'il voit un ;et termine le programme.

Contribution

L'entrée sera un programme valide (par exemple pas en boucle infinie) donné via STDIN. Vous pouvez également lire un fichier si vous le souhaitez. Les lignes de chaque programme ne seront pas nécessairement de la même longueur.

L'entrée est donnée sous forme de chaîne, avec des sauts de ligne séparant chaque ligne du programme.

Les programmes ne boucleront pas, ce qui signifie également qu'ils se termineront toujours par a ;.

Production

La sortie sera le programme linéarisé. Autrement dit, vous devez retourner tous les caractères (y compris les changeurs de direction) que le poisson verrait s'il exécutait le programme "normalement". C'est tous les personnages sur son chemin vers le ;.

Si l'entrée contient des lignes de longueur inégale et que le poisson finit par se déplacer le long d'une ligne plus courte que la longueur de la ligne la plus longue, vous devez traiter cela comme si le poisson se déplaçait sur un espace (voir les cas de test).

Ceux qui sont familiers avec> <> sauront que les changeurs de direction ne sont pas le seul moyen d'y faire du mouvement, mais pour des raisons de simplicité, traitez l'entrée comme s'ils étaient le seul moyen d'affecter le mouvement.

Règles

  1. Des échappatoires standard s'appliquent
  2. Vous pouvez écrire soit un programme complet soit une fonction
  3. L'entrée est fournie via STDIN ou un fichier sous la forme d'une chaîne contenant les lignes de programme séparées par des sauts de ligne ( \n)
    • Vous pouvez prendre la saisie différemment, dans des limites raisonnables (n'hésitez pas à me demander si vous avez une sorte spécifique de contribution à l'esprit). Vous ne pouvez pas remplir l'entrée avec des espaces afin que les longueurs de ligne correspondent.
    • Reportez-vous à cette méta-publication concernant la saisie flexible. Dans l'état actuel de l'affichage, le consensus général doit être aussi flexible que possible dans les limites du raisonnable.
  4. La sortie est une chaîne unique via STDOUT ou renvoyée par la fonction (selon ce que vous choisissez de faire, voir la règle 2)

Cas de test

v     >v
>abcv//;
gfed<^ih

v>abcv<defghi^//>v;



v     >v
>abcv//;
gfed<^

v>abcv<defg  ^//>v;


abcdef;

abcdef;


abcd|;

abcd|dcba;


abcd#;

abcd#dcba;


abcd\;
    _

abcd\_\dcba;


^;
>abcde/
 ^jihg<

^ >abcde/ <ghij^a;


;

;
cole
la source
2
Pouvons-nous prendre l'entrée comme un tableau de chaînes?
Luke
2
Peut-on supposer que le premier caractère (celui en haut à gauche) ne sera pas un point-virgule?
Kritixi Lithos
1
@KritixiLithos bonne question, je vais dire que vous ne pouvez pas supposer cela. Je vais ajouter un cas de test.
cole
1
@Luke vous pouvez prendre l'entrée comme un tableau de chaînes s'il est très difficile ou impossible d'opérer sur le format d'entrée (chaîne avec des lignes séparées par des retours à la ligne). Voir la règle 3 désormais ajoutée.
cole
3
Vote positif pour justification absurde
Patrick Roberts

Réponses:

13

Röda , 405 393 392 391 371 366 361 236 234 232 230 223 200 octets

F f{L=f()|[#_]|sort|tail
c=""x=0
y=0
X=1
Y=0{l=f[y]l.=[" "]*(L-#l)c=l[x]a=X
[c]
C=indexOf(c,`><v^/\|_#`)X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]x+=X
x=x%L
y+=Y
y=y%#f}until[c=";"]}

Essayez-le en ligne!

Vérifiez les sorties!

Explication (obsolète)

F f{                          /* Declares a function F with parameter f */
                              /* Takes a 2D array of single-char Strings as f */
L =                           /* L contains the value of the length of the longest line*/
    f()                       /* Push the contents each element of f to the stream; this pushes each line*/
        | [#_]                /* Pull a line and push its length to the stream*/
               |sort|tail     /* Sort it and get the last value (the largest one) */
c=""                          /* c contains the value of the current char that is being processed */
x=0; y=0                      /* x and y contain the position of the fish */
X=1; Y=0                      /* X and Y contain the direction of the fish */
{ ... }while [c != ";"]       /* While c is not `;` do: */
l=f[y]                        /*  l is the line (row) the fish is at */
c=" " if [x >= #l]            /*  If x is more than or equal to the line's length, set c to a space (so that we don't need to pad spaces to the array at the beginning)*/
else c = l[x]                 /*  Else set c to the character a position x of l*/
[c]                           /*  Push c to the output stream; ie prints c without a trailing newline*/
a = X                         /*  a preserves the value of X before analysing c */
C = indexOf(c,`><v^/\|_#`)    /*  Simple enough */
X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]/*  Map each value of C to their respective X-direction in the array */
                              /*  If c cannot be found in `><v^/\|_#` then it will be given the value of -1, or in other words, the -1th element of an array its last element */
Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]/*  Do the same thing for Y */
x += X                        /*  Change the x-pos by the X-direction */
x = x%L                       /*  Wrap around the right edge */
y += Y                        /*  Do the same for y */
y=y%#f                        /*  But wrap around the bottom instead */
x+=L if[x<0]                  /*  Wrap around the left */
y+=#f if[y<0]                 /*  Wrap around the top */
}

Modifications

  • 10 octets économisés grâce à @fergusq en utilisant %au lieu de vérifier si x ou y dépasse les limites, ce qui a ouvert la voie à 2 autres!
  • Utilisé `\`au lieu de"\\"
  • Déplacé c=""vers la deuxième ligne, puis supprimé la nouvelle ligne qui la suit
  • Déplacement de la conversion des lignes en tableau à un caractère dans les boucles plutôt qu'au début (inspiré par la réponse Python)
  • Utilisé la syntaxe d'accolade de while(merci à @fergusq pour l'avoir repéré)
  • Déplacement des a=Xinstructions if
  • Merci à @fergusq d'avoir trouvé un moyen plus court de trouver la longueur de la ligne la plus longue
  • Syntaxe de tableau utilisée au lieu d'instructions if (comme la réponse Python) pour économiser des tonnes d'octets
  • Suppression du code qui remplissait les espaces, à la place des espaces sont ajoutés à mesure que le> <> se déplace
  • Correction d'un bug grâce et golfé un personnage grâce à @fergusq
  • Suppression du code +1à la fin indexOfet restructuration pour économiser 2 octets
  • Sauvegardé 2 octets en déplaçant les choses (merci encore à @fergusq)
  • 1 octet enregistré grâce à @fergusq en utilisant une méthode différente de remplissage des espaces
  • 1 octet enregistré en utilisant until[c=";"]au lieu dewhile[c!=";"]
  • Grâce à un indice de @fergusq, j'ai supprimé la boucle qui remplit les espaces et l'ai remplacée par l.=[" "]*L
  • Enregistré plus de 20 octets en supprimant les instructions if à la fin qui enveloppent le programme sur les bords gauche et supérieur
Kritixi Lithos
la source
Je pense que vous pouvez économiser quelques octets en utilisant x=((x+X)%#l)au lieu de x+=X. Malheureusement, (-1)%#lrevient toujours -1.
fergusq
@fergusq Golfed your suggestion :)
Kritixi Lithos
Vous pouvez l' utiliser avec ytrop: y=y%#f.
fergusq
@fergusq Était sur le point d'ajouter cela :)
Kritixi Lithos
J'ai pensé à cela plus, voici deux autres conseils de golf: utiliser à la keyplace de cmpet utiliser à la {...}while[...]place de while[...]do ... done.
fergusq
10

Python 2, 262 243 237 235 234 233 231 221 219 218 217 octets

Prend l'entrée comme ['<line_1>', '<line_2>', ...]

i=input()
q=max(map(len,i))
i=[k+' '*q for k in i]
x=y=k=0
j=1
o=''
while';'not in o:r=[1,-1,-j,-k,0,0];o+=i[y][x];l='><#\\v^/|_'.find(o[-1]);a=(r+[k,-j,j])[l];k=([k,-k,k,j]+r)[~l];j=a;x=(x+j)%q;y=(y-k)%len(i)
print o

Essayez-le en ligne!

-19 octets grâce à @math_junkie
-6 octets grâce à @ThisGuy
-2 octets en extrayant max(map(L,i))vers une variable (car elle est théoriquement utilisée deux fois).
-1 octet en réduisant le nombre d' i[y][x]apparitions.
-1 octet en utilisant '\x00'donc je n'ai pas à faire la [1:]partie de o[1:]la sortie
-2 octets en utilisant \0au lieu de \x00
-10 octets grâce à @KritixiLithos pour se rendre compte que je peux remplir autant que je veux sur le côté droit parce que le extra sera ignoré
(pas de changement d'octet) bug fixe car la variable extraite était en dehors de la boucle
-2 octets car maintenant je n'utilise que len2 fois donc la réaffectation prend 2 octets supplémentaires
-2 octets en utilisant while';'not in oau lieu dewhile o[-1]!=';'et en utilisant o=''au lieu de o='\0'. Cela permet non seulement d'économiser 2 octets, mais aussi de supprimer le premier octet nul qui n'était techniquement pas vraiment valide.

Explication

i = input()                       # Takes input as an array of strings
q = max(map(len,i))               # Finds the width of the longest line
i = [k + ' ' * q for k in i]      # Makes sure everything is at least that width
x = y = k = 0                     # Set the point to (0, 0). Set the vertical motion to 0
j = 1                             # Set the horizontal motion to 1
o = '\0'                          # Initialize the output to a null byte (this is output as nothing, so it doesn't actually affect output)
while o[-1] != ';':               # While the last character in the output is not ';' (this is why the output needs to be initialized with something, otherwise o[-1] gives an index error)
    r = [1,-1,-j,-k,0,0]          # Some of the vertical and horizontal coordinates correspond in opposite order
    o += i[y][x]                  # Add the current character to the output
    l = '><#\\v^/|_'.find(o[-1])  # Find the index of the current character here (or -1 if it's just a regular character)
    a = (r + [k, -j, j])[l]       # The fancy array contains the horizontal movement for each control character
    k = ([k, -k, k, j] + r)[~l]   # The fancy array contains the vertical movement for each control character. Using ~l to get the right index, because r has the values backwards
    j = a                         # a was a placeholder because otherwise k would not be correct
    x = (x + j) % q               # Adjust the pointer position
    y = (y - k) % len(i)          # Adjust the pointer position
print o                           # Print the output after the loop is finished
HyperNeutrino
la source
Vous pouvez jouer au golf trydepuis le findretour -1s'il n'est pas trouvé: TIO
math junkie
@math_junkie Oh d'accord, merci!
HyperNeutrino
Vous pouvez affecter lenà une variable, par exemple Lpour enregistrer 3 octets et 4 autres en changeant l'affectation multiligne 0en 1 ligne x=y=k=0.
caird coinheringaahing
@ThisGuy Merci!
HyperNeutrino
2
@Cole Dans mon golf suggéré, j'ai ajouté j et k à la fin de chaque tableau. C'est ainsi que la direction est maintenue
junkie mathématique
5

Rubis, 274 200 187 183

Réduit quelques caractères supplémentaires en supprimant le tableau de quantité de mouvement, d .

Je suis assez fier de celui-ci. C'était amusant! Il prend un tableau de chaînes et renvoie la chaîne appropriée.

->a{o,x,y='',-1,0
b,m=1,0
(o+=n=a[y=(y+m)%a.size][x=(x+b)%(a.map &:size).max]||' '
b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[2*('><^v/\\|_#'.index(n)||9),2])until o[?;]
o}

Commenté ci-dessous.

->a{
    o,x,y='',-1,0  # o is the output string, x and y are the positions in the array
    b,m=1,0          # b and m are the direction of momentum
    until o[?;] # until o contains a semicolon
        w=(a.map &:size).max # w is the max width of the arrays
        h=a.size    # h is the height of arrays
        x=x+b % w   # increment cursor position
        y=y+m % h
        o+=n=a[y][x]||' ' # add the new char (or " ") to o
        ix=2*('><^v/\\|_#'.index(n)||9) # find the index new char in the string
        b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[ix,2] # set momentum to its new value
    end
    o # return output string
}
Pas que Charles
la source
1

PHP 7, 291 260 octets

for($m=max(array_map(strlen,$z=explode("
",$argv[1]))),$y=0,$r=count($z)-$v=1;';'!=$c;[$v,$w]=[[$v,1,-1,0,0,-$w,$w,-$v,$v,-$v][$o=strpos(' ><^v/\|_#',$c)],[$w,0,0,-1,1,-$v,$v,$w,-$w,-$w][$o]],$x+=$m+$v,$x%=$m,$y=0<=($y+=$w)?$r<$y?:$y:$r)echo$c=$z[$y][$x]??' ';
chocochaos
la source
Je compte 291 octets / caractères.
HyperNeutrino
Vous avez raison, j'échoue à compter apparemment = P
chocochaos
Hah ne t'inquiète pas, j'ai fait ça aussi.
HyperNeutrino
J'ai trouvé certaines choses au golf, ce qui a diminué de 25% à 218 octets. Non testé, mais définitivement vaut détour .
Titus
2
une faille dans l'un de mes golfs et six octets de plus: liste de golf mise à jour .
Titus
1

JavaScript, 242 236 235 231 220 octets

a=>{n=a.length;m=x=y=p=0;a.map(g=>m=(w=g.length)<m?m:w);q=1,o="";while((t=a[y][x]||" ")!=";")o+=t,h=q,q=[q,1,0,p,-q][(s=">v\\| <^/_#".indexOf(t)+1)%5]*(r=s>5?-1:1),p=[p,0,1,h,p][s%5]*r,x=(x+q+m)%m,y=(y+p+n)%n;return o+t}

Essayez-le en ligne!

fəˈnɛtɪk
la source
vous pouvez enregistrer 13 caractères si vous prenez la chaîne sous forme de tableau. Les spécifications ont été modifiées.
Pas que Charles