Menulis tangga

35

Tulis sebuah program atau fungsi yang akan menghasilkan string yang diberikan dengan cara tangga, menulis setiap bagian kata yang dimulai dengan vokal satu baris di bawah bagian sebelumnya.

Sebagai contoh:

Input: Programming Puzzles and Code Golf


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

Memasukkan

String yang hanya berisi huruf dan spasi.

String dapat dikirimkan melalui STDINatau berfungsi argumen atau apa pun yang setara

Huruf dapat berupa huruf kecil atau huruf besar.

Input selalu dianggap mengikuti aturan itu, Anda tidak perlu memeriksa input yang salah.

Keluaran

Setiap kali vokal (yaitu, a, e, i, o, uatau y) ditemui dalam kata, Anda harus output sisa kata pada baris berikutnya (vokal ditemui termasuk), pada posisi horisontal yang benar. Aturan ini bersifat rekursif, yang berarti bahwa jika ada n vokal dalam kata, itu akan ditulis pada n + 1 baris.

  • Vokal harus ditulis di awal baris berikutnya, dan bukan di akhir baris sebelumnya saat ditemui.

  • Setiap kata dimulai pada baris pertama, dan karenanya harus diformat secara independen dari kata-kata lain. Dua kata dipisahkan oleh spasi.

  • Jika sebuah kata dimulai dengan vokal, Anda harus menulisnya mulai dari baris kedua.

Uji kasus

  • Memasukkan: Programming Puzzles and Code Golf

Keluaran:

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

Keluaran:

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

Keluaran:

 
a
 e
  i
   o
    u
     y
  • Memasukkan: YEAh UppErcAsE VOwEls

Keluaran:

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

Keluaran:

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

Mencetak gol

Ini , jadi kode terpendek menang.

Fatalisasi
sumber
Contoh keluaran ketiga tampaknya tidak konsisten dengan aturan "Jika sebuah kata dimulai dengan vokal, Anda harus menulisnya mulai dari baris kedua."
JohnE
1
Y adalah Y vokal?
Pengoptimal
1
@ JohnE memang itu, saya memperbaikinya. Terima kasih.
Fatalkan
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.Setelah beberapa pemikiran, saya mengerti bahwa ini berarti bahwa pindah ke baris berikutnya harus terjadi sebelum vokal dicetak, bukan setelah, tetapi mungkin layak untuk menuliskannya dengan cara yang dapat dimengerti secara instan - butuh beberapa saat.
trichoplax
3
Apakah membuntuti baris baru / spasi diizinkan?
Loovjo

Jawaban:

18

Retina , 50 44 34 (+10) 32 30 byte

Terima kasih kepada Dennis karena telah menyimpan 14 byte dengan menggunakan karakter kontrol yang sebenarnya.

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

Berdasarkan jawaban ini , saya menggunakan kode pelarian ANSI untuk memindahkan kursor terminal secara vertikal. The <ESC>harus diganti dengan karakter kontrol 0x1b, dan <VT>dengan tab vertikal 0x0B. Untuk pengujian yang lebih sederhana, Anda juga dapat menggantinya <ESC>dengan \e, <VT>dengan , \vdan mengumpankan hasilnya printf.

Untuk tujuan penghitungan, setiap baris dimasukkan dalam file terpisah. Namun, untuk kenyamanan, lebih mudah untuk hanya menempelkan kode ke satu file dan memohon Retina dengan -sopsi.

Penggantian pertama mengelilingi masing-masing vokal \v...#, di mana \vmenggeser kursor ke bawah dan #merupakan penanda untuk langkah kedua. Ini i`adalah notasi Retina untuk pencocokan case-insensitive.

Langkah kedua kemudian berulang kali ( +`) menghilangkan a #dari sebuah kata dan meletakkan a e\[Adi akhir kata yang menggeser kursor ke atas. Ini berhenti setelah string berhenti berubah, yaitu ketika tidak ada lagi #penanda dalam string.

Martin Ender
sumber
Anda tidak perlu printf. Ganti saja \edengan byte ESC (0x1b).
Dennis
@ Dennis Oh, itu jauh lebih baik, terima kasih.
Martin Ender
1
Ini luar biasa!!!
kirbyfan64sos
Jawaban ini adalah mengapa tidak ada yang menganggap serius Retina;)
Christopher Wirt
@ChristopherWirt Tolong jelaskan :) (Meskipun saya benar-benar akan takut jika ada yang menganggap Retina serius.)
Martin Ender
8

CJam, 39 36 byte

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}/

Di atas adalah dump xxd reversibel, karena kode sumber berisi karakter VT yang tidak dapat dicetak (titik kode 0x0b) dan ESC (titik kode 0x1b).

Seperti jawaban ini , ia menggunakan tab vertikal dan urutan pelarian ANSI .

Ini memerlukan terminal teks video pendukung, yang mencakup sebagian besar emulator terminal non-Windows.

Uji coba

Sebelum menjalankan kode yang sebenarnya, kami akan menonaktifkan prompt dan menghapus layar.

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

Ini memastikan output ditampilkan dengan benar.

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

Untuk mengembalikan prompt, jalankan ini:

PS1="$PS1save"

Bagaimana itu bekerja

Kami menyisipkan tab vertikal sebelum setiap vokal untuk memindahkan kursor ke bawah dan salinan cukup dari urutan byte 1b 5b 41 ( "\e[A") setelah setiap ruang untuk memindahkan kursor kembali ke baris pertama.

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
sumber
Jangan lupa untuk unset PS1savesesudahnya.
usandfriends
5

Java, 428 byte

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]);}

Saya tahu, ini mengerikan. Mungkin ada beberapa karakter yang bisa dicukur, tapi aku terlalu malas untuk melakukan itu.

Loovjo
sumber
Anda mungkin dapat menyatakan banyak dari Anda intvariabel (yaitu i, r, p, o, dan x) di mana Anda menginisialisasi ldan mkarena mereka akan diberi nilai kemudian. Anda juga dapat melakukan String v="...",a[]=...;dan melakukan hal yang sama seperti di atas String u. Itu akan menurunkan skor Anda sedikit.
TNT
Saya sukax++-~-p
Ypnypn
4

Perl, 31 byte

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

Di atas adalah dump xxd reversibel, karena kode sumber berisi karakter VT yang tidak dapat dicetak (titik kode 0x0b) dan ESC (titik kode 0x1b).

Panjang kode 27 byte dan membutuhkan sakelar 040p(4 byte).

Program ini membutuhkan terminal teks video yang mendukung tab vertikal dan urutan pelarian ANSI , yang mencakup sebagian besar emulator terminal non-Windows.

Uji coba

Sebelum menjalankan kode yang sebenarnya, kami akan menonaktifkan prompt dan menghapus layar.

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

Ini memastikan output ditampilkan dengan benar.

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

Untuk mengembalikan prompt, jalankan ini:

PS1="$PS1save"

Bagaimana itu bekerja

  • perl -040psecara otomatis membaca input sebagai token yang dipisahkan spasi ( -040), menyimpan setiap token di $_( -p) dan menjalankan program.

  • s/[aeiouy]/.$&/gimelakukan pencarian global, tidak peka $_huruf besar-kecil untuk vokal dan mengganti setiap vokal dengan karakter kontrol VT (memindahkan kursor ke bawah), diikuti oleh vokal itu sendiri.

  • smengembalikan jumlah penggantian yang dibuatnya, sehingga $\=".[A"x s...menyimpan banyak salinan dari urutan byte 1b 5b 41 (memindahkan kursor ke atas) $\, satu untuk setiap vokal.

  • Pada akhir program, Perl secara otomatis mencetak "$_$\", karena -psaklar.

Dennis
sumber
4

C, 200 190 byte

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);}

Tidak Disatukan:

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);
}

Ini mengalokasikan buffer persegi panjang (sebenarnya persegi), mengisinya dengan spasi dan baris baru, kemudian melintasi string yang diberikan. Pada akhirnya ia menambahkan karakter nol untuk mencegah tertinggal baris baru.

Secara teknis itu bukan fungsi karena mengandung global; bahkan tidak dapat dipanggil lebih dari sekali ( jdan lharus 0 di awal). Untuk mematuhi, i,j,k,l,M;bisa dipindahkan ke int i,j=0,k,l=0,M;pada awal fungsi.

jcai
sumber
char*t=malloc(M*M);-> char t[M*M];dan for(i=0;i<M*M;++i)->for(;i<M*M;++i)
Spikatrix
Hasil tangkapan bagus, diedit.
jcai
Bukankah C99 ini hanya karena char t[M*M]?
Zacharý
4

CJam, 47

Ya, ini agak panjang, tapi tidak "curang" dengan kode ANSI :)

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

Cobalah online

Idenya adalah untuk menghitung nomor baris untuk setiap karakter (mulai dari 0, menambah vokal dan melompat kembali ke 0 di spasi), dan kemudian untuk setiap baris, ulangi string tetapi ganti karakter yang memiliki nomor baris berbeda dengan spasi. .

aditsu
sumber
3

K, 81 72 70 66 byte

Yah, ini awal:

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

Contoh Penggunaan:

  `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       

Edit 1:

Lebih baik. Melakukan beberapa peningkatan level permukaan:

`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}

Khususnya, saya membalikkan argumen ?ketika saya melakukan pencarian vokal dan dengan demikian menghilangkan kebutuhan akan lambda, melakukan inversi yang sama dengan di _mana saya membagi kata-kata di ruang putih, dan saya menyadari bahwa itu ~{" "?x}'xadalah cara mengatakan yang sangat konyol, terlalu rumit " "=x.

Edit 2:

Level permukaan lain mengubah ssebelum menerapkannya pada lambda, menghemat parens di dalam:

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

Edit 3:

OK, mari kita ambil pendekatan berbeda untuk menghitung offset untuk setiap karakter. Alih-alih membelah urutan pada spasi dan menghitung jumlah running ( +\) dari posisi vokal, kita dapat beroperasi pada seluruh string input dalam satu lintasan, mengalikan jumlah running dengan 0 setiap kali kita menemukan spasi. Saya perlu negasi dari urutan ini, jadi saya bisa mengurangi alih-alih menambahkan saat saya memindai dan menggunakan jumlah-of-berbeda ( #?) bukannya max ( |/) ketika saya menghitung jumlah padding vertikal.

`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}

Itu menghemat 4 karakter lainnya. Fiuh!

JohnE
sumber
2

Ruby: 135 131 124 124 115 112 karakter

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

Contoh dijalankan:

bash-4.3$ ruby staircase.rb <<< 'Programming Puzzles and Code Golf'
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing
manatwork
sumber
Jika saya tidak salah, Anda dapat mempersingkat regex Anda menjadi /(?=[aeiouy ])/i.
Alex A.
Ah, kamu benar @AlexA. Ruang sebagai kata yang terpisah hanya penting untuk teori sebelumnya. Terima kasih.
manatwork
2

C, 192 byte

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);}}

Ini berulang melalui string, mengosongkan karakter saat mencetaknya. Itu berulang sampai tidak ada karakter non-spasi yang tersisa untuk dicetak. Ini portabel C, tidak membuat asumsi tentang pengkodean karakter.

Versi yang mudah dibaca

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
sumber
' '-> 32dan f(char*s){int l=0,r=1,v,c;->l,r=1,v,c;f(char*s){
Spikatrix
@Cool - ' ' mungkin menjadi 32, tapi itu tergantung pada pengkodean karakter, dan seperti yang saya katakan, saya membuat ini portable C. menjatuhkan eksplisit intbesar, meskipun - tidak yakin mengapa aku lupa itu!
Toby Speight
2

Python 3, 265 207 202 185 177 karakter

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

Ini mengerikan dan saya tidak bangga. Saya tahu ini bisa dibuat lebih pendek, tapi saya pikir saya tetap akan memposting.

Terinspirasi oleh versi C, ia membuat daftar yang kemudian diisi saat melintasi string input.

InputUsername
sumber
2

GNU Sed, 151 +1

(+1 karena perlu -rbendera)

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

Saya pikir sed akan menjadi alat untuk pekerjaan ini, tetapi ternyata sangat sulit.

Versi yang dapat dibaca:

#!/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
sumber
Saya khawatir, itu harus 128 karakter. Versi satu baris tidak ada p, jadi tidak menghasilkan apa-apa. Masalah kecil adalah bahwa output dimulai dengan ruang ekstra. Masalah besar adalah teks pertama yang dimulai dengan vokal menghilang.
manatwork
Saya yakin itu bekerja lebih awal. Saya akan melihat dan melihat apa yang saya rusak. Terima kasih untuk informasi selanjutnya, @manatwork!
Toby Speight
Saya salah melompat ke lingkaran c, karena garis sebelumnya tx. Saya telah mengaktifkan kembali versi sebelumnya dengan loop yang serupa, dan saya akan mencoba lagi nanti.
Toby Speight
2

Python 2, 145 142 Bytes

Mungkin tidak sekompetitif beberapa metode lain, tapi saya pikir ini adalah cara keren menggunakan regex.

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

Regex (?!([^aeiouy ]*[aeiouy]){N}[^aeiouy]* ).cocok dengan karakter tunggal apa pun yang tidak berada dalam grup huruf ke-N dari akhir kata. Karena itu terhitung dari akhir dunia, saya membalikkan string sebelum dan sesudahnya, dan saya juga harus menambahkan spasi di akhir, tetapi setelah itu menjadi masalah sederhana menggunakan re.subuntuk mengganti setiap instance dari karakter ini dengan spasi. Ini melakukan ini untuk setiap nilai N sampai string kosong.

KSab
sumber
Seperti bagus dan mudah dibaca untuk digunakan re.I, Anda dapat menyimpan 3 byte dengan mengganti nilai flag yang sesuai, yaitu 2.
Sp3000
1
@ Sp3000 Hanya dalam kode-golf yang memiliki asosiasi negatif dengan "baik dan mudah dibaca"
KSab
1

Oktaf, 132 129 karakter

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)

Uji

Memasukkan: "YEAh UppErcAsE VOwEls"

Keluaran:

               V     
Y Upp Ow   
 E Erc Els
  Ah As        
             E       
sudo rm -rf slash
sumber
1

Gema : 53 48 karakter

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

Perhatikan bahwa ^[(x1b) dan ^K(x0b) adalah karakter tunggal. (Pada contoh di bawah ini saya menggunakan copy-paste friendly \edan \vpadanannya, jika Anda ingin mencobanya.)

Contoh dijalankan:

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 
manatwork
sumber
1

Jelly , 42 byte (tidak bersaing?)

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

Cobalah online!

Mengapa Jelly, mengapa? :-(

Erik the Outgolfer
sumber
Lebih lama dari CJam tampaknya aneh
Fatalkan
@Fatalize Itu karena Jelly tidak cocok dengan string ... biasanya. Anda juga tidak dapat benar-benar membandingkan paradigma pemrograman yang berbeda (cjam berbasis stack, jelly adalah diam-diam).
Erik the Outgolfer