Escrita de escadaria

35

Escreva um programa ou uma função que produza uma determinada sequência em forma de escada, escrevendo cada parte de uma palavra que comece com uma vogal uma linha abaixo da parte anterior.

Por exemplo:

Input: Programming Puzzles and Code Golf


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

Entrada

Uma string contendo nada além de letras e espaços.

A cadeia pode ser passada através de STDINargumentos de função ou algo equivalente.

As letras podem ser minúsculas ou maiúsculas.

As entradas sempre são assumidas para seguir essas regras; você não precisa verificar se há entradas incorretas.

Saída

Cada vez que uma vogal (isto é, a, e, i, o, uou y) é encontrado em uma palavra, você deve emitir o resto da palavra na próxima linha (a vogal encontrou incluído), na posição horizontal correta. Essa regra é recursiva, o que significa que, se houver n vogais na palavra, ela será escrita em n + 1 linhas.

  • A vogal deve ser escrita no início da próxima linha e não no final da linha anterior quando uma for encontrada.

  • Cada palavra começa na primeira linha e, portanto, deve ser formatada independentemente de outras palavras. Duas palavras são separadas por um espaço.

  • Se uma palavra começa com uma vogal, você deve escrevê-la começando na segunda linha.

Casos de teste

  • Entrada: Programming Puzzles and Code Golf

Saída:

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

Saída:

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

Saída:

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

Saída:

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

Saída:

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

Pontuação

Isso é , então o código mais curto vence.

Fatalizar
fonte
O terceiro exemplo de saída parece inconsistente com a regra "Se uma palavra começa com uma vogal, você deve escrevê-la iniciando na segunda linha".
Johne
11
Y é uma vogal?
Optimizer
11
@ JohnE de fato era, eu consertei. Obrigado.
Fatalize 01/07
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.Depois de pensar um pouco, entendo que isso significa que a mudança para a próxima linha deve ocorrer antes da impressão da vogal, não depois, mas pode valer a pena redigir isso de uma maneira que seja instantaneamente compreensível - demorei um pouco.
Trichoplax
3
Novas linhas / espaços à direita são permitidos?
Loovjo 01/07

Respostas:

18

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

Agradecemos a Dennis por salvar 14 bytes usando caracteres de controle reais.

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

Com base nesta resposta , estou usando códigos de escape ANSI para mover o cursor do terminal verticalmente. O <ESC>deve ser substituído pelo caractere de controle 0x1B e <VT>pela guia vertical 0x0B. Para testes mais simples, você também pode substituir <ESC>por \e, <VT>com \ve alimentar a saída printf.

Para fins de contagem, cada linha entra em um arquivo separado. No entanto, por conveniência, é mais simples colar o código em um único arquivo e chamar Retina com a -sopção

A primeira substituição envolve cada vogal \v...#, onde \vo cursor #é deslocado para baixo e é um marcador para o segundo passo. A i`é a notação de Retina para a correspondência de maiúsculas e minúsculas.

O segundo passo, em seguida, repetidamente ( +`) remove a #de uma palavra e coloca a e\[Ano final da palavra que move o cursor para cima. Isso para quando a string parar de mudar, ou seja, quando não houver mais #marcadores na string.

Martin Ender
fonte
Você não precisa printf. Apenas substitua \epelo byte ESC (0x1b).
Dennis
@ Dennis Oh, isso é muito melhor, obrigado.
Martin Ender
11
Isso é tão incrível!!!
Kirbyfan64sos
Esta resposta é por isso que ninguém leva a sério Retina;)
Christopher Wirt
@ChristopherWirt Por favor explique :) (Embora eu seria realmente apavorada, se alguém tomou Retina sério.)
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}/

O acima é um despejo xxd reversível, pois o código-fonte contém o caractere não imprimível VT (ponto de código 0x0b) e ESC (ponto de código 0x1b).

Como esta resposta , ele usa guias verticais e seqüências de escape ANSI .

Isso requer um terminal de texto de vídeo de suporte, que inclui a maioria dos emuladores de terminal não Windows.

Execução de teste

Antes de executar o código real, desativaremos o prompt e limparemos a tela.

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

Isso garante que a saída seja mostrada corretamente.

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 o prompt, execute o seguinte:

PS1="$PS1save"

Como funciona

Nós inserimos uma guia vertical antes de cada vogal para mover o cursor para baixo e cópias suficientes da sequência de bytes 1b 5b 41 ( "\e[A") após cada espaço para mover o cursor de volta para a primeira linha.

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
fonte
Não esqueça unset PS1savedepois.
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]);}

Eu sei, é horrível. Provavelmente existem alguns caracteres que podem ser raspados, mas tenho preguiça de fazer isso.

Loovjo
fonte
Você provavelmente pode declarar muitas das suas intvariáveis (ou seja i, r, p, o, e x), onde você inicializar le muma vez que vai ser dada valores posteriormente. Você também pode fazer String v="...",a[]=...;e fazer o mesmo que acima String u. Isso deve diminuir bastante sua pontuação.
TNT
Eu gosto dex++-~-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

O acima é um despejo xxd reversível, pois o código-fonte contém o caractere não imprimível VT (ponto de código 0x0b) e ESC (ponto de código 0x1b).

O código tem 27 bytes e requer as opções 040p(4 bytes).

O programa requer um terminal de texto de vídeo que suporte guias verticais e seqüências de escape ANSI , que incluem a maioria dos emuladores de terminal não Windows.

Execução de teste

Antes de executar o código real, desativaremos o prompt e limparemos a tela.

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

Isso garante que a saída seja mostrada corretamente.

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 o prompt, execute o seguinte:

PS1="$PS1save"

Como funciona

  • perl -040plê automaticamente a entrada como tokens separados por espaço ( -040), salva cada token em $_( -p) e executa o programa.

  • s/[aeiouy]/.$&/girealiza uma pesquisa global sem distinção entre maiúsculas e minúsculas $_e substitui cada vogal pelo caractere de controle VT (move o cursor para baixo), seguido pela própria vogal.

  • sretorna o número de substituições feitas e $\=".[A"x s...salva várias cópias da sequência de bytes 1b 5b 41 (move o cursor para cima) $\, uma para cada vogal.

  • No final do programa, o Perl imprime automaticamente "$_$\", devido à -ptroca.

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

Aloca um buffer retangular (na verdade quadrado), preenche-o com espaços e novas linhas e, em seguida, percorre a sequência especificada. No final, ele adiciona um caractere nulo para evitar novas linhas.

Tecnicamente, não é uma função, pois contém globais; na verdade, não pode ser chamado mais de uma vez ( je ldeve ser 0 no início). Para estar em conformidade, i,j,k,l,M;pode ser movido para int i,j=0,k,l=0,M;no início da função.

jcai
fonte
char*t=malloc(M*M);-> char t[M*M];and for(i=0;i<M*M;++i)->for(;i<M*M;++i)
Spikatrix
Boas capturas, editadas.
jcai
Não é este C99 apenas devido a char t[M*M]?
Zachary
4

CJam, 47

Sim, é um pouco longo, mas não está "trapaceando" com códigos ANSI :)

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

Experimente online

A idéia é calcular um número de linha para cada caractere (começando em 0, aumentando em vogais e pulando de volta para 0 no espaço) e, em seguida, para cada linha, repita a sequência, mas substitua os caracteres que têm um número de linha diferente por um espaço .

aditsu
fonte
3

K, 81 72 70 66 bytes

Bem, é um começo:

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

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

Melhor. Foram feitas algumas melhorias no nível da superfície:

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

Notavelmente, inverti os argumentos para ?quando realizo a pesquisa por vogal e, assim, eliminei a necessidade de uma lambda, fiz a mesma inversão com_ em que dividi as palavras no espaço em branco e percebi que ~{" "?x}'xé uma maneira muito tola e complicada de dizer " "=x.

Edição 2:

Outro nível de superfície é alterado santes de aplicá-lo ao lambda, salvando parênteses no 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}

Edição 3:

OK, vamos adotar uma abordagem diferente para calcular o deslocamento de cada caractere. Em vez de dividir a sequência em espaços e calcular uma soma contínua ( +\) das posições das vogais, podemos operar toda a cadeia de entrada de uma só vez, multiplicando a soma contínua por 0 sempre que encontrarmos um espaço. Preciso da negação dessa sequência, para que eu possa subtrair em vez de adicionar à medida que digitalizo e uso número de distintos ( #?) em vez de max ( |/) ao calcular a quantidade de preenchimento 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}

Isso economiza outros 4 caracteres. Ufa!

JohnE
fonte
2

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

Exemplo de execução:

bash-4.3$ ruby staircase.rb <<< 'Programming Puzzles and Code Golf'
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing
homem a trabalhar
fonte
Se não me engano, você pode reduzir seu regex para /(?=[aeiouy ])/i.
Alex A.
Ah, você está certo @AlexA. O espaço como palavra separada era importante apenas para uma teoria anterior. Obrigado.
Manatwork 01/07/2015
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);}}

Isso percorre a string, apagando os caracteres à medida que os imprime. Ele se repete até que não haja caracteres que não sejam espaços para imprimir. É C portátil, sem fazer suposições sobre a codificação de caracteres.

Versão legível

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
fonte
' '-> 32e f(char*s){int l=0,r=1,v,c;->l,r=1,v,c;f(char*s){
Spikatrix
@Cool - ' ' pode ser 32, mas depende da codificação de caracteres, e como eu disse, fiz esse C. portátil. Largar o explícito inté ótimo, no entanto - não sei por que esqueci isso!
21815 Toby Speight
2

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

Isso é terrível e não tenho orgulho. Sei que isso pode ser mais curto, mas pensei em publicar de qualquer maneira.

Inspirado na versão C, ele cria uma lista que é preenchida enquanto percorre a string de entrada.

InputUsername
fonte
2

GNU Sed, 151 + 1

(+1 porque precisa da -rbandeira)

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

Eu pensei que o sed seria a ferramenta para este trabalho, mas achei surpreendentemente difícil.

Versão legível:

#!/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
fonte
Receio que sejam 128 caracteres. Falta a versão de uma linha e p, portanto, não gera nada. Um pequeno problema é que as saídas começam com um espaço extra. Um grande problema é que o primeiro pedaço de texto que começa com vogal desaparece.
Manatwork
Tenho certeza que estava funcionando mais cedo. Vou dar uma olhada e ver o que quebrei. Obrigado pelo aviso, @manatwork!
Toby Speight
Eu errei ao entrar em loop c, devido à linha pouco antes tx. Restabeleci uma versão anterior com seu loop semelhante e tentarei mais tarde.
precisa
2

Python 2, 145 142 bytes

Provavelmente não é tão competitivo quanto alguns outros métodos, mas achei que essa era uma maneira legal de usar o 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

A regex (?!([^aeiouy ]*[aeiouy]){N}[^aeiouy]* ).corresponde a qualquer caractere único que não esteja no N-ésimo grupo de letras do final de uma palavra. Como conta desde o fim do mundo, inverto a string antes e depois, e também tenho que adicionar um espaço no final, mas depois disso se torna uma simples questão de usar re.subpara substituir todas as instâncias desses caracteres por um espaço. Faz isso para todos os valores de N até que a cadeia esteja vazia.

KSab
fonte
Por mais agradável e legível que seja re.I, você pode salvar 3 bytes substituindo o valor de flag apropriado, ou seja 2.
SP3000
11
@ SP3000 Apenas em code-golf têm associações negativas com "agradável e legível"
KSab
1

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

Teste

Entrada: "YEAh UppErcAsE VOwEls"

Saída:

               V     
Y Upp Ow   
 E Erc Els
  Ah As        
             E       
barra sudo rm -rf
fonte
1

Gema : 53 48 caracteres

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

Observe que ^[(x1b) e ^K(x0b) são caracteres únicos. (Na amostra abaixo, eu uso as cópias e pastas compatíveis \ee \vequivalentes, caso você queira experimentá-las.)

Exemplo de execução:

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 
homem a trabalhar
fonte
1

Gelatina , 42 bytes (não concorrente?)

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

Experimente online!

Por que Jelly, por que? :-(

Erik, o Outgolfer
fonte
Mais do que CJam parece estranho
Fatalize
@Fatalize É porque Jelly simplesmente não combina com cordas ... normalmente. Também não é possível comparar diferentes paradigmas de programação (cjam é baseado em pilha, geléia é tácita).
Erik the Outgolfer