Analysieren Sie eine Quaternion


27

Wenn Sie es noch nicht wissen, ist eine Quaternion im Grunde eine 4-teilige Nummer. Für die Zwecke dieser Herausforderung besteht sie aus einer realen Komponente und drei imaginären Komponenten. Die imaginären Komponenten durch das Suffix dargestellt sind i, j, k. Zum Beispiel 1-2i+3j-4kist eine Quaternion mit 1der realen Komponente und mehr -2, 3und -4die imaginären Komponenten zu sein.

In dieser Herausforderung müssen Sie die Zeichenfolgenform eines Quaternions (z. B. "1+2i-3j-4k") in eine Liste / ein Array von Koeffizienten (z. B. [1 2 -3 -4]) zerlegen . Die Quaternion-Zeichenfolge kann jedoch auf viele verschiedene Arten formatiert werden ...

  • Es kann normal sein: 1+2i-3j-4k
  • Es können fehlende Begriffe: 1-3k, 2i-4k(Wenn Sie fehlende Begriffe, Ausgabe 0für diese Begriffe)
  • Es kann hat Koeffizienten fehlen: i+j-k(In diesem Fall ist dies gleichbedeutend mit 1i+1j-1kanderen Worten, a. i, jOder kohne eine Zahl vor angenommen wird , eine haben , 1standardmäßig vor)
  • Möglicherweise ist die Reihenfolge nicht richtig: 2i-1+3k-4j
  • Die Koeffizienten können einfache Ganzzahlen oder Dezimalzahlen sein: 7-2.4i+3.75j-4.0k

Beim Parsen sind einige Dinge zu beachten:

  • Es wird immer ein +oder -zwischen den Begriffen geben
  • Sie erhalten immer eine gültige Eingabe mit mindestens einem Begriff und ohne wiederholte Buchstaben (keine j-j).
  • Es kann davon ausgegangen werden, dass alle Zahlen gültig sind
  • Sie können Zahlen in einer anderen Form ändern , nachdem das Parsen , wenn Sie wollen (ex. 3.0 => 3, 0.4 => .4, 7 => 7.0)

Parsing / Quaternion-Builtins und Standard-Lücken sind nicht zulässig. Dies beinhaltet evalSchlüsselwörter und Funktionen. Die Eingabe ist eine einzelne Zeichenfolge, und die Ausgabe ist eine Liste, ein Array, durch Leerzeichen getrennte Werte usw.

Da es sich um , kürzeste Code in Bytes gewinnt.

Tonnenweise Testfälle

1+2i+3j+4k             => [1 2 3 4]
-1+3i-3j+7k            => [-1 3 -3 7]
-1-4i-9j-2k            => [-1 -4 -9 -2]
17-16i-15j-14k         => [17 -16 -15 -14]

7+2i                   => [7 2 0 0]
2i-6k                  => [0 2 0 -6]
1-5j+2k                => [1 0 -5 2]
3+4i-9k                => [3 4 0 -9]

42i+j-k                => [0 42 1 -1]
6-2i+j-3k              => [6 -2 1 -3]
1+i+j+k                => [1 1 1 1]
-1-i-j-k               => [-1 -1 -1 -1]

16k-20j+2i-7           => [-7 2 -20 16]
i+4k-3j+2              => [2 1 -3 4]
5k-2i+9+3j             => [9 -2 3 5]
5k-2j+3                => [3 0 -2 5]

1.75-1.75i-1.75j-1.75k => [1.75 -1.75 -1.75 -1.75]
2.0j-3k+0.47i-13       => [-13 0.47 2.0 -3] or [-13 .47 2 -3]
5.6-3i                 => [5.6 -3 0 0]
k-7.6i                 => [0 -7.6 0 1]

0                      => [0 0 0 0]
0j+0k                  => [0 0 0 0]
-0j                    => [0 0 0 0] or [0 0 -0 0]
1-0k                   => [1 0 0 0] or [1 0 0 -0]

Wird es jemals unnötige +Zeichen in der Eingabe geben? Wie +1k:?
FryAmTheEggman

@FryAmTheEggman Nr. Eingaben werden niemals mit a beginnen +.
GamrCorps

1
Ist -0ein Teil der rechtlichen Ergebnisse für die letzten beiden Beispiele?
Isaacg

1
@isaacg ja, das ist in Ordnung
GamrCorps

1
@LLlAMnYP Sie sprechen einen guten Punkt an. Definieren Sie die evalEinschränkung, die in einer Zeichenfolge verwendet werden soll, und interpretieren Sie diese als Code und / oder Eingabe. Alle Konvertierungen zählen nicht darunter, weil Sie beispielsweise die Zeichenfolge nicht "test"an eine Ganzzahl-Konvertierungsfunktion übergeben können, um eine Ganzzahl zu erhalten, sondern testin einer normalen evalFunktion als Code interpretiert würden . TLDR: eval: nein, Typkonvertierungen: ja.
GamrCorps

Antworten:


5

Pyth, 48 Bytes

jm+Wg\-K--e|d0G\+K1+]-I#GJczfT.e*k<b\.zm/#dJ"ijk

Demonstration Testsuite

Das Ausgabeformat ist durch Zeilenumbrüche getrennt. Der Code der Testsuite verwendet eine Leerzeichen-Trennung, um das Lesen zu erleichtern, ist aber ansonsten derselbe.

Gibt -0in den letzten 2 Fällen ein aus, was ich hoffe ist OK.

Erklärung folgt.


9

Retina, 115

\b[ijk]
1$&
^(?!.*\d([+-]|$))
0+
^(?!.*i)
+0i+
^(?!.*j)
0j+
^(?!.*k)
0k+
O$`[+-]*[\d.]*(\w?)
$1
-
+-
^\+

S`[ijk+]+

Probieren Sie es online!

Dank @Chris Jester-Young 1 Byte gespart .

Ein Bug behoben und 6 Bytes gespart dank @Martin Büttner

Es wurden einige Fehler gefunden, die einige Randfälle betrafen.

Gibt die durch Zeilenumbrüche getrennten Zahlen zurück. Wie auch immer, dies ist eine meist elegante Lösung, die durch Kantenfälle ruiniert wird, aber hey, ich muss den Sortiermodus verwenden, das heißt, ich habe das richtige Werkzeug für den Job verwendet, oder?

Erläuterung:

Schritt für Schritt, wie immer.

\b[ijk]
1$&

Die einzigen Zeichen in der Eingabe, die Wortgrenzen erstellen können, sind -+.. Das heißt, wenn wir eine Grenze finden, der ein Buchstabe folgt, haben wir einen Implizit, 1den wir mit der Ersetzung hinzufügen. $&ist ein Synonym für $0.

^(?!.*\d([+-]|$))
0+

Vielen Dank an Martin für diesen einen, dieser fügt den impliziten Teil 0für den Realteil hinzu, wenn er in der Eingabe fehlte. Wir stellen sicher, dass wir keine Zahl finden, auf die ein Plus- oder Minuszeichen oder das Ende der Zeichenfolge folgt. Alle komplexen Zahlen haben einen Buchstaben nach sich.

^(?!.*i)
+0i+

Die nächsten drei Stufen sind fast alle gleich, es sei denn, auf welchen Buchstaben sie sich auswirken. Alle sehen nach, ob wir den Buchstaben nicht finden können, und wenn wir ihn nicht finden können, fügen wir einen 0Begriff hinzu. Der einzige Grund, warum ies ein Extra gibt +, ist zu verhindern, dass der reale Wert mit dem is-Koeffizienten unlesbar wird. Die anderen Zahlen werden alle durch ihre komplexe Variable getrennt.

O$`[+-]*[\d.]*(\w?)
$1

Ah, der lustige Teil. Dies verwendet die neue Sortierstufe, die durch das OBacktick vor dem Optionstrennzeichen gekennzeichnet ist. Der Trick dabei ist, die ganze Zahl zu erfassen, gefolgt von einem optionalen Wortzeichen, das in diesem Fall immer nur einem von beiden entspricht ijk. Die andere verwendete Option $bewirkt, dass der zum Sortieren dieser Übereinstimmungen verwendete Wert der Ersatz ist. Hier verwenden wir nur den optionalen Buchstaben als Sortierwert. Da Retina standardmäßig lexikografisch sortiert, werden die Werte wie in einem Wörterbuch sortiert, was bedeutet, dass wir die Übereinstimmungen in der richtigen "", "i", "j", "k"Reihenfolge erhalten.

-
+-

Diese Phase setzt ein +Vorzeichen vor alle Minuszeichen. Dies ist erforderlich, wenn wir ispäter in der Teilungsphase einen negativen Wert für haben .

^ \ +

Wir entfernen die +führenden Zeilen, um sicherzustellen, dass keine zusätzlichen führenden Zeilen vorhanden sind.

S`[ijk+]+

Teilen Sie die verbleibenden Zeilen in Läufen der komplexen Variablen oder des Pluszeichens. Dies gibt uns einen Wert pro Zeile.


3

Perl 5, 125 Bytes

#!perl -p
%n=(h,0,i,0,j,0,k,0);$n{$4//h}=0+"$1@{[$3//$5//1]}"while/([+-]?)(([\d.]+)?([ijk])|([\d.]+))/g;s/.*/@n{qw(h i j k)}/

1
@KennyLau Leider entspricht Ihre vorgeschlagene Änderung nicht Ihren Erwartungen. Ich habe das versucht, bevor ich meine Antwort gepostet habe. ;-)
Chris Jester-Young

@KennyLau In Bezug auf diese vorgeschlagene Änderung\a stimmt Perl mit "Alarm" überein, nicht alphabetisch. Es gibt \wfür Wortzeichen (alphanumerisch und Unterstrich), aber das wird hier nicht funktionieren; Wir brauchen es nicht, um auf eine Zahl zu passen.
Chris Jester-Young

3
@KennyLau Übrigens, Sie haben genug Repräsentanten, um im Chat zu sprechen . Sie können dort auch Ideen diskutieren, anstatt Ihre Bearbeitungsvorschläge ständig abzulehnen. ;-)
Chris Jester-Young

Ich habe jetzt auch genug Repräsentanten, um Kommentare abzugeben. Hat Perl kein Muster für [az]?
Undichte Nonne

1
@KennyLau Meines Wissens nicht.
Chris Jester-Young

3

Lua , 185 187 195 183 166 Bytes ( online testen) [Regex verwendet]

Vielen Dank an @Chris Jester-Young für den verbesserten Regex.

Vielen Dank an @Katenkyo für die Reduzierung auf 166 Bytes.

Golf gespielt:

r={0,0,0,0}for u in(...):gsub("([+-])(%a)","%11%2"):gmatch("-?[%d.]+%a?")do n,i=u:match("(.+)(%a)")r[i and(" ijk"):find(i)or 1]=(n or u)end print(table.concat(r," "))

Ungolfed:

n = "42i+j-k+0.7"

result = {0,0,0,0}

for unit in n:gsub("([+-])(%a)","%11%2"):gmatch("-?[%d.]+%a?") do
  num, index = unit:match("(.+)(%a)")
  if index == "i" then
    result[2] = num
  elseif index == "j" then
    result[3] = num
  elseif index == "k" then
    result[4] = num
  else
    result[1] = unit
  end
end

print(table.concat(result," "))

2
Hallo Kenny, danke für die Lösung. Normalerweise lassen wir die Eingabe nicht in einer Variablen beginnen (wie nin diesem Fall), daher sollten Sie den Code hinzufügen, um die Eingabe zu lesen.
Isaacg

Sie sollten in der Lage sein, einige Bytes zu speichern, indem Sie Ihre Eingabe von STDIN in argument ändern, anstatt io.read()use zu verwenden (...). Es wird auf das erste Befehlszeilenargument verweisen und Sie können 4 weitere Bytes speichern :)
Katenkyo

1
Außerdem kann die angeforderte Ausgabe beliebig sein, solange sie von Menschen als Liste interpretiert werden kann, sodass Sie die zusätzliche Formatierung entfernen können. Einschließlich einiger weiterer Whitespaces, die Sie abschneiden können, kann Ihr Code auf 166 Bytes r={0,0,0,0}for u in(...):gsub("([+-])(%a)","%11%2"):gmatch("-?[%d.]+%a?")do n,i=u:match("(.+)(%a)")r[i and(" ijk"):find(i)or 1]=(n or u)end print(table.concat(r," "))
sinken

3

C 236 Bytes

char j,n[9][9],s[9],y[9],i=8,k,*p=n[8];main(c){for(**n=48;c=getchar(),c+1;)c-32&&(c<46&&(k&&(y[1]=i),k=0,s[--i]=c-43,p=n[i])||c>57&&(k||(*p=49),k=0,y[c-103]=i)||(*p++=c,k=1));for(k&&(y[1]=i);++j<5;)printf("%c%s ",s[y[j]]?45:0,n[y[j]]);}

(Bei Werten wie -0 oder -0.0 wird das Minuszeichen auch in der Ausgabe ausgegeben. Da die Abfrage jedoch besagt, dass "Sie Zahlen nach dem Parsen in eine andere Form ändern können, wenn Sie möchten", und wenn -0 in der Eingabe angezeigt wird, Daraus folgt, dass es auch in der Ausgabe akzeptabel ist . @GamrCorps hat jetzt klargestellt, dass dies in Ordnung ist.)


3

JavaScript (ES6), 103 100 Bytes

f=s=>s.replace(/(?=.)(\+|-|)([\d.]*)(\w?)/g,(_,s,x,c)=>a[c.charCodeAt()&3]=+(s+(x||1)),a=[0,0,0,0])&&a

Bearbeiten: 3 Bytes durch Umschalten von parseIntauf gespeichert charCodeAt, was praktisch ist &3, um mir den richtigen Array-Index zu beschaffen.


Schöne Idee parseInt + mod. Nachdenken über Basis und Präfix
edc65

1

JavaScript (ES6) 106

s=>(s.replace(/([+-]?)([\d.]*)(\w?)/g,(a,b,c,d)=>a&&(s[d||9]=b+(c||1)),s={}),[...'9ijk'].map(i=>+s[i]||0))

Prüfung

f=s=>(s.replace(/([+-]?)([\d.]*)(\w?)/g,(a,b,c,d)=>a&&(s[d||9]=b+(c||1)),s={}),[...'9ijk'].map(i=>+s[i]||0))

function Test()
{
  var t,k,r,ts=TS.value.split('\n')
  
  O.textContent=ts.map(x=>x.trim()&&(
    [t,k]=x.split('=>').map(x=>x.trim()),
    console.log(t,'*',k),
    k=k.match(/[\d+-.]+/g).map(x=>+x),
    r=f(t),
    t+' => '+r+(r+''==k+''?' OK':' KO (check: '+k+')')
  )).join('\n')
}    

Test()
#TS { width:90%; height:10em}
<pre id=O></pre>

Test data (modify if you like)<button onclick='Test()'>repeat test</button>
<textarea id=TS>
1+2i+3j+4k             => [1 2 3 4]
-1+3i-3j+7k            => [-1 3 -3 7]
-1-4i-9j-2k            => [-1 -4 -9 -2]
17-16i-15j-14k         => [17 -16 -15 -14]
  
7+2i                   => [7 2 0 0]
2i-6k                  => [0 2 0 -6]
1-5j+2k                => [1 0 -5 2]
3+4i-9k                => [3 4 0 -9]
  
42i+j-k                => [0 42 1 -1]
6-2i+j-3k              => [6 -2 1 -3]
1+i+j+k                => [1 1 1 1]
-1-i-j-k               => [-1 -1 -1 -1]
  
16k-20j+2i-7           => [-7 2 -20 16]
i+4k-3j+2              => [2 1 -3 4]
5k-2i+9+3j             => [9 -2 3 5]
5k-2j+3                => [3 0 -2 5]
  
1.75-1.75i-1.75j-1.75k => [1.75 -1.75 -1.75 -1.75]
2.0j-3k+0.47i-13       => [-13 0.47 2.0 -3]
5.6-3i                 => [5.6 -3 0 0]
k-7.6i                 => [0 -7.6 0 1]
  
0                      => [0 0 0 0]
0j+0k                  => [0 0 0 0]
-0j                    => [0 0 0 0]
1-0k                   => [1 0 0 0]
</textarea>


0

PowerShell, 178 Byte

param($a);$p="(-?)([\d.]+)?";$g={param($s)if($a-match"$p$s"){if(($r=$matches)[2]){$r[1]+$r[2]}else{$r[1]+1}}else{0}};$a-match"$p(\+|-|$)">$null;+$matches[2];"i","j","k"|%{&$g $_}

Ungolfed mit Erklärung

# Get the whole string into a variable
param($a)
# Pattern shared getting both imaginary and real numbers. 
$p="(-?)([\d.]+)?"
# Anonymous function that will locate a imaginary number using a letter sent as a parameter. 
# If no value is assigned a signed 1 is returned. If no value is matched 0 is returned
$g={param($s)if($a-match"$p$s"){if(($r=$matches)[2]){$r[1]+$r[2]}else{$r[1]+1}}else{0}}
# Locate the real component if any. Null is converted to 0
$a-match"$p(\+|-|$)">$null;+$matches[2]
# Call the anonymous function using each of the imaginary suffixes.                                               
"i","j","k"|%{&$g $_}

Nicht super beeindruckt, aber es ist trotzdem ein Ergebnis.


0

PHP, 179 Bytes

$a=[''=>0,'i'=> 0,'j'=>0,'k'=>0];preg_match_all("/([-+]?)(\d*(\.\d+)?)([ijk]?)/",$argv[1],$m,2);foreach($m as$n)if($n[0])$a[$n[4]]=$n[1].($n[2]===''?1:$n[2]);echo implode(',',$a);

Probieren Sie die Testsuite aus .


0

Python 3.5 - 496 Bytes [mit regulären Ausdrücken]:

from re import*
def wq(r):
 a=sub('[+](?![0-9])','+1',sub('[-](?![0-9])','-1',r));q=lambda x:(not x.isdigit(),''.join(filter(str.isalpha,x)))
 for z in findall('(?<![0-9])[a-z]',a):a=a.replace(z,('+1{}'.format(z)))
 if not str(sorted(((sub('[.]','',sub('[+-]',' ',a))).split(' ')),key=q)[0]).isdigit():a+='+0, '
 for i in list(set(findall('[a-z]',a))^{'i','j','k'}):a+='+0{}, '.format(i)
 print(findall('[-]?\d+(?:\.\d+)?',''.join(sorted(sub('(?<=[A-Za-z0-9])(?=[+-])',', ',a).split(' '),key=q))))

Es mag lange dauern, aber zu meiner Verteidigung funktioniert es perfekt, um das zu tun, was das OP will, da alle angegebenen Testfälle mit meinem Code erfolgreich waren.

Ungolfed-Version mit Erklärung:

from re import*
def w(r):
    # Substitute all minus (-) and plus (+) signs NOT followed by a number  (if there are any) with a "-1"/"+1", respectively.
    a=sub('[+](?![0-9])','+1',sub('[-](?![0-9])','-1',r))
    # Lambda function created for later use to sort the Quaternion. This function, when given as a key to the "sorted" function, arranges the input Quaternion in the order where the whole number comes first, and then the rest are placed in order of increasing letter value (i,j,k in this case) 
    q=lambda x:(not x.isdigit(),''.join(filter(str.isalpha,x)))
    # The following "for" loop replaces the letters NOT preceded by a number with a one followed by that letter
    for z in findall('(?<![0-9])[a-z]',a):
        a=a.replace(z,('+1{}'.format(z)))
    # The following first substitutes all pluses and minuses (+ and -) with a space, and then that new string is split at those spaces, and returned as a list. After that, the list is sorted according the the "lambda" function shown above. Then, the first item in that list, which is supposed to be a lone number, is checked to make sure that it indeed is a lone number. If it isn't, then "+0, " is appended to the Quaternion. 
    if not str(sorted(((sub('[.]','',sub('[+-]',' ',a))).split(' ')),key=q)[0]).isdigit():
        a+='+0, '
    # The following "for" loop finds ALL the letters NOT in the list, by finding the symmetric difference between a set of all the letters found, and a set containing all the letters needed. For the letters not in the list, a '+0' is added the quaternion, followed by that letter, and then a comma and a space.
    for i in list(set(findall('[a-z]',a))^{'i','j','k'}):
        a+='+0{}, '.format(i)
    # Finally, in this last step, a ", " is added IN BETWEEN unicode characters and pluses/minuses (+/-). Then, it splits at those spaces, and the commas separate different parts of the Quaternion from each other (otherwise, you would get something like `12i+3j+4k` from `2i+3j+4k+1`) in a returned list. Then, that list is sorted according to the lambda expression "q" (above), and then, finally, the NUMBERS (of any type, courtesy to Regex) are extracted from that joined list, and printed out in the correct order.
    print(findall('[-]?\d+(?:\.\d+)?',''.join(sorted(sub('(?<=[A-Za-z0-9])(?=[+-])',', ',a).split(' '),key=q))))

Wenn das oben Genannte etwas zu schwer zu lesen ist, geschieht im Grunde Folgendes:

  1. Falls vorhanden, werden alle + oder - Zeichen, denen KEINE Zahl folgt, durch "+1" / "- 1" ersetzt.

  2. Es lambdaist eine Funktion definiert, die bei Verwendung in einer sortedFunktion als Schlüssel die Liste nach der ersten Ganzzahl sortiert und den Rest in aufsteigender Reihenfolge der Buchstaben sortiert ("i", dann "j", dann "k"). in diesem Fall).

  3. Die Quaternion, in der jetzt bei Bedarf alle +/- Zeichen durch eine 1 ersetzt sind, wird unter Verwendung regulärer Ausdrücke nach ALLEN Buchstaben durchsucht, denen NICHT mindestens eine Ziffer vorausgeht, und die übereinstimmenden Buchstaben werden durch ein "+1" gefolgt von ersetzt dieser Brief.

  4. Die "if" -Anweisung ersetzt dann ALL +/- -Zeichen durch ein Leerzeichen, und das geänderte Quaternion wird nun an diesen Leerzeichen "aufgeteilt" und in einer Liste zurückgegeben. Anschließend wird die Liste nach der zuvor erläuterten Lambda-Funktion sortiert. Schließlich wird das erste Element in dieser Liste überprüft, um sicherzustellen, dass es sich um eine Zahl handelt, da dies der Fall sein soll. Wenn dies nicht der Fall ist, wird der Quaternion ein "+0" hinzugefügt.

  5. Die zweite "for" -Schleife findet ALLE Buchstaben, die NICHT in der Quaternion enthalten sind, indem eine symmetrische Differenz zwischen einer Menge der im Ausdruck gefundenen Buchstaben und einer Menge mit allen erforderlichen Buchstaben ermittelt wird. Wenn welche gefunden werden, wird ein "+0" gefolgt vom fehlenden Buchstaben und einem Leerzeichen zum Quaternion hinzugefügt.

  6. Schließlich wird in diesem letzten Schritt zwischen jedem Zeichen ein "," gefolgt von einem +/- Symbol eingefügt. Anschließend wird die Quaternion an diesen Stellen aufgeteilt. Anschließend wird die zurückgegebene Liste zum letzten Mal nach sortiert Lambda-Funktion wurde früher als "q" definiert. Die Kommas im Ausdruck trennen jeden Teil des Quaternions (andernfalls erhalten Sie so etwas wie 14i+5j+6kvon 4i+5j+6k+1). Zuletzt wird diese nun sortierte Liste zu einer Zeichenfolge zusammengefügt, und nur die Zahlen eines beliebigen Typs (mit freundlicher Genehmigung von regulären Ausdrücken) werden extrahiert und schließlich jedes Mal in der richtigen Reihenfolge in einer Liste zurückgegeben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.