Rastgele ASCII Günün Sanatı # 5: Elmas Döşeme


21

Mash Up Zamanı!

Bu benim Rastgele Günde Golf'ümün ve Optimize Edici'nin Günün Sanat Sanatı serisinin 5. bölümü . Bu yarışmadaki gönderim (leriniz) her iki lider tahtasına (bağlantılı mesajları bulabileceğiniz) sayılacaktır. Elbette, buna diğer herhangi bir kod golf mücadelesi gibi davranabilir ve herhangi bir seri için endişelenmeden yanıtlayabilirsiniz.

Delik 5: Elmas Döşemeler

Düzenli bir altıgen her zaman böyle elmaslarla döşenebilir:

Bu devirlerin ASCII sanat temsilini kullanacağız. Yan uzunlukta 2 bir altıgen için, 20 böyle eğim vardır:

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

Bir kenar uzunluğu göz önüne alındığında , rastgele Nyan uzunlukta bir altıgen için böyle bir döşeme oluşturmalısınız N. Tam dağıtım önemli değil, ancak her fayans sıfır olmayan bir olasılık ile iade edilmelidir.

Çünkü N ≤ 4gönderiminiz, zamanın en az% 80'inde en az% 80 oranında bir fayans üretmeli ve eğimlerin en az% 80'inin potansiyel olarak 1 dakika içinde üretilmesi gerekir. Çoğu yaklaşım bu kural için endişelenmek zorunda kalmayacak (çok cömertçe) - bu sadece bir kiremit oluncaya kadar rastgele dizeler oluşturan çok saf reddetme tabanlı algoritmaları dışlamaktır.

Verilen N için toplam olası eğim sayısının OEIS A008793'te bulunduğunu bilmek isteyebilirsiniz .

Tam bir program veya bir işlev yazabilir ve STDIN (veya en yakın alternatif), komut satırı argümanı veya işlev argümanı ile giriş yapabilir ve STDOUT (veya en yakın alternatif), işlev dönüş değeri veya işlev (çıkış) parametresi üzerinden çıktı üretebilirsiniz.

Altıgeni hizalamak için gerekenden daha fazla ön boşluk çıkarmamalısınız (bu, altıgenin sol köşesinde önünde boşluk olmamalıdır). Her satır, en çok Ntakip eden boşluklar içerebilir (mutlaka tutarlı olması gerekmediğinden, örneğin altıgenlerin sınırlama kutusunu basarak dikdörtgen bir çıktınız olabilir).

Bu kod golf, yani en kısa gönderme (bayt cinsinden) kazanır. Ve elbette, kullanıcı başına en kısa teslim aynı zamanda serinin genel lider tablosuna girecektir.

Liderler

Her serinin ilk yazı bir afiş oluşturur.

Cevaplarınızın göründüğünden emin olmak için, lütfen aşağıdaki Markdown şablonunu kullanarak her bir başlığa başlıkla başlayın:

# Language Name, N bytes

Gönderinizin Nbüyüklüğü nerede ? Puanınızı artırmak varsa, olabilir onları içinden vurarak, başlığa eski hesapları tutmak. Örneğin:

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

(Dil şu anda gösterilmiyor, ancak snippet bunu gerektiriyor ve ayrıştırıyor ve gelecekte bir dilin lider tahtası ekleyebilirim.)


3
Örnek görüntüyü 3D olarak görmeye devam eden sadece ben miyim?
LegionMammal978

3
@ LegionMammal978 Hayır, bu tamamen normal. ;) (Muhtemelen bu zorluğa yaklaşmak için de iyi bir yoldur.)
Martin Ender

For N ≤ 4, your submission must produce a tiling within 1 minute at least 80% of the time.çok kolay: zamanın% 80'i aynı, temel fayans, aksi halde istediğim zaman başka bir fayans bulurum
edc65

@ edc65 İyi nokta, bunu tekrar ifade edeyim.
Martin Ender,

Yanıtlar:


10

CJam, 105 bayt

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;

Kaymayı önlemek için yeni satır eklendi. Çevrimiçi deneyin

Açıklama:

Bu çözüm, her bir satırı zikzak olarak başlatır, daha sonra önceki satırdaki konumlarına ve birkaç kurala dayanarak N altını çizer. Çıktıya düz bir 2D karakter matrisi olarak bakarken bunu bir dizi gözlemden aldım:

  • Her çizginin tam olarak N alt çizgi vardır
  • mükemmel bir şekilde tekrar eden zikzak deseni oluşturmak için alt çizgiler / veya \ ile değiştirilebilir ( /\üst yarıda, \/alt yarıda)
  • alt çizgiler kenarlara dokunamaz ve başka bir alt çizgiye bitişik olamaz
  • Bir sonraki satıra giderken, her alt çizginin konumu -1, 0 veya 1 olarak değişir.
  • Bundan daha fazlası, /_/sadece -1 veya 0 ile \_\değişebilir ve sadece 0 veya 1 ile değişebilir
  • İlk alt çizgi konumları için , her ikisinin de iyi olduğu bir "_ "desen veya bir " _"desen kullanabiliriz.
  • Yukarıdaki kurallar tüm yatırmaları elde etmek için yeterlidir.

Bu yüzden önceki alt çizgi pozisyonlarını koruyarak, onları rastgele bir faktörle değiştirerek (her alt çizgi için 2 seçenek) ve kuralları yerine getirene kadar tekrarlayarak uygulamaya karar verdim. İyileştirme sürecinde, altıgenin sol tarafına göre (boşluklar hariç) alt çizgi konumlarına geçtim.

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

Eski "3D" versiyonu, 189 bayt:

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*

Çevrimiçi deneyin


Müthiş iş için +1 ve ayrıca bir oy daha sizi 10 bin temsilciye çıkaracak, ancak çoğunlukla harika işler için kullanacak. (Oh hey, şuna bakın. 10k için tebrikler :))
Alex A.

Desenler üzerinde harika bir analiz! Cevabım için kullanacağım.
anatolyg

6

Python 2, 337 335 324 318 311 300 296 bayt

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)

Buradaki fikir, ilk önce böyle bir elmas altıgen oluşturmaktır:

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

Ve sonra aşağı doğru alt çizgi yolları ile doldurun, şunun gibi:

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

Tüm yolların eklenmesiyle elde edilen nihai sonuç, şunun gibi görünür:

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

Bu yolların sınırların dışına çıkmadığından veya birbirlerini geçmediğinden emin olmak için bir miktar kod giriliyor.

Ungolfed kodu:

# 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
Çıktınızın yanlış göründüğünü farkettim. İki örnekli sonuçlarınızda üçgenler var (sağ üst ve sağ alt).
Martin Ender

1
@MartinEnder Örnekler, algoritma fikrini göstermek için sadece bir 'alt çizgi yolu' gösterdi. Son çıktıda, üçgenleri ortadan kaldıran tüm yollar (bu durumda 2) vardır. Nihai çıktının örneklerine de ekledim.
Matty,

Ohhh anladım, bu mantıklı. Açıklama için teşekkürler.
Martin Ender

2
Sana kısaltmak düşünüyorum randint(0,1)*(p<n*3+i*2-j)için randint(0,p<n*3+i*2-j).
12Me21

Oooh evet, teşekkürler!
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.$/}

Deneyin beni .


Her zaman aynı döşemeyi oluşturuyor gibi görünüyor (en azından ideone üzerinde)
aditsu

@aditsu, sadece bağlantıya tıklarsanız Ideone önbelleklenmiş bir sonuç gösterir. Gerçekten tekrar çalıştırmak için çatal gerekir.
nutki

2

JavaScript ( ES6 ), 376 416 494

Sadece orada olmak ...

Bu, tüm hareketleri inşa eder, sonra rastgele bir tane seçer. Dizüstü bilgisayarımda N = 4 olan 232848 devrilme süresi ~ 45 sn. N = 5 denemedim.

EcmaScript 6 olarak yalnızca Firefox'ta çalışır.

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>


Chromium 42'de "Yakalanmamış SözdizimiError: Beklenmeyen token =>" ve "Yakalanmamış ReferenceError: go tanımlanmadı"
aditsu

1
@aditsu ES6, Chrome: hayır Firefox: evet. İyi bilinen bir gerçek değil mi?
edc65

Hiçbir fikrim yoktu, Chromium'un javascript denen en son ve en büyük denilen şeyi kullanmasını beklerdim. Açıkladığınız için teşekkürler.
aditsu

Şimdi firefox'ta çalıştırdım (31.5.3) ve N = 1, 2 veya 3 için çalışıyor, ancak N = 4 için yaklaşık 10 saniye çalışıyor, bitiyor ve hiçbir şey göstermiyor (ve konsolda hata yok) )
aditsu

@aditsu emin değil ... belki bir sanal alandaki javascript zaman sınırını aştığında sessizce öldürülür dom.max_script_run_time. Bu konuda genel bir tercih: config, mine 30 olarak ayarlandı.
edc65

1

SmileBASIC, 241 bayt

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

Matty'nin cevabını esas alarak

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.