Bir Kuaterniyon Ayrıştırma


27

Zaten bilmiyorsanız, bir kuaterniyon temel olarak 4 parçalı bir sayıdır. Bu zorluğun amaçları doğrultusunda, gerçek bir bileşene ve üç hayali bileşene sahiptir. Sanal bileşenlerinin son takı ile temsil edilir i, j, k. Örneğin, 1-2i+3j-4kbir Dördey olan 1gerçek bileşeni olan ve -2, 3ve -4sanal bileşenlerini olmak.

Bu zorlukta, bir kuaterniyonun (ör. "1+2i-3j-4k") Dize şeklini bir katsayılar listesi / dizisine (ör. ) Ayrıştırmanız gerekir [1 2 -3 -4]. Ancak, kuaterniyon dizgisi birçok farklı şekilde biçimlendirilebilir ...

  • Normal olabilir: 1+2i-3j-4k
  • Bu eksik şartları olabileceğini: 1-3k, 2i-4k(eksik terimleri varsa, çıktı 0bu terimleri)
  • Bu katsayıları eksik olabilir: i+j-k(Bu durumda, bu eşdeğerdir 1i+1j-1kBir başka deyişle, bir. i, jYa da könünde bir sayı olduğu varsayılır olmadan 1varsayılan olarak ön)
  • Doğru sırada olmayabilir: 2i-1+3k-4j
  • Katsayılar sadece tamsayılar veya ondalık sayılar olabilir: 7-2.4i+3.75j-4.0k

Ayrıştırırken dikkat edilmesi gereken bazı şeyler var:

  • Her zaman bir +veya -arasında terimler olacak
  • Her zaman en az 1 terimle geçerli girdi geçti ve tekrarlanan harfler (hayır olmadan edilecek j-jler)
  • Tüm numaraların geçerli olduğu varsayılabilir
  • İsterseniz ayrıştırma sonra başka forma numaralarını değiştirebilirsiniz (ex. 3.0 => 3, 0.4 => .4, 7 => 7.0)

Ayrıştırma / kuaterniyon yerleşikleri ve standart boşluklar izin verilmez. Bu evalanahtar kelimeler ve fonksiyonlar içerir . Giriş tek bir dize olacak ve çıktı bir liste, bir dizi, boşlukla ayrılmış değerler vb. Olacaktır.

Bu , bayt cinsinden en kısa kod kazanır.

Tonlarca test davası

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]

Girdide gereksiz +işaretler olacak mı? Gibi: +1k?
FryAmTheEggman

@FryAmTheEggman No. girişleri asla bir ile başlamaz +.
GamrCorps,

1
-0Son iki örnek için yasal çıktının bir parçası mı ?
isaacg

1
@ isaacg evet bu iyi
GamrCorps

1
@LLlAMnYP İyi bir noktaya değindiniz. evalBir dizgede alınacak kısıtlamayı tanımlayalım, kod ve / veya girdi olarak yorumlayalım. Örneğin, "test"bir tamsayı almak için bir tamsayı dönüştürme işlevine dize iletilemediğinden, testnormal bir evalişlevde kod olarak yorumlanacağından, herhangi bir dönüşüm sayılmaz . TLDR: eval: hayır, tür dönüşümleri: evet.
GamrCorps

Yanıtlar:


5

Pyth, 48 bayt

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

Gösteri test paketi

Çıkış formatı newline ayrılmış. Test paketi kodu, okuma kolaylığı için boşluk ayırmayı kullanır, ancak aynıdır.

Çıktığım -0son 2 davada bir sonuç çıktığını umuyorum.

Takip edilecek açıklama.


9

Retina, 115

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

S`[ijk+]+

Çevrimiçi deneyin!

@Chris Jester-Young sayesinde 1 bayt kurtarıldı .

@Martin Büttner sayesinde bir hata düzeltildi ve 6 bayt kurtarıldı

Bazı kenar durumları içeren bir kaç hata bulundu, çarptı bayt sayısı biraz.

Ayrılan yeni satırı döndürür. Her neyse, bunun son durumlardan mahrum kalması için daha zarif bir çözümü var ama hey sıralama modunu kullanmalıyım, bu da iş için doğru aracı kullandım, değil mi?

Açıklama:

Her zamanki gibi, aşama aşama aşama.

\b[ijk]
1$&

Girişte sözcük sınırları oluşturabilen tek karakterler -+.. Bu, mektubu izleyen bir sınır 1bulursak, yerine yenisini ekleyeceğimiz bir örtüklüğümüz olduğu anlamına gelir . $&eşanlamlıdır $0.

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

Bunun için Martin'e çok teşekkürler, bu 0girdide eksik olsaydı, asıl kısmı örtük olarak ekliyor . Artı veya eksi işareti tarafından izlenen bir sayı veya dizenin sonu bulamadığımızdan emin oluruz. Tüm karmaşık sayılar onlardan sonra bir harf alacak.

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

Sonraki 3 aşama, hangi mektubu etkilediklerini engellemekle hemen hemen aynı. Hepsi, mektubu eşleştirip eşleştiremeyeceğimizi göremez ve bunun için bir 0terim ekleyemezsek . Bunun tek nedeni i, +gerçek değerin is katsayısı ile okunamaz hale gelmesini önlemektir , diğer tüm sayılar karmaşık değişkenleriyle ayrılır.

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

Ah, eğlenceli kısım. Bu O, seçenek ayırıcı backtickinden önce gösterilen newish sort aşamasını kullanır . Buradaki hile isteğe bağlı olarak takip edilen sayının tamamını, bu durumda sadece biriyle eşleşecek olan bir kelime karakteriyle kapmaktır ijk. Kullanılan diğer seçenek, $bu eşleşmeleri sıralamak için kullanılan değerin yerine geçmesine neden olan seçenektir . Burada sadece sıralama değerimizde kalan isteğe bağlı harfi kullanırız. Retina varsayılan olarak sözlüksel olarak sıraladığından, değerler bir sözlükteki gibi sıralanır, bu da eşleşmeleri "", "i", "j", "k"sırayla alacağımız anlamına gelir .

-
+-

Bu aşama +tüm eksi işaretlerinin önüne bir işaret koyar i, daha sonra bölünmüş aşamada negatif bir değere sahip olmamız gerekiyorsa bu gereklidir .

^ \ +

+Fazladan lider yeni hattımız olmadığından emin olmak için lideri kaldırıyoruz .

S`[ijk+]+

Kalan satırları karmaşık değişkenlerin ya da artı işaretinin koşularında bölün. Bu, bize her satırda bir değer verir.


3

Perl 5, 125 bayt

#!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 Ne yazık ki, teklif ettiğiniz değişiklik beklediğiniz şeyi yapmıyor. Cevabımı göndermeden önce bunu denedim. ;-)
Chris Jester-Young

@KennyLau Bu önerilen değişiklik ile ilgili olarak , Perl \aalfabetik değil "alarm" ile eşleşiyor. Orada \wsözcük karakteri (alfanümerik ve alt çizgi) için, ama bu burada çalışmaz; bir sayıya uymamak için ona ihtiyacımız var.
Chris Jester-Young

3
@KennyLau BTW, sohbette konuşmak için yeterli sayıda temsilciniz var . Düzenleme önerilerinizi sürekli olarak reddetmek yerine, oradaki fikirleri tartışmaktan çekinmeyin. ;-)
Chris Jester-Young

Ayrıca şimdi yorum yapmak için yeterli sayıda temsilcim var. Perl'in [az] için kalıbı yok mu?
Çatlak Rahibe

1
@KennyLau Bildiğim kadarıyla değil.
Chris Jester-Young,

3

Lua , 185 187 195 183 166 bayt ( çevrimiçi dene ) [kullanılmış regex]

Geliştirilmiş regex için @ Chris Jester-Young teşekkürler .

166Kat'a getirdiği için @Katenkyo'ya teşekkürler .

golfed:

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
Merhaba Kenny, çözüm için teşekkürler. Genellikle girişin bir değişkende başlamasına izin vermiyoruz ( nbu durumda olduğu gibi ), bu yüzden girişi okumak için kodu eklemelisiniz.
isaacg

Sen yerine, argüman için STDIN'den girişinizi değiştirerek bazı byte kaydetmek gerekir io.read()kullanımı, (...). İlk komut satırı argümanını gösterecek ve 4 bayttan daha tasarruf etmenizi sağlayacaktır :)
Katenkyo

1
Ayrıca, istenen çıktı, insanlar tarafından bir liste olarak yorumlanabildiği sürece herhangi bir şey olabilir, bu yüzden fazladan biçimlendirmeyi kaldırabilirsiniz. Tıraş edebileceğiniz daha fazla beyaz alan dahil, kodunuz 166 bayta kadar 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," "))
çıkabilir

3

C, 236 bayt

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

(-0 veya -0 gibi değerler için, eksi işareti çıktıda da yazdırılır, ancak zorluk, "sayıları ayrıştırdıktan sonra başka bir forma değiştirebileceğinizi" belirtir ve girişte -0 göründüğünde, çıktıda da kabul edilebilir olduğunu takip ediyor. @GamrCorps şimdi bunun iyi olduğunu açıkladı.)


3

JavaScript (ES6), 103 100 bayt

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

Düzenleme: Kaydedilen 3 geçiş yaparak bayt parseIntiçin charCodeAtuygun sadece gereken bu özel &3bana doğru dizi dizinini alır.


Güzel fikir ayrıştırma + mod. Temel ve ön ek hakkında düşünme
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))

Ölçek

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 bayt

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 $_}

Açıklama ile Ungolfed

# 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 $_}

Süper etkilendim değil ama yine de bir sonuçtur.


0

PHP, 179 bayt

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

Test odasını dene .


0

Python 3.5 - 496 bayt [Normal İfadeler kullanarak]:

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

Uzun olabilir, ancak savunmamda OP'nin istediğini yapmada mükemmel çalışıyor, çünkü verilen tüm test durumları kodumu kullanarak başarılı oldu.

Açıklama ile Ungolfed versiyonu dahil:

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

Yukarıdakilerin okunması biraz zorsa, temelde olan şudur:

  1. Varsa, numaralardan sonra gelen tüm + veya - işaretleri sırasıyla "+1" / "- 1" ile değiştirilir.

  2. Bir lambdafonksiyonda sortedanahtar olarak kullanıldığında , listeyi önce tüm sayıyı koymaya göre sıralayan ve ardından kalanı artan harf değeriyle ("i", sonra "j", sonra "k" olarak sıralayan bir fonksiyon tanımlanır. bu durumda).

  3. Artık tüm +/- işaretlerinin gerektiğinde 1 ile değiştirilmesini sağlayan Quaternion, Normal İfadeler kullanılarak, en az bir rakamdan önce gelmeyen TÜM harfler için aranır ve eşleşen harfleri "+1" ile değiştirir. bu mektup.

  4. "İf" ifadesi daha sonra ALL +/- işaretlerini bir boşlukla değiştirir ve sonra değiştirilen Quaternion şimdi bu boşluklarda "bölünür" ve listeye geri döner. Ardından, liste daha önce açıklanan lambda fonksiyonuna göre sıralanır. Son olarak, bu listedeki ilk öğe bir sayı olduğundan emin olmak için kontrol edilir, çünkü olması gerektiği ve eğer değilse, Quaternion'a bir "+0" eklenir.

  5. "For" döngüsünün ikinci ifadesi, İfadede Bulunan Harflerin bir kümesi ve daha sonra gereken tüm harfleri içeren bir küme arasında simetrik bir fark bularak DÖRTÜNLÜK'deki TÜM harfleri bulur. Herhangi bir bulunursa, o zaman "+0" ve ardından eksik harf ile bir boşluk eklenir ve Kuvaterniyona bir boşluk eklenir.

  6. Son olarak, bu son adımda, bir +/- sembolünün ardından her karakterin arasına bir "," eklenir ve daha sonra Kuaterniyon bu boşluklara ayrılır, ardından geri dönen liste son kez sırasıyla Daha önce "q" olarak tanımlanan lambda işlevi. İfadesinde virgül (aksi takdirde, böyle bir şey almak olacaktır quaternion her parçası ayrı 14i+5j+6kitibaren 4i+5j+6k+1). Son olarak, şu an sıralı liste bir dize bir araya birleştirilir ve yalnızca sayılar her türlü (Normal İfade nezaket) çıkarılan ve son olarak doğru sırayla bir listede her seferinde geri gönderilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.