Podziel zakładki na pół

31

Święte wojny toczyły się o spacje kontra karty. (I oczywiście przestrzenie, będąc obiektywnie lepszymi, wygrały.) - Alex A.

S OMe PEO P le jeszcze śmieci do w ccept że WHI c h Cl e arly Ś upreme. Właśnie otrzymaliśmy do pliku przy użyciu INCOR re ct, b reklamę i inf e formularz rior whi t espace, a teraz t he cd e NTS pliku r e skażony i zniszczony.

Ty decydujesz, że równie dobrze możesz pokazać osobie, która przesłała ci plik, jak bardzo się mylą - gwałtownie.

Opis

Jak sugeruje tytuł, Twoim wyzwaniem jest pobranie pliku zawierającego jedną lub więcej kart:

this is an evil tab    onoes

i bezwzględnie rozbija je na kawałki:

this is an evil tab

                     o
                     n
                     o
                     e
                     s

Zauważ, że oprogramowanie Stack Exchange zamienia dosłowne tabulatory na cztery spacje (ponieważ ma rację), więc tabulatory w tym poście będą wyświetlane jako cztery spacje. Dane wejściowe do programu będą jednak zawierać rzeczywiste zakładki.

Wyzwanie

Rozwiązanie powinno przyjmować pojedynczy ciąg jako dane wejściowe, które mogą zawierać ASCII do drukowania, znaki nowej linii i tabulatory. Na wejściu zawsze będzie przynajmniej jedna zakładka.

Dane wyjściowe powinny być tego samego łańcucha, przy zastosowaniu następujących reguł:

  • Rozpocznij kursor od współrzędnych (0,0) i kierunku w prawo. Współrzędne to (kolumna, rząd), indeksowane od zera, a kierunek to kierunek, w którym należy przesuwać kursor po wydrukowaniu znaku.

  • Dla każdego znaku w ciągu:

    • Jeśli jest to nowa linia, przejdź do współrzędnych (0, n), gdzie n to liczba nowych linii w ciągu (do tej pory) i zresetuj kierunek w prawo.

    • Jeśli jest to tabulator, wypisz dwie spacje, obróć kursor o 90 stopni zgodnie z ruchem wskazówek zegara i wypisz jeszcze dwie spacje, skutecznie „dzieląc” tab na pół. Oto wizualny przykład, w którym karta jest reprezentowana jako, --->a spacje jako ·:

      foo--->bar--->baz
      

      staje się

      foo···
           ·
           b
           a
           r
           ·
           ·
       zab··
      
    • W przeciwnym razie po prostu wypisz znak na kursor i przesuń kursor o jeden krok w bieżącym kierunku.

Ponieważ czytasz ciąg znaków od początku do końca, możliwe jest, że będziesz musiał napisać „na wierzchu” istniejących znaków - to jest w porządku. Na przykład dane wejściowe

foo--->bar


spaces are superior

powinien dać wynik

foo

     b
spaces are superior
     r

Możesz wybrać, czy „zepsute karty” powinny zastępować inne znaki - pierwotna intencja była taka, że ​​nie, ale specyfikacja była dwuznaczna, więc to twoja decyzja.

Ponadto, po zastosowaniu tych zasad, możesz również

  • dodaj lub usuń tyle spacji, ile chcesz.

  • dodaj maksymalnie jeden końcowy znak nowej linii.

Dane wejściowe nigdy nie będą zawierać spacji końcowych; nigdy nie będzie zawierał wiodących ani końcowych znaków nowej linii. Zawsze możesz również założyć, że nigdy nie będziesz musiał pisać do kolumny lub wiersza mniejszej niż 0 (tj. Poza ekranem).

Przypadek testowy

Karty w tym przypadku testowym są reprezentowane jako, --->ponieważ w przeciwnym razie SE je pożera.

Wkład:

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

Wydajność:

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

Fantazyjna animacja:

Zasady

  • To jest , więc wygra najkrótszy kod w bajtach!
Klamka
źródło
Kiedy mówisz, że kursor musi zaczynać się od początku (0,0), masz na myśli, że najpierw musimy wyczyścić konsolę, czy masz na myśli jedynie domyślną pozycję kursora?
Martin Ender
18
Głosuję za zamknięciem tego pytania jako nie na temat, ponieważ jest pełne nienawiści i bluźnierstwa.
aditsu
1
Twoja animacja wygląda tak bardzo jak interpreter> <>, że chcę teraz zobaczyć samodmodyfikujący się wpis> <>.
Sanchises
1
Podobała mi się ukryta wiadomość w akapicie otwierającym, ale muszę się z tym nie zgodzić.
wf4,
@ MartinBüttner To tylko oznacza pozycję domyślną.
Klamka

Odpowiedzi:

8

MATLAB, 144 bajty

Broń wybrana do radzenia sobie z ciągami znaków jest oczywiście językiem przeznaczonym do manipulowania liczbami [potrzebne źródło]. Żartując na bok, wielką zaletą Matlaba jest to, że nie przejmuje się tym, że przypiszesz tablicę „poza granice”: po prostu zrobi większą matrycę. Ponadto domyślny element macierzy 0, jest renderowany jako spacja zamiast nullznaku zalecanego przez specyfikację ASCII.

Tabulatory są po prostu skokiem współrzędnych, więc dla tabulacji nie są wyświetlane spacje.

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

Zacząłem od 209 bajtów, ale trochę bardziej ostrożnego golfa pozbyłem się większości; w tym kodzie jest wiele powtórzeń, więc zrobiłem kilka prób i błędów, które alternatywy działały najlepiej. Nie sądzę, że dzięki temu kodowi jest dużo miejsca na dalszą optymalizację, ale zawsze cieszę się, że udowodniono mi błąd. Edycja: Tom Carpenter udowodnił, że się mylę; udało mu się zapisać 9 bajtów, które zoptymalizowałem, aby zaoszczędzić aż 29 bajtów. Ostatni bajt zapisany przy założeniu, że na wejściu nie ma znaków kontrolnych (ASCII <9) - łańcuchy MATLAB nie są nullkończone.

Sanchises
źródło
Nie wydaje się działać. Próbowałem tego q('hello<tab>my name<tab>is tom<tab>c'), ale to coś w stylu Attempted to access o(11,-2); on line 7. Chociaż może to być bardziej związane z problemem w pytaniu - jeśli kursor przesuwa się do tyłu i wykracza poza pierwszą kolumnę, co dzieje się z resztą wiersza.
Tom Carpenter,
Tak, mój zły, tęskniłem za tym. Teraz odejdę;)
Tom Carpenter
1
Możesz zapisać kolejne 9 znaków, usuwając dzmienną i zamiast tego mając 4 zmienne, które dla pętli tworzą wzór [1 0 -1 0] jako taki: 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 (oczywiście będąc w komentarzach usunął wszystkie linie, więc będziesz mieć aby sformatować to tak, jak twoje, aby zobaczyć, co zrobiłem)
Tom Carpenter
@TomCarpenter To ... naprawdę brzydkie. Kocham to.
Sanchises
5

Python 3, 272 270 266 262 255 253 244 bajtów

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

\tPowinien być rzeczywisty znak tabulatora.

Kod działa trochę jak odpowiedź Zacha Gatesa, najpierw generując siatkę Mwedług, Mgdzie Mjest sumą długości linii. (To ogromna ilość nadmiaru, ale powoduje, że kod jest krótszy.) Następnie przechodzi przez znaki, umieszczając je w odpowiednich miejscach, śledząc najniższy odwiedzany wiersz. Na koniec wypisuje wszystkie linie do tego wiersza.

Wynik zawiera (zwykle ogromną liczbę) końcowe spacje i 1 końcowy znak nowej linii.

PurkkaKoodari
źródło
3

JavaScript (ES6), 264 245 bajtów

Wypróbowałem metodę „stwórz gigantyczną siatkę przestrzeni, wypełnij i przycinaj”, która skończyła się o 19 bajtów krótsza od drugiej.

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

Modyfikując od drugiego do ostatniego wiersza, możesz usunąć dużą liczbę końcowych spacji w każdej linii:

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

Wypróbuj tutaj:

Wyjaśnienie już wkrótce; sugestie mile widziane!

ETHprodukcje
źródło
3

JavaScript (ES6), 180 183

Używając ciągów szablonów, istnieje kilka nowych linii, które są znaczące i zliczane.

Jest to funkcja zwracająca żądane dane wyjściowe (wypełniona tonami spacji końcowych)

Niewiele można wyjaśnić: rzędy buduje się tak, jak trzeba. Nie ma zmiennej kierunku, tylko przesunięcie 2 dla xiy, ponieważ w rotacji zgodnie z ruchem wskazówek zegara można je łatwo zarządzać:dx <= -dy, dy <= dx

Przetestuj poniższy fragment kodu w przeglądarce 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
źródło
Chciałbym, żeby wszystkie języki miały [x, y] = [expr1, expr2] ...
Sanchises,
1

Python 2, 370 369 368 bajtów

Dzięki @sanchises i @ edc65 za uratowanie mi każdego bajtu.

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

Generuje największą możliwą siatkę, a następnie zapętla się, znak po znaku, przełączając kierunek na każdej karcie.

Zach Gates
źródło
Wskazówka: if !diif d>2
Sanchises
!dnie jest poprawną składnią. @sanchises Dziękuję za d>2podpowiedź.
Zach Gates
Niestety, tak naprawdę nie znam Pythona :) Po prostu zakładam, że tak to zadziała.
Sanchises
Ja również nie rozumiem Pythona, ale jeśli d jest w 0 ... 3, d==0->d<1
edc65
Tak, masz rację. Dzięki za bajt. @ edc65
Zach Gates,