Pisahkan Kuarter


27

Jika Anda belum tahu, angka empat pada dasarnya adalah nomor 4 bagian. Untuk keperluan tantangan ini, ia memiliki komponen nyata dan tiga komponen imajiner . Komponen imajiner yang diwakili oleh akhiran i, j, k. Sebagai contoh, 1-2i+3j-4kadalah angka empat dengan 1menjadi komponen nyata dan -2, 3, dan -4menjadi komponen imajiner.

Dalam tantangan ini, Anda harus menguraikan bentuk string dari angka empat (mis. "1+2i-3j-4k") Ke daftar / array koefisien (mis. [1 2 -3 -4]). Namun, string angka empat dapat diformat dalam berbagai cara ...

  • Mungkin normal: 1+2i-3j-4k
  • Ini mungkin memiliki istilah yang hilang: 1-3k, 2i-4k(Jika Anda memiliki istilah hilang, keluaran 0untuk istilah tersebut)
  • Mungkin hilang koefisien: i+j-k(Dalam hal ini, ini setara dengan 1i+1j-1kkata lain, a. i, j, Atau ktanpa nomor di depan diasumsikan memiliki 1di depan secara default)
  • Itu mungkin tidak dalam urutan yang benar: 2i-1+3k-4j
  • Koefisien mungkin hanya bilangan bulat atau desimal: 7-2.4i+3.75j-4.0k

Ada beberapa hal yang perlu diperhatikan saat parsing:

  • Akan selalu ada +atau -antara istilah
  • Anda akan selalu melewati input yang valid dengan setidaknya 1 istilah, dan tanpa huruf yang diulang (tidak ada j-j)
  • Semua angka dapat dianggap valid
  • Anda dapat mengubah nomor ke dalam bentuk lain setelah parsing jika Anda ingin (ex. 3.0 => 3, 0.4 => .4, 7 => 7.0)

Parsing / angka empat builtinion dan lubang standar tidak diizinkan. Ini termasuk evalkata kunci dan fungsi. Input akan berupa string tunggal dan output akan berupa daftar, array, nilai yang dipisahkan oleh spasi, dll.

Karena ini adalah , kode terpendek dalam byte menang.

Banyak kasus uji

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]

Apakah akan ada +tanda-tanda yang tidak perlu dalam input? Suka +1k:?
FryAmTheEggman

Input @FryAmTheEggman No. tidak akan pernah dimulai dengan a +.
GamrCorps

1
Apakah -0bagian dari hasil hukum untuk dua contoh terakhir?
isaacg

1
@isaacg ya itu baik
GamrCorps

1
@ LLLAMnYP Anda membawa poin yang bagus. Mari kita tentukan evalbatasan yang harus diambil dalam sebuah string, diartikan sebagai kode dan / atau input. Konversi apa pun tidak dihitung di bawah ini karena Anda tidak dapat meneruskan, misalnya, string "test"ke fungsi konversi integer untuk menerima integer, tetapi testakan ditafsirkan sebagai kode dalam evalfungsi normal . TLDR: eval: tidak, ketik konversi: ya.
GamrCorps

Jawaban:


5

Pyth, 48 byte

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

Paket Tes Demonstrasi

Format output dipisahkan oleh baris baru. Kode test suite menggunakan pemisahan ruang, untuk kemudahan membaca, tetapi sebaliknya sama.

Keluaran -0dalam 2 kasus terakhir, yang saya harap tidak apa-apa.

Penjelasan untuk diikuti.


9

Retina, 115

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

S`[ijk+]+

Cobalah online!

1 byte disimpan berkat @Chris Jester-Young .

Bug diperbaiki dan 6 byte disimpan berkat @Martin Büttner

Menemukan beberapa bug yang melibatkan beberapa kasus tepi, menumbuhkan jumlah byte cukup sedikit.

Mengembalikan angka yang dipisahkan baris baru. Ngomong-ngomong, ini memiliki solusi yang sebagian besar anggun seperti rusak oleh kasus tepi tapi hei saya harus menggunakan mode pengurutan, itu berarti saya menggunakan alat yang tepat untuk pekerjaan itu, kan?

Penjelasan:

Tahap demi tahap, seperti biasa.

\b[ijk]
1$&

Satu-satunya karakter dalam input yang dapat membuat batas kata adalah -+.. Ini berarti bahwa jika kami menemukan batas diikuti oleh surat, kami memiliki implisit 1yang kami tambahkan dengan penggantian. $&adalah sinonim untuk $0.

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

Terima kasih banyak untuk Martin untuk yang ini, yang ini menambahkan secara implisit 0untuk bagian yang sebenarnya jika tidak ada dalam input. Kami memastikan bahwa kami tidak dapat menemukan angka yang diikuti oleh tanda plus atau minus, atau akhir dari string. Semua bilangan kompleks akan memiliki surat setelahnya.

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

3 tahap selanjutnya semuanya hampir sama, kecuali huruf mana yang berdampak. Semuanya terlihat untuk melihat apakah kami tidak dapat mencocokkan surat itu, dan jika kami tidak bisa, kami menambahkan 0istilah untuk itu. Satu-satunya alasan imemiliki tambahan +sebelum itu adalah untuk mencegah nilai riil tidak dapat dibaca dengan ikoefisien s, angka-angka lainnya semuanya dipisahkan oleh variabel kompleksnya.

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

Ah, bagian yang menyenangkan. Ini menggunakan tahap sortir agak baru, dilambangkan dengan Osebelum backtick pemisah opsi. Kuncinya di sini adalah untuk mengambil seluruh angka diikuti secara opsional oleh karakter kata, yang dalam hal ini hanya akan cocok dengan salah satunya ijk. Opsi lain yang digunakan adalah $yang menyebabkan nilai yang digunakan untuk mengurutkan kecocokan ini menjadi penggantinya. Di sini kita hanya menggunakan huruf opsional yang tersisa sebagai nilai sortir kami. Karena Retina mengurutkan secara leksikografis secara default, nilai-nilai diurutkan seperti di kamus, artinya kami mendapatkan kecocokan secara "", "i", "j", "k"berurutan.

-
+-

Tahap ini menempatkan +tanda di depan semua tanda minus, ini diperlukan jika kita memiliki nilai negatif untuk idi tahap pemisahan, nanti.

^ \ +

Kami menghapus pimpinan +untuk memastikan kami tidak memiliki baris baru pemimpin tambahan.

S`[ijk+]+

Pisahkan garis yang tersisa pada menjalankan variabel kompleks atau tanda plus Ini dengan baik memberi kita satu nilai per baris.


3

Perl 5, 125 byte

#!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 Sedihnya, perubahan yang Anda usulkan tidak melakukan apa yang Anda harapkan. Saya sudah mencobanya sebelum saya memposting jawaban saya. ;-)
Chris Jester-Young

@ KennyLau Mengenai perubahan yang diajukan ini , Perl \acocok dengan "alarm", bukan alfabet. Ada \wuntuk karakter-kata (alfanumerik dan garis bawah), tetapi itu tidak akan berfungsi di sini; kita membutuhkannya agar tidak cocok dengan angka.
Chris Jester-Young

3
@ KennyLau BTW, Anda memiliki cukup perwakilan untuk berbicara dalam obrolan . Jangan ragu untuk mendiskusikan ide di sana, daripada terus-menerus menerima saran edit Anda. ;-)
Chris Jester-Young

Saya juga punya cukup perwakilan untuk berkomentar sekarang. Apakah Perl tidak memiliki pola untuk [az]?
Leaky Nun

1
@ KennyLau Tidak sepengetahuan saya.
Chris Jester-Young

3

Lua , 185 187 195 183 166 byte ( coba online ) [digunakan regex]

Terima kasih kepada @Chris Jester-Young untuk regex yang ditingkatkan.

Terimakasih untuk @Katenkyo karena membawanya ke 166 byte.

Golf:

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

Tidak Disatukan:

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
Hai Kenny, terima kasih atas solusinya. Biasanya kami tidak mengizinkan input dimulai dari variabel (seperti ndalam kasus ini), jadi Anda harus menambahkan kode untuk membaca input.
isaacg

Anda harus dapat menyimpan beberapa byte dengan mengubah input dari STDIN ke argumen, alih-alih io.read(), gunakan (...). Ini akan mengarah ke argumen command-line pertama dan akan memungkinkan Anda untuk menyimpan 4 byte lagi :)
Katenkyo

1
Juga, output yang diminta dapat berupa apa saja, selama itu dapat diinterpretasikan oleh manusia sebagai daftar, sehingga Anda dapat menghapus format tambahan. Termasuk beberapa spasi putih yang bisa Anda hilangkan, kode Anda bisa turun menjadi 166 byte ->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," "))
Katenkyo

3

C, 236 byte

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

(Untuk nilai-nilai seperti -0 atau -0.0, tanda minus juga dicetak dalam output, tetapi karena tantangan menyatakan bahwa "Anda dapat mengubah angka menjadi bentuk lain setelah parsing jika Anda mau", dan jika -0 muncul di input, karena itu juga dapat diterima di output. @GamrCorps sekarang telah mengklarifikasi bahwa ini ok.)


3

JavaScript (ES6), 103 100 byte

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

Sunting: Disimpan 3 byte dengan beralih dari parseIntke charCodeAt, yang nyaman hanya perlu &3membuat saya indeks array yang benar.


Ide bagus parseInt + mod. Berpikir tentang basis dan awalan
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))

Uji

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

Tidak Digabungkan dengan Penjelasan

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

Tidak super terkesan tapi tetap saja hasilnya.


0

PHP, 179 byte

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

Coba test suite .


0

Python 3.5 - 496 byte [menggunakan Ekspresi Reguler]:

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

Ini mungkin lama, tetapi dalam pembelaan saya, ia bekerja dengan sempurna dalam melakukan apa yang diinginkan OP, karena semua kasus uji yang diberikan berhasil menggunakan kode saya.

Versi tidak dikoleksi dengan penjelasan termasuk:

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

Jika hal di atas agak terlalu sulit untuk dibaca, pada dasarnya yang terjadi adalah:

  1. Jika ada, semua tanda + atau - yang TIDAK diikuti oleh angka diganti dengan "+1" / "- 1", secara berurutan.

  2. Suatu lambdafungsi didefinisikan, yang bila digunakan dalam asorted fungsi sebagai kunci, mengurutkan daftar sesuai dengan menempatkan seluruh angka terlebih dahulu, dan kemudian memerintahkan sisanya dalam meningkatkan nilai huruf ("i", lalu "j", lalu "k" dalam hal ini).

  3. Quaternion, sekarang semua tanda +/- diganti dengan 1 jika perlu, dicari, menggunakan Ekspresi Reguler, untuk SEMUA huruf TIDAK didahului dengan setidaknya satu nomor, dan huruf-huruf yang cocok diganti dengan "+1" diikuti oleh surat itu.

  4. Pernyataan "jika" kemudian menggantikan tanda SEMUA +/- dengan spasi, dan kemudian Quaternion yang dimodifikasi sekarang "terpecah" di spasi tersebut, dan dikembalikan dalam daftar. Kemudian, daftar diurutkan sesuai dengan fungsi lambda yang dijelaskan sebelumnya. Akhirnya, item pertama dalam daftar itu dicentang untuk memastikan itu nomor, karena memang seharusnya begitu, dan jika tidak, maka "+0" ditambahkan ke Quaternion.

  5. Lingkaran "untuk" yang kedua menemukan SEMUA huruf BUKAN dalam Quaternion dengan menemukan perbedaan simetris antara seperangkat huruf-huruf yang ditemukan dalam ekspresi, dan kemudian satu set termasuk semua huruf yang diperlukan. Jika ada yang ditemukan, maka "+0" diikuti dengan huruf yang hilang dan spasi ditambahkan ke Quaternion.

  6. Akhirnya, pada langkah terakhir ini, "," ditambahkan di antara masing - masing karakter diikuti oleh simbol +/-, dan kemudian Quaternion dibagi di ruang-ruang tersebut, kemudian daftar yang dikembalikan diurutkan, untuk yang terakhir kalinya, sesuai dengan fungsi lambda didefinisikan sebagai "q" sebelumnya. Koma dalam ekspresi memisahkan setiap bagian dari angka empat (jika tidak, Anda akan mendapatkan sesuatu 14i+5j+6kdari 4i+5j+6k+1). Terakhir, daftar yang sekarang disortir ini digabungkan menjadi satu string, dan hanya angka dari jenis apa pun (milik Ekspresi Reguler) yang diekstraksi, dan akhirnya dikembalikan dalam daftar, dalam urutan yang benar, setiap saat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.