Escritura de escalera


35

Escriba un programa o una función que generará una cadena dada en forma de escalera, escribiendo cada parte de una palabra que comienza con una vocal una línea debajo de la parte anterior.

Por ejemplo:

Input: Programming Puzzles and Code Golf


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

Entrada

Una cadena que no contiene más que letras y espacios.

La cadena se puede pasar a través de STDINargumentos de función o algo equivalente.

Las letras pueden ser minúsculas o mayúsculas.

Siempre se supone que las entradas siguen esas reglas, no es necesario verificar las entradas incorrectas.

Salida

Cada vez que una vocal (es decir, a, e, i, o, uo y) se encuentra en una palabra, debe emitir el resto de la palabra en la línea siguiente (la vocal encontrado incluido), en la posición horizontal correcta. Esta regla es recursiva, lo que significa que si hay n vocales en la palabra, se escribirá en n + 1 líneas.

  • La vocal debe escribirse al comienzo de la siguiente línea, y no al final de la línea anterior cuando se encuentra una.

  • Cada palabra comienza en la primera línea y, por lo tanto, debe formatearse independientemente de otras palabras. Dos palabras están separadas por un espacio.

  • Si una palabra comienza con una vocal, debe escribirla comenzando en la segunda línea.

Casos de prueba

  • Entrada: Programming Puzzles and Code Golf

Salida:

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

Salida:

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

Salida:

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

Salida:

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

Salida:

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

Tanteo

Este es el , por lo que gana el código más corto.


El tercer ejemplo de salida parece inconsistente con la regla "Si una palabra comienza con una vocal, debe escribirla comenzando en la segunda línea".
JohnE

1
¿Y es Y una vocal?
Optimizador

1
@JohnE de hecho lo fue, lo arreglé. Gracias.
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.Después de pensarlo, entiendo que esto significa que el movimiento a la siguiente línea debe ocurrir antes de que se imprima la vocal, no después, pero puede valer la pena redactar esto de una manera que sea comprensible al instante: me llevó un tiempo.
trichoplax 01 de

3
¿Se permiten líneas / espacios al final?
Loovjo 01 de

Respuestas:


18

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

Gracias a Dennis por guardar 14 bytes usando caracteres de control reales.

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

Según esta respuesta , estoy usando códigos de escape ANSI para mover el cursor del terminal verticalmente. El <ESC>debe ser reemplazado por el carácter de control 0x1B, y <VT>con el tabulador vertical 0x0B. Para una prueba más simple, también puede reemplazar <ESC>con \e, <VT>con \vy alimentar la salida printf.

Para fines de conteo, cada línea va en un archivo separado. Sin embargo, por conveniencia, es más simple pegar el código en un solo archivo e invocar Retina con la -sopción.

El primer reemplazo rodea cada vocal \v...#, donde el \vcursor desplaza hacia abajo y #es un marcador para el segundo paso. Esta i`es la notación de Retina para la coincidencia entre mayúsculas y minúsculas.

El segundo paso luego (repetidamente +`) elimina a #de una palabra y coloca un e\[Aal final de la palabra que desplaza el cursor hacia arriba. Esto se detiene una vez que la cadena deja de cambiar, es decir, cuando no hay más #marcadores en la cadena.


No es necesario printf. Simplemente reemplácelo \econ el byte ESC (0x1b).
Dennis

@ Dennis Oh, eso está mucho mejor, gracias.
Martin Ender

1
¡Esto es increíble!
kirbyfan64sos 01 de

Esta respuesta es por qué nadie toma en serio a Retina;)
Christopher Wirt

@ChristopherWirt Por favor explique :) (Aunque en realidad estaría aterrorizado si alguien tomara a Retina en serio.)
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}/

Lo anterior es un volcado xxd reversible, ya que el código fuente contiene el carácter no imprimible VT (punto de código 0x0b) y ESC (punto de código 0x1b).

Al igual que esta respuesta , utiliza pestañas verticales y secuencias de escape ANSI .

Esto requiere un terminal de texto de video compatible, que incluye la mayoría de los emuladores de terminales que no son de Windows.

Prueba de funcionamiento

Antes de ejecutar el código real, deshabilitaremos el mensaje y borraremos la pantalla.

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

Esto asegura que la salida se muestre correctamente.

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

Para restaurar la solicitud, ejecute esto:

PS1="$PS1save"

Cómo funciona

Insertamos una pestaña vertical antes de cada vocal para mover el cursor hacia abajo y suficientes copias de la secuencia de bytes 1b 5b 41 ( "\e[A") después de cada espacio para mover el cursor de regreso a la primera fila.

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#

No te olvides de unset PS1savedespués.
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]);}

Lo se, es horrible. Probablemente hay algunos caracteres que se pueden depilar, pero soy demasiado vago para hacerlo.


Es probable que pueda declarar muchas de sus intvariables (es decir i, r, p, o, y x) donde se inicializa ly mya que va a dar valores más tarde. También puede hacer String v="...",a[]=...;y hacer lo mismo para arriba String u. Eso debería reducir tu puntaje un poco.
TNT

Me gusta elx++-~-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

Lo anterior es un volcado xxd reversible, ya que el código fuente contiene el carácter no imprimible VT (punto de código 0x0b) y ESC (punto de código 0x1b).

El código tiene 27 bytes de longitud y requiere los conmutadores 040p(4 bytes).

El programa requiere un terminal de texto de video que admita pestañas verticales y secuencias de escape ANSI , que incluye la mayoría de los emuladores de terminal que no son de Windows.

Prueba de funcionamiento

Antes de ejecutar el código real, deshabilitaremos el mensaje y borraremos la pantalla.

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

Esto asegura que la salida se muestre correctamente.

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

Para restaurar la solicitud, ejecute esto:

PS1="$PS1save"

Cómo funciona

  • perl -040plee automáticamente la entrada como tokens separados por espacios ( -040), guarda cada token en $_( -p) y ejecuta el programa.

  • s/[aeiouy]/.$&/girealiza una búsqueda global, sin distinción entre mayúsculas y minúsculas, $_para las vocales y reemplaza cada vocal por el carácter de control VT (mueve el cursor hacia abajo), seguido de la vocal en sí.

  • sdevuelve el número de reemplazos que realizó, por lo que $\=".[A"x s...guarda varias copias de la secuencia de bytes 1b 5b 41 (mueve el cursor hacia arriba) $\, una para cada vocal.

  • Al final del programa, Perl imprime automáticamente "$_$\", debido al -pcambio.


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

Sin golf:

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

Asigna un búfer rectangular (en realidad cuadrado), lo llena con espacios y líneas nuevas, luego atraviesa la cadena dada. Al final, agrega un carácter nulo para evitar el arrastre de nuevas líneas.

Técnicamente no es una función ya que contiene globales; de hecho no se puede llamar más de una vez ( jy ldebe ser 0 al inicio). Para cumplir, i,j,k,l,M;se puede mover al int i,j=0,k,l=0,M;inicio de la función.


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

Buenas capturas, editado.
jcai

¿No se debe solo a este C99 char t[M*M]?
Zacharý

4

CJam, 47

Sí, es un poco largo, pero no es "trampa" con los códigos ANSI :)

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

Pruébalo en línea

La idea es calcular un número de línea para cada carácter (comenzando en 0, aumentando en vocales y volviendo a 0 en el espacio), y luego para cada línea, repita la cadena pero reemplace los caracteres que tienen un número de línea diferente con un espacio .


3

K, 81 72 70 66 bytes

Bueno, es un comienzo:

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

Ejemplos de uso:

  `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       

Editar 1:

Mejor. Se hicieron algunas mejoras a nivel de superficie:

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

Notablemente, invertí los argumentos para ?cuando realizo la búsqueda de vocales y, por lo tanto, eliminé la necesidad de una lambda, hice la misma inversión _donde dividí las palabras en espacios en blanco, y me di cuenta de que ~{" "?x}'xes una forma de decir realmente tonta y complicada " "=x.

Edición 2:

Otro ajuste de nivel de superficie santes de aplicarlo a la lambda, guardando los parens en el interior:

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

Edición 3:

OK, tomemos un enfoque diferente para calcular el desplazamiento de cada carácter. En lugar de dividir la secuencia en espacios y calcular una suma continua ( +\) de las posiciones de las vocales, podemos operar en toda la cadena de entrada en una pasada, multiplicando la suma continua por 0 cada vez que encontremos un espacio. Necesito la negación de esta secuencia, por lo que puedo restar en lugar de sumar mientras escaneo y usar el número de distinción ( #?) en lugar de max ( |/) cuando calculo la cantidad de relleno vertical.

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

Eso ahorra otros 4 caracteres. ¡Uf!


2

Rubí: 135 131 124 115 112 caracteres

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

Ejecución de muestra:

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

Si no me equivoco, puede acortar su expresión regular a /(?=[aeiouy ])/i.
Alex A.

Ah, tienes razón @AlexA. El espacio como palabra separada solo era importante para una teoría anterior. Gracias.
manatwork 01 de

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

Esto itera a través de la cadena, dejando en blanco los caracteres a medida que los imprime. Se repite hasta que no queden caracteres sin espacio para imprimir. Es C portátil, sin hacer suposiciones sobre la codificación de caracteres.

Versión legible

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

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

@Cool: ' ' puede ser 32, pero depende de la codificación de caracteres, y como dije, hice este portátil C. Sin intembargo, descartar lo explícito es genial, ¡no estoy seguro de por qué lo olvidé!
Toby Speight

2

Pitón 3, 265 207 202 185 177 caracteres

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

Esto es terrible y no estoy orgulloso. Sé que esto se puede acortar, pero pensé en publicar de todos modos.

Inspirado por la versión C, crea una lista que luego se llena al atravesar la cadena de entrada.


2

GNU Sed, 151 + 1

(+1 ya que necesita el -r bandera)

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

Pensé que sed sería la herramienta para este trabajo, pero lo encontré sorprendentemente difícil.

Versión legible:

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

Me temo que deberían tener 128 caracteres. A la versión de una línea le falta un p, por lo que no genera nada. Un pequeño problema es que las salidas comienzan con un espacio extra. Un gran problema es que el primer texto que comienza con vocal desaparece.
manatwork

Estoy seguro de que estaba funcionando antes. Echaré un vistazo y veré qué he roto. Gracias por el aviso, @manatwork!
Toby Speight

Me equivoqué al saltar al bucle c, debido a la línea justo antes tx. He restablecido una versión anterior con su bucle similar, y tendré otro intento más tarde.
Toby Speight el

2

Python 2, 145 142 Bytes

Probablemente no sea tan competitivo como algunos otros métodos, pero pensé que esta era una forma genial de usar expresiones regulares.

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

La expresión regular (?!([^aeiouy ]*[aeiouy]){N}[^aeiouy]* ).coincide con cualquier carácter individual que no se encuentre dentro del grupo N-ésimo de letras desde el final de una palabra. Como cuenta desde el fin del mundo, invierto la cadena antes y después, y también tengo que agregar un espacio al final, pero después de eso se convierte en una simple cuestión de usar re.subpara reemplazar cada instancia de estos caracteres con un espacio. Hace esto para cada valor de N hasta que la cadena está vacía.


Tan agradable y fácil de leer que es usar re.I, se puede ahorrar 3 bytes sustituyendo el valor del indicador apropiado, es decir 2.
SP3000

1
@ Sp3000 Solo en code-golf tienen asociaciones negativas con "agradable y legible"
KSab

1

Octava, 132 129 caracteres

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)

Prueba

Entrada: "YEAh UppErcAsE VOwEls"

Salida:

               V     
Y Upp Ow   
 E Erc Els
  Ah como        
             mi       

1

Gema : 53 48 caracteres

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

Tenga en cuenta que ^[(x1b) y ^K(x0b) son caracteres individuales. (En la ejecución de muestra a continuación, utilizo sus equivalentes \ey \vequivalentes de copiar y pegar , en caso de que desee probarlo).

Ejecución de muestra:

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 (¿no compite?)

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

Pruébalo en línea!

¿Por qué Jelly, por qué? :-(


Más largo de lo que CJam parece extraño
Fatalize

@Fatalize Es porque Jelly simplemente no va con hilos ... por lo general. Tampoco puedes comparar diferentes paradigmas de programación (cjam está basado en pila, jelly es tácito).
Erik the Outgolfer
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.