Rasgele bir hexa-glif çizin


23

görüntü tanımını buraya girin

Yukarıdaki görüntü bir heksa-glif olarak adlandırılır. Hexa-glifleri, DiffEq dersim sırasında doodling yaparken oluşturduğum harika desenler. İşte nasıl bir tane:

  1. Düzenli bir heksagram şeklinde olan aşağıdaki nokta kümesini göz önünde bulundurun. İç altıgen, son glifi içerecek olan şeydir, dış 6 nokta bir yıldız oluşturur ve çizgilerimizi çizmeye başlayacağımız yer.

görüntü tanımını buraya girin

  1. Dış altı noktadan rastgele bir çift seçin. Verimlilik için, seçilen iki nokta arasında en az bir başka nokta bulunmalıdır (aksi takdirde nihai rakam üzerinde bir etkisi olmaz). Sonra, iki noktadan her birinden diğerine bir ışın attı. Bu ışın önceki satırlarla engellendi .

görüntü tanımını buraya girin

  1. Sonraki birkaç görüntüde gösterildiği gibi, 9 kenarın tümü oluşana kadar bu işlemi tekrarlayın.

görüntü tanımını buraya girin

  1. İşte engellenen ışınların bir örneği. Işın bölümünün uçları hala görünmektedir, ancak orta bölüm çizdiğimiz ilk iki bölüm tarafından kapatılmaktadır.

görüntü tanımını buraya girin

  1. Bu iki ışın da "tıkanır", ancak bu aynı çizgide engellendiği için görünür bir farka neden olmaz.

görüntü tanımını buraya girin

  1. 9 çizginin tamamı çizilene kadar hızlı ileri sarma. Bu atlanan adımların daha ayrıntılı bir açıklamasını isterseniz, açıklayabilirim.

görüntü tanımını buraya girin

  1. Son olarak, yıldızın noktalarını kaldırın. Daha güzel görünmesi için kalın noktalar da kaldırılır.

görüntü tanımını buraya girin

Meydan okuma

Zorluk, rastgele bir heksa-glifinin görsel temsilini ortaya çıkarmaktır. Bu kod golf, en az bayt kazanıyor.

  1. Tüm olası heksa glifleri, bazı pozitif olasılıklarla görünmelidir. 9 kenarın çizilme sırasını değiştirerek farklı heksa-glifleri üretilir.

  2. Ayrıca, programınız tarafından gönderilen tüm görüntüler geçerli hexa-glifleri olmalıdır. Bazı desenler (iç altıgenin tam bir taslağı gibi) muhtemelen bir heksaflif olarak görünemez ve bu nedenle bunları programlamamalısınız.

  3. Çıktı grafiksel bir görüntü olmalıdır (ekrana veya dosyaya yazdırılır).

  4. Altıgen düzenli olmalı, ancak herhangi bir yönde görünebilir.

  5. Yansımalar / rotasyonlar edilir değil benzersiz düşündü. (Bu, gereksinim 1'in takip edilmesini kolaylaştırabilir).


8
I made up while doodling during my DiffEq class. Tüm harika keşiflerin gerçekleşmesi ...: P
Rɪᴋᴇʀ

Görüntü için minimum gereksinimler nelerdir? Bir ASCII sanatı, her kenarı belirsizce doğru noktaya yerleştirildiği ve yerleştirildiği müddetçe ne ölçüde tanınmalıdır?
John Dvorak

@JanDvorak ASCII-art ve grafik çıktıları üreten programlar kolayca karşılaştırılamaması nedeniyle (ASCII-art ve grafiksel çıktıları üreten programlar gibi) zorlamanın ASCII art seçeneğini kaldırdım.
PhiNotPi

Peki o zaman piksel sanatı? Bir PPM başlığı çok ağır değildir ve daha sonra tek fark '01'yerine boşluk bırakarak boşluk kullanmaktır ' *'.
John Dvorak

@JanDvorak Çıktı doğru şekilde biçimlendirilmiş bir görüntü dosyası olurdu, değil mi? O zaman yanlış bir şey görmüyorum.
PhiNotPi

Yanıtlar:


18

Mathematica, 273 268 264 242 bayt

c=CirclePoints;b@_=k=1>0;Graphics[Line/@Cases[Append[Join@@({c@6,{3^.5/2,-Pi/6}~c~6}),{0,0}][[b@#=!k;#]]&/@TakeWhile[#,t=k;(r=t;t=b@#;r)&]&/@Join@@RandomSample[{#,Reverse@#}&/@Partition[Range@12,3,2,1]~Join~Array[{2#,13,2#+6}&,3]],{_,__}]]

Bir üst simge olarak vermektedir TMathematica ve postfix devrik operatörüdür.

Buradaki hataları çözmek sonsuza dek sürdü ... sona doğru birkaç şeyi bir araya getirdim, çalışmasını sağlamak için, bu kesinlikle yetersiz kaldı. Spesifikasyonu dış altıgen boyunca çizgilerden daha tam anlamıyla uygulamak ve Mathematica'nın geometri fonksiyonlarının kesişmeleri ele almasına izin vermenin genel olarak daha iyi olabileceğini de merak ediyorum.

Bunun tam bir program olduğunu ve kodu tek bir REPL oturumu içerisinde birden çok kez çalıştırmak istiyorsanız, onu öneklemek zorunda kalacağınızı unutmayın Clear[b].

İşte 20 çalışmanın sonuçları:

görüntü tanımını buraya girin

açıklama

Bu çözüm dış yıldız noktalarından hiç faydalanmıyor. Bunun yerine doğrudan altıgen parçanın parçası olan noktalarla ve bir seferde üçünü kapsayan çizgileriyle çalışır.

Noktaları etiketleyelim:

görüntü tanımını buraya girin

1biraz garip bir köşeden başlıyor, ancak bunun nedeni (biraz garip) varsayılan davranış CirclePoints. Altı köşeden oradan başlayarak en ucuza çıktı.

Şimdi ilgili çizgileri, dış yıldızın bağlı noktalarına karşılık gelen üç noktadan bulmak istiyoruz. Altıgen etrafındakiler elbette tek bir sayıdan başlayarak sadece 3 bitişik nokta (modulo 12). Merkezinin olanlar, çift sayıda oluşur n, 13ve n+6.

Bu satırların gösterimi (üç noktadan oluşan listeler şeklinde aşağıdaki kodla üretilmiştir):

Partition[Range@12,3,2,1]~Join~Array[{2#,13,2#+6}&,3]

PartitionAltıgen çevresinde çizgiler ve üretir Arraymerkezinden hatları. İki ışını da işlemek için bu işlevi satırlar listesi üzerinde eşleriz:

{#,Reverse@#}&

Şimdi RandomSamplebunları rastgele sırayla işlemek için karıştırıyoruz . Join @@çiftlerin listesini düzleştirir, böylece kirişlerin bir listesine sahip oluruz.

Kısa müdahale: Hangi noktaların zaten engellenmiş olduğunu takip betmek Trueiçin tüm değerler için başlatılan bir arama işlevi kullanırız b@_=k=1>0;. Bir ışını işlerken, tüm noktaları b[n] == False(bu dahil ) olan ilk noktaya kadar tutarız :

TakeWhile[#,t=k;(r=t;t=b@#;r)&]&

Şu an bunun en golf tutulabilir kısmı olduğunu hissediyorum ... Mastermind'ı oynamak için iki geçici değişkenin kullanılması gerçekten pahalı görünüyor. Neyse, bunun sonucu bize çizmemize izin verilen bir çizgide puan veriyor. Şimdi bu işlev şu noktaların her biri üzerinde eşleştirildi:

Append[Join@@({c@6,{3^.5/2,-Pi/6}~c~6}),{0,0}][[b@#=!k;#]]&

İlk bölüm, iki çağrının serpiştirilmiş sonuçlarını kullanarak CirclePoints(kenar merkezleri ve altıgen köşeleri için farklı yarıçaplarla) 13 noktanın listesini oluşturur . Not b@#=!kşimdi mevcut noktası için arama tablonun değerini ayarlar hangi Falsebaşka ışın geçmesine böylece. Son olarak, doğru 2D noktasını elde etmek için değer koordinatlar listesine bir indeks olarak kullanılır.

Cases[...,{_,__}]

Bu, tüm tek eleman listelerini atar, çünkü bunlar bireysel (ve görünür) puanlar oluşturur. Sonunda sonucu veririz:

Graphics[Line/@...]

b@_=1>0=b=1>0&
CalculatorFeline

@CatsAreFluffy Bunun işe yaradığını sanmıyorum, çünkü daha sonra bireysel değerlerin üzerine yazabilmem gerekiyor.
Martin Ender

CirclePoints’in güzel kullanımı.
DavidC

Bu Youtube bağlantısını takdir ettim.
DanTheMan

8

Ayakkabılar (Yakut) Rev C 184 bytes

Ana programdan çizim yöntemine belirli bir yarım çizginin çizilmesi gerekip gerekmediğini kontrol etme sorumluluğunu transfer ederek 12 bayt. Ana program hala tüm hattın tamamen tıkalı olup olmadığını kontrol etmek zorunda.

Shoes.app{t=[]
d=->p,q{t[p]&&t[q]||line(p/6*8,p%6*14,q/6*8,q%6*14)}
%w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|b=i.sum/2
c=b*2-a=i.ord
t[a]&&t[c]||(d[a,b]
d[b,c]
t[a]=t[b]=t[c]=1)}}

Ayakkabı (Yakut) 205 ... Rev B 196 bytes

Shoes, GUI'leri yapmak için yakut tabanlı bir araçtır. İlk defa kullanıyorum. mothereff.in/byte-counter gönderimimi 196 bayt olarak sayar, ancak bir nedenden dolayı Shoes bunu 202 olarak sayar.

Ayrıca, Ruby gibi şeyler yapmanıza izin veriyor t[a=i.ord]ama garip bir şekilde, Ayakkabı ile beklendiği gibi çalışmıyor gibi görünüyor.

Shoes.app{t=[]
d=->p,q{line(p/6*8,p%6*14,q/6*8,q%6*14)}
%w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|b=i.sum/2
c=b*2-a=i.ord
t[a]&&t[c]||(t[a]&&t[b]||d[a,b]
t[b]&&t[c]||d[b,c]
t[a]=t[b]=t[c]=1)}}

açıklama

Çizginin altıgen dışındaki kısımlarını göz önünde bulundurmam. Sadece çizilmesi gereken kısmı çiziyorum. Önemli olan, çizgilerin kesişme noktalarından geçip geçmediğidir (Sadece çizilmesi gereken parçaları çizersek, bu onların kesişme noktalarında başladığı / bittiği anlamına gelir).

Temel kural, bir çizginin her iki bitiş noktası da ziyaret edilmişse, çizginin engellenmesi ve çizilmemesi gerektiğidir. Çizgiler iki yarıya çekildiği için, her iki yarının da çizilip çizilmeyeceğini görmek için orta noktanın ziyaret edilip edilmediğini kontrol etmemiz gerekir.

Dizideki hangi noktaların ziyaret edildiğini takip ediyorum t[]. Bu, aşağıdaki ızgaradaki her fiziksel koordinat için bir giriş içermesiyle sona erer. Ayrı bir 13 eleman mantıksal dizi yoktur. Sonunda, t[]87 öğeye sahip olabilir, ancak yalnızca 13'e kadar faydalı veri içerecektir.

Dahili olarak, çizgilerin bitiş noktalarının koordinatları, tek bir z tarafından verilir; burada z% 6, y koordinatıdır ve z / 6, x koordinatıdır. Bu sistemde altıgen düzleşmiştir. Çizgiler çizildiğinde, x ölçeği 8 ile çarpılır ve y ölçeği 14 ile çarpılır; bu, doğru orana çok yakın bir rasyonel yaklaşımdır: 14/8 = 1.75 ve sqrt (3) = 1.732.

Dahili koordinat sistemi, birkaç örnek çıktısı ile aşağıda gösterilmiştir.

görüntü tanımını buraya girin

Ungolfed

Shoes.app{
  t=[]                                          #Empty array for status tracking
  d=->p,q{line(p/6*8,p%6*14,q/6*8,q%6*14)}      #Drawing method. Convert p and q into x,y pairs, scale and draw line.
  %w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|#take an array of the coordinates of the endpoints of each line, shuffle, then for each line
    b=i.sum/2                                   #b = midpoint of line, convert ASCII sum to number (average of the two coordinates)
    a=i.ord                                     #a = first endpoint of line, convert ASCII to number (no need to write i[0].ord)
    c=b*2-a                                     #c = second endpoint of line (calculating is shorter than writing i[1].ord)
    t[a]&&t[c]||(                               #if both endpoints have already been visited, line is completely blocked, do nothing. ELSE
      t[a]&&t[b]||d[a,b]                        #if first endpoint and midpoint have not both been visited, draw first half of line
      t[b]&&t[c]||d[b,c]                        #if second endpoint and midpoint have not both been visited, draw second half of line
      t[a]=t[b]=t[c]=1                          #mark all three points of the line as visited
    )
  }
}

Daha fazla Örnek çıktı

Bunlar programın eski bir sürümü ile yapıldı. Tek fark, hexaglyph'in pencerede konumlandırılmasının şimdi biraz farklı olmasıdır.

görüntü tanımını buraya girin


mothereff.in/byte-counter counts my submission as 196 bytes, but for some reason Shoes counts it as 202.Bunun doğru olup olmadığını% 100 bilmiyorum, ancak Shoes'un kodunuzu 196 yerine 202 bayt olarak saymasının sebebi, yeni satırlarınızın aslında iki karakterli bir karakter dizisi olmasıdır. Bu, her yeni satırın iki kez sayılmasını sağlar. İşte \ r ve \ n ile ilgili yığın taşması cevabı.
K Zhang,

Ruby isminin üzerine gelemiyorum. Shoes with XD
Beta Decay

3

Python, 604 591 574 561 538 531 536 534 528 493 483 452 431 420 419 415 388 385 384 bayt

Level River St'in hattın her iki bitiş noktasının daha önce ziyaret edilip edilmediğini kontrol ederek bir hattın engellenip engellenmeyeceğini kontrol etme fikrini uyarladım . Bu, 27 bayt kazandırır. Golf önerileri kabul edilir.

Düzenleme: Hata düzeltme ve g(p,q)3 baytlık golf . LBir bayt için golf oynadım .

from turtle import*
from random import*
R=range
G=goto
*L,=R(9)
shuffle(L)
a=[0]*13
ht()
T=12
c=[(j.imag,j.real)for j in(1j**(i/3)*T*.75**(i%2/2)for i in R(T))]+[(0,0)]
def g(p,q):pu();G(c[p]);a[p]*a[q]or pd();G(c[q])
for m in L:
 p=2*m;x,y,z=R(p,p+3)
 if m<6:
  if a[x]*a[z%T]<1:g(x,y);g(y,z%T);a[x]=a[y]=a[z%T]=1
 else:
  if a[p-11]*a[p-5]<1:g(p-11,T);g(p-5,T);a[p-11]=a[p-5]=a[T]=1

Ungolfing:

from turtle import*
from random import*

def draw_line(points, p_1, p_2):
    penup()
    goto(points[p_1])
    if not (a[p] and a[q]):
        pendown()
    goto(points[p_2])

def draw_glyph():
    ht()
    nine_lines = list(range(9))
    shuffle(nine_lines)
    size = 12
    center = [0,0]

    points = []
    for i in range(12):      # put in a point of a dodecagon
                             # if i is even, keep as hexagon point
                             # else, convert to hexagon midpoint
        d = 1j**(i/3) * 12   # dodecagon point
        if i%2:
            d *= .75**.5     # divide by sqrt(3/4) to get midpoint
        points += (d.imag, d.real)
    points.append(center)

    a = [0]*13
    for m in nine_lines:
        p = 2*m
        if m<6:
            x, y, z = p, p+1, p+2
            if not (a[x] and a[z%12]):
                draw_line(points, x, y)
                draw_line(points, y, z%12)
                a[x] = a[y] = a[z%12] = 1
        else:
            if not (a[p-11] and a[p-5]):
                draw_line(p-11, 12)
                draw_line(p-5, 12)
                a[p-11] = a[p-5] = a[12] = 1

Temel olarak 12 piksel altıgen bir altıgen kullandığımızdan heksa-gliflerin kendisi oldukça küçüktür (golf oynamak için). İşte bazı örnek hexa-glifleri (zayıf kırpma için özür dileriz):

Örnek bir heksa-glif Örnek bir heksa-glif Örnek bir heksa-glif Örnek bir heksa-glif Örnek bir heksa-glif Örnek bir heksa-glif


Birkaç byte tasarruf R=range;G=goto
sağlayabilir
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.