Лестница написание


35

Напишите программу или функцию, которая будет выводить данную строку в виде лестницы, записывая каждую часть слова, которая начинается с гласной на одну строку ниже предыдущей части.

Например:

Input: Programming Puzzles and Code Golf


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

вход

Строка, содержащая только буквы и пробелы.

Строка может быть передана через STDIN аргументы функции или аргументы или что-нибудь эквивалентное

Буквы могут быть строчными или прописными.

Предполагается, что входы всегда следуют этим правилам, вам не нужно проверять правильность входных данных.

Выход

Каждый раз , когда гласный (т.е. a, e, i, o, uили y) встречается в слове, вы должны выводить остальные слова на следующей строке (встречается гласный включен), в правильном горизонтальном положении. Это правило является рекурсивным, что означает, что если в слове n гласных, оно будет записано в n + 1 строках.

  • Гласный должен быть написан в начале следующей строки, а не в конце предыдущей строки, когда он встречается.

  • Каждое слово начинается с первой строки и поэтому должно быть отформатировано независимо от других слов. Два слова разделены пробелом.

  • Если слово начинается с гласного, вы должны написать его, начиная со второй строки.

Контрольные примеры

  • Входные данные: Programming Puzzles and Code Golf

Выход:

Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing
  • Входные данные: The quick brown fox jumps over the lazy dog

Выход:

Th  q     br    f   j          th  l    d
  e  u      own  ox  umps ov     e  az   og
      ick                   er        y
  • Входные данные: aeiouy

Выход:

 
a
 e
  i
   o
    u
     y
  • Входные данные: YEAh UppErcAsE VOwEls

Выход:

               V
Y    Upp        Ow
 E      Erc       Els
  Ah       As  
             E
  • Входные данные: If you only knew the power of the Dark Side

Выход:

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

счет

Это , поэтому выигрывает самый короткий код.


Третий пример вывода кажется несовместимым с правилом «Если слово начинается с гласного, вы должны написать его, начиная со второй строки».
JohnE

1
Y гласный?
Оптимизатор

1
@Джон действительно так и было, я исправил это. Спасибо.
Роковая

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.Подумав немного, я понимаю, что это означает, что переход к следующей строке должен произойти до того, как будет напечатана гласная, а не после, но, возможно, стоило бы сформулировать это так, чтобы это было понятно сразу - это заняло у меня некоторое время.
Трихоплакс

3
Разрешены ли завершающие символы новой строки / пробелы?
Loovjo

Ответы:


18

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

Thanks to Dennis for saving 14 bytes by using actual control characters.

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

Based on this answer, I'm using ANSI escape codes to move the terminal cursor vertically. The <ESC> should be replaced with the control character 0x1B, and <VT> with the vertical tab 0x0B. For simpler testing, you can also replace <ESC> with \e, <VT> with \v and feed the output through printf.

For counting purposes, each line goes in a separate file. However, for convenience it's simpler to just paste the code into a single file and invoke Retina with the -s option.

The first replacement surrounds each vowel in \v...#, where the \v shifts the cursor downward and the # is a marker for the second step. The i` is Retina's notation for case-insensitive matching.

The second step then repeatedly (+`) removes a # from a word and puts a e\[A at the end of the word which shifts the cursor upward. This stops once the string stops changing, i.e. when there are no more # markers in the string.


You don't need printf. Just replace \e with the ESC byte (0x1b).
Dennis

@Dennis Oh, that's much better, thank you.
Martin Ender

1
This is so awesome!!!
kirbyfan64sos

This answer is why no one takes Retina seriously ;)
Christopher Wirt

@ChristopherWirt Please elaborate :) (Although I would actually be terrified if anyone took Retina seriously.)
Martin Ender

8

CJam, 39 36 bytes

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

The above is a reversible xxd dump, since the source code contains the unprintable character VT (code point 0x0b) and ESC (code point 0x1b).

Like this answer, it uses vertical tabs and ANSI escape sequences.

This requires a supporting video text terminal, which includes most non-Windows terminal emulators.

Test run

Before executing the actual code, we'll disable the prompt and clear the screen.

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

This makes sure the output is shown properly.

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

To restore the prompt, execute this:

PS1="$PS1save"

How it works

We insert a vertical tab before each vowel to move the cursor down and sufficient copies of the byte sequence 1b 5b 41 ("\e[A") after each space to move the cursor back to the first row.

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#

Don't forget to unset PS1save afterwards.
usandfriends

5

Java, 428 bytes

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

I know, it's horrible. There's probably some chars that can be shaved of, but I'm too lazy to do that.


You can probably declare many of your int variables (namely i, r, p, o, and x) where you initialize l and m since they'll be given values later. You can also do String v="...",a[]=...; and do the same as above for String u. That should lower your score quite a bit.
TNT

I like the x++-~-p
Ypnypn

4

Perl, 31 bytes

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

The above is a reversible xxd dump, since the source code contains the unprintable character VT (code point 0x0b) and ESC (code point 0x1b).

The code is 27 bytes long and requires the switches 040p (4 bytes).

The program requires a video text terminal that supports vertical tabs and ANSI escape sequences, which includes most non-Windows terminal emulators.

Test run

Before executing the actual code, we'll disable the prompt and clear the screen.

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

This makes sure the output is shown properly.

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

To restore the prompt, execute this:

PS1="$PS1save"

How it works

  • perl -040p automatically reads the input as space-separated tokens (-040), saves each token in $_ (-p) and executes the program.

  • s/[aeiouy]/.$&/gi performs a global, case-insensitive search in $_ for vowels and replaces each vowel by the control character VT (moves the cursor down), followed by the vowel itself.

  • s returns the number of replacements it made, so $\=".[A"x s... saves multiple copies of the byte sequence 1b 5b 41 (moves the cursor up) in $\, one for each vowel.

  • At the end of the program, Perl automatically prints "$_$\", because of the -p switch.


4

C, 200 190 bytes

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

Ungolfed:

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

It allocates a rectangular buffer (actually square), fills it with spaces and newlines, then traverses the given string. At the end it adds a null character to prevent trailing newlines.

Technically it's not a function since it contains globals; in fact it can't be called more than once (j and l must be 0 at the start). To comply, i,j,k,l,M; could be moved to int i,j=0,k,l=0,M; at the start of the function.


char*t=malloc(M*M); --> char t[M*M]; and for(i=0;i<M*M;++i) --> for(;i<M*M;++i)
Spikatrix

Good catches, edited.
jcai

Isn't this C99 only due to char t[M*M]?
Zacharý

4

CJam, 47

Yeah, it's a bit long, but it's not "cheating" with ANSI codes :)

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

Try it online

The idea is to calculate a line number for each character (starting at 0, incrementing at vowels and jumping back to 0 at space), and then for each line, repeat the string but replace the characters that have a different line number with a space.


3

K, 81 72 70 66 bytes

Well, it's a start:

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

Usage Examples:

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

Better. Made some surface level improvements:

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

Notably, I inverted the arguments for ? when I perform the vowel search and thus eliminated the need for a lambda, did the same inversion with _ where I split words on whitespace, and I realized that ~{" "?x}'x is a really silly, overcomplicated way of saying " "=x.

Edit 2:

Another surface level tweak- negate s before applying it to the lambda, saving parens inside:

`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, let's take a different approach to calculating the offset for each character. Instead of splitting the sequence at spaces and calculating a running sum (+\) of the positions of vowels, we can operate on the whole input string in one pass, multiplying the running sum by 0 whenever we encounter a space. I need the negation of this sequence, so I can subtract instead of adding as I scan and use number-of-distinct (#?) instead of max (|/) when I calculate the amount of vertical padding.

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

That saves another 4 characters. Phew!


2

Ruby: 135 131 124 115 112 characters

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

Sample run:

bash-4.3$ ruby staircase.rb <<< 'Programming Puzzles and Code Golf'
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing

If I'm not mistaken, you can shorten your regex to /(?=[aeiouy ])/i.
Alex A.

Ah, you are right @AlexA. The space as separate word was only important for an earlier theory. Thanks.
manatwork

2

C, 192 bytes

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

This iterates through the string, blanking characters as it prints them. It repeats until there are no non-space characters left to print. It's portable C, making no assumptions about character encoding.

Readable version

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

' ' --> 32 and f(char*s){int l=0,r=1,v,c; --> l,r=1,v,c;f(char*s){
Spikatrix

@Cool - ' ' may be 32, but it depends on the character encoding, and as I said, I made this portable C. Dropping the explicit int is great, though - not sure why I forgot that!
Toby Speight

2

Python 3, 265 207 202 185 177 characters

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

This is terrible and I'm not proud. I know this can be made shorter, but I thought I'd post anyway.

Inspired by the C version, it creates a list which is then filled while traversing the input string.


2

GNU Sed, 151 + 1

(+1 as it needs the -r flag)

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

I thought that sed would be the tool for this job, but found it surprisingly hard.

Readable version:

#!/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

I'm afraid, that should be 128 characters. The one-line version is missing a p, so it outputs nothing. A small issue is that outputs starts with an extra space. A huge issue is that first piece of text starting with vowel disappears.
manatwork

I'm sure it was working earlier. I'll have a look and see what I've broken. Thanks for the heads-up, @manatwork!
Toby Speight

I was wrong to jump into loop c, due to the line just before tx. I've reinstated an earlier version with its similar loop, and I'll have another attempt later.
Toby Speight

2

Python 2, 145 142 Bytes

Probably isn't as competitive as some other methods, but I thought this was a cool way of using 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

The regex (?!([^aeiouy ]*[aeiouy]){N}[^aeiouy]* ). matches any single character not within the N-th group of letters from the end of a word. Since it counts from the end of the world I reverse the string before and afterward, and I also have to add a space at the end, but after that it becomes a simple matter of using re.sub to replace every instance of these characters with a space. It does this for every value of N until the string is empty.


As nice and readable it is to use re.I, you can save 3 bytes by substituting the appropriate flag value, i.e. 2.
Sp3000

1
@Sp3000 Only in code-golf do have negative associations with "nice and readable"
KSab

1

Octave, 132 129 characters

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

Input: "YEAh UppErcAsE VOwEls"

Output:

               V     
Y    Upp        Ow   
 E      Erc       Els
  Ah       As        
             E       

1

Gema: 53 48 characters

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

Note that ^[ (x1b) and ^K (x0b) are single characters. (In the below sample run I use their copy-paste friendly \e and \v equivalents, in case you want to try it out.)

Sample run:

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 

1

Jelly, 42 bytes (non-competing?)

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

Try it online!

Why Jelly, why? :-(


Longer than CJam seems weird
Fatalize

@Fatalize It's because Jelly just doesn't go with strings...usually. Also you can't really compare different programming paradigms (cjam is stack-based, jelly is tacit).
Erik the Outgolfer
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.