Schreiben Sie eine benannte Funktion oder ein benanntes Programm, das das Quaternionsprodukt von zwei Quaternionen berechnet. Verwenden Sie so wenig Bytes wie möglich.
Quaternionen
Quaternionen sind eine Erweiterung der reellen Zahlen, die die komplexen Zahlen weiter erweitert. i
Quaternionen verwenden nicht nur eine imaginäre Einheit , sondern drei imaginäre Einheiten i,j,k
, die die Beziehungen erfüllen.
i*i = j*j = k*k = -1
i*j = k
j*i = -k
j*k = i
k*j = -i
k*i = j
i*k = -j
(Es gibt auch Tabellen auf der Wikipedia-Seite .)
Mit anderen Worten, jede imaginäre Einheit ist ein Quadrat zu -1
und das Produkt von zwei verschiedenen imaginären Einheiten ist die verbleibende dritte Einheit mit einem in +/-
Abhängigkeit davon, ob die zyklische Reihenfolge (i,j,k)
eingehalten wird (dh die Rechtsregel ). Es kommt also auf die Reihenfolge der Multiplikation an.
Eine allgemeine Quaternion ist eine lineare Kombination eines Realteils und der drei imaginären Einheiten. Es wird also durch vier reelle Zahlen beschrieben (a,b,c,d)
.
x = a + b*i + c*j + d*k
Wir können also mit der Eigenschaft distributive zwei Quaternionen multiplizieren, wobei wir darauf achten, die Einheiten in der richtigen Reihenfolge zu multiplizieren und im Ergebnis ähnliche Begriffe zu gruppieren.
(a + b*i + c*j + d*k) * (e + f*i + g*j + h*k)
= (a*e - b*f - c*g - d*h) +
(a*f + b*e + c*h - d*g)*i +
(a*g - b*h + c*e + d*f)*j +
(a*h + b*g - c*f + d*e)*k
So gesehen kann die Quaternion-Multiplikation als eine Abbildung von einem Paar von 4-Tupeln auf ein einzelnes 4-Tupel betrachtet werden, was Sie implementieren müssen.
Format
Sie sollten entweder ein Programm oder eine benannte Funktion schreiben . Ein Programm sollte Eingaben von STDIN nehmen und das Ergebnis ausdrucken. Eine Funktion sollte Funktionseingaben aufnehmen und eine Ausgabe zurückgeben (nicht drucken).
Eingabe- und Ausgabeformate sind flexibel. Die Eingabe besteht aus acht reellen Zahlen (die Koeffizienten für zwei Quaternionen), und die Ausgabe besteht aus vier reellen Zahlen. Die Eingabe kann aus acht Zahlen, zwei Listen mit vier Zahlen, einer 2x4-Matrix usw. bestehen. Das Eingabe- / Ausgabeformat muss nicht identisch sein. Die Reihenfolge der (1,i,j,k)
Koeffizienten liegt bei Ihnen.
Die Koeffizienten können negativ oder nicht ganz sein. Sorgen Sie sich nicht um echte Präzision oder Überläufe.
Verboten: Funktion oder Typen speziell für Quaternionen oder Äquivalente.
Testfälle
Diese sind im (1,i,j,k)
Koeffizientenformat.
[[12, 54, -2, 23], [1, 4, 6, -2]]
[-146, -32, 270, 331]
[[1, 4, 6, -2], [12, 54, -2, 23]]
[-146, 236, -130, -333]
[[3.5, 4.6, -0.24, 0], [2.1, -3, -4.3, -12]]
[20.118, 2.04, 39.646, -62.5]
Referenzimplementierung
In Python als Funktion:
#Input quaternions: [a,b,c,d], [e,f,g,h]
#Coeff order: [1,i,j,k]
def mult(a,b,c,d,e,f,g,h):
coeff_1 = a*e-b*f-c*g-d*h
coeff_i = a*f+b*e+c*h-d*g
coeff_j = a*g-b*h+c*e+d*f
coeff_k = a*h+b*g-c*f+d*e
result = [coeff_1, coeff_i, coeff_j, coeff_k]
return result
Python -
90 75 7269Pure Python, keine Bibliotheken - 90:
Es ist wahrscheinlich ziemlich schwierig, diese "Standard" -Lösung in Python zu verkürzen. Ich bin aber sehr gespannt, was sich die anderen einfallen lassen. :)
Verwenden von NumPy -
75 7269:Nun, da die Eingangs- und Ausgangs ziemlich flexibel sind, können wir einige NumPy Funktionen nutzen und nutzen die Skalar-Vektordarstellung :
Eingabeargumente
s
undt
sind die skalaren Teile der beiden Quaternionen (die Realteile) undp
undq
sind die entsprechenden Vektorteile (die imaginären Einheiten). Die Ausgabe ist eine Liste mit Skalar- und Vektorteilen des resultierenden Quaternions, wobei letzteres als NumPy-Array dargestellt wird.Einfaches Testskript:
(
mult(...)
Ist die Referenzimplementierung des OP.)Ausgabe:
quelle
Haskell, 85
Das Portieren nach Haskell erspart uns ein paar Zeichen;)
quelle
Mathematica
8350Wahrscheinlich kann mehr golfen werden ..
Leerzeichen und Zeilenumbrüche werden nicht gezählt und nicht benötigt.
Verwendung:
BEARBEITEN Wie das funktioniert.
Die Mathematica-Funktion
Permutations
macht alle möglichen Permutationen von#2
(dem zweiten Argument). Es gibt 24 Permutationen, aber wir brauchen nur{e,f,g,h}
,{f,e,h,g}
,{g,h,e,f}
, und{h,g,f,e}
. Dies sind die erste, 8., 17. und 24. Permutation. Also der CodeWählt diese genau aus den Permutationen des zweiten Arguments aus und gibt sie als Matrix zurück. Dann haben sie aber noch nicht das richtige Vorzeichen. Der Code
p[{-1,1,-1,1}][[1;;3]]
gibt eine 3x4-Matrix mit dem richtigen Vorzeichen zurück. Wir stellen es voran,{1,1,1,1}
indemJoin
wir eine normale Multiplikation (Times
oder wie hier, indem wir sie einfach nacheinander schreiben) zwischen zwei Matrizen verwenden und in Mathematica eine elementweise Multiplikation durchführen.Also endlich das Ergebnis von
ist die Matrix
Eine Matrixmultiplikation zwischen
{a,b,c,d}
(dem ersten Argument#1
) und der vorherigen Matrix ergibt das gewünschte Ergebnis.EDIT 2 Kürzere Code
Inspiriert durch den Python-Code von Falko habe ich das Quaternion in einen Skalar- und einen Vektorteil aufgeteilt und den in Mathematica eingebauten Befehl verwendet
Cross
, um das Kreuzprodukt der Vektorteile zu berechnen:Verwendung:
quelle
1, 8, 17, 24
?Python, 94
Der einfachste Weg ist nicht zu lang.
quelle
JavaScript ES6 - 86
quelle
Lua - 99
Könnte auch.
Luas "unpack ()" befreit die Elemente einer Tabelle. In der Tabelle 'arg' werden also alle Kommandozeilen-Eingaben gespeichert (einschließlich
arg[0]
des Dateinamens des Programms, der verworfen wird).quelle
Python,
5856 ZeichenIch nehme sehr großzügigen Einsatz der Ein- / Ausgabeformat Wiggleraum. Die Eingaben sind 4 komplexe Zahlen, die folgendermaßen codiert sind:
Es gibt ein Paar komplexer Zahlen in einem ähnlichen Format aus. Das erste Paar codiert den Realteil und den
i
Teil, das zweite codiert den Teilj
und denk
Teil.Beachten Sie, dass das erste Quaternion
x+y*j
und das zweite Quaternion ist, um zu sehen, dass das funktioniertz+w*j
. Bewerten(x+y*j)*(z+w*j)
und realisieren Sie dasj*t
=conj(t)*j
für jede imaginäre Zahlt
.quelle
i
undj
wie sich innere und äußere komplexe Koeffizienten verhalten. Wie faszinierend!(2*w.real-w)
.abs(w)**2/w
würde aber für 0 funktionieren. Vielleicht wäre sogar exec mit String-Ersetzung es wert? `Whispers v2 , 396 Bytes
Probieren Sie es online!
Nimmt Eingaben in das Formular auf
und Ausgänge als
zu repräsentierenq= w + x i + yj + zk
Der Strukturbaum dieser Antwort lautet:
Ein guter Teil dieser Antwort rührt von zwei Hauptfehlern in Whispers her:
Daher können wir den Code in drei Abschnitte aufteilen.
Wie es funktioniert
Die folgenden Definitionen dienen der Klarheit und Übersichtlichkeit:
Abschnitt 1: PermutierenEIN und B
Der erste Abschnitt ist mit Abstand der längste und erstreckt sich von Linie 1 bis Linie 22 :
Der Hauptzweck dieses Abschnitts ist das PermutierenB so dass einfache elementweise Multiplikation zwischen EIN und B ist möglich. Es gibt vier verschiedene Anordnungen vonB die Elemente von multiplizieren EIN mit:
Die zweite Eingabe,B wird in Zeile 6 gespeichert . Wir haben uns dann getrenntB in der Mitte, wie jede mögliche Anordnung von B ist paarweise gruppiert. Um diese Paare umzukehren (um die richtigen Befehle zu erhalten)B2 und B4 ) nehmen wir das erste und das letzte Element und verketten sie dann in umgekehrter Reihenfolge:
(Bildung[ f, e ] ) und
(Bildung[ h , g] ). Wir haben jetzt alle Hälften, die zur Bildung der Arrangements benötigt werden, und verknüpfen sie zu einer EinheitB1, B2, B3 und B4 . Schließlich verknüpfen wir diese vier Arrangements zu einer EinheitBT . Wir machen es dann schnellEINT , definiert als EIN wiederholt 4 mal:
Wenn jedes Element vonBT wird mit dem entsprechenden Element in multipliziert EINT erhalten wir die (vorzeichenlosen) Werte in q⋅ p
Abschnitt 2: Zeichen und Produkte
Wie in Abschnitt 1 erwähnt, sind die Werte inEINT und BT entsprechen den vorzeichenlosen (dh positiven) Werten jedes der Koeffizienten in q⋅ p . Die Zeichen enthalten kein offensichtliches Muster, das kürzer wäre, als das Array nur hart zu codieren. Daher codieren wir das Array hart:
Wir werden dieses Array nennenS (Zeichen). Als nächstes zippen wir jedes Element zusammenEINT, BT und S und nimm das Produkt jedes Subarrays, z [ [ a , e , 1 ] , [ b , f, - 1 ] , … , [ e , f, - 1 ] , [ d, e , 1 ] ] → D = [ a e , - b f,…,−ef,de] .
Section 3: Partitions and final sums.
Once we have the array of coefficients ofq⋅p , with signs, we need to split it into 4 parts (i.e. the four factorised coefficients of q⋅p ), and then take the sums. This leads us to the only golfing opportunity found: moving the
to line 4 rather than 26, as it is used 6 times, each time saving a byte by moving it. Unfortunately, this costs a byte changing the 9 to a 10, so only5 bytes are saved. The next section takes slices of size 4 from the front of D , saving each slice to the corresponding row and passing on the shortened list of D . Once 4 slices are taken, we the take the sum of each, before outputting them all.
quelle