Random ASCII Art of the Day # 5: Diamond Tilings


21

Tempo di schiacciamento!

Questa è la puntata numero 5 della mia serie Random Golf of the Day e ASCII Art of the Day di Optimizer . Le tue proposte in questa sfida verranno conteggiate in entrambe le classifiche (che puoi trovare i post collegati). Ovviamente, puoi trattarlo come qualsiasi altra sfida di golf del codice e rispondere senza preoccuparti delle due serie.

Hole 5: Diamond Tilings

Un esagono regolare può sempre essere piastrellato con diamanti in questo modo:

Useremo una rappresentazione artistica ASCII di questi tasselli. Per un esagono di lunghezza laterale 2, ci sono 20 tetti di questo tipo:

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

Data una lunghezza laterale N, dovresti generare una tale piastrellatura per un esagono di lunghezza laterale Na caso. L'esatta distribuzione non ha importanza, ma ogni piastrellatura deve essere restituita con probabilità diversa da zero.

Perché N ≤ 4, il tuo invio deve produrre una piastrellatura entro 1 minuto almeno l'80% delle volte e almeno l'80% dei massimali deve essere potenzialmente generato entro 1 minuto. La maggior parte degli approcci non dovrà preoccuparsi di questa regola (è molto indulgente) - questo è solo per escludere algoritmi basati sul rifiuto molto ingenui che generano stringhe arbitrarie fino a quando non si capita di essere una piastrellatura.

Potresti sapere che il numero totale di tetti possibili per una data N può essere trovato in OEIS A008793 .

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

Non è necessario generare più spazi iniziali del necessario per allineare l'esagono (ovvero l'angolo sinistro dell'esagono non dovrebbe avere spazi davanti ad esso). Ogni riga può contenere fino a Nspazi finali (non necessariamente coerenti, quindi potresti ad esempio avere un output rettangolare, stampare il rettangolo di selezione dell'esagono).

Questo è il golf del codice, quindi vince l'invio più breve (in byte). E, naturalmente, la presentazione più breve per utente entrerà anche nella classifica generale della serie.

Classifiche

Il primo post di ogni serie genera una classifica.

Per assicurarti che le tue risposte vengano visualizzate, inizia ogni risposta con un titolo, utilizzando il seguente modello Markdown:

# Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(La lingua non è attualmente mostrata, ma lo snippet richiede e analizza, e potrei aggiungere una classifica per lingua in futuro.)


3
Sono solo io che continuo a vedere l'immagine di esempio in 3D?
LegionMammal978,

3
@ LegionMammal978 No, è perfettamente normale. ;) (Ed è probabilmente anche un buon modo per affrontare la sfida.)
Martin Ender,

For N ≤ 4, your submission must produce a tiling within 1 minute at least 80% of the time.troppo facile: l'80% delle volte lo stesso, piastrellatura di base, altrimenti trovo un'altra piastrellatura in qualsiasi momento voglio
edc65

@ edc65 Un buon punto, fammi riformulare.
Martin Ender,

Risposte:


10

CJam, 105 byte

ri:A" __"e*A,2f*:B,[W1]{J+B:):B,{N1$S*"\/"J%A2*4$-:D*
0{;B{_1&!2mr+J*m1e>D(2*e<}%__:)&}g:B{'_t}/+@J+}*}fJ;

Newline aggiunto per evitare lo scorrimento. Provalo online

Spiegazione:

Questa soluzione avvia ogni riga come un zigzag, quindi posiziona N caratteri di sottolineatura su di essa, in base alla loro posizione sulla riga precedente e ad un paio di regole. Ho ottenuto questo da una serie di osservazioni mentre guardavo l'output come una semplice matrice 2D di caratteri:

  • ogni riga ha esattamente N trattini bassi
  • i caratteri di sottolineatura possono essere sostituiti con / o \ per creare un motivo a zigzag perfettamente ripetuto ( /\nella metà superiore, \/nella metà inferiore)
  • i trattini bassi non possono toccare i lati e non possono essere adiacenti a un altro trattino basso
  • quando si passa alla riga successiva, la posizione di ciascun carattere di sottolineatura cambia di -1, 0 o 1
  • più di questo, /_/può cambiare solo di -1 o 0 e \_\può cambiare solo di 0 o 1
  • per le posizioni iniziali di sottolineatura possiamo usare uno "_ "schema o uno " _"schema, entrambi vanno bene
  • le regole di cui sopra sono sufficienti per ottenere tutti i massimali

Così ho deciso di implementarlo mantenendo le posizioni di sottolineatura precedenti, modificandole con un fattore casuale (2 scelte per ciascun trattino di sottolineatura) e ripetendole fino a quando le regole sono soddisfatte. Nel processo di ottimizzazione, sono passato alle posizioni di sottolineatura relative al lato sinistro dell'esagono (esclusi gli spazi).

ri:A" __"e*       read the input (A) and generate the top line
A,2f*:B           make an array [0 2 4 ... 2A-2] and store in B
                  these are the initial positions for the underscores
,                 B's length = A, used as the initial number of leading spaces
                  let's call it C
[W1]{…}fJ         for J in [-1 1] (top half, bottom half)
  J+              add J to C
  B:):B           increment the underscore positions (adjustment before each half)
  ,{…}*           repeat A times
    N1$S*         add a newline and C spaces
    "\/"J%        take "\/" and reverse it if J=-1 (zigzag pattern)
    A2*4$-:D*     calculate D=A*2-C and repeat the pattern
    0             dummy value (for the next loop)
    {…}g          do-while
      ;B          pop last value and push B
      {…}%        apply block to each item (say x)
        _1&!      duplicate x and calculate !(x&1) (for /_/ vs \_\)
        2mr+      randomly add 0 or 1
        J*m       multiply by J and subtract from x
        1e>       limit the minimum value to 1
        D(2*e<    and the maximum value to 2*(D-1)
      __:)&       check if the modified array has any adjacent values
    :B            store the new positions in B
    {'_t}/        place underscores over the zigzag pattern
    +@J+          bring C to the top and add J to it
;                 pop C

Vecchia versione "3D", 189 byte:

ri:A" __"e*aA4*S*aA2**+[0-2XXW1]:C;"/\_\\\/_/":D;A3m*{{C2/.f*:.+~
A(2*+:V;A+:U;2{UI+1$1$=4{_V+D4/I=@=t}/t}fI}:F~}/[0Y1WWW]:C;
"/_/\\\_\/":D;AaA*:B;A{A[_{_BI=e<)mr}fI]:B;{BQ={[PQR]F}fR}fQ}fPN*

Provalo online


+1 per un lavoro fantastico e anche perché un altro voto ti metterebbe a 10k rappresentanti, ma soprattutto per il fantastico lavoro. (Oh hey, guarda. Complimenti per 10k :))
Alex A.

Un'ottima analisi sugli schemi! Lo userò per la mia risposta.
Anatolyg,

6

Python 2, 337 335 324 318 311 300 296 byte

from random import*
n=input()
R=range(n*2)
b=[]
l=[]
for i in R:o=abs(i-n)-(i<n);b+=[o];l+=[list(' '*o+'\//\\'[i<n::2]*(n*2-o))]
for i in R[:n]:
 o=1;p=n+i*2
 for j in R:r=randint(0,p<n*3+i*2-j);p+=(r or-1)*(o==r);q=p<=b[j];o=r|q;p+=q;l[j][p]='_';b[j]=p+1
for s in[' '*n+'__'*n]+l:print''.join(s)

L'idea è di creare prima un esagono di diamanti, in questo modo:

  ____
 /\/\/\
/\/\/\/\
\/\/\/\/
 \/\/\/

E poi riempilo con percorsi verso il basso di caratteri di sottolineatura, in questo modo:

  ____                          ____
 /_/\/\                        /\_\/\
/_/\/\/\    or maybe this:    /\/_/\/\
\_\/\/\/                      \/_/\/\/
 \_\/\/                        \_\/\/

Il risultato finale con tutti i percorsi aggiunti sarebbe quindi simile al seguente:

  ____                          ____  
 /_/\_\                        /\_\_\ 
/_/\/_/\    or maybe this:    /\/_/\_\
\_\/_/\/                      \/_/\/_/
 \_\_\/                        \_\/_/ 

Un bel po 'di codice fa in modo che questi percorsi non vadano oltre i limiti o si incrociano.

Il codice ungolfed:

# Initialize l with all diamonds
blocked = []
l = [[] for _ in range(n*2)]
for i in range(n*2):
    offset = n-i-1 if i<n else i-n
    blocked.append(offset)
    l[i] += ' '*offset + ('/\\' if i<n else '\/')*(2*n - offset)

# Generate the random _'s
for i in range(n):
    oldright = True
    pos = n + i*2
    for j in range(n*2):
        # Go randomly right (true) or left (false), except when you out of bounds on the right side
        right = randint(0, 1) and pos < n*3 + i*2 - j
        if right == oldright:
            pos += 1 if right else -1
        if pos <= blocked[j]:
            right = True
            pos += 1
        l[j][pos] = '_'
        blocked[j] = pos + 1
        oldright = right

# Print the result
print ' '*n + '__'*n
for s in l:
    print ''.join(s)

1
Ho appena notato che il tuo output sembra sbagliato. Hai dei triangoli nei due risultati dell'esapolo (in alto a destra e in basso a destra).
Martin Ender,

1
@MartinEnder Gli esempi hanno mostrato solo un 'percorso di trattini bassi', per mostrare l'idea dell'algoritmo. L'output finale ha tutti i percorsi (in questo caso 2), che elimina i triangoli. Ho aggiunto anche esempi dell'output finale.
Matty,

Ohhh capisco, ha senso. Grazie per il chiarimento.
Martin Ender,

2
Penso che si possa ridurre randint(0,1)*(p<n*3+i*2-j)a randint(0,p<n*3+i*2-j).
12ee21

Oooh sì, grazie!
Matty

4

Perl, 174 168 166 161

#!perl -n
for$l(-$_..$_){$t=/_/?join'',map'/_'x($%=rand
1+(@z=/__?/g)).'/\\'.'_\\'x(@z-$%),split/\/\\/:__
x$_;$l>0&&$t!~s!^.(\\.*/).$!$1!?redo:print$"x abs$l-.5,$_=$t.$/}

Prova a me .


Sembra sempre generare la stessa piastrellatura (almeno su ideone)
aditsu,

@aditsu, Ideone mostra un risultato memorizzato nella cache se si fa semplicemente clic sul collegamento. È necessario fork per eseguirlo di nuovo effettivamente.
nutki,

2

JavaScript ( ES6 ), 376 416 494

Solo per essere lì ...

Questo crea tutti i limiti, quindi scegline uno casuale. Il tempo per i limiti di 232848 per N = 4 è ~ 45 secondi sul mio laptop. Non ho provato N = 5.

Essendo EcmaScript 6 funziona solo su Firefox.

F=n=>{
  for(i=s=r=b='';i<n;i++)
    s='\n'+b+'/\\'[R='repeat'](n-i)+'_\\'[R](n)+s,
    r+='\n'+b+'\\/'[R](n-i)+'_/'[R](n),
    b+=' ';
  for(h=[t=0],x=[s+r];s=x[t];t++)
    for(d='';!d[n*3];d+='.')
      if(l=s.match(r=RegExp("(\n"+d+"/)\\\\_(.*\n"+d+"\\\\)/_","g")))
        for(j=2<<l.length;j-=2;h[z]||(h[z]=x.push(z)))
          z=s.replace(r,(r,g,h)=>(k+=k)&j?g+'_/'+h+'_\\':r,k=1);
  return b+'__'[R](n)+x[Math.random()*t|0]
}


function go()
{
  var n = N.value | 0,
  t0 = performance.now(),
  r = F(n),
  t1 = performance.now();
  
  O.innerHTML = r+'\n\nTime (msec): '+(t1-t0)
}
N: <input id=N value=3><button onclick="go()">GO</button>
<pre id=O></pre>


In Chromium 42 ottengo "Uncaught SyntaxError: token imprevisto =>" e "Uncaught ReferenceError: go non definito"
aditsu,

1
@aditsu è ES6, Chrome: no Firefox: sì. Non è un fatto ben noto?
edc65,

Non avevo idea, mi aspettavo che Chromium usasse l'ultimo e il più grande qualunque cosa si chiami-apparentemente-non-javascript. Grazie per aver spiegato.
aditsu,

L'ho eseguito ora in Firefox (31.5.3) e funziona per N = 1, 2 o 3, ma per N = 4 funziona per circa 10 secondi, termina e non mostra nulla (e non c'è errore nella console )
aditsu,

@aditsu non è sicuro ... forse javascript in una sandbox viene tranquillamente ucciso quando supera il limite di tempo dom.max_script_run_time. È una preferenza globale in circa: config, il mio è impostato su 30.
edc65,

1

SmileBASIC, 241 byte

INPUT N
T=N*2CLS?" "*N;"__"*N
DIM B[T]FOR I=-1TO N-1O=1P=N+I*2FOR J=0TO T-1IF I<0THEN O=ABS(J0N+.5)<<0B[J]=O?" "*O;MID$("\/\",J<N,2)*(T-O)ELSE R=P<N*3+I*2-J&&RND(2)P=P+(R*2-1)*(O==R)A=P<=B[J]R=R||A:P=P+A:LOCATE P,J+1?"_"B[J]=P+1O=R
NEXT
NEXT

Fortemente basato sulla risposta di Matty

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.