Casser les onglets en deux

31

Des guerres sacrées ont été menées contre des espaces contre des onglets. (Et bien sûr, les espaces, étant objectivement supérieurs, ont gagné.) - Alex A.

S ome PEO p le refusent encore à un V ALIDER que WHI c h est cl e arly s SUPRÊME. Vous venez de recevoir un fichier en utilisant le inté re ct, b ad et inf e forme de rior WHI t espace, et maintenant t que il cont e nts du fichier un r e frelatée et ruiné.

Vous décidez que vous pourriez aussi bien montrer à la personne qui vous a envoyé le fichier à quel point ils se trompent - violemment.

La description

Comme le titre l'indique, votre défi est de prendre un fichier contenant un ou plusieurs onglets:

this is an evil tab    onoes

et les briser impitoyablement en morceaux:

this is an evil tab

                     o
                     n
                     o
                     e
                     s

Notez que le logiciel Stack Exchange transforme les onglets littéraux en quatre espaces (car c'est exact), donc les onglets de ce message seront affichés comme quatre espaces. Cependant, l'entrée de votre programme contiendra des onglets réels.

Défi

La solution doit prendre une seule chaîne en entrée, qui peut contenir des caractères ASCII imprimables, des sauts de ligne et des tabulations. Il y aura toujours au moins un seul onglet dans l'entrée.

La sortie doit être la même chaîne, avec les règles suivantes appliquées:

  • Commencez le curseur aux coordonnées (0,0) et avec une direction de droite. Les coordonnées sont (colonne, ligne), indexées à zéro et la direction est le sens dans lequel vous devez déplacer le curseur après l'impression d'un caractère.

  • Pour chaque caractère de la chaîne:

    • S'il s'agit d'une nouvelle ligne, déplacez-vous vers les coordonnées (0, n), où n est le nombre de nouvelles lignes dans la chaîne jusqu'à présent (y compris celle-ci), et réinitialisez la direction vers la droite.

    • S'il s'agit d'un onglet, affichez deux espaces, faites pivoter le curseur de 90 degrés dans le sens des aiguilles d'une montre et affichez deux autres espaces, ce qui "brise" l'onglet en deux. Voici un exemple visuel, où un onglet est représenté par --->et des espaces comme ·:

      foo--->bar--->baz
      

      devient

      foo···
           ·
           b
           a
           r
           ·
           ·
       zab··
      
    • Sinon, il suffit de sortir le caractère au niveau du curseur et de déplacer le curseur d'un pas dans la direction actuelle.

Puisque vous lisez la chaîne du début à la fin, il est possible que vous deviez écrire "au-dessus" des caractères existants - ce n'est pas grave. Par exemple, l'entrée

foo--->bar


spaces are superior

devrait se traduire par une sortie de

foo

     b
spaces are superior
     r

Vous pouvez choisir si les "onglets cassés" doivent remplacer les autres caractères - l'intention initiale était qu'ils ne le fassent pas, mais la spécification était ambiguë, c'est donc votre décision.

En outre, après avoir appliqué ces règles, vous pouvez également

  • ajoutez ou supprimez autant d'espaces de fin que vous le souhaitez.

  • ajoutez un maximum d'une seule nouvelle ligne de fin.

L'entrée ne contiendra jamais d'espaces de fin; il ne contiendra également jamais de nouvelles lignes de début ou de fin. Vous pouvez également toujours supposer que vous n'aurez jamais besoin d'écrire dans une colonne ou une ligne inférieure à 0 (c'est-à-dire hors de l'écran).

Cas de test

Les onglets dans ce cas de test sont représentés comme --->sinon sinon SE les engloutit.

Contribution:

Test case. Here's a tab--->there's a tab--->everywhere a tab--->tab--->this is some more text
blah
blah
blah blah blah blah blah blah--->blaah--->blaah--->blah--->blaaaaah--->blah--->blah--->blah--->blah--->blah

Sortie:

Test case. Here's a tab
blah
blah                     t
blah blah blah blah blah blah
                        blaablah
                         r     b
                         e     l  b
                      h  'h    a  l
                      a  sa    a  a
                      l   l    h  h
       this is some mobe tbxt

                         haalhalb
     b                   a
     a                   b
     t

        bat a erehwyreve

Animation fantaisie:

Règles

  • Il s'agit de , donc le code le plus court en octets gagnera!
Poignée de porte
la source
Lorsque vous dites que le curseur doit commencer à (0,0), voulez-vous dire que nous devons d'abord effacer la console, ou voulez-vous simplement dire la position par défaut du curseur par cela?
Martin Ender
18
Je vote pour clore cette question comme hors sujet car elle est pleine de haine et de blasphème.
aditsu
1
Votre animation ressemble tellement à l'interpréteur> <> que je veux maintenant voir une entrée auto-modifiable> <>.
Sanchises
1
J'ai aimé le message caché dans le premier paragraphe mais je ne suis pas d'accord.
wf4
@ MartinBüttner Cela signifie simplement la position par défaut.
Poignée de porte

Réponses:

8

MATLAB, 144 octets

L'arme de choix pour traiter les chaînes est bien sûr un langage conçu pour manipuler les nombres [citation nécessaire]. Blague à part, la grande chose à propos de Matlab est qu'il ne se soucie pas si vous attribuez à un tableau `` hors limites '': il fera simplement une matrice plus grande. De plus, l'élément de matrice par défaut,, 0est rendu sous forme d'espace au lieu d'un nullcaractère prescrit par la spécification ASCII.

Les tabulations sont simplement un saut de coordonnées, donc aucun espace n'est généré pour une tabulation.

function o=q(t)
u=2;v=0;x=1;y=1;n=1;for s=t
if s==9 x=x+u-v;y=y+v+u;a=v;v=u;u=-a;elseif s<11
n=n+1;x=1;y=n;else
o(y,x)=s;x=x+u/2;y=y+v/2;end
end

J'ai commencé avec 209 octets, mais un golf plus prudent s'est débarrassé de la plupart de cela; il y a beaucoup de répétition dans ce code, j'ai donc fait quelques essais et erreurs sur les alternatives qui fonctionnaient le mieux. Je ne pense pas qu'il y ait beaucoup d'espace pour plus d'optimisation avec ce code, mais je suis toujours heureux d'avoir tort. Edit: Tom Carpenter a réussi à me prouver le contraire; il a réussi à économiser 9 octets que j'ai optimisé pour enregistrer un énorme 29 octets. Dernier octet enregistré en supposant qu'il n'y a pas de caractères de contrôle (ASCII <9) dans l'entrée - les chaînes MATLAB ne sont pas nullterminées.

Sanchises
la source
Ne semble pas fonctionner. J'ai essayé cela q('hello<tab>my name<tab>is tom<tab>c'), mais c'est quelque chose dans le sens de Attempted to access o(11,-2); on line 7. Bien que cela puisse être davantage lié à un problème dans la question - si le curseur se dirige vers l'arrière et dépasse la première colonne, qu'arrive-t-il au reste de la ligne.
Tom Carpenter
Oui, mon mauvais, j'ai raté ce morceau. Je m'en vais maintenant;)
Tom Carpenter
1
Vous pouvez enregistrer 9 autres caractères en supprimant la dvariable et en ayant à la place 4 variables qui, pour une boucle, créent le modèle [1 0 -1 0] en tant que tel: function o=q(t) u=1;v=0;w=-1;z=0;x=0;y=1;n=1;for s=t if s==9 x=x+2*u-2*v;y=y+2*v+2*u;a=z;z=w;w=v;v=u;u=a;elseif s==10 n=n+1;x=0;y=n;else x=x+u;y=y+v;o(y,x)=s;end end (étant évidemment dans les commentaires, il a supprimé toutes les lignes, vous aurez donc pour le reformater comme le vôtre pour voir ce que j'ai fait)
Tom Carpenter
@TomCarpenter C'est ... vraiment moche. J'aime cela.
Sanchises
5

Python 3, 272 270 266 262 255 253 244 octets

I=[]
try:
 while 1:I+=[input()]
except:r=m=0
M=sum(map(len,I))
O=[M*[' ']for _ in[0]*M]
for l in I:
 x=b=0;y=r;a=1;r+=1
 for c in l:
  if'\t'==c:a,b=-b,a;x+=a+2*b;y+=b-2*a
  else:O[y][x]=c
  x+=a;y+=b;m=max(m,y)
for l in O[:m+1]:print(*l,sep='')

Le \tdevrait être un caractère de tabulation réel.

Le code fonctionne un peu comme la réponse de Zach Gates, générant d'abord une grille Mpar MMest la somme des longueurs des lignes. (C'est une énorme quantité d'excès, mais rend le code plus court.) Il parcourt ensuite les caractères, les place aux bons endroits, en gardant une trace de la ligne la plus visitée. Enfin, il imprime toutes les lignes jusqu'à cette ligne.

La sortie contient (généralement une énorme quantité) d'espaces de fin et 1 nouvelle ligne de fin.

PurkkaKoodari
la source
3

Javascript (ES6), 264 245 octets

J'ai essayé l'approche «créer une grille géante d'espaces, remplir et découper», qui s'est avérée 19 octets plus courte que l'autre.

a=t=>(o=`${' '.repeat(l=t.length)}
`.repeat(l).split`
`.map(q=>q.split``),d=x=y=z=0,s=c=>o[d>2?y--:d==1?y++:y][d?d==2?x--:x:x++]=c,[...t].map(c=>c=='\t'?(s` `,s` `,++d,d%=4,s` `,s` `):c==`
`?(x=d=0,y=++z):s(c)),o.map(p=>p.join``).join`
`.trim())

En modifiant ainsi l'avant-dernière ligne, vous pouvez supprimer la grande quantité d'espaces de fin sur chaque ligne:

...o.map(p=>p.join``.trimRight())...

Essayez-le ici:

Explication à venir; suggestions bienvenues!

ETHproductions
la source
3

JavaScript (ES6), 180 183

À l'aide de chaînes de modèle, il existe des nouvelles lignes qui sont importantes et comptées.

C'est une fonction renvoyant la sortie demandée (rembourrée avec des tonnes d'espaces de fin)

Il y a peu à expliquer: les rangées sont construites comme nécessaires. Il n'y a pas de variable de direction, juste le décalage de 2 pour x et y, car dans la rotation dans le sens horaire, ils sont facilement gérés:dx <= -dy, dy <= dx

Testez l'exécution de l'extrait ci-dessous dans Firefox

f=s=>[...s].map(c=>c<`
`?(x+=2*(d-e),y+=2*(e+d),[d,e]=[-e,d]):c<' '?(y=++r,e=x=0,d=1):(t=[...(o[y]||'')+' '.repeat(x)],t[x]=c,o[y]=t.join``,x+=d,y+=e),o=[r=x=y=e=0],d=1)&&o.join`
`

// TEST  

// Avoid evil tabs even in this source 
O.innerHTML = f(`Test case. Here's a tab--->there's a tab--->everywhere a tab--->tab--->this is some more text
blah
blah
blah blah blah blah blah blah--->blaah--->blaah--->blah--->blaaaaah--->blah--->blah--->blah--->blah--->blah`
 .replace(/--->/g,'\t'))
<pre id=O></pre>

edc65
la source
Je souhaite que toutes les langues aient [x, y] = [expr1, expr2] ...
Sanchises
1

Python 2, 370 369 368 octets

Merci à @sanchises et @ edc65 de m'avoir sauvé un octet chacun.

J=''.join
u=raw_input().replace('\t','  \t  ')
w=u[:]
G=range(len(u))
d,r=0,[[' 'for _ in G]for _ in G]
u=u.split('\n')
for t in G:
 x,y=0,0+t
 for c in u[t]:
  if c=='\t':d=(d+1)%4
  if c!='\t':
   if c.strip():r[y][x]=c
   if d<1:x+=1
   if d==1:y+=1
   if d==2:x-=1
   if d>2:y-=1
r=r[:max(i for i,n in enumerate(r)if J(n).strip())+1]
for i in r:print J(i).rstrip()

Il génère la plus grande grille possible et boucle ensuite, caractère par caractère, en changeant de direction à chaque onglet.

Zach Gates
la source
Astuce: if !detif d>2
Sanchises
!dn'est pas une syntaxe valide. @sanchises Merci pour l' d>2astuce, cependant.
Zach Gates
Désolé, je ne connais pas vraiment python :) Je suppose que cela fonctionnerait comme ça.
Sanchises
Moi aussi, je ne comprends pas python, mais si d dans 0 ... 3, d==0->d<1
edc65
Oui, tu as raison. Merci pour l'octet. @ edc65
Zach Gates