Extrudieren Sie die Flächen eines Würfels symmetrisch entlang XYZ

33

Sandkasten

Für die Zwecke der aktuellen Aufgabe wird ein Würfel mit Einheitslänge in Schrägprojektion mit ASCII-Symbolen wie folgt gerendert:

  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+
  • + für die Eckpunkte.
  • -für die X-Kanten. Die Einheitslänge entlang X wird durch fünf -zwischen zwei Eckpunkten dargestellt.
  • |für die Y-Kanten. Die Einheitslänge entlang Y wird durch zwei |zwischen zwei Eckpunkten dargestellt.
  • /für die Z-Kanten. Die Einheitslänge entlang Z wird durch einen /zwischen zwei Eckpunkten dargestellt.
  • Scheitelpunkte werden nur dort gezeichnet, wo sich alle drei Ebenen schneiden.
  • Kanten werden nur dort gezeichnet, wo sich genau zwei Ebenen schneiden.

Wenn eine Einheitsfläche extrudiert wird, wird sie von ihrer ursprünglichen Position um eine Einheitslänge versetzt, und für jede Richtung (positiv und negativ) werden vier neue Kanten erstellt.

Bei der Extrusion werden die Achsen eines kartesischen 3D-Koordinatensystems gezeichnet, wobei jede Achse als Quader mit einem Querschnitt von 1x1 und einer Länge nvon (0,0,0) dargestellt wird.

Mit 1 entlang X extrudiert:

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

Aufgabe

Extrudieren Sie bei drei Zahlen für die XYZ-Achsen die Flächen eines Einheitswürfels symmetrisch um die angegebenen Beträge und geben Sie das Ergebnis mit den oben angegebenen ASCII-Symbolen wieder.

Eingang

x, y, z - nicht negative Zahlen - Extrusionslängen für die jeweiligen Achsen. 0 bedeutet keine Extrusion. Die Eingabe kann aus drei Zahlen, einer Liste mit drei Zahlen, einem Tripel, einer Zeichenfolge oder einem beliebigen für Sie geeigneten Wert bestehen.

Ausgabe

Die ASCII-Zeichnung des Würfels nach der Extrusion. Führende und nachfolgende Leerzeichen sind erlaubt.

Testfälle

X Y Z
0 0 0

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

1 0 0

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


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


1 1 0

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

2 0 1

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

1 1 1 

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

Gewinnkriterien

Die kürzeste Lösung in Bytes in jeder Sprache gewinnt. Bitte fügen Sie eine kurze Beschreibung der verwendeten Methode und Ihres Codes hinzu.

Galen Ivanov
quelle
Gibt es für jede Extrusion eine Obergrenze?
Verkörperung der Ignoranz
@Embodiment of Ignorance - 9 sollte reichen
Galen Ivanov

Antworten:

14

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

13 Bytes dank @Neil eingespart

Übernimmt die Eingabe als Array [X,Y,Z]. Gibt eine Zeichenmatrix zurück.

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

Probieren Sie es online!

Wie?

Zeichenschritte

Die Ausgabe besteht aus 15 Seiten, die in einer bestimmten Reihenfolge gezeichnet werden.

Animation

Implementierung

g

  • (x,y)
  • w
  • h
  • t

c

t=0

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

t=1

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

t=2

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

(x,y)(w,h)XYZ

c[1..8]

Zusammenfassend ist eine Seite vollständig beschrieben mit:

{ctx=ox+mx×Py=oy+my×Pw=ow+mw×Ph=oh+mh×P

Pc

Daher müssen wir für jede Seite die folgenden 10 Parameter speichern:

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

Nachfolgend sind die Parameter der 15 Seiten aufgeführt, die gezeichnet werden müssen:

sidecoxmxoymyowmwohmht0400237046014602346302226222403423366204030243062071240052220270341632600712301720222704008562224012294200370301101002370130111602313302126002070400137200070301148602040302

[0..9]

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

Es ergeben sich 15 Zahlen mit genau 10 Dezimalstellen, die als 15 Gruppen mit 7 Stellen in der Basis 36 gespeichert werden.

Beispielsweise wird die erste Seite als codiert 4032070460und als gespeichert 1uol9h8.

Arnauld
quelle
Ich denke, Array(W*2+9).fill` ` spart ein Byte.
Neil,
Hoppla, tut mir leid, ich muss es falsch gesehen haben oder so. Außer Acht lassen.
Verkörperung der Ignoranz
@EmbodimentofIgnorance Keine Sorge. :)
Arnauld
3
Hervorragende Visualisierung zusätzlich zu Ihrer traditionell coolen Beschreibung! Respekt!
Galen Ivanov
@GalenIvanov Vielen Dank! Ich habe es wirklich genossen, an dieser Herausforderung zu arbeiten.
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×⍵]}

Probieren Sie es online!

  • Erzeugen Sie ein 3D-Bool-Array von Einheiten-Cubies
  • repliziere jeden Cubie 6 3 2 mal entlang xyz
  • mit Nullen umgeben
  • für jeweils 2 × 2 × 2 Subarray compute eine Zahl zwischen 0 und 16, die dem entsprechende Ausgabe char bestimmt: in (1 + 4*cx + 2*cy + cz) mod 16denen cx, cy, czentlang der Achse x, y, z, dh Vektoren entlang dieser Achse die Anzahl von gleich Wert „rods“ sind , die besteht aus mit dem gleichen Wert: 0 0 oder 1 1. Wir machen eine Ausnahme, wenn das Subarray nur Null ist (oder nur Eins - das ist egal) und wir betrachten seine Nummer 0 anstelle von 28
  • für jede Zelle berechnen, wo das entsprechende Zeichen auf dem Bildschirm gezeichnet werden soll
  • Bilde für jede Zelle eine transparente (0-gepolsterte) Matrix, die nur ein undurchsichtiges "Pixel" enthält
  • mischen Sie die Matrizen - an dieser Stelle haben wir ein 5d-Array mit den Dimensionen inx, iny, inz, outx, outy
  • Verkleinern Sie die ersten drei Achsen, und lassen Sie nur das erste nicht transparente Element (along 0) daneben
  • Verwenden Sie eine Nachschlagetabelle (eine Zeichenfolge), um die Zahlen in zu konvertieren -|/+

Vielen Dank, Scott Milner, für das Erkennen einiger +s, die als ?s gerendert wurden

ngn
quelle
Wie testest du das eigentlich? Ich wollte zum Beispiel Extrusionen von 2,3,4 ausprobieren, aber nichts offensichtliches schien zu funktionieren.
Neil,
Das Algo ist sehr verschwenderisch, 2 3 4 hat
keinen
@Neil ich habe ein kleines Update gemacht und jetzt 2 3 4 funktioniert. als Nebeneffekt ein Byte verloren :)
ngn
Eine APL-Lösung, die nur halb so lang ist wie eine Charcoal-Lösung bei einer ASCII-Kunst- Herausforderung ?! Was ist los?!
Shaggy
3
Nicht 100% sicher, aber ich bin mir ziemlich sicher, dass dieses Verhalten nicht erwünscht ist bei 0 1 1
Scott Milner
6

Holzkohle , 325 Bytes

≔×⁶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←∧∧ηζ⁶+

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

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

Geben Sie die Extrusionen ein, multiplizieren Sie sie jedoch vorab, um Bytes zu sparen.

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

Wenn mindestens zwei der Extrusionen Null sind, zeichnen Sie einfach einen Quader mit Abmessungen (2x + 1, 2y + 1, 2z + 1). Andernfalls:

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

Drucken Sie die linke Extrusion, falls vorhanden.

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

Drucken Sie die Daunenextrusion, falls vorhanden.

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

Drucken Sie ggf. die hintere Extrusion.

J⁶¦⁰

Die verbleibenden Extrusionen treffen sich alle an diesem Punkt (der erst am Ende gezeichnet wird!)

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

Drucken Sie die vordere Extrusion, falls vorhanden, und achten Sie darauf, Teile der linken und unteren Extrusion zu entfernen, die sich möglicherweise überlappen.

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

Drucken Sie die Extrusion nach oben, falls vorhanden, und achten Sie darauf, Teile der hinteren und linken Extrusion, die sich möglicherweise überlappen, zu entfernen.

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

Drucken Sie gegebenenfalls die richtige Extrusion aus, und achten Sie darauf, Teile der Daunen- und Rückenextrusion zu entfernen, die sich möglicherweise überlappen.

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

Zeichnen Sie die Verbindungen zwischen den letzteren Extrusionen.

Neil
quelle
325 Bytes in Holzkohle ?! Auf einer ASCII-Kunst- Herausforderung ?! Das ist genug, um mich nicht einmal dazu zu bringen, dies in Ja (vaScri) pt zu versuchen!
Shaggy
@Shaggy Dies ist möglicherweise kein optimaler Ansatz, und es gibt Möglichkeiten zum Golfen, die ich ohnehin übersehen habe. Ich muss sagen, dass die Methode von ngn faszinierend aussieht, als ob er die Form in ein internes Array zeichnet und dann eine Kantenerkennung durchführt, um seine Ausgabe zu generieren.
Neil,
@Shaggy Ich habe mir eine 195-Byte-Lösung ausgedacht, die ich separat veröffentlicht habe, da dies ein völlig anderer Ansatz ist. Aber immer noch weit hinter APL zurück.
Neil,
3

Charcoal , 195 164 144 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Ich poste dies als separate Antwort, da es einen völlig anderen Ansatz zum Zeichnen der Extrusion verwendet. Erläuterung:

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

Geben Sie die Extrusionen ein und berechnen Sie die Hälfte der Größe des einschließenden Quaders, jedoch in Ganzzahlarithmetik, da die Bereiche von Charcoal immer Ganzzahlen sind. Der Ursprung der Ausgabe wird auf die Mitte des ursprünglichen Einheitswürfels abgebildet.

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

Alle Koordinaten innerhalb (einschließlich der Begrenzung) des Quaders mit der Extrusion durchlaufen.

J⁻λι⁺κι

Springe zu der Ausgabeposition, die diesen Koordinaten entspricht.

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

Schauen Sie von den angegebenen Koordinaten aus in alle acht diagonalen Richtungen, um festzustellen, ob sich die Extrusion in dieser Richtung überlappt. Es wird überprüft, ob die gespähten Koordinaten noch im Quader liegen, und dann muss die Anzahl der Achsen, in denen die Koordinate im ursprünglichen Würfel liegt, größer als 1 sein Das sind ganze Zahlen, während die anderen Achsen Bruchkoordinaten verwenden.

≡Σδ

Berücksichtigen Sie die Anzahl der Richtungen, in die sich die Extrusion überlappt. Es gibt fünf Fälle von Interesse, in denen wir etwas drucken möchten, wie im Fall von Null, was bedeutet, dass dies ein leerer Raum ist und wir nichts drucken möchten, während im Fall von Acht dies bedeutet, dass dies drinnen ist Die Extrusion und alles, was wir gedruckt haben, würde durch eine Schicht näher am Augenpunkt überdruckt.

¹+

Wenn sich die Extrusion nur in einer Richtung überlappt, ist dies eine äußere Ecke und wir müssen a ausgeben +.

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

Wenn die Extrusion in zwei Richtungen überlappt, ist dies eine Außenkante. Welche Art von Kante wird aus dem Abstand zwischen den beiden Überlappungen bestimmt; 6 und 7 sind nach hinten gerichtete Kanten und werden überschrieben, 4 ist eine diagonale Kante, 2 ist eine vertikale Kante und 1 ist eine horizontale Kante. (Ich berechne eigentlich 7 minus der Trennung, da es einfacher zu sein scheint.)

³+

Wenn sich die Extrusion in drei Richtungen überlappt, ist dies eine innere Ecke für den Fall, dass eine der Extrusionen Null ist und wir a ausgeben müssen +.

⁴§ +Σ…δ⁴¦

Wenn sich die Extrusion in vier Richtungen überlappt, gibt es zwei Fälle: Flächen (jede Richtung) und innere Ecken im Fall mit drei positiven Extrusionen. Im letzteren Fall gibt es eine ungerade Anzahl von Überlappungen zum Betrachter hin.

⁶§ |-/⌕δ⁰

Wenn die Extrusion in sechs Richtungen überlappt, ist dies eine Innenkante. Es funktioniert wie das Komplement einer Außenkante, außer dass es uns nur interessiert, wenn einer der beiden leeren Bereiche die Richtung zum Augenpunkt ist (der letzte Eintrag im Array).

Neil
quelle
2

K (ngn / k) , 172 Bytes

{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]}

Probieren Sie es online!

obligatorisches umschreiben meiner apl-lösung

Der gleiche Algorithmus, außer dass das Rendern von 3d-> 2d mit (dem k-Äquivalent von) Streuindexzuweisung durchgeführt wird, anstatt 2d-Matrizen für jedes 3d-Element zu erstellen und diese zu mischen

ngn
quelle
Wie würde sich Ihre ngn/aplLeistung im Vergleich zu Ihrer Dyalog APLLösung entwickeln?
Galen Ivanov
@GalenIvanov es wäre kein fairer Vergleich, weil ich in meiner apl-Lösung viel Speicher verschwenden, um ein paar Bytes zu sparen, und in k kürzer ist in diesem Fall schneller
ngn
Ich fragte nach einem Vergleich zwischen zwei APL-Lösungen - Ihrer APL / Dyalog-Lösung und einer hypothetischen Lösung in ngn / apl
Galen Ivanov,
hoppla, ich weiß nicht warum ich das als "ngn / k" gelesen habe ... es ist wieder unfair - ngn / apl ist hobbyist javascript, dyalog ist professionell c
ngn
1
@GalenIvanov wahrscheinlich nicht. In ngn / apl fehlen die jüngsten Ergänzungen der Sprache wie der
Rangoperator