Pisanie na schodach

35

Napisz program lub funkcję, która wypisze dany ciąg w sposób schodowy, pisząc każdą część słowa rozpoczynającą się od samogłoski o jeden wiersz poniżej poprzedniej części.

Na przykład:

Input: Programming Puzzles and Code Golf


Output: Pr          P           C    G
          ogr        uzzl   and  od   olf
             amm         es        e
                ing

Wkład

Ciąg zawierający tylko litery i spacje.

Ciąg może być przekazywany przez STDINargumenty funkcji lub dowolne równoważne.

Litery mogą być małe lub wielkie.

Zakłada się, że dane wejściowe zawsze są zgodne z tymi zasadami, nie trzeba sprawdzać, czy dane wejściowe są nieprawidłowe.

Wydajność

Za każdym razem gdy samogłoski (czyli a, e, i, o, ulub y) spotyka się w słowie, należy wyjście reszta słowo na następnej linii (napotkał samogłoska w zestawie), w prawidłowej pozycji poziomej. Ta reguła jest rekurencyjna, co oznacza, że ​​jeśli słowo zawiera n samogłosek, zostanie zapisane w n + 1 wierszach.

  • Samogłoska powinna być zapisywana na początku następnego wiersza, a nie na końcu poprzedniego wiersza, gdy zostanie napotkany.

  • Każde słowo zaczyna się w pierwszym wierszu i dlatego powinno być sformatowane niezależnie od innych słów. Dwa słowa są oddzielone spacją.

  • Jeśli słowo zaczyna się od samogłoski, musisz je zapisać zaczynając od drugiej linii.

Przypadki testowe

  • Wkład: Programming Puzzles and Code Golf

Wydajność:

Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing
  • Wkład: The quick brown fox jumps over the lazy dog

Wydajność:

Th  q     br    f   j          th  l    d
  e  u      own  ox  umps ov     e  az   og
      ick                   er        y
  • Wkład: aeiouy

Wydajność:

 
a
 e
  i
   o
    u
     y
  • Wkład: YEAh UppErcAsE VOwEls

Wydajność:

               V
Y    Upp        Ow
 E      Erc       Els
  Ah       As  
             E
  • Wkład: If you only knew the power of the Dark Side

Wydajność:

            kn   th  p        th  D    S
If y   onl    ew   e  ow   of   e  ark  id
    o     y             er                e
     u

Punktacja

To jest , więc wygrywa najkrótszy kod.

Fatalizować
źródło
Trzeci przykład wyjściowy wydaje się niezgodny z regułą „Jeśli słowo zaczyna się od samogłoski, musisz je zapisać zaczynając od drugiego wiersza”.
JohnE
1
Y jest Y samogłoską?
Optymalizator
1
@ John rzeczywiście było, naprawiłem to. Dzięki.
Fatalize
2
The vowel should be written at the beginning of the next line, and not at the end of the previous line when one is encountered.Po namyśle rozumiem, że oznacza to, że przejście do następnej linii powinno nastąpić przed wydrukowaniem samogłoski, a nie później, ale może warto sformułować to w sposób, który jest natychmiast zrozumiały - zajęło mi to trochę czasu.
trichoplax
3
Czy dozwolone są końcowe linie / spacje?
Loovjo,

Odpowiedzi:

18

Siatkówka , 50 44 34 (+10) 32 30 bajtów

Dzięki Dennisowi za zapisanie 14 bajtów przy użyciu rzeczywistych znaków kontrolnych.

i`[aeiouy]
<VT>$0#
+`#(\S*)
$1<ESC>[A

W oparciu o tę odpowiedź używam kodów specjalnych ANSI, aby przesunąć kursor terminala w pionie. <ESC>Należy zastąpić znakiem kontrolnym 0x1b oraz <VT>z zakładki pionowej 0x0B. Dla prostszych testów, można również wymienić <ESC>z \e, <VT>ze \vi paszy poprzez wyjście printf.

Do celów zliczania każda linia przechodzi w osobny plik. Jednak dla wygody łatwiej jest po prostu wkleić kod do jednego pliku i wywołać Retinę z -sopcją.

Pierwsza zamiana otacza każdą samogłoskę, w \v...#której \vprzesuwa kursor w dół, a #znacznik drugiego kroku. Jest i`to notacja Retina dla dopasowywania bez rozróżniania wielkości liter.

Drugi krok następnie ( +`) usuwa a #ze słowa i umieszcza e\[Ana końcu słowa, co przesuwa kursor w górę. Zatrzymuje się, gdy ciąg przestanie się zmieniać, tj. Gdy nie będzie więcej #znaczników w ciągu.

Martin Ender
źródło
Nie trzeba printf. Wystarczy zastąpić \ebajtem ESC (0x1b).
Dennis
@Dennis Oh, o wiele lepiej, dziękuję.
Martin Ender
1
To jest niesamowite!!!
kirbyfan64sos
Ta odpowiedź jest powodem, dla którego nikt nie bierze poważnie Retiny;)
Christopher Wirt
@ChristopherWirt Proszę opracować :) (Chociaż byłbym przerażony, gdyby ktoś wziął poważnie Retinę.)
Martin Ender
8

CJam, 39 36 bajtów

0000000: 6c 7b 5f 65 6c 22 61 65 69 6f 75 79 22  l{_el"aeiouy"
000000d: 26 7b 22 1b 5b 41 22 27 0b 6f 5c 7d 26  &{".[A"'.o\}&
000001a: 5f 53 26 7b 5d 7d 26 6f 7d 2f           _S&{]}&o}/

Powyżej jest odwracalny zrzut xxd, ponieważ kod źródłowy zawiera niedrukowalny znak VT (punkt kodowy 0x0b) i ESC (punkt kodowy 0x1b).

Podobnie jak ta odpowiedź , wykorzystuje pionowe tabulatory i sekwencje specjalne ANSI .

Wymaga to obsługi terminalu tekstowego wideo, który obejmuje większość emulatorów terminali innych niż Windows.

Testowe uruchomienie

Przed wykonaniem rzeczywistego kodu wyłączymy monit i wyczyścimy ekran.

$ PS1save="$PS1"
$ unset PS1
$ clear

Dzięki temu dane wyjściowe są wyświetlane poprawnie.

echo -n Programming Puzzles and Code Golf | cjam <(xxd -ps -r <<< 6c7b5f656c226165696f757922267b221b5b4122270b6f5c7d265f53267b5d7d266f7d2f)
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing

Aby przywrócić monit, wykonaj następujące czynności:

PS1="$PS1save"

Jak to działa

Wstawiamy pionową zakładkę przed każdą samogłoską, aby przesunąć kursor w dół, oraz wystarczającą liczbę sekwencji bajtów 1b 5b 41 ( "\e[A") po każdej spacji, aby przenieść kursor z powrotem do pierwszego rzędu.

l           e# Read a line from STDIN.
{           e# For each character C:
  _el       e#   Push lowercase(C).
  "aeiouy"& e#   Intersect with "aeiouy".
  {         e#   If the intersection is non-empty:
    ".[A"   e#     Push "\e[A" (will be printed later).
    '.o     e#     Print "\v".
    \       e#     Swap "\e[A" with C.
  }&        e#
  _S&       e#   Intersect C with " ".
  {         e#   If the intersection is non-empty:
    ]       e#     Wrap the entire stack in an array.
  }&
  o         e#   Print C or the entire stack.
}/          e#
Dennis
źródło
Nie zapomnij unset PS1savepóźniej.
usandfriends
5

Java, 428 bajtów

void s(String s){int l=s.length(),m=0;char[][]c=new char[l][];for(int i=0;i<c.length;java.util.Arrays.fill(c[i++],' '))c[i]=new char[l];String v="aeiouyAEIOUY";String[]a=s.split(" ");for(int r=0,p=0;r<a.length;r++){String u=a[r]+" ";int o=v.indexOf(u.charAt(0))>=0?1:0,x=p;for(;x<u.length()-1+p;o+=v.indexOf(u.charAt(x++-~-p))>=0?1:0)c[o][x]=u.charAt(x-p);p+=u.length();m=m<o?o:m;}for(int i=0;i<=m;i++)System.out.println(c[i]);}

Wiem, to okropne. Prawdopodobnie jest kilka znaków, które można ogolić, ale jestem zbyt leniwy, aby to zrobić.

Loovjo
źródło
Prawdopodobnie można zadeklarować wiele swoich intzmiennych (czyli i, r, p, o, i x) gdzie można zainicjować li mponieważ zostaną one podane wartości później. Możesz także zrobić String v="...",a[]=...;i zrobić to samo, co powyżej String u. To powinno znacznie obniżyć twój wynik.
TNT
Lubięx++-~-p
Ypnypn
4

Perl, 31 bajtów

0000000: 24 5c 3d 22 1b 5b 41 22 78 20 73 2f 5b 61  $\=".[A"x s/[a
000000e: 65 69 6f 75 79 5d 2f 0b 24 26 2f 67 69     eiouy]/.$&/gi

Powyżej jest odwracalny zrzut xxd, ponieważ kod źródłowy zawiera niedrukowalny znak VT (punkt kodowy 0x0b) i ESC (punkt kodowy 0x1b).

Kod ma 27 bajtów i wymaga przełączników 040p(4 bajty).

Program wymaga terminalu tekstowego wideo, który obsługuje pionowe tabulatory i sekwencje specjalne ANSI , który obejmuje większość emulatorów terminali innych niż Windows.

Testowe uruchomienie

Przed wykonaniem rzeczywistego kodu wyłączymy monit i wyczyścimy ekran.

$ PS1save="$PS1"
$ unset PS1
$ clear

Dzięki temu dane wyjściowe są wyświetlane poprawnie.

echo -n Programming Puzzles and Code Golf | perl -040pe "$(xxd -ps -r <<< 245c3d221b5b41227820732f5b6165696f75795d2f0b24262f6769)"
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e 
        ing

Aby przywrócić monit, wykonaj następujące czynności:

PS1="$PS1save"

Jak to działa

  • perl -040pautomatycznie odczytuje dane wejściowe jako oddzielone spacjami tokeny ( -040), zapisuje każdy token w $_( -p) i wykonuje program.

  • s/[aeiouy]/.$&/giwykonuje globalne wyszukiwanie wielkości liter bez rozróżniania wielkości liter $_i zastępuje każdą samogłoskę znakiem kontrolnym VT (przesuwa kursor w dół), a następnie samą samogłoskę.

  • szwraca liczbę dokonanych zamian, więc $\=".[A"x s...zapisuje wiele kopii sekwencji bajtów 1b 5b 41 (przesuwa kursor w górę) $\, po jednej dla każdej samogłoski.

  • Po zakończeniu programu Perl automatycznie drukuje z "$_$\"powodu -pprzełącznika.

Dennis
źródło
4

C, 200 190 bajtów

i,j,k,l,M;f(char*s){M=strlen(s)+1;char t[M*M];for(;i<M*M;++i)t[i]=(i+1)%M?32:10;for(i=0;i<M-1;++i)k=(strspn(s+i,"aeiouyAEIOUY")?++j:s[i]==32?j=0:j)*M+i,l<k?l=k:0,t[k]=s[i];t[l+1]=0;puts(t);}

Nie golfowany:

i,j,k,l,M;
f(char *s){
    M = strlen(s)+1;
    char t[M*M];
    for(; i<M*M; ++i) t[i] = (i+1)%M ? 32 : 10;
    for(i=0; i<M-1; ++i)
        k = (strspn(s+i,"aeiouyAEIOUY") ? ++j : s[i]==32 ? j=0 : j) * M + i,
        l<k ? l=k : 0,
        t[k] = s[i];
    t[l+1]=0;
    puts(t);
}

Przydziela bufor prostokątny (właściwie kwadratowy), wypełnia go spacjami i znakami nowej linii, a następnie przechodzi przez podany ciąg. Na końcu dodaje pusty znak, aby zapobiec końcowym znakom nowej linii.

Technicznie nie jest to funkcja, ponieważ zawiera globale; w rzeczywistości nie może być wywoływany więcej niż raz ( ji lmusi być 0 na początku). Aby zachować zgodność, i,j,k,l,M;można go przenieść int i,j=0,k,l=0,M;na początku funkcji.

jcai
źródło
char*t=malloc(M*M);-> char t[M*M];i for(i=0;i<M*M;++i)->for(;i<M*M;++i)
Spikatrix
Dobre połowy, zredagowane.
jcai
Czy to nie C99 tylko z powodu char t[M*M]?
Zacharý
4

CJam, 47 lat

Tak, jest trochę długi, ale to nie jest „oszukiwanie” za pomocą kodów ANSI :)

q_{_S&!\el"aeiouy"-!U+*:U}%_0|$])\zff{~@-S@?}N*

Wypróbuj online

Chodzi o to, aby obliczyć liczbę wierszy dla każdego znaku (zaczynając od 0, zwiększając samogłoski i skacząc z powrotem do 0 w spacji), a następnie dla każdej linii powtórz ciąg, ale zamień znaki, które mają inny numer wiersza, spacją .

aditsu
źródło
3

K, 81 72 70 66 bajtów

Cóż, to początek:

`0:{+{(-z)!y,x#" "}[|/s].'x,'s:,/{+\{12>"aeiouyAEIOUY"?x}'x}'(0,&~{"  "?x}'x)_ x}

Przykłady użycia:

  `0:{+{(-z)!y,x#" "}[|/s].'x,'s:,/{+\{12>"aeiouyAEIOUY"?x}'x}'(0,&~{"  "?x}'x)_ x} "Programming Puzzles and Code Golf"
Pr          P           C    G   
  ogr        uzzl   and  od   olf
     amm         es        e     
        ing                      
  `0:{+{(-z)!y,x#" "}[|/s].'x,'s:,/{+\{12>"aeiouyAEIOUY"?x}'x}'(0,&~{"  "?x}'x)_ x} "YEAh UppErcAsE VOwEls"
               V     
Y    Upp        Ow   
 E      Erc       Els
  Ah       As        
             E       

Edycja 1:

Lepszy. Wprowadzono pewne ulepszenia poziomu powierzchni:

`0:{+{(-z)!y,x#" "}[|/s].'x,'s:,/{+\{12>"aeiouyAEIOUY"?x}'x}'(0,&~{"  "?x}'x)_ x}
`0:{+{(-z)!y,x#" "}[|/s].'x,'s:,/(+\12>?["aeiouyAEIOUY"]')'_[0,&" "=x]x}

W szczególności odwróciłem argumenty, ?gdy wykonuję wyszukiwanie samogłosek, i tym samym wyeliminowałem potrzebę lambda, zrobiłem tę samą inwersję z tym, w _którym dzielę słowa na białe znaki, i zdałem sobie sprawę, że ~{" "?x}'xto naprawdę głupi, zbyt skomplikowany sposób wypowiadania się " "=x.

Edycja 2:

Kolejna poprawka poziomu powierzchni - negacja sprzed nałożeniem jej na lambda, oszczędzając w środku pareny:

`0:{+{(-z)!y,x#" "}[|/s].'x,'s:,/(+\12>?["aeiouyAEIOUY"]')'_[0,&" "=x]x}
`0:{+{z!y,x#" "}[|/s].'x,'-s:,/(+\12>?["aeiouyAEIOUY"]')'_[0,&" "=x]x}

Edycja 3:

OK, zastosujmy inne podejście do obliczania przesunięcia dla każdego znaku. Zamiast dzielić sekwencję na spacje i obliczać sumę bieżącą ( +\) pozycji samogłosek, możemy operować na całym ciągu wejściowym w jednym przejściu, mnożąc sumę bieżącą przez 0 za każdym razem, gdy napotykamy spację. Potrzebuję negacji tej sekwencji, więc mogę odejmować zamiast dodawać podczas skanowania i używać liczby-odrębnych ( #?) zamiast max ( |/) podczas obliczania ilości pionowego wypełnienia.

`0:{+{z!y,x#" "}[|/s].'x,'-s:,/(+\12>?["aeiouyAEIOUY"]')'_[0,&" "=x]x}
`0:{+{z!y,x#" "}[#?s].'x,'s:1_0{(~" "=y)*x-12>"aeiouyAEIOUY"?y}\x}

To oszczędza kolejne 4 znaki. Uff!

JohnE
źródło
2

Rubin: 135 131 124 115 112 znaków

a=[]
y=l=0
gets.split(r=/(?=[aeiouy ])/i).map{|w|w=~r&&y+=1
w<?A&&y=0
a[y]='%*s%s'%[-l,a[y],w]
l+=w.size}
puts a

Przykładowy przebieg:

bash-4.3$ ruby staircase.rb <<< 'Programming Puzzles and Code Golf'
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing
człowiek w pracy
źródło
Jeśli się nie mylę, możesz skrócić wyrażenie regularne do /(?=[aeiouy ])/i.
Alex A.
Ach, masz rację @AlexA. Przestrzeń jako osobne słowo była ważna tylko dla wcześniejszej teorii. Dzięki.
manatwork
2

C, 192 bajty

f(char*s){int l=0,r=1,v,c;for(;r;l=1){v=l;r=0;char*p;for(p=s;*p;++p){c=*p;if(c==' ')v=l,putchar(c);else if((strchr("aoeuiyAOEUIY",c)?--v:v)<0)r=1,putchar(' ');else*p=' ',putchar(c);}puts(p);}}

Powoduje to iterację ciągu, wygaszanie znaków podczas ich drukowania. Powtarza się, dopóki nie zostaną żadne znaki spacji do wydrukowania. Jest przenośnym C, nie przyjmuje żadnych założeń dotyczących kodowania znaków.

Wersja do odczytu

f(char *s) {
    int l=0,       /* true if we've done the first line (no vowels) */
        r=1,       /* true if characters remain in buffer */
        v,         /* how many vowels to print from current word */
        c;         /* current character value */
    for (l=0; r; l=1) {
        v = l;
        r = 0;
        char *p;
        for (p=s;*p;++p) {
            c=*p;
            if (c==' ') {       /* a space - reset vowel counter */
                v=l;
                putchar(c);
            } else if ((strchr("aoeuiyAOEUIY",c)?--v:v)<0) {
                /* vowel conter exceeded - print a space */
                putchar(' ');
                r=1;
            } else {
                /* print it, and obliterate it from next line of output */
                putchar(c);
                *p=' ';
            }
        }
        puts(p); /* p points at the NUL, so this just prints a newline */
    }
}
Toby Speight
źródło
' '-> 32i f(char*s){int l=0,r=1,v,c;->l,r=1,v,c;f(char*s){
Spikatrix
@Cool - ' ' może być 32, ale zależy to od kodowania znaków, i jak powiedziałem, zrobiłem to przenośne C. Upuszczenie wyraźnego intjest jednak świetne - nie jestem pewien, dlaczego o tym zapomniałem!
Toby Speight,
2

Python 3, 265 207 202 185 177 znaków

i=input()
w,e=i.split(" "),lambda:[[" "]*len(i)]
o,x=e(),0
for p in w:
    y=0
    for c in p:
        if c in"AEIOUYaeiouy":o+=e();y+=1
        o[y][x],x=c,x+1
    x+=1
for l in o:print("".join(l))

To okropne i nie jestem dumny. Wiem, że można to skrócić, ale myślałem, że i tak opublikuję.

Zainspirowany wersją C tworzy listę, która jest następnie wypełniana podczas przechodzenia przez ciąg wejściowy.

InputUsername
źródło
2

GNU Sed, 151 + 1

(+1, ponieważ potrzebuje -rflagi)

s/^/ /;h;s/[aoeuiy]/_/ig;:a;s/_[^ _]/__/;ta;y/_/ /;g;:x;:b;s/ [^ aoeuiy]/  /i;tb;h;s/([^ ])[aoeuiy]/\1_/ig;:c;s/_[^ _]/__/;tc;y/_/ /;g;s/ [^ ]/  /ig;tx

Myślałem, że sed będzie narzędziem do tej pracy, ale uznałem to za zaskakująco trudne.

Wersja do odczytu:

#!/bin/sed -rf

# make sure the string starts with a space
s/^/ /
h

# print leading consonants, if any
s/[aoeuiy]/_/ig
:a
s/_[^ _]/__/
ta
y/_/ /
p
g

:x
# strip the consonants just printed
:b
s/ [^ aoeuiy]/  /i
tb
h

s/([^ ])[aoeuiy]/\1_/ig
:c
s/_[^ _]/__/
tc
y/_/ /
p
g
# remove leading vowel of each word
s/ [^ ]/  /ig
tx
Toby Speight
źródło
Obawiam się, że powinno to być 128 znaków. W wersji jednowierszowej brakuje a p, więc nic nie wyświetla. Mały problem polega na tym, że wyjścia zaczynają się od dodatkowej przestrzeni. Ogromnym problemem jest to, że znika pierwsza część tekstu zaczynająca się od samogłoski.
manatwork
Jestem pewien, że działało to wcześniej. Zajrzę i zobaczę, co złamałem. Dzięki za heads-up, @manatwork!
Toby Speight,
Myliłem się, skacząc w pętlę c, z powodu linii tuż przed tx. Przywróciłem wcześniejszą wersję z podobną pętlą i spróbuję później.
Toby Speight,
2

Python 2, 145 142 bajtów

Prawdopodobnie nie jest tak konkurencyjny jak niektóre inne metody, ale pomyślałem, że to fajny sposób na użycie wyrażenia regularnego.

import re;s=I=input()[::-1]+" ";i=0
while s.strip()or i<2:s=re.sub("(?!([^aeiouy ]*[aeiouy]){%s}[^aeiouy]* )."%i," ",I,0,2)[::-1];print s;i+=1

Wyrażenie regularne (?!([^aeiouy ]*[aeiouy]){N}[^aeiouy]* ).dopasowuje dowolny pojedynczy znak spoza N-tej grupy liter od końca słowa. Ponieważ liczy się od końca świata, odwracam ciąg przed i po nim, a także muszę dodać spację na końcu, ale potem staje się prostą sprawą re.subzastąpienie każdego wystąpienia tych znaków spacją. Robi to dla każdej wartości N, dopóki łańcuch nie będzie pusty.

KSab
źródło
Ponieważ jest przyjemny i czytelny w użyciu re.I, możesz zapisać 3 bajty, zastępując odpowiednią wartość flagi, tj 2.
Sp3000,
1
@ Sp3000 Tylko w golfie kodowym mają negatywne skojarzenia z „ładnym i czytelnym”
KSab
1

Oktawa, 132 129 znaków

p=1;x=[];y=input(0);for j=1:numel(y);if regexpi(y(j),'[aeiouy]');p+=1;elseif y(j)==" ";p=1;end;x(p,j)=y(j);end;x(x==0)=32;char(x)

Test

Wkład: "YEAh UppErcAsE VOwEls"

Wydajność:

               V.     
Y Upp Ow   
 E Erc Els
  Ah As        
             mi       
sudo rm -rf slash
źródło
1

Gema : 53 48 znaków

/[aeiouyAEIOUY]/=@append{u;^[[A}^K$1
 = $u@set{u;}

Zauważ, że ^[(x1b) i ^K(x0b) są pojedynczymi znakami. (W poniższym przykładzie biegu używam ich kopiowania i wklejania przyjazny \ei \vekwiwalentów, w przypadku, gdy chcesz go wypróbować.)

Przykładowy przebieg:

bash-4.3$ gema '/[aeiouyAEIOUY]/=@append{u;\e[A}\v$1; = $u@set{u;}' <<< 'Programming Puzzles and Code Golf'
Pr          P           C    G    
  ogr        uzzl   and  od   olf 
     amm         es        e 
        ing 
człowiek w pracy
źródło
1

Galaretka , 42 bajty (niekonkurujące?)

Ḳµe€Øyœṗ⁸⁶ṁ$;¥\z⁶Zµ€µḷ/⁶ṁW⁸;ḣ®µ€L€Ṁ©$¡ZK€Y

Wypróbuj online!

Dlaczego galaretka, dlaczego? :-(

Erik the Outgolfer
źródło
Dłużej niż CJam wydaje się dziwny
Fatalize
@ Fatalizuj To dlatego, że galaretka po prostu nie pasuje do łańcuchów ... zwykle. Nie można też tak naprawdę porównywać różnych paradygmatów programowania (cjam opiera się na stosie, galaretka jest milcząca).
Erik the Outgolfer,