Scala una piastrellatura diamantata


27

Qualsiasi esagono regolare può essere piastrellato con diamanti, ad esempio in questo modo:

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

Considereremo quanto sopra una piastrellatura di dimensioni 1(poiché i lati dei diamanti sono fatti di uno /o \ciascuno). La stessa piastrellatura delle dimensioni 2sarebbe simile a:

      ____________ 
     /   /   /\   \  
    /___/___/  \___\ 
   /   /\   \  /\   \  
  /___/  \___\/  \___\ 
 /\   \  /   /\  /   /\  
/  \___\/___/  \/___/  \ 
\  /   /\   \  /   /\  /
 \/___/  \___\/___/  \/ 
  \   \  /   /\   \  /
   \___\/___/  \___\/ 
    \   \   \  /   /
     \___\___\/___/ 

Il tuo compito è ricevere una tale piastrellatura di arte ASCII (di dimensioni 1) come input, insieme a un numero intero positivo N(in decimale o unario), specificando la dimensione dell'output desiderato. Dovresti quindi produrre una versione ingrandita della stessa piastrellatura.

Si noti che l' esagono potrebbe essere di qualsiasi dimensione e piccolo come 1x1x1 (contenente tre diamanti).

Né input né output devono contenere spazi finali, né più spazi iniziali di quelli necessari per allineare la forma esagonale. Sia l'input che l'output possono contenere facoltativamente una nuova riga finale (questa scelta non deve essere la stessa per input e output).

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

Questo è il golf del codice, quindi la risposta più breve (in byte) in vittorie.

Tetti di esempio

Ecco una manciata di massimali di input che è possibile utilizzare per testare l'invio.

 __
/_/\
\_\/

  ____
 /_/\_\
/\_\/_/\
\/_/\_\/
 \_\/_/

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

    ________
   /_/\_\_\_\
  /\_\/\_\_\_\
 /\/_/\/_/_/\_\
/\/\_\/_/_/\/\_\ 
\/\/_/\_\_\/\/_/
 \/\_\/_/\_\/_/
  \/\_\_\/_/_/
   \/_/_/_/_/

Il frammento seguente contiene gli output corrispondenti per gli input N = 1through N = 6.


20
Vedo che sei interessato ai diamanti ora che ne hai uno accanto al tuo nome utente.
user12205,

3
@ace: sai cosa si dice: i diamanti sono i migliori amici di un moderatore.
Alex A.

Penso di conoscere la risposta, ma spero di sbagliarmi: le linee vuote in testa contano come spazio in testa, che hai dichiarato illegale? La mia soluzione iniziale ha N-1linee vuote iniziali . :(
Reto Koradi,

@RetoKoradi In effetti, nessuna nuova linea principale. Scusate.
Martin Ender,

1
Sono giunto alla conclusione. Mi è costato circa 10 byte. Non male come sembrava quando ho riconosciuto il problema per la prima volta.
Reto Koradi,

Risposte:


8

CJam, 85 79 76 72 byte

li:Tlf*NqN/T,f{ff{"_/"2$#_1<@+*~ST*@t}:+z{S+e`);e~{"_ "/"__"*W%}T2**N}/}

Le dimensioni dovrebbero essere sulla prima riga. E il diamante segue.

Non ho giocato molto bene ... E la metà dei personaggi è venuta dai dettagli.

Spiegazioni (della versione precedente)

li:T            e# Read the size and save to T.
qN/             e# Read and split to lines.
\,fm*           e# Convert each character X to [X 0] [X 1]... [X T(]
{~              e# For each [X I] in each line:
    ST*         e# T spaces.
    \           e# I.
    "_\\"3$#    e# If X is '_, '\ or '/, return Y = 0, 1, -1 respectively.
    _W>@+       e# If it was '_ or '\, increase I by one.
    *(          e# I * Y - 1.
    @t          e# Set the character at that position to X.
}f%
:z:+            e# Make the returned lists from each iteration across T lines.
{S+e`);e~N+}%   e# Boring details to remove trailing spaces and append a newline.
T(>(\s          e# Boring details to extract the first line and only work on others.
{_{"_ "/"__"*W%}2*_@=!}g
                e# Boring details to make underlines expand left and right.

10

Python 2, 164

def g(s,n,j=1):
 for W in s.split("\n"):exec"O=p='';d=0\nfor c in W:q=' _'[j*'_'in p+c];e=[n-j,j-1][c=='/'];O+=q*(e+d)+[c,q][c>'^'];p=c;d=n+~e\nprint O;j-=1;"*j;j=n

Uscita su casi di test.

Allora, cosa sta succedendo qui?

L'idea principale è che ogni personaggio dell'originale esploda in un n*nblocco. Ad esempio, per n = 4, /potrebbe diventare

   /
  /
 /
/___

Il personaggio originale appare una volta su ogni riga e c'è un'imbottitura su entrambi i lati. Qui, è a sinistra, e e _sulla destra. È possibile riempire solo la riga inferiore '_'; il resto è sempre ' '.

La difficoltà principale è che l'imbottitura a destra può dipendere dal simbolo imminente. In particolare, '/ 'ha un'imbottitura diversa dalla '/_', quindi avremmo bisogno di un po 'di anticipo. Inoltre, per evitare spazi finali, dovremmo notare che siamo all'ultimo simbolo e ci asteniamo dall'imbottire sulla destra.

Superiamo entrambi questi problemi solo riempiendo a sinistra del personaggio attuale. Quando lo facciamo, eseguiamo anche il padding destro del carattere precedente usando il simbolo di padding corrente. Quindi, stampiamo il padding destro dovuto dal carattere precedente, il padding sinistro dal carattere corrente, quindi il carattere corrente. Memorizziamo anche la quantità di "debito" di riempimento che il prossimo personaggio dovrà pagare.

Ora andiamo oltre il codice.

def g(s,n,j=1):
    for W in s.split("\n"):
        while j:
            O=p='';d=0
            for c in W:
                q=' _'[j*'_'in p+c]
                e=[n-j,j-1][c=='/']
                O+=q*(e+d)+[c,q][c>'^']
                p=c
                d=n+~e
            print O;j-=1;
        j=n

La stringa di input è se il fattore di scala è n. Andiamo riga per riga, stampando le nrighe per ogni riga di input W, con le copie indicizzate j=n,n-1,...,2,1. La prima riga viene copiata una sola volta, cosa che otteniamo inizializzando jsu 1 ma cambiandola in nciascun loop.

Esaminiamo la riga di input, accumulando la riga in cui stampare O. Innanzitutto, scopriamo il carattere di riempimento appropriato q, che è un carattere di sottolineatura se siamo sulla linea di fondo e il carattere corrente o precedente è un carattere di sottolineatura, o comunque uno spazio.

Quindi, decidiamo la quantità di imbottitura da mettere a sinistra ( e). Per /, è j-1(decrescente con il numero decrescente di copia di riga) e complementare n-jper \. Trattiamo altri personaggi allo stesso modo. Ad esempio, sebbene _sembri dare una riga di caratteri di nsottolineatura, in realtà fornisce un singolo carattere di sottolineatura, imbottito da caratteri di sottolineatura a sinistra e a destra. Questo sembra inefficiente, ma ci consente di lavorare con _e nello stesso framework di /e \La posizione del carattere di sottolineatura "centrale" non ha importanza, quindi la raggruppiamo e con \; questa scelta fa funzionare anche la fila superiore senza involucro speciale.

Successivamente, aggiungiamo alla stringa di output. Abbiamo individuato il simbolo dell'imbottitura qe l'attuale importo dell'imbottitura e, ma dobbiamo anche ricordare il debito di imbottitura ddel simbolo precedente. Quindi, aggiungiamo q*(e+d). Quindi, aggiungiamo il simbolo corrente c, tranne che dobbiamo evitare i caratteri di sottolineatura in una riga non inferiore, che risolviamo convertendo i caratteri di sottolineatura nel simbolo di riempimento.

Infine, registriamo l'importo del debito di riempimento, che costituisce il complemento n+~ddell'attuale importo di riempimento di sinistra. Registriamo anche il simbolo corrente p, in modo da sapere in seguito se fosse il simbolo precedente _.


3

JavaScript ( ES6 ) 274 281 289 338

// GOLFED
F=(b,n)=>{
b=b[R='replace'](/ |_/g,c=>c[T='repeat'](n))[R](/_(?=[\\\/])/g,'_'[T](n))[R](/\/\\/g,`/${'  '[T](n-1)}\\`)
.split('\n');
for(i=l=b.length*n-n+1;--i;)
b[i]=i%n?b[i+1][R](/_/g,' ')[R](/\/ ?/g,' /')[R](/ \\(.)?/g,'\\$1$1')
:' '[T](i>l/2?n-1:0)+b[i/n];
return b.join('\n')}


// UNGOLFED
U=(b,n)=>{
  b=b
  .replace(/ |_/g,c=>c.repeat(n))
  .replace(/_(?=[\/\\])/g,'_'.repeat(n))
  .replace(/\/\\/g,`/${'  '.repeat(n-1)}\\`)
  .split('\n');
  for(i=l=b.length*n-n+1;--i;)
  {
    if(i%n)
     b[i]=b[i+1]
     .replace(/_/g,' ')
     .replace(/\/ ?/g,' /')
     .replace(/ \\/g,'\\ ').replace(/ +$/,'')
     .replace(/ \\(.)?/g,'\\$1$1')
    else {
      b[i]=b[i/n]
      if(i>l/2)b[i]=' '.repeat(n-1)+b[i];
    }
  }
  return b.join('\n')
}

//TEST

test=[
' __\n/_/\\\n\\_\\/',
'  ____\n /_/\\_\\\n/\\_\\/_/\\\n\\/_/\\_\\/\n \\_\\/_/',
'   ______\n  /_/_/\\_\\\n /_/\\_\\/\\_\\\n/\\_\\/_/\\/_/\\\n\\/_/\\_\\/_/\\/\n \\_\\/_/\\_\\/\n  \\_\\_\\/_/',
'    ________\n   /_/\\_\\_\\_\\\n  /\\_\\/\\_\\_\\_\\\n /\\/_/\\/_/_/\\_\\\n/\\/\\_\\/_/_/\\/\\_\\\n\\/\\/_/\\_\\_\\/\\/_/\n \\/\\_\\/_/\\_\\/_/\n  \\/\\_\\_\\/_/_/\n   \\/_/_/_/_/'
]

test.forEach(t=>{
  var row = '<td>'+t+'<td>'
  for(rr=2;rr<5;rr++)
    row += '<td>'+F(t,rr)+'</td>'
  OUT.innerHTML += '<tr>'+row+'</tr>'
})
td {
  font-family: monospace;
  white-space: pre;
}
(better full page)
<table id=OUT></table>


3

Python 2, 217 211 195 194 190

b,f,s='\/ '
R=str.replace
def m(g,n,z=1):
 for d in g.split('\n'):
    for i in range(z):a=z+~i;print[i,a][d[-1]>f]*s+R(R(R(R(d,s,s*n),'_','_ '[i<z-1]*(z+n-1)),f+b,f+s*2*i+b),b+f,b+s*2*a+f);z=n

6 byte grazie a Sp3000.

Chiama mcon il primo argomento come il diamante come una stringa e il secondo argomento il numero di ripetizione.

Questo si basa su una sequenza di sostituzione della stringa in 3 passaggi:

  • In primo luogo, sostituire i trattini bassi con spazi 2n-1 o underscore, a seconda della linea.
  • In secondo luogo, sostituire /\con / \, con il numero di spazi intermedi che vanno da 2 a 2 * (n-1) sulle linee.
  • In terzo luogo, sostituire \/con \ /, con il numero di spazi intermedi che vanno da 2 * (n-1) a 2 sulle linee.

Quindi, c'è una varietà di mucking per ottenere gli spazi iniziali giusti e per ottenere la prima linea giusta.

Nota che l'ultima riga del programma dovrebbe essere una scheda, non 4 spazi. Markdown non supporta le schede.


Due golf: (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]e lo usi solo '_'una volta, quindi perdi un byte per definirlo.
Sp3000,

3

Python, 272 238 228 243 byte

Versione aggiornata, ora accetta una singola stringa come input, anziché una sequenza di stringhe. Rimuove anche gli spazi vuoti finali presenti nella versione precedente. Sfortunatamente questi cambiamenti aumentano le dimensioni.

s,u,f,b=' _/\\'
r=str.replace
def d(t,n,j=1):
 for p in t.split('\n'):
  for k in range(n-j,n):m,v=n+~k,'_ '[k<n-1];print r(r(r(r(r(r(r(r(p,f+u,'(_'),u+b,'_)'),s,s*n),u,v*n),f,s*m+f+s*k),'(',v*m+f+v*k),b,s*k+b+s*m),')',v*k+b+v*m).rstrip();j=n

Versione con spazi bianchi e istruzioni suddivise in unità più piccole per la leggibilità:

s, u, f, b = ' ', '_', '/', '\\'
def d(t, n):
    j = n - 1
    for p in t:
        for k in range(j, n):
            m, v = n - 1 - k, '_ '[k < n - 1]
            q = p[:-1]
            q = q.replace(f + u, '(_')
            q = q.replace(u + b, '_)')
            q = q.replace(s, s * n)
            q = q.replace(u, v * n)
            q = q.replace(f, s * m + f + s * k)
            q = q.replace('(', v * m + f + v * k)
            q = q.replace(b, s * k + b + s * m)
            q = q.replace(')', v * k + b + v * m)
            print q
            j = 0

L'approccio di base qui è:

  1. Passa su tutte le linee in ingresso.
  2. Per ogni riga, eseguire il loop sopra la dimensione di output N, generando una riga di output in ogni iterazione di loop. C'è un caso speciale per la prima riga, in cui viene generata solo l'ultima riga di output, per evitare di generare righe vuote all'inizio dell'output.
  3. Sostituisci ogni carattere nella riga con Ncaratteri, dove:
    • Ogni spazio è sostituito da Nspazi.
    • Ogni carattere di sottolineatura viene sostituito da Nspazi per le N -1iterazioni del primo ciclo e caratteri di Nsottolineatura per l'ultima iterazione del ciclo.
    • Le barre e le barre rovesciate sono riempite con N - 1spazi o caratteri di sottolineatura.

La parte più difficile qui è che l'imbottitura per barre / barre rovesciate utilizza spazi o caratteri di sottolineatura a seconda del carattere di input successivo (per barre) o precedente (per barre rovesciate). Ciò non sembrava adattarsi bene alla strategia di sostituzione delle stringhe.

Ciò che ho fatto per risolvere questo problema è che per prima cosa sostituisco alcune combinazioni di due caratteri con caratteri diversi, in modo da poterli trattare in modo diverso durante la sostituzione effettiva. Ad esempio, /_è sostituito da (_. Dopo questo, (è effettivamente una "barra seguita da un trattino basso", che può quindi essere sostituita di conseguenza.

Programma principale utilizzato per testare la funzione:

import sys
import Golf

n = int(sys.argv[1])
t = ''.join(sys.stdin).rstrip()

Golf.d(t, n)

1
n-1-kèn+~k
ricorsivo

Nell'interesse della piena divulgazione: ho appena scoperto che la mia soluzione produce alcuni spazi finali. Poiché ciò non è consentito nella definizione di output, non soddisfa i requisiti. Nel peggiore dei casi, dovrò aggiungere un .rstrip()altro 9 caratteri. Spero di poter fare di meglio e ho anche trovato il modo di ritagliare 5 personaggi.
Reto Koradi,

Sembra che il tuo formato di input non sia consentito. sys.stdinnon è un parametro di input consentito: è necessario manipolare la stringa stessa.
isaacg,

Bene, puoi usarlo sys.stdine int(sys.argv[1])non li otterrai gratuitamente aspettandoti che vengano passati come variabili (se quello era un gioco corretto, allora potresti anche aspettarti degli alias rangee sostituirli) e qualsiasi altra cosa tu debba essere predefinita .
Martin Ender,

@ MartinBüttner Dice che posso prendere l'input come argomento di funzione. Non è quello che sto facendo qui? Stavo per cambiare l'argomento della funzione in un elenco di stringhe comunque. Sarebbe ok? Non è molto diverso, poiché entrambi stdine un elenco di stringhe sono sequenze di stringhe.
Reto Koradi,

1

Perl, 132

#!perl -p
INIT{$f=pop}s!.!$&x$f!ge;s! $!! while s!\\+\K\\|/(/)! $1!;
for$x(2..m!/!*$f){print y!_! !r;s!\\.?! \\!g;s!./(.)?!/$1$1!g;s!_ !__!g}

Ingresso combinato STDIN e ARGV. Esempio:

$ perl ~/hex.pl <~/hex.txt 3
         __________________
        /     /     /\     \
       /     /     /  \     \
      /_____/_____/    \_____\
     /     /\     \    /\     \
    /     /  \     \  /  \     \
   /_____/    \_____\/    \_____\
  /\     \    /     /\    /     /\
 /  \     \  /     /  \  /     /  \
/    \_____\/_____/    \/_____/    \
\    /     /\     \    /     /\    /
 \  /     /  \     \  /     /  \  /
  \/_____/    \_____\/_____/    \/
   \     \    /     /\     \    /
    \     \  /     /  \     \  /
     \_____\/_____/    \_____\/
      \     \     \    /     /
       \     \     \  /     /
        \_____\_____\/_____/

1

Rubino 236 237

->i,z{i.split(?\n).map{|l|z.times.map{|y|l.size.times.map{|i|z.times.map{|x|c=l[i]
z<y+2&&(l[i-1..i]=='_\\'||l[i..i+1]=='/_')&&o=?_
(c<?!||(x==y&&c==?\\)||(z==y+1&&c>?^)||(x+y+1==z&&c==?/))&&o=c
o||' '}.join}.join.rstrip}-['']}.join ?\n}

Test online: http://ideone.com/e6XakQ

Questo è il codice prima del golf:

-> diamond, zoom {
  diamond.split(?\n).map do |l|
    zoom.times.map do |y|
      l.size.times.map do |i|
        zoom.times.map do |x|
          out_char = crt_char = l[i]

          out_char = ' '

          # _ has to be continued under / or \
          if zoom == y+1 && l[i-1..i]=='_\\'
            out_char = ?_
          end
          if zoom == y+1 && l[i..i+1]=='/_'
            out_char = ?_
          end

          # logic to "zoom" \, / and _ characters 
          out_char = crt_char if crt_char == ' '
          out_char = crt_char if x==y && crt_char == ?\\  
          out_char = crt_char if zoom==y+1 && crt_char == ?_
          out_char = crt_char if x+y+1==zoom && crt_char == ?/

          out_char
        end.join
      end.join.rstrip
    end - ['']
  end.join ?\n
}
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.