Drehe einen Hyperwürfel

27

Einführung

Ein Hyperwürfel / Tesserakt ist das vierdimensionale Äquivalent eines normalen Würfels. Es wird hergestellt, indem ein Würfelnetz genommen, auf die 3. Dimension erweitert und dann - unter Verwendung der 4. Dimension - zu einem Hyperwürfel gefaltet wird. Es ist im Grunde ein Würfel, bei dem jede Seite ein Würfel ist.

Um einen Hypercube zu erstellen, benötigen Sie 16 4d-Vektoren (einen Vektor mit einer x, einer y, einer zund einer wKomponente). Diese Vektoren sind die folgenden:

A(0, 0, 0, 0); B(1, 0, 0, 0); C(1, 0, 1, 0); D(0, 0, 1, 0); E(0, 1, 0, 0); F(1, 1, 0, 0); G(1, 1, 1, 0); H(0, 1, 1, 0); 
I(0, 0, 0, 1); J(1, 0, 0, 1); K(1, 0, 1, 1); L(0, 0, 1, 1); M(0, 1, 0, 1); N(1, 1, 0, 1); O(1, 1, 1, 1); P(0, 1, 1, 1);

Der Hyperwürfel hat 24 Gesichter. Die folgende Liste enthält alle (jede Gruppe markiert ein Quad):

ABFE, CDHG, BCGF, DAEH, DCBA, FEHG
IJNM, KLPO, JKON, LIMP, LKJI, PMNO
ABJI, DCKL, BCKJ, DAIL, FEMN, GHPO, FGON, EHPM, EAIM, BFNJ, CGOK, HDLP

Mit all diesen Informationen haben Sie technisch gesehen einen Hypercube im Code. Um dies zu drehen, benötigen Sie 6 verschiedene Matrizen für jede Rotationsebene, eine für die Ebenen YZ, XZ, XY, XW, YW und ZW. Nachdem Sie jede Matrix haben, müssen Sie die Eckpunkte des Würfels mit ihnen multiplizieren.

Die folgenden Bilder zeigen die Struktur jeder Matrix:

Für die Rotation auf der YZ-Ebene:

Für die Drehung auf der XZ-Ebene:

Für die Drehung auf der XY-Ebene:

Für die Drehung auf der XW-Ebene:

Für die Drehung auf der YW-Ebene:

Für die Rotation auf der ZW-Ebene:

Die Rotationen werden in dieser Reihenfolge angewendet.

Nach all dem haben Sie einen gedrehten Hyperwürfel. Jetzt musst du es zeichnen. Sie sollten eine orthogonale Projektion in Kombination mit einer perspektivischen Projektion verwenden, an die gesendet werden (x, y, z, w)soll (2x/(2+z), 2y/(2+z)).

Eingang

Ihre Eingabe besteht aus 6 ganzen Zahlen zwischen 0 (einschließlich) und 360 (ausschließlich). Diese repräsentieren die Rotationen in Grad auf den verschiedenen Rotationsebenen des Hyperwürfels.

Ausgabe

Ihre Ausgabe sollte ein einzelnes Bild sein, das den Hypercube enthält. Die Anzeige kann ein gerastertes Bild, ein Vektorbild oder eine ASCII-Grafik sein. Das Ausgabebild sollte mindestens 100 * 100 Pixel groß sein und der Würfel muss mindestens 50% des Bildschirms einnehmen. Jedes Standardformat für die Bildausgabe ist zulässig.

Testfälle

0 0 0 0 0 0

0 0 0 0 0 30

30 0 0 0 0 30

0 0 0 30 30 30

45 45 45 0 0 0

45 45 45 45 45 45

Öffnen Sie die Bilder in einem neuen Tab, um sie in voller Größe anzuzeigen.

Regeln

  • Es gelten die Standardregeln
  • Standardlücken sind verboten
  • Kürzester Code in Bytes gewinnt
Bálint
quelle
Warum hast du den anderen Beitrag geknackt?
17.
@ EᴀsᴀIᴛᴇʀʟʏ Ich habe es für eine letzte Überprüfung im Chat gepostet
Bálint
7
Wie ich bereits zweimal im Sandkasten erwähnt habe, ist die Beschreibung der Projektion für die Anzeige unvollständig, da davon ausgegangen wird, dass das zu projizierende Objekt dreidimensional ist, während es offensichtlich vierdimensional ist.
Peter Taylor
2
@ Lauserdroog Ich denke, das "U" muss "N" sein.
Becher
2
@ Bálint Danke für die Herausforderung, es hat mir Spaß gemacht. Hoffentlich bekommen wir mehr Antworten und unterschiedliche Ansätze. : D
Becher

Antworten:

9

Oktave, 474 433 429 Bytes

function H(a,b,c,d,e,f) C=@cosd;S=@sind;R=[1,0,0,0;0,C(e),0,-S(e);0,-S(e)*S(f),C(f),-C(e)*S(f);0,S(e)*C(f),S(f),C(e)*C(f)]*[C(c)*C(d),-S(c)*C(d),0,S(d);S(c),C(c),0,0;0,0,1,0;-C(c)*S(d),S(c)*S(d),0,C(d)]*[C(b),S(a)*S(b),C(a)*S(b),0;0,C(a),-S(a),0;-S(b),S(a)*C(b),C(a)*C(b),0;0,0,0,1]*(dec2bin(0:15)'-48.5);Z=R(3,:)+2;R=2*R./Z;Q=[1,2,10,12,11,9,10,14,16,12,4,8,16,15,11,3,7,15,13,9,1,5,13,14,6,8,7,5,6,2,4,3,1];plot(R(1,Q),R(2,Q));

Gedreht:

function H(a,b,c,d,e,f) 
C=@cosd;S=@sind;
R=[1,0,0,0;0,C(e),0,-S(e);0,-S(e)*S(f),C(f),-C(e)*S(f);0,S(e)*C(f),S(f),C(e)*C(f)]*
  [C(c)*C(d),-S(c)*C(d),0,S(d);S(c),C(c),0,0;0,0,1,0;-C(c)*S(d),S(c)*S(d),0,C(d)]*
  [C(b),S(a)*S(b),C(a)*S(b),0;0,C(a),-S(a),0;-S(b),S(a)*C(b),C(a)*C(b),0;0,0,0,1]*
  (dec2bin(0:15)'-48.5);
Z=R(3,:)+2;
R=2*R./Z;
Q=[1,2,10,12,11,9,10,14,16,12,4,8,16,15,11,3,7,15,13,9,1,5,13,14,6,8,7,5,6,2,4,3,1];
plot(R(1,Q),R(2,Q));

Die Rotationsmatrizen verbrauchen immer noch eine Menge Bytes, aber der Eulersche Zyklus funktionierte recht gut und reduzierte die Anzahl der besuchten Vertices von 96 auf 120 auf 33.

Vertices werden erzeugt, indem die 4-Bit-Binärdarstellung von [0:15]msb als x-Koordinate und lsb als w-Koordinate betrachtet wird.

Bearbeiten: Das Vormultiplizieren aller Rotationsmatrizen war ein Albtraum, weshalb ich es anfangs nicht verwendet habe, sondern sie paarweise vormultipliziert habe. Das sparte 41 Byte. Suchen Sie nun die optimale Kombination. :) Das Multiplizieren der Matrizen mit drei war schlimmer als gar keine Vormultiplikation, daher bin ich mit dem paarweisen Ansatz zufrieden.


Ausgabe:

H(0,0,0,0,0,0)

H (0,0,0,0,0,0)

H(0,0,0,0,0,30)

H (0,0,0,0,0,30)

H(30,0,0,0,0,30)

H (30,0,0,0,0,30)

H(0,0,0,30,30,30)

H (0,0,0,30,30,30)

H(45,45,45,0,0,0)

H (45,45,45,0,0,0)

H(45,45,45,45,45,45)

H (45,45,45,45,45,45)

Becherglas
quelle
Edit: Ich bin blöd. überall von derselben Variablen getäuscht ... [Wollen Sie wirklich nicht die vollständige vormultiplizierte Matrix? :) i.imgur.com/nkM6y6g.png]
Algmyr
@algmyr Ja, die vollständig multiplizierte Matrix wurde ungefähr doppelt so lang ausgegeben, wenn ich mich richtig erinnere.
Becher
Dies sollte eher so sein, genießen Sie
Maximas
Um dies auszugleichen, finden Sie hier eine bessere Version Ihres Codes (330 Byte): paste.ee/p/2GRyJ
algmyr
14

Nachsatz 1075 732 683 640 631 601 590 545 542 526 514 478 470

Verwendet mat.ps und G .

Edit: -343 Angewandte binäre Codierungserzeugung von Vektoren und Euler-Schaltunggestohlenvon anderen Antworten entlehnt. Und angewandte binäre Token-Strings aus der G-Bibliothek.
Edit: -49 Neu definiert sin cosund negzu kürzeren Namen.
Edit: -43 Definierte Kurznamen für Sequenzen 0 0 0 1 1 0.
Bearbeiten: -9 al (d. H.aload ) Ist kürzer als (")@. Faktor 3 Anrufe nach idi(d. H. idiv) Auf Kosten eines Nichtstuns 1 idiv.
Edit: -30 Angewandter impliziter Definitionsblock aus G.
Edit: -10 Noch ein paar dreifach verwendete Sequenzen.
Bearbeiten: -45 Entferne Variablen i j k l m nfür die Winkel und definiere immer den aktuellen Winkel als tund Funktionen von Winkeln benutze den Wert des (globalen)tVariable. Verschieben Sie die Ausführung der Codebeschreibung der Rotationsmatrix, bis ihr tWert fertig ist.
Bearbeiten: -3 Entfernen Sie <16>$dh. closepath. Und ein Leerzeichen.
Edit: -16 Array-Klammern aus Einheitsvektoren in den Rotationsmatrizen ( J K Lund M) herausrechnen . Bewerben Sie sich erneut mofür modund sufür sub.
Bearbeiten: -12 Inline die Projekt-und-Zeichnen- Funktion und entfernen (jetzt leer) umschließendes Wörterbuch.
Edit: -36 Codiert die Schaltung (dh die Gesichter ) in einer Zeichenfolge.
Bearbeiten: -8 Definition des Vertices-Arrays entfernen V. Stattdessen auf Stapel lassen unddupArbeitskopien nach Bedarf (einmal, zuerst und wieder am Ende der Schleife). Außerdem wurden einige Operatoren von binären Token-Zeichenfolgen zurück in abgekürzte Namen übersetzt, bei denen die BTS keine Einsparungen ergab, so (I)$ist es jetzt fora(d. H. forall). if dukönnte sein (T8)$, ist aber if dueindeutig eine bessere Wahl (es ist Golf , keine Verschleierung per se). Führen Sie auch das scale Vorher durch translate , damit übersetzte Koordinaten 3und 4anstelle von 300und sein können 400.

(mat.ps)run 3(G)run $
t sin
A neg
t cos
0 0
0 1
1 0
2 mu Z 2(!V)@
idi 2 mo .5 su
(>8)$
[F D]
[D E]
[E D]
[D F]

3 4 100(&>88)$(,)# div(<N)#[E 15{[I 1 H I 2 H I 4 H ex 8 H]}fo]E
5{ARGUMENTS 1(XK/)$/t ex d{{J[0 C B 0][0 A C 0]K}{[C 0 A 0]L[B 0
C 0]K}{[C B D][A C D]M K}{[C D A]L M[B D C]}{J[0 C 0 B]M[0 A 0
C]}{J L[D C B][D A C]}}(>K)$[(>?)$]transpose matmul}fo
du(019;:89=?;37?>:26><804<=576451320){48 su get al po{W
Z Y X}{(>3)$}fora X G Y G{li}(D)#{mov}if du}fora(HB)#

Die 3 4und 100in der ersten Zeile des zweiten Blocks sind Parameter, die den Mittelpunkt x, den Mittelpunkt y bzw. den Maßstab der Zeichnung auf der Seite darstellen (die Mittelpunktkoordinaten werden um skaliert scale). (300.400) ist ungefähr das Zentrum des US-amerikanischen Briefpapiers (612.792) in PS-Einheiten.

Wenn Sie Postscript grob befolgen können, sind die wichtigen bizarren Dinge der implizite Prozedurblock und die codierten Operatorzeichenfolgen. Wie aus den Kommentaren in der Arbeitsdatei hervorgeht, ist jede Zeile des ersten Blocks implizit mit A, B, C usw. benannt. F E Dwürde produzieren 1 0 0 1 0 0. Für die codierten Operatorzeichenfolgen ist alles, was ein Argument für $ #oder @eine Folge von Operatoraufrufen ist, mit den Bytes Operatoren aus der Systemnamentabelle, PLRM 3ed Anhang F, auszuwählen. Diese und weitere Funktionen sind für PostScript mit der G-Bibliothek verfügbar ( enthält jetzt auch die mat.ps Funktionen).

Arbeitsdatei:

(mat.ps)run 3(G)run $
t sin %/A
A neg %/B
t cos %/C
0 0 %/D
0 1 %/E
1 0 %/F
2 mu Z 2(!V)@ %/G  %ad div %add div %108 1 54
idi 2 mo .5 su %idiv mod sub %/H %106 169 51
(>8)$ %/I %exch dup
[F D] %/J
[D E] %/K
[E D] %/L
[D F] %/M


3 4
100(&>88)$ %currentlinewidth exch dup dup %38
(,)#  %scale %139-95=44
div(<N)# %div setlinewidth %54 155-95=60 %translate %173-95=78
%/V
[E 15{[ I
    1 H I
    2 H I
    4 H ex
    8 H]}fo]

E 5{ARGUMENTS 1(XK/)$ %index get cvr %88 75 47
    /t ex d %exch def %62 51
    {{J[0 C B 0][0 A C 0]K} 
     {[C 0 A 0]L[B 0 C 0]K} 
     {[C B D][A C D]M K} 
     {[C D A]L M[B D C]}
     {J[0 C 0 B]M[0 A 0 C]}
     {J L[D C B][D A C]}}
    (>K)$ %exch get %62 75
    [
        (>?)$ %exch exec %62 63
    ]
    transpose matmul
}fo %for
du %dup
%d %def
%{transpose matmul}fora d

%[E 9 11 10 8 9 13 15 11 3 7 15 14 10 2 6 14 12 8 0 4 12 13 5 7 6 4 5 1 3 2 0]
%<0001090b0a08090d0f0b03070f0e0a02060e0c0800040c0d050706040501030200>
%          abcdef
%0123456789:;<=>?
(019;:89=?;37?>:26><804<=576451320)
{48 su get % 169 75 %V (>K)$ %sub %exch get

    al po %aload pop %2 117
    {W Z Y X}{(>3)$ %exch def
    }fora %forall %2 117  62 51 73
    X G
    Y G
    {li}(D)# %stopped
    {mov}
    if du%(T8)$ %if %84 du %dup 56
}
%<49a7a1>$ %forall stroke showpage %73 167-95=72 161-95=66
fora(HB)#

Ungolfed und leicht kommentiert:

300 400 translate   %roughly center of letter paper
currentlinewidth
100 dup dup scale
div setlinewidth    %scale x100, reduce line-width/100
(mat.ps)run         %load matrix library
ARGUMENTS aload pop{f e d c b a}{exch cvr def}forall  %define args as 
                                 % a,b,etc and convert to real numbers
/m{2 mod .5 sub}def
/P{aload pop{w z y x}{exch def}forall   %P: [x y z w]  project-and-draw  -
    x 2 mul z 2 add div 
    y 2 mul z 2 add div 
    {lineto}stopped{moveto}if %catch(&handle!) nocurrentpoint error in lineto
}bind def
/V[0 1 15{    % generate vectors with a for-loop
    [ exch
        dup m
        1 index 2 idiv m
        2 index 4 idiv m
        4 3 roll 8 idiv m
    ]
}for]
[[[1 0 0 0][0 a cos a sin neg 0][0 a sin a cos 0][0 0 0 1]] 
     [[b cos 0 b sin 0][0 1 0 0][b sin neg 0 b cos 0][0 0 0 1]] 
     [[c cos c sin neg 0 0][c sin c cos 0 0][0 0 1 0][0 0 0 1]] 
     [[d cos 0 0 d sin][0 1 0 0][0 0 1 0][d sin neg 0 0 d cos]]
     [[1 0 0 0][0 e cos 0 e sin neg][0 0 1 0][0 e sin 0 e cos]]
     [[1 0 0 0][0 1 0 0][0 0 f cos f sin neg][0 0 f sin f cos]]]
{transpose matmul} forall def   % apply array of rotations and define

%Eulerian circuit (borrowed and adjusted for 0-based indexing)
[0 1 9 11 10 8 9 13 15 11 3 7 15 14 10 2 6 14 12 8 0 4 12 13 5 7 6 4 5 1 3 2 0]

% the main program!
% on the stack is the Eulerian circuit array
{
    V exch get  %lookup index in (sextuply-transformed) vertex array
    P           %call project-and-draw
} forall
closepath stroke %draw it, don't just think about it

showpage % gs's cmd-line-args option automatically sets -dBATCH,
    % so without a showpage, gs will immediately exit before you
    % can look at the picture :(

Einige meiner Ausgaben spiegeln die Beispiele der Frage wider.

Denn gs -- hc.ps 0 0 0 0 0 0ich bekomme:
Bildbeschreibung hier eingeben

gs -- hc.ps 0 0 0 0 0 30
Bildbeschreibung hier eingeben

gs -- hc.ps 30 0 0 0 0 30
Bildbeschreibung hier eingeben

gs -- hc.ps 0 0 0 30 30 30
Bildbeschreibung hier eingeben

gs -- hc.ps 45 45 45 0 0 0
Bildbeschreibung hier eingeben

gs -- hc.ps 45 45 45 45 45 45
Bildbeschreibung hier eingeben

Bonusanimation habe ich gerade mit diesem Programm gemacht. Dieses Bild entspricht der Rotationssequenz 0 30 60 0 i i , wobei i von 0 bis 360 mal 2 reicht.
Bildbeschreibung hier eingeben

Luser Droog
quelle
2
Wow. Eine PostScript-Antwort für ein mathematisches Problem.
TuxCrafting
@ TùxCräftîñg In dieser Frage gibt es eigentlich nicht so viel Mathematik, solange man Matrixmultiplikation leicht machen kann. Und ich wollte dieses Programm schreiben, seit ich AK Dewdneys The Armchair Universe gelesen habe .
Luser Droog
Neue Funktionen zur G-Bibliothek hinzugefügt. Kann hier nicht verwendet werden, aber es ermöglicht diese 307-Byte-Version .
Luser Droog
8

C # + Unity, 1060 845 835 Bytes

C # ≈ Java

Es wird davon ausgegangen, dass diese Funktion in einem Skript enthalten ist, auf dem platziert wurde MainCamera.

Bearbeiten:
Vielen Dank an @TuukkaX für die Vorschläge zum Speichern von 19 Bytes Gespeicherte ~ 200 Bytes mit dem Euler-Zyklus.

Golf gespielt:

void d(float[]r){transform.position=Vector3.back*2;GetComponent<Camera>().backgroundColor=Color.black;Vector4[]p=new Vector4[16];Matrix4x4[]m=new Matrix4x4[6];int i=0;for(;i<16;i++)p[i]=new Vector4(i%2,i/2%2,i/4%2,i/8%2)-new Vector4(.5f,.5f,.5f,.5f);int[,]X={{6,8,1,12,7,11},{5,0,0,0,5,10},{10,10,5,15,15,15}};for(i=0;i<6;i++){m[i]=Matrix4x4.identity;r[i]=Mathf.Deg2Rad*r[i];float c=Mathf.Cos(r[i]),s=Mathf.Sin(r[i]);m[i][X[1,i]]=c;m[i][X[2,i]]=c;m[i][X[0,i]]=s;m[i][X[0,i]%4*4+X[0,i]/4]=-s;}for(i=0;i<16;i++)foreach(Matrix4x4 x in m)p[i]=x*p[i];int[]F={0,1,9,11,10,8,9,13,15,11,3,7,15,14,10,2,6,14,12,8,0,4,12,13,5,7,6,4,5,1,3,2,0};LineRenderer l=new GameObject().AddComponent<LineRenderer>();l.SetVertexCount(33);l.material=new Material(Shader.Find("Sprites/Default"));l.SetWidth(.03f,.03f);for(i=0;i<33;i++)l.SetPosition(i,p[F[i]]);

Zeilenumbruch + Einrückung + Vollschale:

using UnityEngine;
using System.Collections;

public class h : MonoBehaviour {

    void d(float[]r)
    {
        transform.position=Vector3.back*2.5f;
        GetComponent<Camera>().backgroundColor=Color.black;
        Vector4[]p=new Vector4[16];
        Matrix4x4[]m=new Matrix4x4[6];
        int i=0;
        for(;i<16;i++)p[i]=new Vector4(i%2,i/2%2,i/4%2,i/8%2)-new Vector4(.5f,.5f,.5f,.5f);
        int[,]X={{6,8,1,12,7,11},{5,0,0,0,5,10},{10,10,5,15,15,15}};
        for (i=0;i<6;i++){
            m[i]=Matrix4x4.identity;
            r[i]=Mathf.Deg2Rad*r[i];
            float c=Mathf.Cos(r[i]);
            float s=Mathf.Sin(r[i]);
            m[i][X[1,i]]=c;
            m[i][X[2,i]]=c;
            m[i][X[0,i]]=s;
            m[i][X[0,i]%4*4+X[0,i]/4]=-s;
        }
        for (i=0;i<16;i++)foreach(Matrix4x4 x in m)p[i]=x*p[i];
        int[]F={0,1,9,11,10,8,9,13,15,11,3,7,15,14,10,2,6,14,12,8,0,4,12,13,5,7,6,4,5,1,3,2,0};
        LineRenderer l=new GameObject().AddComponent<LineRenderer>();
        l.SetVertexCount(33);
        l.material=new Material(Shader.Find("Sprites/Default"));
        l.SetWidth(.03f,.03f);
        for (i=0;i<33;i++)
            l.SetPosition(i,p[F[i]]);
        l.gameObject.tag = "Player";
    }
    public float[] input;
    void Start()
    {
        d(input);
    }
}

Ich konnte weder eine einfache Formel zum Konstruieren der Rotationsmatrizen noch der zu zeichnenden "Flächen" finden, so dass der Hardcode viele Bytes kostete. Ich habe den Eulerschen Zyklus von @beaker ausgeliehen. Außerdem sind die integrierten Unity-Funktionen äußerst ausführlich.

Sie können alle Testfälle online überprüfen .

Blau
quelle
Dies ist das erste Mal, dass ich hier eine C # + Unity-Antwort sehe. +1
DanTheMan
Ich denke, jeder 0.5fkann auf .5fund 0.01fauf reduziert werden .01f. Ich denke auch, dass die Integer-Arrays mit einem Komma getrennt werden können, anstatt int[]mehrere Male zu sagen .
Yytsi
@Blau Oh, du hast recht! Ich habe C # eine Weile nicht benutzt und war mir des letzten Tipps nicht sicher.
Yytsi
@ TuukkaX Ignoriere meinen vorherigen Kommentar, den ich verwenden kann int[,]. Trotzdem danke.
Blue
Sie haben noch eine, Vector4(0.5f,0.5f,0.5f,0.5f)die reduziert werden könnte Vector4(.5f,.5f,.5f,.5f).
Yytsi
6

Javascript ES6, 584 Bytes

f=(...R)=>(P=s=>[...s].map(i=>parseInt(i,16)),C=document.createElement`canvas`,X=C.getContext`2d`,X.translate((C.width=300)/2,(C.height=300)/2),X.lineWidth=0.01,X.scale(100,100),X.beginPath(),P("0267fd9804c8ab915dcefb37546ea2310").map((e,i)=>{[x,y,z]=P("084c2a6e195d3b7f").map(i=>[...(1e3+i.toString(2)).slice(-4)].map(i=>i-0.5)).map(e=>(R.map((R,i,_,M=Math,C=M.cos(r=R*M.PI/180),S=M.sin(r))=>((a,b,s=1)=>[e[a],e[b]]=[C*e[a]-s*S*e[b],s*S*e[a]+C*e[b]])(...[[1,2],[0,2,-1],[0,1],[0,3,-1],[1,3],[2,3]][i])),e))[e];[x,y]=[2*x/(2+z),2*y/(2+z)];i?X.lineTo(x,y):X.moveTo(x,y)}),X.stroke(),C)

"Ungolfed":

f=(...R)=>(                                                              // function that accepts rotations in the following form: f(a,b,c,d,e,f)
    P=s=>[...s].map(i=>parseInt(i,16)),                                  // function to convert strings to hex-arrays
    V=P("084c2a6e195d3b7f")                                              // vertices encoded as hex values ( [0,1,1,0] -> 6 )
        .map(i=>[...(1e3+i.toString(2)).slice(-4)].map(i=>i-0.5))        // convert hex values to vertices, center the hypercube
        .map(e=>(R.map((R,i,_,M=Math,C=M.cos(r=R*M.PI/180),S=M.sin(r))=> // convert angles to degrees, precalculate sin and cos values
        ((a,b,s=1)=>[e[a],e[b]]=[C*e[a]-s*S*e[b],s*S*e[a]+C*e[b]])       // apply matrix transforms to all vertices
        (...[[1,2],[0,2,-1],[0,1],[0,3,-1],[1,3],[2,3]][i])),e)),        // list of encoded matrix transforms
    C=document.createElement`canvas`,X=C.getContext`2d`,                 // create image to draw on
    X.translate((C.width=300)/2,(C.height=300)/2),                       // setup image dimensions, center transform
    X.lineWidth=0.01,X.scale(100,100),X.beginPath(),                     // setup line, scale the transform and begin drawing
    P("0267fd9804c8ab915dcefb37546ea2310").map((e,i)=>{                  // hypercube edge path indices encoded as hex values
        [x,y,z]=V[e];[x,y]=[2*x/(2+z),2*y/(2+z)];                        // project vertex
        i?X.lineTo(x,y):X.moveTo(x,y)}),X.stroke(),                      // draw vertex
    C)                                                                   // return image

Sehen Sie es in Aktion (modifiziert, um sich kontinuierlich zu drehen):

with(document)with(Math)with(document.getElementById`canvas`)with(getContext`2d`){render=()=>{requestAnimationFrame(render);clearRect(0,0,width,height);save();K=performance.now();R=[K*0.01,K*0.02,K*0.03,K*0.04,K*0.05,K*0.06];X=s=>[...s].map(i=>parseInt(i,16));V=X("084c2a6e195d3b7f").map(i=>[...(1e3+i.toString(2)).slice(-4)].map(i=>i-0.5)).map(e=>(R.map((R,i,_,C=cos(r=R*PI/180),S=sin(r))=>((a,b,s=1)=>[e[a],e[b]]=[C*e[a]-s*S*e[b],s*S*e[a]+C*e[b]])(...[[1,2],[0,2,-1],[0,1],[0,3,-1],[1,3],[2,3]][i])),e));translate((width=300)/2,(height=300)/2);lineWidth=0.01;scale(100,100);beginPath();X("0267fd9804c8ab915dcefb37546ea2310").map((e,i)=>{[x,y,z]=V[e];[x,y]=[2*x/(2+z),2*y/(2+z)];i?lineTo(x,y):moveTo(x,y)});stroke();restore();};render();}
<html><body><canvas id="canvas"></canvas></body></html>

Die Funktion gibt ein HTML5-Zeichenbereichsobjekt zurück. Sie müssen es beispielsweise der Seite hinzufügen document.body.appendChild(f(0,0,0,0,0,0)).

Derzeit werden die Rotationen nicht in der richtigen Reihenfolge angewendet. Ich arbeite an der Neuordnung, aber so wie sie ist, dreht sie einen Hypercube korrekt.

Dendrobium
quelle
Clever, ich habe eine Weile gebraucht, um herauszufinden, was Sie mit den Matrixtransformationen gemacht haben. : D Außerdem kann ich Ihr Code-Snippet nicht zum Laufen bringen ... es gibt mir einen nicht hilfreichen "Skriptfehler". in Zeile 0.
Becher
@beaker Welchen Browser verwenden Sie? Ich habe es auf dem neuesten Firefox getestet.
Dendrobium
Ich bin auf Safari 9.1.1. Lassen Sie mich einen anderen ausprobieren.
Becher
1
Ja, Chrome funktioniert einwandfrei.
Becher
1
Safari ist Mist. Verwenden Sie es nicht, um zu überprüfen, ob etwas funktioniert.
Patrick Roberts
1

Mathematica, 453 415 Byte *

Verkürzt durch Verwendung der Euler-Tour und Bereinigung in einer einzigen Anweisung, ohne Funktionen in Variablen zu definieren. Dadurch wird der Code aus irgendeinem Grund langsamer. Ich vermute, Mathematica wertet die Funktionen jetzt mehrmals neu aus, da sie nicht in einer Variablen gespeichert sind.

Graphics[Line[Table[{2#/(2+#3),2#2/(2+#3)}&@@Map[Dot@@Table[Table[If[n==m==#2||n==m==#,Cos[#3],If[n==#2&&m==#,If[#2==1&&(#==3||#==4),1,-1]Sin[#3],If[n==#&&m==#2,If[#2==1&&(#==3||#==4),-1,1]Sin[#3],If[n==m,1,0]]]],{n,4},{m,4}]&[k[[1]],k[[2]],a[[k[[3]]]]°],{k,{{4,3,6},{4,2,5},{4,1,4},{2,1,3},{3,1,2},{3,2,1}}}].#&,Tuples[{0,1},4]-.5,{1}][[i]],{i,{1,2,10,12,11,9,10,14,16,12,4,8,16,15,11,3,7,15,13,9,1,5,13,14,6,8,7,5,6,2,4,3,1}}]]]

* Ich zähle °und ==als einzelne Bytes, da sie in Mathematica als einzelne Zeichen dargestellt werden. Ich halte das für fair, da viele Sprachen seltsame Zeichenkodierungen verwenden.

Ungolfed mit Kommentaren. Die Eingabe ist oben als fest codiert a={30,0,0,0,0,30};. Ich habe das nicht auf meine Punktzahl angerechnet.


a = {45, 45, 45, 45, 45, 45};



(* #2,#-th rotation matrix as a funciton of #3 *)
(* Using the \
#-notation saved 6 bytes over the more common function definition \
notation*)
r = 
  Table[If[n == m == #2 || n == m == #, Cos[#3], 
     If[n == #2 && m == #, 
      If[#2 == 1 && (# == 3 || # == 4), 1, -1] Sin[#3], 
      If[n == # && m == #2, 
       If[#2 == 1 && (# == 3 || # == 4), -1, 1] Sin[#3], 
       If[n == m, 1, 0]]]], {n, 4}, {m, 4}] &;

(* Total rotation matrix. Need six of them. Function of the six \
angles to rotate.*)

u = Dot @@ 
     Table[r[k[[1]], 
       k[[2]], \[Degree]*
        a[[k[[3]]]]], {k, {{4, 3, 6}, {4, 2, 5}, {4, 1, 4}, {2, 1, 
         3}, {3, 1, 2}, {3, 2, 1}}}].# &;



(* List of all vertices of the hypercube *)
t = Tuples[{0, 1}, 4];
t -= .5;
v = Map[u, t, {1}];

(*projection*)
p = {2 #/(2 + #3), 2 #2/(2 + #3)} &;

(*Eulerian tour*)

l = Table[
   p @@ v[[i]], {i, {1, 2, 10, 12, 11, 9, 10, 14, 16, 12, 4, 8, 16, 
     15, 11, 3, 7, 15, 13, 9, 1, 5, 13, 14, 6, 8, 7, 5, 6, 2, 4, 3, 
     1}}];
Graphics[Line[l]]

0 0 0 0 0 30

0 0 0 30 30 30

Bildbeschreibung hier eingeben

405 10 -14 -8 -9 205

Bildbeschreibung hier eingeben

dylnan
quelle