Ekstrusi wajah kubus secara simetris di sepanjang XYZ

33

Bak pasir

Untuk keperluan tugas saat ini, kubus satuan panjang diberikan dalam proyeksi miring dengan simbol ASCII sebagai berikut:

  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+
  • + untuk simpul.
  • -untuk tepi X. Panjang unit sepanjang X diwakili oleh lima -antara dua simpul.
  • |untuk tepi Y. Panjang unit sepanjang Y diwakili oleh dua |antara dua simpul.
  • /untuk tepi Z. Panjang unit di sepanjang Z diwakili oleh satu di /antara dua simpul.
  • Verteks hanya digambar di mana ketiga pesawat berpotongan.
  • Tepi hanya ditarik di mana dua pesawat bersilangan.

Ketika sebuah unit wajah diekstrusi, itu diimbangi oleh panjang unit dari posisi aslinya dan empat tepi baru dibuat untuk setiap arah (positif dan negatif).

Anda dapat memikirkan ekstrusi sebagai menggambar sumbu dari sistem koordinat Cartesian 3D di mana setiap sumbu direpresentasikan sebagai berbentuk kubus dengan penampang 1x1 dan panjangnya ndari (0,0,0)

Diekstrusi oleh 1 sepanjang X:

  +-----------------+
 /                 /|   
+-----------------+ |
|                 | +
|                 |/
+-----------------+

Tugas

Diberikan tiga angka untuk sumbu XYZ, mengusir wajah kubus unit secara simetris dengan jumlah yang ditunjukkan dan memberikan hasilnya dengan simbol ASCII seperti yang ditentukan di atas.

Memasukkan

x, y, z - angka non-negatif - panjang ekstrusi untuk masing-masing sumbu. 0 berarti tidak ada ekstrusi. Input dapat berupa tiga angka, daftar tiga angka, tiga, string atau apa pun yang sesuai untuk Anda.

Keluaran

Gambar ASCII dari kubus setelah ekstrusi. Wihtespaces terkemuka dan tertinggal diizinkan.

Uji kasus

X Y Z
0 0 0

  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+

1 0 0

  +-----------------+
 /                 /|   
+-----------------+ |
|                 | +
|                 |/
+-----------------+


0 0 1   
        +-----+
       /     /|
      /     / |
     /     /  +
    /     /  /
   /     /  /
  +-----+  /
  |     | / 
  |     |/
  +-----+


1 1 0

        +-----+
       /     /|      
      +-----+ |
  +---|     | +-----+
 /    |     |/     /|
+-----+     +-----+ |
|                 | +
|                 |/
+-----+     +-----+
      |     | +
      |     |/
      +-----+

2 0 1

                +-----+
               /     /|
  +-----------+     +-----------+
 /                             /|
+-----------+     +-----------+ |
|          /     /|           | +
|         +-----+ |           |/
+---------|     | +-----------+
          |     |/
          +-----+

1 1 1 

        +-----+
       /     /|-+   
      +-----+ |/|
  +---|     | +-----+
 /    |     |/     /|
+-----+-----+-----+ |
|    /     /|     | +
|   +-----+ |     |/
+---|     | +-----+
    |     |/| +
    +-----+ |/
      +-----+

Kriteria menang

Solusi terpendek dalam byte di setiap bahasa menang. Harap tambahkan deskripsi singkat tentang metode yang digunakan dan kode Anda.

Galen Ivanov
sumber
Apakah ada batas atas untuk masing-masing ekstrusi?
Perwujudan Ketidaktahuan
@Embodiment of Ignorance - 9 sudah cukup
Galen Ivanov

Jawaban:

14

JavaScript (ES6),  525 ... 475 471  459 byte

Disimpan 13 byte berkat @Neil

Mengambil input sebagai array [X,Y,Z]. Mengembalikan matriks karakter.

a=>([X,Y,Z]=a,m=[],W=X*6+Z*2,'1uol9h824lsqpq17de52u1okgnv21dnjaww111qmhx1gxf4m50xg6pb42kzijq21xyh34t0h2gueq0qznnza2rrimsg3bkrxfh3yrh0em').replace(/.{7}/g,s=>[[c,x,A,y,B,w,C,h,D,t]=parseInt(s,36)+s,Y*W,Z,X,Y|!W,Z*X,X*Y*!Z,X*Z*!Y,Y*Z*!X][c]&&(g=H=>V<h&&((m[r=y-(3-B)*p+(t>1?H-V:V)+Y*3+Z*2]=m[r]||Array(W*2+9).fill` `)[x-2*(3-A)*p+(t>1?V:H-V*t)+W]=` ${c>5?'  + ':t>1?'|-':'-|'}+/+`[(H%~-w?0:+t?4:2)|!(V%~-h)],g(++H<w?H:!++V)))(V=0,p=a[c%3],w-=-3*C*p,h-=-D*p))&&m

Cobalah online!

Bagaimana?

Langkah menggambar

Output terdiri dari 15 sisi, dibuat dalam urutan tertentu.

animasi

Pelaksanaan

Fungsi menggambar adalah g . Ini bekerja dengan parameter berikut:

  • (x,y) : di mana mulai menggambar
  • w : lebar
  • h : tinggi
  • t : jenis sisi

Verteks selalu ditarik. Bergantung pada nilai parameter lain c , ujung-ujungnya digambar atau dihapus.

Jika t=0 , fungsi tersebut menggambar sisi depan:

...........      ...........
..+-----+..      ..+     +..
..|     |..  or  ..       ..
..|     |..      ..       ..
..+-----+..      ..+     +..
...........      ...........

Jika t=1 , itu menarik sisi atas:

...........      ...........
...+-----+.      ...+     +.
../     /..  or  ..       ..
.+-----+...      .+     +...
...........      ...........

t=2

......+....      ......+....
...../|....      .....  ....
....+ |....  or  ....+  ....
....| +....      ....  +....
....|/.....      ....  .....
....+......      ....+......

(x,y)(w,h)XYZ

c[1..8]

Untuk meringkas, suatu sisi sepenuhnya dijelaskan dengan:

{ctx=Haix+mx×Py=Haiy+my×Pw=Haiw+mw×Ph=Haih+mh×P

Pc

Karena itu, kita perlu menyimpan 10 parameter berikut untuk setiap sisi:

[c,ox,mx,oy,my,ow,mw,oh,mh,t]

Di bawah ini adalah parameter dari 15 sisi yang perlu ditarik:

sidecoxmxoymyowmwohmht0400237046014602346302226222403423366204030243062071240052220270341632600712301720222704008562224012294200370301101002370130111602313302126002070400137200070301148602040302

We force all values into the range [0..9] by applying the following operations:

mx(mx+6)/2mymy+3mwmw/3

It results in 15 numbers of exactly 10 decimal digits, which are stored as 15 groups of 7 digits in base 36.

For instance, the first side is encoded as 4032070460 and stored as 1uol9h8.

Arnauld
sumber
I think Array(W*2+9).fill` ` saves a byte.
Neil
Oops,sorry, my bad, I must of saw it wrong or something. Disregard.
Embodiment of Ignorance
@EmbodimentofIgnorance No worries. :)
Arnauld
3
Great visualization in addition to your traditionally cool description! Respect!
Galen Ivanov
@GalenIvanov Thank you! I really enjoyed working on this challenge.
Arnauld
13

APL (Dyalog Classic) , 162 161 132 130 bytes

{' |+/+ +-? ??? ++'[⍉(⊃~∘0)⍤13⍉↑a↑¨⍨↓(--1-⌊/∘,)2-/1⌽↑⍳⍴a←16|29|1+{2⊥+/¨∊¨=⌿¨⍵(⍉⍵)(⍉↓⍵)}⌺2 2 2{⍉⍤2⍉⌽0,⍵}⍣63/↓2/61<⍵+.=⍨↑⍳1+2×⍵]}

Cobalah online!

  • menghasilkan array bool 3d unit cubies
  • replikasi setiap cubie 6 3 2 kali bersama xyz
  • dikelilingi dengan nol
  • untuk setiap 2 × 2 × 2 subarray menghitung angka antara 0 dan 16 yang menentukan output arang yang sesuai: (1 + 4*cx + 2*cy + cz) mod 16di mana cx, cy,cz adalah jumlah yang sama-nilai "batang" sepanjang sumbu x, y, z, yaitu vektor sepanjang sumbu yang yang terdiri dengan nilai yang sama: 0 0 atau 1 1. kami membuat pengecualian jika subarray adalah semua-nol (atau semua-satu - itu tidak masalah) dan kami menganggap angka 0 bukan 28
  • untuk setiap sel menghitung di mana arang yang sesuai harus digambar di layar
  • untuk setiap sel, buat matriks transparan (berbantalan 0) yang hanya berisi satu "piksel" buram
  • mencampur matriks - pada titik ini kita memiliki array 5d dengan dimensi inx, iny, inz, outx, outy
  • kurangi tiga sumbu pertama, hanya simpan item pertama yang tidak transparan (≠ 0)
  • gunakan tabel pencarian (string) untuk mengubah angka menjadi -|/+

thanks Scott Milner for spotting that some +s rendered as ?s

ngn
sumber
How do you actually test this? I wanted to try extrusions of 2,3,4 for example, but nothing obvious seemed to work.
Neil
algo sangat boros, jadi 2 3 4 kehabisan memori, tetapi 2 3 3 berada dalam jangkauan
ngn
@Neil saya membuat perbaikan kecil dan sekarang 2 3 4 berfungsi. kehilangan byte sebagai efek samping :)
ngn
Solusi APL yang setengahnya sebagai solusi Arang untuk tantangan ascii-art ?! Apa yang sedang terjadi?!
Shaggy
3
Tidak 100% yakin, tapi saya cukup yakin bahwa ini bukan perilaku yang diinginkan pada 0 1 1
Scott Milner
6

Arang , 325 byte

≔×⁶Nθ≔׳Nη≔⊗Nζ¿‹¹№⟦θηζ⟧⁰«B⁺⁷⊗θ⁺⁴⊗η↗↗⊕⊗ζ+⁺⁵⊗θP↙⊗⊕ζ↓+↓⁺²⊗η↙+↙⊕⊗ζ»«F‹⁰θ«↗+↗←+←⊖θ↙+/P→θ↓+↓²+⊖θ+»F‹⁰η«J⁶¦³↗+↗↓+↓⊖η↙+/P↑η←+←⁵↑+↑⊖η+»F‹⁰ζ«J⁸±²↓+↓↓↗+↗⊖ζ↑+↑²P↙ζ←+←⁵↙+↙⊖ζ+»J⁶¦⁰F‹⁰ζ«G↓³↙⊕ζ←⁷↑³↗⊕ζ ↙+↙⊖ζ↓+↓²+→⁵P↗ζ↑+↑²P←⁶↗+↗⊖ζ»F‹⁰η«G←⁶↑⊕η↗³→⁶↓⊕η ↑+↑⊖η←+←⁵↙+/P↓η+⁵P↗²↓+↓⊖η»F‹⁰θ«G↗²→⊕θ↓⁴↙²←⊕θ →+⊖θ↗+/↑+↑²P←θ↙+/P↓³←+←⊖θ»P↗∧∧θη²P↓∧∧ζθ³P←∧∧ηζ⁶+

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

≔×⁶Nθ≔׳Nη≔⊗Nζ

Masukkan ekstrusi, tetapi sebelum itu untuk menyimpan byte.

¿‹¹№⟦θηζ⟧⁰«B⁺⁷⊗θ⁺⁴⊗η↗↗⊕⊗ζ+⁺⁵⊗θP↙⊗⊕ζ↓+↓⁺²⊗η↙+↙⊕⊗ζ»«

Jika setidaknya dua ekstrusi adalah nol, maka cukup gambarkan kuboid dimensi (2x + 1, 2y + 1, 2z + 1). Jika tidak:

F‹⁰θ«↗+↗←+←⊖θ↙+/P→θ↓+↓²+⊖θ+»

Cetak ekstrusi kiri, jika ada.

F‹⁰η«J⁶¦³↗+↗↓+↓⊖η↙+/P↑η←+←⁵↑+↑⊖η+»

Cetak ekstrusi bawah, jika ada.

F‹⁰ζ«J⁸±²↓+↓↓↗+↗⊖ζ↑+↑²P↙ζ←+←⁵↙+↙⊖ζ+»

Cetak ekstrusi belakang, jika ada.

J⁶¦⁰

Ekstrusi yang tersisa semua bertemu pada titik ini (yang tidak bisa ditarik sampai akhir!)

F‹⁰ζ«G↓³↙⊕ζ←⁷↑³↗⊕ζ ↙+↙⊖ζ↓+↓²+→⁵P↗ζ↑+↑²P←⁶↗+↗⊖ζ»

Cetak ekstrusi depan, jika ada, berhati-hati untuk menghapus bagian ekstrusi kiri dan bawah yang mungkin tumpang tindih.

F‹⁰η«G←⁶↑⊕η↗³→⁶↓⊕η ↑+↑⊖η←+←⁵↙+/P↓η+⁵P↗²↓+↓⊖η»

Cetak ekstrusi ke atas, jika ada, berhati-hati untuk menghapus bagian ekstrusi belakang dan kiri yang mungkin tumpang tindih.

F‹⁰θ«G↗²→⊕θ↓⁴↙²←⊕θ →+⊖θ↗+/↑+↑²P←θ↙+/P↓³←+←⊖θ»

Cetak ekstrusi yang tepat, jika ada, berhati-hati untuk menghapus bagian ekstrusi bawah dan belakang yang mungkin tumpang tindih.

P↗∧∧θη²P↓∧∧ζθ³P←∧∧ηζ⁶+

Gambarkan gabungan antara ekstrusi terakhir.

Neil
sumber
325 byte di Arang ?! Pada tantangan ascii-art ?! Itu cukup untuk membuat saya bahkan tidak mencoba ini di Ja (vaScri) pt!
Shaggy
@Shaggy Ini mungkin bukan pendekatan yang optimal, dan mungkin ada cara untuk bermain golf yang saya abaikan. Saya harus mengatakan bahwa metode ngn terlihat menarik, sepertinya ia menggambar bentuk menjadi array internal dan kemudian melakukan deteksi tepi untuk menghasilkan outputnya.
Neil
@ Shaggy Saya datang dengan solusi 195 byte, yang saya posting secara terpisah karena ini pendekatan yang sama sekali berbeda. Masih jauh dari APL.
Neil
3

Charcoal , 195 164 144 byte

≔⁺³×⁶Nθ≔⁺²×³Nη≔⊕⊗NζF…·±ζζF…·±ηηF…·±θθ«J⁻λι⁺κι≔⟦⟧δFE²↔⁻⁺ιμ·⁵FE²↔⁻κνFE²↔⁻⁺λξ·⁵⊞δ⌊⟦‹μζ‹νη‹ξθ‹¹№E⟦μνξ⟧‹π⊕ρ¹⟧≡Σδ¹+²§ |-/⁺⌕δ¹⌕⮌δ¹¦³+⁴§ +Σ…δ⁴¦⁶§ |-/⌕δ⁰

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Saya memposting ini sebagai jawaban terpisah karena menggunakan pendekatan yang sama sekali berbeda untuk menggambar ekstrusi. Penjelasan:

≔⁺³×⁶Nθ≔⁺²×³Nη≔⊕⊗Nζ

Masukkan ekstrusi dan hitung setengah ukuran kuboid tertutup, tetapi dalam hitung bilangan bulat karena rentang Charcoal selalu bilangan bulat. Asal peta keluaran ke pusat kubus unit asli.

F…·±ζζF…·±ηηF…·±θθ«

Lingkari semua koordinat di dalam (termasuk batas) berbentuk kubus yang berisi ekstrusi.

J⁻λι⁺κι

Lompat ke posisi keluaran sesuai dengan koordinat tersebut.

≔⟦⟧δFE²↔⁻⁺ιμ·⁵FE²↔⁻κνFE²↔⁻⁺λξ·⁵⊞δ⌊⟦‹μζ‹νη‹ξθ‹¹№E⟦μνξ⟧‹π⊕ρ¹⟧

Dari koordinat yang diberikan, mengintip semua delapan arah diagonal untuk menentukan apakah ekstrusi tumpang tindih ke arah itu. Koordinat yang diintip diperiksa bahwa mereka masih berada di dalam kuboid, dan kemudian jumlah sumbu di mana koordinat berada di dalam kubus asli harus lebih besar dari 1. Perhatikan bahwa karena kubus memiliki tinggi tampilan ganjil, nilai sumbu Y nilai sumbu Y yang mengintip adalah bilangan bulat sedangkan sumbu lainnya menggunakan koordinat fraksional.

≡Σδ

Pertimbangkan jumlah arah di mana ekstrusi tumpang tindih. Ada lima kasus yang menarik di mana kita ingin mencetak sesuatu, seperti dalam kasus nol, itu berarti bahwa ini adalah ruang kosong dan kami tidak ingin mencetak apa pun, sedangkan dalam kasus delapan, itu berarti bahwa ini ada di dalam ekstrusi dan apa pun yang kami lakukan akan dicetak berlebihan oleh lapisan yang lebih dekat ke titik mata.

¹+

Jika ekstrusi hanya tumpang tindih dalam satu arah maka ini adalah sudut luar dan kita perlu output a +.

²§ |-/⁺⌕δ¹⌕⮌δ¹¦

Jika ekstrusi tumpang tindih dalam dua arah maka ini adalah tepi luar. Jenis tepi mana yang ditentukan dari pemisahan antara kedua tumpang tindih; 6 dan 7 adalah tepi yang menghadap ke belakang dan akan ditimpa, 4 adalah tepi diagonal, 2 adalah tepi vertikal dan 1 adalah tepi horizontal. (Saya benar-benar menghitung 7 minus pemisahan karena tampaknya lebih mudah dilakukan.)

³+

Jika ekstrusi tumpang tindih dalam tiga arah maka ini adalah sudut dalam dalam kasus di mana salah satu ekstrusi adalah nol dan kita perlu output a +.

⁴§ +Σ…δ⁴¦

Jika ekstrusi tumpang tindih dalam empat arah maka ada dua kasus: wajah (segala arah), dan sudut dalam kasus dengan tiga ekstrusi positif. Dalam kasus terakhir ada jumlah tumpang tindih ganjil terhadap pemirsa.

⁶§ |-/⌕δ⁰

Jika ekstrusi tumpang tindih dalam enam arah maka ini adalah tepi bagian dalam. Ini bekerja seperti pelengkap tepi luar kecuali bahwa kami hanya tertarik ketika salah satu dari dua ruang kosong adalah arah menuju titik mata (entri terakhir dalam array).

Neil
sumber
2

K (ngn / k) , 172 byte

{s:1+|/'i-:&//i:1_--':1_4#!#'2*:\a:16!29!1+2/(!3){+'+x}/'{2+':''1+':'0=':x}'{++'x}\6{+'+0,|x}/{6}#{3}#'{2}#''s#1<+/x=!s:1+2*x;" |+/+ +-? ??? ++"s#@[&*/s;s/i;{x+y*~x};,//a]}

Cobalah online!

wajib menulis ulang solusi apl saya

algoritma yang sama, kecuali bahwa rendering 3d-> 2d dilakukan dengan (k ekivalen dari) penugasan indeks alih-alih membuat matriks 2d untuk setiap elemen 3d dan mencampurkannya

ngn
sumber
Bagaimana ngn/aplkinerja Anda jika dibandingkan dengan Dyalog APLsolusi Anda ?
Galen Ivanov
@ GalenIvanov itu tidak akan menjadi perbandingan yang adil karena dalam solusi apl saya, saya membuang banyak memori untuk menghemat beberapa byte, dan dalam k lebih pendek kebetulan lebih cepat dalam kasus ini
ngn
Saya bertanya tentang perbandingan antara dua solusi APL - milik Anda APL / Dyalog satu dan solusi hipotetis dalam ngn / apl
Galen Ivanov
oops, saya tidak tahu mengapa saya membaca itu sebagai "ngn / k" ... itu lagi tidak adil - ngn / apl adalah javascript hobi, dyalog adalah profesional c
ngn
1
@ GalenIvanov mungkin tidak. ngn / apl tidak memiliki tambahan baru pada bahasa seperti operator peringkat ( ) dan stensil ( )
ngn