Girar um hipercubo

27

Introdução

Um hipercubo / tesserato é o equivalente em 4 dimensões de um cubo normal. É feito pegando uma rede de cubos, estendendo-a para a 3ª dimensão e depois - usando a 4ª dimensão - dobrando-a em um hipercubo. É basicamente um cubo, onde cada lado é um cubo.

Para criar um hipercubo, você precisa de 16 vetores 4d (um vetor com um x, a y, a ze um wcomponente). Esses vetores são os seguintes:

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

O hipercubo tem 24 faces. A lista a seguir contém todos eles (cada grupo marca um 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

Com todas essas informações, você tecnicamente tem um hipercubo no código. Para girar isso, você precisa de 6 matrizes diferentes para cada plano de rotação, uma para os planos YZ, XZ, XY, XW, YW e ZW. Depois de ter todas as matrizes, você precisa multiplicar os vértices do cubo com eles.

As seguintes imagens mostram a estrutura de cada matriz:

Para a rotação no plano YZ:

Para a rotação no plano XZ:

Para a rotação no plano XY:

Para a rotação no plano XW:

Para a rotação no plano YW:

Para a rotação no plano ZW:

As rotações são aplicadas nesta ordem.

Depois de tudo isso, você tem um hipercubo girado. Agora você precisa desenhá-lo. Você deve usar uma projeção ortogonal combinada com uma projeção em perspectiva para enviar (x, y, z, w)para (2x/(2+z), 2y/(2+z)).

Entrada

Sua entrada é de 6 números inteiros entre 0 (inclusive) e 360 ​​(exclusivamente). Eles representam as rotações em graus nos diferentes planos de rotação do hipercubo.

Saída

Sua saída deve ser uma única imagem contendo o hipercubo. A tela pode ser uma imagem rasterizada, uma imagem vetorial ou uma arte ASCII. A imagem de saída deve ter pelo menos 100 * 100 pixels e o cubo precisa ocupar pelo menos 50% da tela. Qualquer formato de saída de imagem padrão é permitido.

Casos de teste

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

Abra as imagens em uma nova guia, para vê-las em tamanho real.

Regras

  • Aplicam-se regras padrão
  • As brechas padrão são proibidas
  • O menor código em bytes ganha
Bálint
fonte
Por que você destruiu o outro post?
Rɪᴋᴇʀ
@ EᴀsᴛᴇʀʟʏIʀᴋ Eu o publiquei no chat para uma última revisão
Bálint
7
Como apontei em duas ocasiões distintas na caixa de areia, a descrição da projeção para exibição é incompleta porque pressupõe que o objeto a ser projetado é tridimensional, enquanto na verdade é, obviamente, tridimensional.
Peter Taylor
2
@luserdroog Acho que o 'U' deve ser 'N'.
copo
2
@ Bálint Obrigado pelo desafio, eu gostei. Esperamos obter mais respostas e abordagens diferentes. : D
copo

Respostas:

9

Oitava, 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));

Rodado:

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

As matrizes de rotação ainda consomem muitos bytes, mas o ciclo euleriano funcionou muito bem, reduzindo o número de vértices visitados de 96 120 para 33.

Os vértices são gerados considerando a representação binária de 4 bits [0:15]e considerando o msb como coordenada x e o lsb como coordenada w.

Edit: A pré-multiplicação de todas as matrizes de rotação foi um pesadelo, razão pela qual eu não a usei inicialmente, mas a pré-multiplicação em pares salvou 41 bytes. Agora, procure a combinação ideal. :) Multiplicar as matrizes por três foi pior do que nenhuma pré-multiplicação, por isso ficarei feliz com a abordagem em pares.


Saída:

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)

taça
fonte
Edit: Eu sou estúpido. enganado pela mesma variável em todos os lugares ... [Tem certeza de que não deseja a matriz pré-multiplicada completa? :) i.imgur.com/nkM6y6g.png]
algmyr
@ alggyr Sim, a matriz totalmente multiplicada saiu duas vezes mais, se bem me lembro.
301216
Este deve ser mais parecido com ele, desfrutar de "simplificações" estúpidas do Maxima: i.imgur.com/klkXLPf.png
algmyr
Para compensar por não miserável em matemática, aqui é uma versão mais golfed do seu código, 330 bytes: paste.ee/p/2GRyJ
algmyr
14

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

Usa mat.ps e G .

Edit: -343 Geração aplicada de codificação binária de vetores e circuito eulerianoroubadoemprestado de outras respostas. E aplicou strings binárias de tokens da biblioteca G.
Editar: -49 Redefinidos sin cose negcom nomes mais curtos.
Edit: -43 Nomes abreviados definidos para sequências 0 0 0 1 1 0.
Edit: -9 al (ie. aload) É menor que (")@. O fator 3 chama para idi(ie. idiv) Ao custo de um não fazer nada 1 idiv.
Edit: -30 Bloco de definição implícita aplicado de G.
Edit: -10 Mais algumas sequências triplamente usadas.
Edit: -45 Remova variáveis i j k l m npara os ângulos e sempre defina o ângulo atual, pois as tfunções dos ângulos usam o valor de (global)tvariável. Adie a execução da descrição de código da matriz de rotação até que seu tvalor esteja pronto.
Edit: -3 Remover <16>$ie. closepath. E um espaço.
Edit: -16 Suportes de matriz de fator fora dos vetores unitários nas matrizes de rotação ( J K Le M). Reaplicar retirado mopara mode supara sub.
Edit: -12 In-line a função project-and-draw e remova (agora vazio) o dicionário anexo.
Edit: -36 Codificou o circuito (isto é, as faces ) em uma string.
Edit: -8 Remova a definição da matriz de vértices V. Em vez disso, deixe na pilha edupcópias de trabalho conforme necessário (uma vez, no início e novamente no final do loop). Além disso, traduzimos alguns operadores de seqüências binárias de token de volta para nomes abreviados nos quais o BTS não deu economia, o mesmo (I)$acontece agora fora(ie. forall). if dupoderia ser (T8)$, mas if dué claramente uma escolha melhor (é golfe , não ofuscação por si só). Além disso, execute o scale antes translate , para que as coordenadas traduzidas possam ser 3e em 4vez de 300e 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)#

A 3 4e 100na primeira linha do segundo bloco são parâmetros que representam o centro-x, y e centro-escala, respectivamente, do desenho na página (coordenadas do centro são dimensionadas em scale). (300.400) é aproximadamente o centro do papel tamanho carta dos EUA (612.792) em unidades PS.

Se você pode seguir aproximadamente o postscript, as coisas bizarras importantes são o bloco de procedimento implícito e as seqüências de caracteres codificadas do operador. Conforme mostrado pelos comentários no arquivo de trabalho, abaixo, cada linha do primeiro bloco é implicitamente nomeada por A, B, C, etc. Então, por exemplo. F E Dproduziria 1 0 0 1 0 0. Para as cadeias de operadores codificadas, qualquer coisa que seja um argumento $ #ou @uma sequência de chamadas do operador, usando os bytes para selecionar operadores da tabela de nomes do sistema, PLRM 3ed Apêndice F. Esses recursos e mais estão disponíveis para PostScript na biblioteca G ( agora também inclui as funções mat.ps).

Arquivo de trabalho:

(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 e levemente comentou:

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 :(

Algumas das minhas saídas são imagens espelhadas dos exemplos da pergunta.

Pois gs -- hc.ps 0 0 0 0 0 0eu recebo:
insira a descrição da imagem aqui

gs -- hc.ps 0 0 0 0 0 30
insira a descrição da imagem aqui

gs -- hc.ps 30 0 0 0 0 30
insira a descrição da imagem aqui

gs -- hc.ps 0 0 0 30 30 30
insira a descrição da imagem aqui

gs -- hc.ps 45 45 45 0 0 0
insira a descrição da imagem aqui

gs -- hc.ps 45 45 45 45 45 45
insira a descrição da imagem aqui

Animação bônus que acabei de criar com este programa. Esta imagem corresponde à sequência de rotação 0 30 60 0 i i , onde i varia de 0 a 360 por 2.
insira a descrição da imagem aqui

luser droog
fonte
2
Uau. Uma resposta PostScript para um problema matemático.
TuxCrafting
@ TùxCräftîñg Na verdade, não há muita matemática nesta questão, desde que você possa fazer a multiplicação de matrizes facilmente. E eu queria escrever esse programa desde a leitura de The Armchair Universe, de AK Dewdney .
Luser droog
Adicionadas novas funções à biblioteca G. Não pode ser usado aqui, mas permite esta versão de 307 bytes .
Luser droog,
8

C # + Unidade, 1060 845 835 bytes

C # ≈ Java

Supõe que esta função esteja em um script colocado em MainCamera.

Edit:
Obrigado a @TuukkaX pelas sugestões para salvar 19 bytes salvos ~ 200 bytes usando o ciclo euleriano.

Golfe:

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]]);

Novas linhas + recuo + shell completo:

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

Não consegui descobrir uma fórmula simples para construir as matrizes de rotação nem as "faces" que desenhar, de modo que custam muitos bytes para codificar. Peguei emprestado o ciclo euleriano da @beaker. Além disso, os integrados do Unity são extremamente detalhados.

Você pode verificar todos os casos de teste online .

Azul
fonte
Esta é a primeira vez que eu vejo uma resposta C # + Unity aqui. 1
DanTheMan
Eu acho que tudo 0.5fpode ser reduzido para .5fe 0.01fpara .01f. Eu também acho que as matrizes inteiras podem ser separadas por vírgula em vez de dizer int[]várias vezes.
Yytsi 29/07/16
@ Blue Oh, você está certo! Não usei o C # por um tempo, então não tinha certeza da última dica.
Yytsi 29/07/16
@TuukkaX Ignore meu comentário anterior, eu posso usar int[,]. Ainda assim, obrigada.
Azul
Você ainda tem um Vector4(0.5f,0.5f,0.5f,0.5f)que pode ser reduzido a Vector4(.5f,.5f,.5f,.5f).
Yytsi 3/08/16
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

Veja em ação (modificado para girar continuamente):

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>

A função retorna um objeto de tela HTML5, é necessário adicioná-lo à página, por document.body.appendChild(f(0,0,0,0,0,0))exemplo.

Atualmente, as rotações são aplicadas fora de ordem, estou trabalhando na reordenação, mas, como é, gira um hipercubo corretamente.

Dendrobium
fonte
Inteligente, demorei um pouco para descobrir o que você estava fazendo com as transformações matriciais. : D Além disso, não consigo fazer o seu snippet de código funcionar ... está me dando um "erro de script" inútil. na linha 0.
copo
@beaker Qual navegador você está usando? Eu testei no Firefox mais recente.
Dendrobium
Estou no Safari 9.1.1. Deixe-me tentar um diferente.
23286 copo beaker
1
Sim, o Chrome funciona muito bem.
copo
1
Safari é uma porcaria. Não use para verificar se algo funciona.
Patrick Roberts
1

Mathematica, 453 415 bytes *

Encurtado usando o tour euleriano e limpando tudo em uma única instrução sem definir funções nas variáveis. Isso torna o código mais lento por algum motivo. Suponho que o Mathematica reavalia as funções várias vezes agora que não estão armazenadas em uma variável.

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

* Estou contando °e ==como bytes únicos cada, pois são representados como um único caractere no Mathematica. Eu acho que isso é justo, pois muitas línguas usam codificações de caracteres estranhas.

Ungolfed com comentários. A entrada é codificada no topo como a={30,0,0,0,0,30};. Eu não contei isso na minha pontuação.


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

insira a descrição da imagem aqui

405 10 -14 -8 -9 205

insira a descrição da imagem aqui

dylnan
fonte