Tabs halbieren

31

Heilige Kriege wurden um Leerzeichen und Tabulatoren geführt. (Und natürlich haben Räume gewonnen, die objektiv überlegen sind.) - Alex A.

S ome peo p le noch weigern , zu einem ccept dass WHI c h cl e arly s upreme. Sie haben gerade erhalten eine Datei mit dem incor re ct, b Anzeige und inf e rior Form von WHI t espace, und jetzt t er cont e nts der Datei ein r e verdorben und ruiniert.

Sie können der Person, die die Datei an Sie gesendet hat, auch zeigen, wie falsch sie ist - und zwar mit Gewalt.

Beschreibung

Wie der Titel schon sagt, besteht Ihre Herausforderung darin, eine Datei zu erstellen, die eine oder mehrere Registerkarten enthält:

this is an evil tab    onoes

und sie rücksichtslos in Stücke zerschmettern:

this is an evil tab

                     o
                     n
                     o
                     e
                     s

Beachten Sie, dass die Stack Exchange-Software Literal-Registerkarten in vier Leerzeichen umwandelt (weil es richtig ist), sodass Registerkarten in diesem Beitrag als vier Leerzeichen angezeigt werden. Die Eingabe in Ihr Programm enthält jedoch die eigentlichen Registerkarten.

Herausforderung

Die Lösung sollte eine einzelne Zeichenfolge als Eingabe verwenden, die druckbare ASCII-Zeichen, Zeilenumbrüche und Tabulatoren enthalten kann. In der Eingabe ist immer mindestens ein Tab enthalten.

Die Ausgabe sollte dieselbe Zeichenfolge sein und die folgenden Regeln enthalten:

  • Starten Sie den Cursor bei Koordinaten (0,0) und mit einer Richtung nach rechts. Die Koordinaten sind (Spalte, Zeile), mit einem Index von Null, und in welche Richtung soll der Cursor nach dem Drucken eines Zeichens bewegt werden.

  • Für jedes Zeichen in der Zeichenfolge:

    • Wenn es sich um eine neue Zeile handelt, gehen Sie zu den Koordinaten (0, n), wobei n die Anzahl der neuen Zeilen in der Zeichenfolge ist (einschließlich dieser), und setzen Sie die Richtung nach rechts zurück.

    • Wenn es sich um eine Registerkarte handelt, geben Sie zwei Leerzeichen aus, drehen Sie den Cursor um 90 Grad im Uhrzeigersinn und geben Sie zwei weitere Leerzeichen aus, wodurch die Registerkarte in zwei Hälften geteilt wird. Hier ist ein visuelles Beispiel, in dem eine Registerkarte als --->und Leerzeichen als dargestellt wird ·:

      foo--->bar--->baz
      

      wird

      foo···
           ·
           b
           a
           r
           ·
           ·
       zab··
      
    • Ansonsten geben Sie einfach das Zeichen am Cursor aus und bewegen den Cursor einen Schritt in die aktuelle Richtung.

Da Sie die Zeichenfolge von Anfang bis Ende lesen, müssen Sie möglicherweise "über" vorhandene Zeichen schreiben. Dies ist in Ordnung. Zum Beispiel die Eingabe

foo--->bar


spaces are superior

sollte zu einer Ausgabe von führen

foo

     b
spaces are superior
     r

Sie können wählen, ob "kaputte Tabulatoren" andere Zeichen überschreiben sollen - die ursprüngliche Absicht war, dass sie dies nicht tun, aber die Spezifikation war nicht eindeutig. Dies ist also Ihre Entscheidung.

Nachdem Sie diese Regeln angewendet haben, können Sie dies auch tun

  • Fügen Sie so viele Leerzeichen hinzu oder entfernen Sie sie, wie Sie möchten.

  • Fügen Sie maximal eine einzelne nachgestellte Zeile hinzu.

Die Eingabe enthält niemals nachgestellte Leerzeichen. Es wird auch niemals führende oder nachfolgende Zeilenumbrüche enthalten. Sie können auch immer davon ausgehen, dass Sie niemals in eine Spalte oder Zeile schreiben müssen, die kleiner als 0 ist (dh außerhalb des Bildschirms).

Testfall

Tabs werden in diesem Testfall so dargestellt, --->weil sie sonst von SE verschlungen werden.

Eingang:

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

Ausgabe:

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

Ausgefallene Animation:

Regeln

  • Das ist , also gewinnt der kürzeste Code in Bytes!
Türknauf
quelle
Wenn Sie sagen, der Cursor muss bei beginnen, (0,0)müssen wir dann zuerst die Konsole leeren, oder meinen Sie damit nur die Standardposition des Cursors?
Martin Ender
18
Ich stimme dafür, diese Frage als "Off-Topic" zu schließen, weil sie voller Hass und Gotteslästerung ist.
Aditsu
1
Ihre Animation ähnelt so sehr dem Interpreter> <>, dass ich jetzt einen selbstmodifizierenden Eintrag> <> sehen möchte.
Sanchises
1
Mir hat die versteckte Botschaft im ersten Absatz gefallen, aber ich muss nicht zustimmen.
wf4
@ MartinBüttner Das heißt nur die Standardposition.
Türklinke

Antworten:

8

MATLAB, 144 Bytes

Die Waffe der Wahl für den Umgang mit Strings ist natürlich eine Sprache, die für die Manipulation von Zahlen entwickelt wurde. Scherz beiseite, das Tolle an Matlab ist, dass es egal ist, ob Sie ein Array außerhalb der Grenzen zuweisen: Es wird einfach eine größere Matrix erstellen. Darüber hinaus wird das Standardmatrixelement 0als Leerzeichen anstelle eines in nullder ASCII-Spezifikation vorgeschriebenen Zeichens gerendert .

Tabulatoren sind einfach ein Sprung in die Koordinaten, sodass für einen Tabulator keine Leerzeichen ausgegeben werden.

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

Ich habe mit 209 Bytes angefangen, aber das meiste davon wurde durch vorsichtiges Golfen beseitigt. Dieser Code enthält viele Wiederholungen, daher habe ich einige Versuche durchgeführt, welche Alternativen am besten funktionieren. Ich denke, es gibt nicht viel Raum für mehr Optimierung mit diesem Code, aber ich bin immer froh, wenn ich mich als falsch erweisen kann. Edit: Tom Carpenter hat es geschafft, mir das Gegenteil zu beweisen. es gelang ihm, 9 Bytes zu speichern, die ich optimierte, um satte 29 Bytes zu speichern. Letztes Byte, das gespeichert wurde, wenn keine Steuerzeichen (ASCII <9) in der Eingabe vorhanden sind - MATLAB-Zeichenfolgen werden nicht abgeschlossen null.

Sanchises
quelle
Scheint nicht zu funktionieren. Ich habe es versucht q('hello<tab>my name<tab>is tom<tab>c'), aber es ist etwas in der Art von Attempted to access o(11,-2); on line 7. Dies hat möglicherweise mehr mit einem Problem in der Frage zu tun - wenn der Cursor rückwärts zeigt und über die erste Spalte hinausgeht, was mit dem Rest der Zeile geschieht.
Tom Carpenter
Ja, mein Schlechtes, ich habe das bisschen verpasst. Ich gehe jetzt weg;)
Tom Carpenter
1
Sie können durch das Entfernen der weiteren 9 Zeichen speichern dVariable und stattdessen vier Variablen, welche für eine Schleife , die [1 0 -1 0] Muster zu machen als solche: 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 (natürlich in den Kommentaren wobei alle Linien entfernt, so dass Sie werden um es wie deine neu zu formatieren, um zu sehen, was ich getan habe)
Tom Carpenter
@ TomCarpenter Das ist ... wirklich hässlich. Ich liebe es.
Sanchises
5

Python 3, 272 270 266 262 255 253 244 Bytes

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='')

Das \tsollte ein tatsächliches Tabulatorzeichen sein.

Der Code funktioniert ähnlich wie die Antwort von Zach Gates M By- MGrid in dem Mdie Summe der Linienlängen angegeben ist. (Das ist ein riesiger Überschuss, aber der Code wird kürzer.) Anschließend werden die Zeichen durchlaufen, an den richtigen Stellen platziert und die unterste besuchte Zeile verfolgt. Schließlich werden alle Zeilen bis zu dieser Zeile gedruckt.

Die Ausgabe enthält (normalerweise sehr viele) nachgestellte Leerzeichen und eine nachgestellte Zeile.

PurkkaKoodari
quelle
3

Javascript (ES6), 264 245 Bytes

Versuchte den Ansatz "Erstellen Sie ein riesiges Raster aus Leerzeichen, füllen und trimmen", der 19 Byte kürzer als der andere endete.

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())

Indem Sie die vorletzte Zeile wie folgt ändern, können Sie die große Anzahl von Leerzeichen in jeder Zeile entfernen:

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

Probieren Sie es hier aus:

Erklärung folgt in Kürze; Vorschläge willkommen!

ETHproductions
quelle
3

JavaScript (ES6), 180 183

Unter Verwendung von Vorlagenzeichenfolgen gibt es einige Zeilenumbrüche, die signifikant und gezählt sind.

Dies ist eine Funktion, die die angeforderte Ausgabe zurückgibt (aufgefüllt mit Tonnen von nachgestellten Leerzeichen).

Es gibt wenig zu erklären: Die Zeilen werden nach Bedarf erstellt. Es gibt keine Richtungsvariable, nur den 2-Versatz für x und y, da sie bei Drehung im Uhrzeigersinn einfach verwaltet werden können:dx <= -dy, dy <= dx

Testen Sie das folgende Snippet in 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
quelle
Ich wünschte, alle Sprachen hätten [x, y] = [Ausdruck1, Ausdruck2] ...
Sanchises
1

Python 2, 370 369 368 Bytes

Vielen Dank an @sanchises und @ edc65 , die mir jeweils ein Byte gespart haben.

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()

Es erzeugt das größtmögliche Gitter und durchläuft dann zeichenweise die Schaltrichtung auf jeder Registerkarte.

Zach Gates
quelle
Hinweis: if !dundif d>2
Sanchises
!dist keine gültige Syntax. @sanchises Danke für den d>2Tipp.
Zach Gates
Tut mir leid, ich kenne Python eigentlich nicht :) Ich habe einfach angenommen, dass es so funktionieren würde.
Sanchises
Ich verstehe auch Python nicht, aber wenn d in 0 ... 3, d==0->d<1
edc65
Ja, du hast recht. Danke für das Byte. @ edc65
Zach Gates