Gambarlah heksa-mesin terbang acak

23

masukkan deskripsi gambar di sini

Gambar di atas disebut hexa-glyph. Hexa-glyphs adalah beberapa pola keren yang saya buat saat mencoret-coret selama kelas DiffEq saya. Begini cara Anda membuatnya:

  1. Pertimbangkan kumpulan titik berikut, berbentuk seperti heksagram biasa. Heksagon bagian dalam adalah yang akan berisi mesin terbang terakhir, sedangkan 6 titik luar membentuk bintang dan di mana kita akan mulai menggambar garis kita.

masukkan deskripsi gambar di sini

  1. Dari enam poin terluar, pilih satu pasangan secara acak. Untuk efisiensi, harus ada setidaknya satu titik lain di antara dua titik yang dipilih (jika tidak, itu tidak akan berpengaruh pada angka akhir). Kemudian, dari masing-masing dari dua titik, melemparkan sinar ke arah yang lain. Sinar ini diblokir oleh garis sebelumnya.

masukkan deskripsi gambar di sini

  1. Ulangi proses ini sampai semua 9 tepi telah terbentuk, seperti yang ditunjukkan pada beberapa gambar berikutnya.

masukkan deskripsi gambar di sini

  1. Berikut adalah contoh sinar yang diblokir. Ujung-ujung segmen sinar masih terlihat, tetapi bagian tengah terhalang oleh dua segmen pertama yang kita gambar.

masukkan deskripsi gambar di sini

  1. Kedua sinar ini juga "diblokir," tetapi ini tidak menyebabkan perbedaan yang terlihat karena mereka diblokir oleh garis lain yang sama.

masukkan deskripsi gambar di sini

  1. Maju cepat sampai semua 9 garis ditarik. Jika Anda ingin penjelasan lebih rinci tentang langkah-langkah yang dilewati ini, saya bisa menguraikannya.

masukkan deskripsi gambar di sini

  1. Akhirnya, hapus titik-titik bintang. Agar terlihat lebih cantik, titik-titik tebal juga dihilangkan.

masukkan deskripsi gambar di sini

Tantangan

Tantangan Anda adalah menampilkan representasi visual dari heksa-mesin terbang acak. Ini adalah kode-golf, byte terkecil menang.

  1. Semua kemungkinan hexa-glyphs akan muncul dengan beberapa probabilitas positif. Heksa-mesin terbang yang berbeda dihasilkan dengan mengubah urutan 9 tepi digambar.

  2. Lebih lanjut, semua gambar yang dihasilkan oleh program Anda haruslah hexa-glyph yang valid Pola-pola tertentu (seperti garis besar lengkap segi enam dalam) tidak mungkin muncul sebagai hexa-glyph, jadi Anda memprogram tidak boleh menampilkan ini.

  3. Outputnya harus berupa gambar grafis (dicetak ke layar atau file).

  4. Segi enam harus teratur, tetapi dapat muncul dalam orientasi apa pun.

  5. Refleksi / rotasi tidak dianggap unik. (Ini mungkin membuat persyaratan 1 lebih mudah diikuti).

PhiNotPi
sumber
8
I made up while doodling during my DiffEq class. Cara semua penemuan hebat terjadi ...: P
Rɪᴋᴇʀ
Apa persyaratan minimal untuk gambar? Sejauh mana seni ASCII harus dikenali selama setiap sisi direpresentasikan dan ditempatkan di tempat yang tepat?
John Dvorak
@JanDvorak Saya menghapus opsi seni ASCII dari tantangan (seperti dalam 2 menit posting) karena program yang menghasilkan ASCII-seni dan output grafis tidak mudah dibandingkan.
PhiNotPi
bagaimana dengan pixel art? Header PPM tidak terlalu berat, dan setelah itu satu-satunya perbedaan adalah menggunakan '01'ruang disisipkan alih-alih ' *'.
John Dvorak
@JanDvorak Output kemudian akan menjadi file gambar yang diformat dengan benar, kan? Maka saya tidak melihat ada yang salah dengan itu.
PhiNotPi

Jawaban:

18

Mathematica, 273 268 264 242 byte

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]],{_,__}]]

The menjadikan sebagai superscript Tdi Mathematica dan adalah operator postfix transpose.

Menyortir bug dalam ini butuh selamanya ... menjelang akhir saya meretas beberapa hal bersama untuk membuatnya bekerja, jadi ini pasti suboptimal. Saya juga bertanya-tanya apakah mungkin lebih baik secara keseluruhan untuk mengimplementasikan spesifikasi secara lebih harfiah melalui garis-garis di heksagon luar dan membiarkan fungsi geometri Mathematica menangani persimpangan.

Perhatikan bahwa ini adalah program lengkap dan jika Anda ingin menjalankan kode beberapa kali dalam satu sesi REPL, Anda harus mengawasinya Clear[b].

Berikut ini adalah hasil dari 20 run:

masukkan deskripsi gambar di sini

Penjelasan

Solusi ini tidak menggunakan titik bintang luar sama sekali. Sebaliknya ia bekerja secara langsung dengan titik-titik yang merupakan bagian dari hexaglyph dan garis-garis yang mencakup tiga dari mereka sekaligus.

Mari beri label poin:

masukkan deskripsi gambar di sini

1dimulai pada sudut yang agak aneh tapi ini karena perilaku default (juga agak aneh) dari CirclePoints. Memulai segi enam dari sana ternyata termurah.

Sekarang kami ingin menemukan garis yang relevan melalui tiga titik yang sesuai dengan titik terhubung dari bintang luar. Yang di sekitar segi enam tentu saja hanya 3 titik yang berdekatan (modulo 12), mulai dari angka ganjil. Yang di tengah terdiri dari angka genap n, 13dan n+6.

Representasi dari baris-baris ini (dalam bentuk daftar tiga poin dihasilkan oleh kode berikut):

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

The Partitionmenghasilkan garis-garis di sekitar segi enam dan Arraygaris melalui pusat. Untuk memproses kedua balok, kami memetakan fungsi ini di atas daftar baris:

{#,Reverse@#}&

Sekarang kita mengacak ini dengan RandomSampleuntuk memprosesnya secara acak. Join @@meratakan daftar pasangan sehingga kami memiliki daftar balok.

Intermission singkat: untuk melacak titik mana yang sudah diblokir, kami menggunakan fungsi pencarian b, yang diinisialisasi Trueuntuk semua nilai oleh b@_=k=1>0;. Saat memproses balok, kami menyimpan semua titik hingga titik pertama yang memiliki b[n] == False( termasuk yang itu):

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

Saya merasa seperti ini adalah bagian yang paling golf saat ini ... penggunaan dua variabel sementara untuk bermain Mastermind tampaknya sangat mahal. Bagaimanapun, hasil ini memberi kita poin dalam garis yang diizinkan untuk kita gambar. Sekarang fungsi ini dipetakan di atas masing-masing poin:

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

Bagian pertama menghasilkan daftar semua 13 poin menggunakan hasil dua panggilan untuk disisipkan CirclePoints(dengan jari-jari yang berbeda untuk pusat tepi dan sudut-sudut segi enam). Perhatikan b@#=!kyang sekarang menetapkan nilai tabel pencarian untuk titik saat ini Falsesehingga tidak ada balok lebih lanjut yang bisa melewatinya. Akhirnya, nilai tersebut digunakan sebagai indeks ke dalam daftar koordinat untuk mendapatkan titik 2D yang benar.

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

Ini membuang semua daftar elemen tunggal, karena akan ditampilkan sebagai poin individual (dan terlihat). Akhirnya kami memberikan hasilnya:

Graphics[Line/@...]
Martin Ender
sumber
b@_=1>0=b=1>0&
CalculatorFeline
@CatsAreFluffy Saya tidak berpikir itu berhasil, karena saya harus bisa menimpa nilai individu nanti.
Martin Ender
Penggunaan CirclePoints yang bagus.
DavidC
Saya menghargai tautan Youtube itu.
DanTheMan
8

Sepatu (Ruby) Rev C 184 byte

12 byte disimpan dengan mentransfer tanggung jawab untuk memeriksa apakah setengah garis tertentu harus diambil dari program utama ke metode menggambar. Program utama masih harus memeriksa apakah seluruh baris benar-benar diblokir.

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

Sepatu (Ruby) 205 ... Rev B 196 byte

Sepatu adalah alat berbasis ruby ​​untuk membangun GUI dll. Ini pertama kalinya saya menggunakannya. mothereff.in/byte-counter menghitung kiriman saya sebagai 196 byte, tetapi untuk beberapa alasan Sepatu menghitungnya sebagai 202.

Selain itu, Ruby memungkinkan Anda melakukan hal-hal seperti t[a=i.ord]tetapi anehnya, tampaknya tidak berfungsi seperti yang diharapkan dengan Shoes.

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

Penjelasan

Saya tidak mempertimbangkan bagian-bagian dari garis di luar segi enam. Saya hanya menggambar bagian yang perlu digambar. Yang penting adalah apakah garis melintasi persimpangan (Jika kita hanya menggambar bagian yang perlu digambar, ini berarti mereka mulai / berakhir di persimpangan.)

Aturan dasarnya adalah bahwa jika kedua titik akhir dari suatu garis telah dikunjungi, garis itu diblokir dan tidak boleh ditarik. Karena garis digambar dalam dua bagian, kita juga harus memeriksa apakah titik tengah telah dikunjungi untuk melihat apakah masing-masing bagian harus ditarik atau tidak.

Saya melacak titik mana yang telah dikunjungi dalam array t[]. Ini akhirnya berisi entri untuk setiap koordinat fisik pada kisi di bawah ini. Tidak ada array logis 13-elemen yang terpisah. Pada akhirnya, t[]mungkin ada 87 elemen, meskipun hanya 13 yang akan berisi data yang berguna.

Secara internal, koordinat titik akhir garis diberikan oleh angka tunggal z, di mana z% 6 adalah koordinat y dan z / 6 adalah koordinat x. Dalam sistem ini segi enam diratakan. Ketika garis diplot, skala x dikalikan dengan 8 dan skala y dikalikan dengan 14, yang merupakan pendekatan rasional yang sangat dekat dengan rasio yang benar: 14/8 = 1,75 vs sqrt (3) = 1,732.

Sistem koordinat internal ditunjukkan di bawah ini, dengan beberapa sampel keluaran.

masukkan deskripsi gambar di sini

Tidak disatukan

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

Lebih banyak sampel keluaran

Ini dilakukan dengan versi program yang lebih lama. Satu-satunya perbedaan adalah bahwa posisi hexaglyph di jendela sekarang sedikit berbeda.

masukkan deskripsi gambar di sini

Level River St
sumber
mothereff.in/byte-counter counts my submission as 196 bytes, but for some reason Shoes counts it as 202.Saya tidak 100% tahu apakah ini benar, tetapi saya pikir alasan mengapa Shoes menghitung kode Anda sebagai 202 byte, bukan 196 adalah karena baris baru Anda sebenarnya adalah urutan dua karakter "\ r \ n." Ini membuat setiap baris dihitung dua kali. Berikut ini adalah jawaban overflow tumpukan tentang \ r dan \ n.
K Zhang
Hehe Saya tidak bisa melupakan nama Ruby dengan Shoes XD
Beta Decay
3

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

Saya telah mengadaptasi gagasan Level River St untuk memeriksa apakah suatu garis akan diblokir dengan memeriksa apakah kedua titik akhir dari garis tersebut telah dikunjungi sebelumnya. Ini menghemat 27 byte. Saran bermain golf diterima.

Sunting: Memperbaiki bug dan bermain golf g(p,q)selama 3 byte. Golf Luntuk satu byte.

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

Tidak melakukan pelanggaran:

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

Hexa-glyphs sendiri cukup kecil karena kami menggunakan hexagon 12-pixel sebagai basis (untuk alasan bermain golf). Berikut adalah beberapa contoh hexa-glyphs (permintaan maaf untuk tanam yang buruk):

Contoh hexa-glyph Contoh hexa-glyph Contoh hexa-glyph Contoh hexa-glyph Contoh hexa-glyph Contoh hexa-glyph

Sherlock9
sumber
Bisa menghemat beberapa byte:R=range;G=goto
Tim Čas