Scrittura delle scale


35

Scrivi un programma o una funzione che produrrà una determinata stringa in una scala, scrivendo ogni parte di una parola che inizia con una vocale una riga sotto la parte precedente.

Per esempio:

Input: Programming Puzzles and Code Golf


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

Ingresso

Una stringa contenente nient'altro che lettere e spazi.

La stringa può essere passata tramite STDINo argomenti di funzione o qualcosa di equivalente.

Le lettere possono essere minuscole o maiuscole.

Si presume sempre che gli input seguano tali regole, non è necessario verificare la presenza di input errati.

Produzione

Ogni volta che una vocale (che è, a, e, i, o, uo y) si incontra in una parola, è necessario emettere il resto della parola nella riga successiva (la vocale incontrato inclusa), alla corretta posizione orizzontale. Questa regola è ricorsiva, il che significa che se ci sono n vocali nella parola, sarà scritta su n + 1 righe.

  • La vocale dovrebbe essere scritta all'inizio della riga successiva e non alla fine della riga precedente quando ne viene incontrata una.

  • Ogni parola inizia sulla prima riga e deve quindi essere formattata indipendentemente dalle altre parole. Due parole sono separate da uno spazio.

  • Se una parola inizia con una vocale, devi scriverla a partire dalla seconda riga.

Casi test

  • Ingresso: Programming Puzzles and Code Golf

Produzione:

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

Produzione:

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

Produzione:

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

Produzione:

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

Produzione:

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

punteggio

Questo è , quindi vince il codice più corto.


Il terzo esempio di output sembra incompatibile con la regola "Se una parola inizia con una vocale, è necessario scriverla a partire dalla seconda riga".
Giovanni

1
Y è Y una vocale?
Ottimizzatore

1
@JohnE in effetti lo era, l'ho risolto. Grazie.
Fatalizza il

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.Dopo aver riflettuto un po ', capisco che questo significa che il passaggio alla riga successiva dovrebbe avvenire prima che la vocale venga stampata, non dopo, ma potrebbe valere la pena di formularla in un modo immediatamente comprensibile - mi ci è voluto un po'.
trichoplax,

3
Sono consentite nuove linee / spazi finali?
Loovjo,

Risposte:


18

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

Grazie a Dennis per aver salvato 14 byte usando i caratteri di controllo effettivi.

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

Sulla base di questa risposta , sto usando i codici di escape ANSI per spostare il cursore del terminale in verticale. Il <ESC>deve essere sostituito con il carattere di controllo 0x1B, e <VT>con la linguetta verticale 0x0B. Per test più semplici, è anche possibile sostituire <ESC>con \e, <VT>con \ve trasmettere l'output printf.

Ai fini del conteggio, ogni riga va in un file separato. Tuttavia, per comodità è più semplice incollare il codice in un singolo file e richiamare Retina con l' -sopzione.

Il primo rimpiazzo circonda ciascuna vocale \v...#, in cui \vsposta il cursore verso il basso e #è un marker per il secondo passo. È i`la notazione di Retina per la corrispondenza senza distinzione tra maiuscole e minuscole.

Il secondo passaggio quindi ripetutamente ( +`) rimuove a #da una parola e mette e\[Aa alla fine della parola che sposta il cursore verso l'alto. Questo si interrompe quando la stringa smette di cambiare, cioè quando non ci sono più #marcatori nella stringa.


Non hai bisogno printf. Sostituire semplicemente \econ il byte ESC (0x1b).
Dennis,

@Dennis Oh, va molto meglio, grazie.
Martin Ender,

1
È così fantastico !!!
kirbyfan64sos,

Questa risposta è il motivo per cui nessuno prende sul serio Retina;)
Christopher Wirt,

@ChristopherWirt Per favore, elabora :) (Anche se sarei davvero terrorizzato se qualcuno prendesse sul serio Retina.)
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}/

Quanto sopra è un dump xxd reversibile, poiché il codice sorgente contiene il carattere non stampabile VT (punto codice 0x0b) e ESC (punto codice 0x1b).

Come questa risposta , utilizza schede verticali e sequenze di escape ANSI .

Ciò richiede un terminale di testo video di supporto, che include la maggior parte degli emulatori di terminale non Windows.

Prova

Prima di eseguire il codice effettivo, disabiliteremo il prompt e cancelleremo lo schermo.

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

Questo assicura che l'output sia mostrato correttamente.

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

Per ripristinare il prompt, eseguire questo:

PS1="$PS1save"

Come funziona

Inseriamo una linguetta verticale prima di ogni vocale per spostare il cursore verso il basso e copie sufficienti della sequenza di byte 1b 5b 41 ( "\e[A") dopo ogni spazio per spostare il cursore sulla prima riga.

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#

Non dimenticare di unset PS1savedopo.
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]);}

Lo so, è orribile. Probabilmente ci sono alcuni caratteri che possono essere rasati, ma sono troppo pigro per farlo.


Probabilmente si può dichiarare molte delle vostre intvariabili (vale a dire i, r, p, o, e x), dove si inizializza le mpoiché essi saranno forniti i valori più tardi. Puoi anche fare String v="...",a[]=...;e fare come sopra per String u. Ciò dovrebbe abbassare un po 'il tuo punteggio.
TNT,

Mi piace ilx++-~-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

Quanto sopra è un dump xxd reversibile, poiché il codice sorgente contiene il carattere non stampabile VT (punto codice 0x0b) e ESC (punto codice 0x1b).

Il codice è lungo 27 byte e richiede gli switch 040p(4 byte).

Il programma richiede un terminale di testo video che supporti le schede verticali e le sequenze di escape ANSI , che include la maggior parte degli emulatori di terminali non Windows.

Prova

Prima di eseguire il codice effettivo, disabiliteremo il prompt e cancelleremo lo schermo.

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

Questo assicura che l'output sia mostrato correttamente.

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

Per ripristinare il prompt, eseguire questo:

PS1="$PS1save"

Come funziona

  • perl -040plegge automaticamente l'input come token separati da spazio ( -040), salva ciascun token in $_( -p) ed esegue il programma.

  • s/[aeiouy]/.$&/giesegue una ricerca globale e senza distinzione tra maiuscole e minuscole $_per le vocali e sostituisce ciascuna vocale con il carattere di controllo VT (sposta il cursore verso il basso), seguito dalla vocale stessa.

  • srestituisce il numero di sostituzioni effettuate, quindi $\=".[A"x s...salva più copie della sequenza di byte 1b 5b 41 (sposta il cursore verso l'alto) $\, una per ogni vocale.

  • Alla fine del programma, Perl stampa automaticamente "$_$\", a causa del -pcambio.


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

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

Alloca un buffer rettangolare (in realtà quadrato), lo riempie di spazi e di nuove linee, quindi attraversa la stringa specificata. Alla fine aggiunge un carattere nullo per impedire il trascinamento di nuove righe.

Tecnicamente non è una funzione poiché contiene globali; infatti non può essere chiamato più di una volta ( je ldeve essere 0 all'inizio). Per conformarsi, i,j,k,l,M;potrebbe essere spostato int i,j=0,k,l=0,M;all'inizio della funzione.


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

Buone catture, modificato.
jcai,

Questo C99 non è dovuto solo a char t[M*M]?
Zacharý,

4

CJam, 47

Sì, è un po 'lungo, ma non è "imbrogliare" con i codici ANSI :)

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

Provalo online

L'idea è di calcolare un numero di riga per ogni carattere (a partire da 0, incrementando alle vocali e saltando indietro a 0 nello spazio), quindi per ogni riga, ripetere la stringa ma sostituire i caratteri che hanno un numero di riga diverso con uno spazio .


3

K, 81 72 70 66 byte

Bene, è un inizio:

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

Esempi di utilizzo:

  `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       

Modifica 1:

Meglio. Sono stati apportati alcuni miglioramenti al livello della 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}

In particolare, ho invertito gli argomenti per ?quando eseguo la ricerca vocale e così ho eliminato la necessità di una lambda, ho fatto la stessa inversione con _cui ho diviso le parole su uno spazio bianco e ho capito che ~{" "?x}'xè un modo di dire davvero sciocco e complicato " "=x.

Modifica 2:

Un altro aggiustamento del livello di superficie - annulla sprima di applicarlo alla lambda, salvando le parentesi all'interno:

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

Modifica 3:

OK, adottiamo un approccio diverso per calcolare l'offset per ciascun personaggio. Invece di dividere la sequenza negli spazi e calcolare una somma corrente ( +\) delle posizioni delle vocali, possiamo operare sull'intera stringa di input in un passaggio, moltiplicando la somma corrente per 0 ogni volta che incontriamo uno spazio. Ho bisogno della negazione di questa sequenza, quindi posso sottrarre invece di aggiungere mentre eseguo la scansione e utilizzo il numero di distinto ( #?) anziché max ( |/) quando calcolo la quantità di riempimento verticale.

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

Ciò consente di salvare altri 4 caratteri. Accidenti!


2

Rubino: 135 131 124 115 112 caratteri

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

Esecuzione di esempio:

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

Se non sbaglio, puoi accorciare la tua regex /(?=[aeiouy ])/i.
Alex A.

Ah, hai ragione @AlexA. Lo spazio come parola separata era importante solo per una teoria precedente. Grazie.
arte

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

Questo scorre attraverso la stringa, cancellando i caratteri mentre li stampa. Si ripete fino a quando non ci sono più caratteri non spaziali da stampare. È portatile C, senza fare ipotesi sulla codifica dei caratteri.

Versione leggibile

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

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

@Cool - ' ' può essere 32, ma dipende dalla codifica dei caratteri, e come ho detto, ho creato questo portatile C. Far cadere l'esplicito intè fantastico, però - non sono sicuro del motivo per cui me ne sono dimenticato!
Toby Speight,

2

Python 3, 265 207 202 185 177 caratteri

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

Questo è terribile e non sono orgoglioso. So che questo può essere ridotto, ma ho pensato di pubblicare comunque.

Ispirato alla versione C, crea un elenco che viene quindi riempito mentre attraversa la stringa di input.


2

GNU Sed, 151 + 1

(+1 in quanto necessita della -rbandiera)

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

Pensavo che sed sarebbe stato lo strumento per questo lavoro, ma l'ho trovato sorprendentemente difficile.

Versione leggibile:

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

Temo che dovrebbero essere 128 caratteri. Nella versione a una riga manca un p, quindi non genera nulla. Un piccolo problema è che le uscite iniziano con uno spazio aggiuntivo. Un grosso problema è che il primo pezzo di testo che inizia con la vocale scompare.
arte

Sono sicuro che funzionava prima. Darò un'occhiata e vedrò cosa ho rotto. Grazie per l'heads-up, @manatwork!
Toby Speight,

Ho sbagliato a saltare in loop c, a causa della linea appena prima tx. Ho ripristinato una versione precedente con il suo ciclo simile e avrò un altro tentativo più tardi.
Toby Speight,

2

Python 2, 145 142 byte

Probabilmente non è competitivo come alcuni altri metodi, ma ho pensato che fosse un modo fantastico di usare 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

La regex (?!([^aeiouy ]*[aeiouy]){N}[^aeiouy]* ).corrisponde a qualsiasi singolo carattere non compreso nell'ennesimo gruppo di lettere dalla fine di una parola. Poiché conta dalla fine del mondo, invertisco la stringa prima e dopo, e devo anche aggiungere uno spazio alla fine, ma dopo ciò diventa una semplice questione di utilizzo re.subper sostituire ogni istanza di questi personaggi con uno spazio. Lo fa per ogni valore di N fino a quando la stringa è vuota.


Per quanto bello e leggibile re.I, è possibile salvare 3 byte sostituendo il valore flag appropriato, ad es 2.
Sp3000,

1
@ Sp3000 Solo nel code-golf hanno associazioni negative con "bello e leggibile"
KSab

1

Ottava, 132 129 caratteri

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

Ingresso: "YEAh UppErcAsE VOwEls"

Produzione:

               V     
Y Upp Ow   
 E Erc Els
  Ah As        
             E       

1

Gema : 53 48 caratteri

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

Si noti che ^[(x1b) e ^K(x0b) sono caratteri singoli. (Nell'esempio di seguito riportato uso i loro copia-incolla \ee \vequivalenti, nel caso tu voglia provarlo.)

Esecuzione di esempio:

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

Gelatina , 42 byte (non competitiva?)

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

Provalo online!

Perché Jelly, perché? :-(


Più a lungo di CJam sembra strano
Fatalizza il

@Fatalize È perché Jelly semplicemente non va con le stringhe ... di solito. Inoltre non puoi davvero confrontare diversi paradigmi di programmazione (cjam è basato su stack, jelly è tacito).
Erik the Outgolfer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.