Wyciągnij ściany sześcianu symetrycznie wzdłuż XYZ


33

Piaskownica

Na potrzeby bieżącego zadania sześcian o długości jednostki jest renderowany w skośnym rzucie za pomocą symboli ASCII w następujący sposób:

  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+
  • + dla wierzchołków.
  • -dla krawędzi X. Długość jednostki wzdłuż X jest reprezentowana przez pięć -między dwoma wierzchołkami.
  • |dla krawędzi Y. Długość jednostki wzdłuż Y jest reprezentowana przez dwa| między dwoma wierzchołkami.
  • /dla krawędzi Z. Długość jednostki wzdłuż Z jest reprezentowana przez jeden /między dwoma wierzchołkami.
  • Wierzchołki są rysowane tylko tam, gdzie przecinają się wszystkie trzy płaszczyzny.
  • Krawędzie są rysowane tylko tam, gdzie przecinają się dokładnie dwie płaszczyzny.

Kiedy powierzchnia jednostki jest wyciągana, jest ona przesunięta o długość jednostki od jej pierwotnej pozycji i dla każdego kierunku tworzone są cztery nowe krawędzie (dodatnia i ujemna).

Można myśleć o wytłoczeniu jako o rysowaniu osi trójwymiarowego kartezjańskiego układu współrzędnych, w którym każda oś jest reprezentowana jako prostopadłościan o przekroju 1x1 i długości nod (0,0,0)

Wytłaczany przez 1 wzdłuż X:

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

Zadanie

Biorąc pod uwagę trzy liczby dla osi XYZ, wyciągnij ściany sześcianu jednostkowego symetrycznie o wskazane ilości i renderuj wynik za pomocą symboli ASCII, jak określono powyżej.

Wkład

x, y, z - liczby nieujemne - długości wytłaczania dla odpowiednich osi. 0 oznacza brak wytłaczania. Dane wejściowe mogą składać się z trzech cyfr, listy trzech liczb, potrójnej, ciągu znaków lub dowolnej innej dogodnej dla Ciebie pozycji.

Wydajność

Rysunek kostki ASCII po wytłoczeniu. Dozwolone są wiodące i końcowe przestrzenie.

Przypadki testowe

X Y Z
0 0 0

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

1 0 0

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


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


1 1 0

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

2 0 1

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

1 1 1 

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

Kryteria wygranej

Najkrótsze rozwiązanie w bajtach w każdym języku wygrywa. Dodaj krótki opis zastosowanej metody i kod.


Czy istnieje górna granica dla każdego z profili?
Wcielenie nieznajomości

@Embodiment of Ignorance - 9 powinno wystarczyć
Galen Iwanow

Odpowiedzi:


14

JavaScript (ES6),  525 ... 475 471  459 bajtów

Zaoszczędź 13 bajtów dzięki @Neil

Pobiera dane wejściowe jako tablicę [X,Y,Z]. Zwraca macierz znaków.

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

Wypróbuj online!

W jaki sposób?

Rysowanie kroków

Wyjście składa się z 15 stron, narysowanych w określonej kolejności.

animacja

Realizacja

Funkcja rysowania to g . Działa z następującymi parametrami:

  • (x,y) : od czego zacząć rysowanie
  • w : szerokość
  • h : wysokość
  • t : rodzaj strony

Wierzchołki są zawsze rysowane. W zależności od wartości innego parametruc krawędzie są rysowane lub kasowane.

Jeśli t=0 , funkcja rysuje przednią stronę:

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

Jeśli t=1 , rysuje górną stronę:

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

Jeśli t=2 , rysuje prawą stronę:

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

Współrzędne (x,y) i rozmiar (w,h) każdej strony mają stałą wartość lub zależą dokładnie od jednej ze zmiennych wejściowych: X , Y lubZ

c[1..8]

Podsumowując, strona jest w pełni opisana przez:

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

Pdo .

Dlatego musimy przechowywać następujące 10 parametrów dla każdej strony:

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

Poniżej znajdują się parametry 15 stron, które należy narysować:

sidecoxmxoymyowmwohmht0400237046014602346302226222403423366204030243062071240052220270341632600712301720222704008562224012294200370301101002370130111602313302126002070400137200070301148602040302

[0..9]

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

Wynikiem jest 15 liczb dokładnie 10 cyfr dziesiętnych, które są przechowywane jako 15 grup po 7 cyfr w bazie 36.

Na przykład pierwsza strona jest kodowana jako 4032070460i przechowywana jako 1uol9h8.


Myślę, że Array(W*2+9).fill` ` oszczędza bajt.
Neil

Ups, przepraszam, mój zły, musiałem to widzieć źle lub coś takiego. Lekceważenie.
Wcielenie nieznajomości

@EmbodimentofIgnorance Bez obaw. :)
Arnauld

3
Świetna wizualizacja oprócz tradycyjnie fajnego opisu! Poszanowanie!
Galen Iwanow

@GalenIvanov Dziękujemy! Naprawdę podobała mi się praca nad tym wyzwaniem.
Arnauld

13

APL (Dyalog Classic) , 162 161 132 130 bajtów

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

Wypróbuj online!

  • generuje tablicę bool 3d w jednostkach sześcianów
  • powtórz każdy sześcian 6 3 2 razy wzdłuż xyz
  • otaczaj zerami
  • Dla każdego 2 x 2 x 2 subarray obliczyć liczbę pomiędzy 0 i 16, która określa odpowiadający char wyjściowy: (1 + 4*cx + 2*cy + cz) mod 16gdzie cx, cy, czto liczba samej wartości „pręty” wzdłuż osi x, y, z, to jest wektory wzdłuż tej osi, która składa o tej samej wartości: 0 0 lub 1 1. robimy wyjątek, jeśli podtablica ma wartość zero (lub wszystko-jeden - to nie ma znaczenia) i rozważamy jej liczbę 0 zamiast 28
  • dla każdej komórki oblicz, gdzie odpowiedni znak powinien zostać narysowany na ekranie
  • dla każdej komórki zbuduj przezroczystą (wypełnioną 0) matrycę, która zawiera tylko jeden nieprzezroczysty „piksel”
  • mieszaj matryce - w tym momencie mamy tablicę 5d o wymiarach inx, iny, inz, outx, outy
  • zmniejsz pierwsze trzy osie, pozostawiając tylko pierwszy nieprzezroczysty (≠ 0) element wzdłuż nich
  • użyj tabeli odnośników (ciąg), aby przekonwertować liczby na -|/+

dziękuje Scottowi Milnerowi za wykrycie, że niektórzy +są renderowani jako ?s


Jak to faktycznie testujesz? Chciałem na przykład wypróbować profile 2,3,4, ale nic oczywistego nie działało.
Neil

algo jest bardzo marnotrawne, więc 2 3 4 kończy się pamięć, ale 2 3 3 jest w zasięgu
ngn

@Neil zrobiłem małą poprawkę, a teraz 2 3 4 działa. stracił bajt jako efekt uboczny :)
ngn

Rozwiązanie APL, które jest o połowę krótsze niż węgiel drzewny w wyzwaniu ascii-art ?! Co się dzieje?!
Kudłaty

3
Nie jestem w 100% pewien, ale jestem całkiem pewien, że nie jest to pożądane zachowanie na 0 1 1
Scott Milner

6

Węgiel drzewny , 325 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

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

Wprowadź wyciągnięcia, ale przedwcześnie je zachowaj, aby zaoszczędzić bajty.

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

Jeśli co najmniej dwa profile są zerowe, po prostu narysuj prostopadłościan o wymiarach (2x + 1, 2y + 1, 2z + 1). Inaczej:

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

Wydrukuj lewy profil, jeśli istnieje.

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

Wydrukuj dolny profil, jeśli istnieje.

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

Wydrukuj tylny profil, jeśli istnieje.

J⁶¦⁰

Wszystkie pozostałe profile spotykają się w tym momencie (który nie jest rysowany do samego końca!)

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

Wydrukuj przedni profil, jeśli istnieje, zwracając uwagę na usunięcie części lewych i dolnych profili, które mogą się nakładać.

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

Wydrukuj górny profil, jeśli istnieje, zwracając uwagę na usunięcie części tylnej i lewej, które mogą się pokrywać.

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

Wydrukuj odpowiedni profil, jeśli taki istnieje, zwracając uwagę na usunięcie części profili dolnych i tylnych, które mogą się pokrywać.

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

Narysuj połączenia między tymi ostatnimi wyciągnięciami.


325 bajtów na węglu ?! W wyzwaniu ascii-art ?! To wystarczy, żebym nawet nie próbował tego w Ja (vaScri) pt!
Kudłaty

@Shaggy To może nie być optymalne podejście i mogą istnieć sposoby na grę w golfa, które i tak przeoczyłem. Muszę jednak powiedzieć, że metoda ngn wygląda intrygująco, wygląda na to, że rysuje kształt w wewnętrznej tablicy, a następnie wykonuje wykrywanie krawędzi, aby wygenerować swój wynik.
Neil

@Shaggy Wymyśliłem 195 bajtowe rozwiązanie, które opublikowałem osobno, ponieważ jest to zupełnie inne podejście. Mimo to wciąż brakuje APL.
Neil

3

Węgiel drzewny , 195 164 144 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Publikuję to jako osobną odpowiedź, ponieważ używa zupełnie innego podejścia do rysowania wyciągnięcia. Wyjaśnienie:

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

Wprowadź wyciągnięcia i oblicz połowę wielkości otaczającego prostopadłościanu, ale w liczbach całkowitych, ponieważ zakresy Węgla są zawsze liczbami całkowitymi. Początek danych wyjściowych jest odwzorowany na środku oryginalnej kostki jednostkowej.

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

Zapętlić wszystkie współrzędne w obrębie (w tym granicy) prostopadłościanu zawierającego wytłoczenie.

J⁻λι⁺κι

Przejdź do pozycji wyjściowej odpowiadającej tym współrzędnym.

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

Z podanych współrzędnych zajrzyj we wszystkich ośmiu ukośnych kierunkach, aby ustalić, czy wytłoczenie zachodzi w tym kierunku. Zerknięte współrzędne są sprawdzane, czy nadal znajdują się w prostopadłościanie, a następnie liczba osi, w których współrzędna leży w pierwotnym sześcianie, musi być większa niż 1. Zwróć uwagę, że ponieważ sześcian ma nieparzystą wysokość wyświetlania, wartości osi Y zerkane są liczbami całkowitymi, podczas gdy inne osie używają współrzędnych ułamkowych.

≡Σδ

Rozważ liczbę kierunków, w których wytłoczenie zachodzi na siebie. Istnieje pięć interesujących przypadków, w których chcemy coś wydrukować, tak jak w przypadku zera, co oznacza, że ​​jest to pusta przestrzeń i nie chcemy niczego drukować, podczas gdy w przypadku ośmiu oznacza to, że jest to wewnątrz wytłoczenie i wszystko, co wydrukujemy, zostanie nadrukowane warstwą bliższą punktu oczu.

¹+

Jeśli wytłoczenie zachodzi tylko w jednym kierunku, to jest to narożnik zewnętrzny i musimy wygenerować a +.

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

Jeśli wytłoczenie zachodzi na siebie w dwóch kierunkach, oznacza to krawędź zewnętrzną. Jaki rodzaj krawędzi określa się na podstawie separacji między dwoma zakładkami; 6 i 7 to krawędzie skierowane tyłem do kierunku jazdy i zostaną nadpisane, 4 to krawędź ukośna, 2 to krawędź pionowa, a 1 to krawędź pozioma. (Właściwie obliczam 7 minus separację, ponieważ wydaje się to łatwiejsze.)

³+

Jeśli wytłoczenie zachodzi na siebie w trzech kierunkach, to jest to wewnętrzny narożnik w przypadku, gdy jeden z wytłoczeń ma wartość zero i musimy wygenerować a +.

⁴§ +Σ…δ⁴¦

Jeśli wytłoczenie zachodzi na siebie w czterech kierunkach, wówczas istnieją dwa przypadki: twarze (w dowolnym kierunku) i wewnętrzne rogi w przypadku z trzema dodatnimi wytłoczeniami. W tym drugim przypadku widz ma nieparzystą liczbę zakładek.

⁶§ |-/⌕δ⁰

Jeśli wytłoczenie zachodzi na siebie w sześciu kierunkach, oznacza to wewnętrzną krawędź. Działa jak dopełnienie zewnętrznej krawędzi, z tą różnicą, że interesuje nas tylko wtedy, gdy jedna z dwóch pustych przestrzeni jest kierunkiem w stronę punktu oka (ostatni wpis w tablicy).


2

K (ngn / k) , 172 bajty

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

Wypróbuj online!

obowiązkowe przepisanie mojego rozwiązania APL

ten sam algorytm, z wyjątkiem tego, że renderowanie 3d-> 2d odbywa się przy użyciu (k ekwiwalentu) przypisania indeksu rozproszenia zamiast tworzenia macierzy 2d dla każdego elementu 3d i mieszania ich


Jak wyglądałaby Twoja ngn/aploferta w porównaniu do Dyalog APLrozwiązania?
Galen Iwanow

@GalenIvanov nie byłoby to uczciwe porównanie, ponieważ w moim rozwiązaniu APL marnuję dużo pamięci, aby zaoszczędzić kilka bajtów, a w k jest to w tym przypadku szybsze
ngn

Zapytałem o porównanie dwóch rozwiązań APL - twojego APL / Dyalog i hipotetycznego rozwiązania w ngn / apl
Galen Iwanow

Ups, nie wiem, dlaczego przeczytałem to jako „ngn / k” ... to znowu niesprawiedliwe - ngn / apl to hobbysta javascript, dyalog jest profesjonalny c
ngn

1
@GalenIvanov prawdopodobnie nie. W ngn / apl brakuje ostatnich dodatków do języka, takich jak operator rang ( ) i stencil ( )
ngn
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.