Ekspansi Aljabar Dasar

8

Masalah

Saya punya program baru HEBAT yang akan mengubah cara kita berpikir tentang matematika dalam komputasi, mengambil serangkaian fungsi aljabar dan melakukan hal-hal LUAR BIASA bersama mereka! Satu-satunya masalah, adalah bahwa saya hanya dapat menguraikan aljabar tertentu, jika tidak alam semesta terlipat menjadi dirinya sendiri, yang buruk. Untungnya, saya hanya perlu beberapa operasi dasar dalam input program baru yang menakjubkan ini, tetapi saya masih membutuhkannya diperluas!

Aturan

  • Sebuah jawaban harus dapat menyederhanakan ungkapan berikut

    • 2+2 harus dikurangi menjadi 4
    • (5+x)+6 harus dikurangi menjadi x+11
    • (x+2)^2 harus dikurangi menjadi x^2+4*x+4
    • (x-5)*(3+7*x) harus dikurangi menjadi 7*x^2-32*x-15
    • 5*x+9*x harus dikurangi menjadi 14*x
    • (2*x^2)*x^3 harus dikurangi menjadi 2*x^5
  • Jawaban harus sepenuhnya dapat menghapus tanda kurung, yang menyiratkan bahwa semua distribusi harus dilakukan.

  • Jawaban harus dapat menangani semua operator dan token standar berikut:

    • + (Fungsi tambahan)
    • - (Fungsi pengurangan)
    • * (Fungsi multiplikasi)
    • ( (Tanda kurung kiri, digunakan untuk menunjukkan grup)
    • ) (Tanda kurung kanan, digunakan untuk menunjukkan akhir dari grup yang dimulai terakhir)
    • x (Variabel standar)
    • [0-9]+ (angka non negatif asli)
  • Jawaban harus mampu setidaknya mengkuadratkan, menggunakan notasi expr ^ 2, termasuk (expr) ^ 2 secara rekursif, karena (expr) sendiri merupakan ekspresi;)

  • Suatu solusi harus dalam notasi infix standar, tidak ada yang omong kosong RPN!

  • Tidak ada fungsi perpustakaan seperti Mathematica Simplifyuntuk melakukan ini untuk Anda.

  • Solusi harus merupakan fungsi yang mengambil argumen tunggal dan mengembalikan versi yang diperluas

Karena ini adalah kode-golf, jawaban dengan pukulan paling sedikit (kunci) menang, 1 minggu dari OP.

Catatan

Tidak ada ruang di dunia matematika ini, tentu saja! Hanya tanda kurung.

Jadi tidak ada divisi yang diperlukan untuk menyelamatkan dari anjak piutang

Pesanan operasi standar berlaku.

Saya sadar bahwa sebagian dari apa yang saya minta adalah penyederhanaan (misalnya 2+2=4) di mana bagian lain sebenarnya sebaliknya, seperti memperluas (x+1)^2untuk menjadi x^2+2x+1. Ini disengaja. :)

-25 guratan untuk solusi yang dapat melakukan (expr) ^ n bukan hanya (expr) ^ 2

-15 guratan untuk solusi yang dapat mengevaluasi perkalian disandingkan, seperti 4x+5x== 9x, atau 4(x+1)=4x+4

-5 guratan untuk solusi yang dapat menangani banyak variabel (variabel yang tepat satu karakter alfabet huruf kecil)

-5 guratan untuk solusi yang dapat menghilangkan 0's terkemuka ( 007hanya 7[Tidak hari ini, Bond!] [Ya ampun sekarang aku merasa seperti sedang menulis Lisp])

Christopher Wirt
sumber
Saya percaya bahwa (x-5) * (3 + 7 * x) adalah (1 * x + -5) * (7 * x + 3) adalah 7 * x ^ 2 + (3-35) * x + - 15 atau 7 * x ^ 2-32 * x-15
Jeff Grigg
Bagaimana seharusnya input diberikan? Argumen baris perintah? Masukan standar? Mungkin harus ditentukan.
Frxstrem
@ JeffGrigg Inilah sebabnya saya membutuhkan program;) Hehe Saya sebenarnya menambahkan 7 * x untuk menampilkan lebih banyak kerumitan dan lupa memperbarui solusinya. Terima kasih! Dan saya bisa bersumpah saya memasukkan bahwa mereka harus diambil sebagai argumen untuk suatu fungsi
Christopher Wirt
1
Saya hampir memiliki solusi untuk ini di J, saya hanya perlu menguraikan angka negatif dengan benar. Ini mungkin hal terburuk, paling konyol yang pernah saya tulis, tapi untungnya sudah hampir berakhir.
algoritme
1
@ssdecontrol tanpa divisi, kita berbicara tentang polinomial. Tambahkan divisi dan itu hal yang sangat berbeda
edc65

Jawaban:

2

J - 350 char - 25 = 325 poin

Maafkan aku, Roger Hui, karena aku telah berdosa.

x=:0 1
f=:(('+_';'-';'_';'-')rplc~' '-.~'+'}.@,@|.@,.s(}.@]`(,&":)@.t'*x'"_`('*x^',":)`(''"_)@.t=.*@<:@[)/"1@#~0~:0{|:@s=.,.i.@#)@p=:(0{::'()'+/@,:&,e'+'@((+/@,:&,-)~e'-')@(*/a e'*')@('^'(*/(a=.+//.@)/@#,:e=:2 :'(<@; ::({:u/&.>{.)/.~i.@#-i.@#(>+>:)(<,v){.@i.~])^:_'))@:(([^:(''-:])". ::])&.>)@([-.~;@]<@(p^:(1<#));.1~1,0=2*/\[:+/\(*0,}:@)1 _1 0{~i.)&;:])

Monstrositas di atas mendefinisikan sejumlah variabel, di mana variabel tersebut fadalah fungsi yang memenuhi kendala dalam pertanyaan di atas. Saya mengklaim bonus "expr ^ n" untuk 25 poin.

Inilah golf yang sedang beraksi di J REPL.

   x=:0 1
   f=:(('+_';'-';'_';'-')rplc~' '-.~'+'}.@,@|.@,.s(}.@]`(,&":)@.t'*x'"_`('*x^',":)`(''"_)@.t=.*@<:@[)/"1@#~0~:0{|:@s=.,.i.@#)@p=:(0{::'()'+/@,:&,e'+'@((+/@,:&,-)~e'-')@(*/a e'*')@('^'(*/(a=.+//.@)/@#,:e=:2 :'(<@; ::({:u/&.>{.)/.~i.@#-i.@#(>+>:)(<,v){.@i.~])^:_'))@:(([^:(''-:])". ::])&.>)@([-.~;@]<@(p^:(1<#));.1~1,0=2*/\[:+/\(*0,}:@)1 _1 0{~i.)&;:])

   f '2+2'
4
   f '(5+x)+6'
x+11
   f '(x+2)^2'
x^2+4*x+4
   f '(x-5)*(3+7*x)'
7*x^2-32*x-15
   f '5*x+9*x'
14*x
   f '(2*x^2)*x^3'
2*x^5
   f '(2*x+3)^(2+3)*2^3'   NB. bonus
256*x^8+1920*x^7+5760*x^6+8640*x^5+6480*x^4+1944*x^3

Inilah inti dari apa yang terjadi.

  • '()'...@([-.~;@]<@(p^:(1<#));.1~1,0=2*/\[:+/\(*0,}:@)1 _1 0{~i.)&;:- Secara rekursif memecah ekspresi berdasarkan pada subekspresi yang di-kurung, dan mengevaluasinya ( ...bit, untuk dijelaskan di bawah) saat mereka siap. ;:melakukan tokenizing.
  • (([^:(''-:])". ::])&.>)- Evaluasi atom. Jika atom numerik, itu berubah menjadi angka skalar. Jika atom adalah operator, dibiarkan apa adanya. Jika atom adalah variabel x, itu berubah menjadi vektor 0 1. (Itu sebabnya kami mendefinisikan x=:0 1di awal.) Secara umum kami menyimpan polinomial a*x^n + b*x^(n-1) + ... + c*x + dsebagai n+1daftar -item d c ... b a.
  • e=:2 :'(<@; ::({:u/&.>{.)/.~i.@#([->+>:){.@i.&(<,v))^:_'- Konjungsi yang aneh ini membutuhkan kata kerja di sebelah kiri dan karakter di sebelah kanan. Ia menemukan instance pertama dari karakter itu dalam tokenized, paren-less input, dan mengevaluasinya dengan argumen di sekitarnya, dan mengulangi sampai tidak ada lagi karakter yang ditemukan. Dengan demikian, kami secara iteratif menyederhanakan ekspresi, dengan urutan operasi dikendalikan oleh urutan aplikasi e.
  • Dan kemudian semua yang ada di depan hanyalah hasil cetak yang cantik. rplcadalah fungsi perpustakaan standar untuk penggantian substring. Kami dapat menyimpan tiga karakter lagi jika diizinkan menempatkan istilah tingkat terendah terlebih dahulu, bukan yang tertinggi, dengan menghapus @|..

Jujur saya tidak yakin apakah saya bisa memeras lebih banyak karakter dari golf ini. Saya tidak bisa memikirkan pendekatan lain yang tidak membutuhkan jumlah overengineering yang serupa, tetapi itu tidak berarti tidak ada satu pun. Either way, saya cukup yakin saya sudah memeras semua karakter yang jelas dari versi ini.

algoritme hiu
sumber
Bravo! Dan Anda dapat menyingkirkan perbaikan angka negatif, karena -token hanya dicatat sebagai fungsi pengurangan. :)
Christopher Wirt
@ChristopherWirt Tidak menangkap itu. Either way, dilakukan.
algorithmshark
(2*x+3)^(2+3)*2^3harus memberi 256x^5+1920x^4+5760x^3+8640x^2+6480x+1944atau saya kehilangan sesuatu?
edc65
2

JavaScript (EcmaScript 6) 698 (748-50 bonus) 725 780 1951

Untuk golf . Tapi saya bangga itu berhasil.
(Sunting: perbaikan bug, masalah dengan tanda kurung dan minus)
(Sunting2: golf lebih, diperbaiki bug dalam output)
(Sunting3: golf sekali lagi, terakhir kali saya berjanji)

Komentar

Pada dasarnya, fungsi X adalah kalkulator infiks yang beroperasi pada polinomial literal.
Setiap polinomial disimpan sebagai objek js, kuncinya adalah istilah (x ^ 3y ^ 2) dan nilainya adalah koefisien numerik. Fungsi A, M dan E adalah menambah, mengalikan dan eksponen.

Kode Golf

(Mungkin tidak bisa golf lagi ...) Catatan: tidak termasuk baris baru ditambahkan untuk keterbacaan (ehm ...)

K=x=>Object.keys(x).sort(),
A=(p,q,s,t,c)=>[(c=(s+1)*q[t]+~~p[t])?p[t]=c:delete(p[t])for(t in q)],
M=(p,q,t,c,o,u,f,r,v={})=>([A(v,(r={},[(c=p[f]*q[t])&&(r[o={},(u=f+t)&&(u.match(/[a-z]\^?\d*/ig).map(x=>o[x[0]]=~~o[x[0]]+(~~x.slice(2)||1)),K(o,u=k).map(i=>u+=o[i]>1?i+'^'+o[i]:i)),u]=c)for(f in p)],r),k)for(t in q)],v),
E=(p,n)=>--n?M(p,E(p,n)):p,
O=n=>{for(l=0;h(o=s.pop())>=h(n);)a=w.pop(b=w.pop()),o=='*'?a=M(a,b):o>d?a=E(a,b[k]):A(a,b,o),w.push(a);s.push(o,n)},
X=e=>(l=k='',w=[],s=[d='@'],h=o=>'@)+-*^('.indexOf(o),
(e+')').match(/\D|\d+/g).map(t=>(u=h(t))>5?(l&&O('*'),s.push(d)):u>1?O(t):~u?s.pop(s.pop(O(t)),l=1):(l&&O('*'),l=1,w.push(v={}),t<d?v[k]=t|0:v[t]=1)),
K(p=w.pop()).map(i=>(k+=(c=p[i])>1?s+c+i:c<-1?c+i:(c-1?'-':s)+(i||1),s='+')),k||0)

Tes di konsol FireFox

['2+2','(5+x)+6','(x+2)^2','(a+b)(a-b)','(a+b)*(a-b)','(a-b)(a-b)', '(x-5)*(3+7*x)','5*x+9*x','(2*x^2)*x^3','(2*x+3)^(2+3)*2^3']
.map(x => x + ' => ' + X(x)).join('\n')

Keluaran

2+2 => 4
(5+x)+6 => 11+x
(x+2)^2 => 4+4x+x^2
(a+b)(a-b) => a^2-b^2
(a+b)*(a-b) => a^2-b^2
(a-b)(a-b) => a^2-2ab+b^2
(x-5)*(3+7*x) => -15-32x+7x^2
5*x+9*x => 14x
(2*x^2)*x^3 => 2x^5
(2*x+3)^(2+3)*2^3 => 1944+6480x+8640x^2+5760x^3+1920x^4+256x^5

Bonus

25: 2*x+3)^(2+3)*2^3 => 1944+6480x+8640x^2+5760x^3+1920x^4+256x^5
15: 4x+5x => 9x
5: 007x+05x^(06+2) => 7x+5x^8
5: (a+b)(a-b) => a^2-b^2

Kode Tidak Terkunci

Show=(p)=>(
  Object.keys(p).sort().map(i=>(c=p[i])-1?c+1?c+i:'-'+i:i).join('+').replace(/\+-/g,'-')
)
AddMonoTo=(poly, term, coeff, c)=>(
  (c = coeff + ~~poly[term]) ? poly[term]= c : delete(poly[term])
)
AddPolyTo=(p1, p2, s, t)=>(
  [ AddMonoTo(p1, t, (s+1)*p2[t]) for (t in p2)]
)
MulTerm=(t1, t2, o={})=>(
  (t1+=t2)&&
  (t1.match(/[a-z](\^\d+)?/g).every(x=>o[x[0]]=(~~x.slice(2)||1)+(~~o[x[0]])),
  Object.keys(o,t1='').sort().every(i=>t1+=o[i]>1?i+'^'+o[i]:i)),
  t1  
)
MulMono=(poly, term, coeff, c, r={}, t)=>(
  [(c = poly[p]*coeff) && (r[MulTerm(p,term)] = c) for (p in poly) ],r
)  
MulPoly=(p1, p2, r={}, p)=>(
  [AddPolyTo(r,MulMono(p2, p, p1[p]),'') for (p in p1)],r
)
ExpPoly=(p,n,r=p)=>{
  for(;--n;)r=MulPoly(r,p);
  return r
}
Expand=ex=>
{
  var tokens = ex.match(/\D|\d+/g).push(')')
  var t,a,b,v,LastV=0
  var vstack=[]
  var ostack=['_']
  var op={ '+': 3, '-':3, '*':4, '^':6, '(':8, _: 1, ')':2}
  var OPush=o=>ostack.push(o)
  var OPop=_=>ostack.pop()
  var VPush=v=>vstack.push(v)
  var VPop=v=>vstack.pop()

  var Scan=i=>
  {
    LastV=0 ;
    for (; (t=tokens[i++]) && (t != ')'); )
    {
      if (t == '(')  
      {
        if (LastV) CalcOp('*')
        OPush('_'), i=Scan(i)
      }
      else if (op[t])
        LastV=0, CalcOp(t)
      else
      {
        if (LastV) CalcOp('*')
        LastV = 1
        VPush(v={})
        t < 'a' ? v[''] = t|0 : v[t] = 1
      }
    }
    CalcOp(t);
    OPop();
    OPop();
    LastV=1;
    return i;
  }
  var CalcOp=nop=>
  {
    for (; op[po = OPop()] >= op[nop];)
      b=VPop(), a=VPop(), CalcV(a,b,po);
    OPush(po), OPush(nop);
  }
  var CalcV=(a,b,o)=>
  {
    if (op[o] < 4) 
      AddPolyTo(a,b,o)
    else if (o == '*')
      a=MulPoly(a,b)
    else // ^
      a=ExpPoly(a,b['']) // only use constant term for exp
    VPush(a)
  }
  Scan(0)

  return Show(vstack.pop())
}
edc65
sumber
kamu menggunakan semi-titik dua hanya di beberapa tempat? Apakah karena kurangnya bingkai yang Anda butuhkan? Saya tidak memenuhi syarat EcmaScript dengan JS saya;)
Christopher Wirt
Koma ekspresi terpisah, koma pernyataan terpisah. Ini lebih jelas for(i1,i2,i3; c1,c2; s1,s2,s3). Saya baru saja titik koma di colde golf untuk menutup pernyataan di dalam untuk (fungsi O). Kenapa koma? dua benang sari harus dikelompokkan dengan {} sementara dua atau lebih ekspresi dapat didaftar secara sederhana.
edc65
1

Mathematica: 56 - 25 - 15 - 5 - 5 = 6

Tentu saja tidak ada fungsi perpustakaan sebagai Expandatau Distribute, hanya penggantian pola. Mathematica melakukan hampir segalanya untuk kita (hax!), Yang tersisa hanyalah aturan untuk distribusi dan perluasan daya. Oleh karena itu, satu-satunya contoh non-sepele adalah (x-5)*(3+7*x)dan (x+2)^2.

f=#//.{x_ y_Plus:>(x #&/@y),x_Plus^n_:>(x #&/@x)^(n-1)}&

Contohnya

(x-5)*(3+7*x) // f
-15 - 32 x + 7 x^2

(x + 2)^2 // f
4 + 4 x + x^2
desir
sumber
Anda memiliki beberapa karakter yang sangat aneh di kedua contoh Anda. Bisakah Anda membersihkannya?
edc65
@ edc65 M10 bertingkah aneh dengan copy / paste kurasa.
desir
Saya mungkin seharusnya telah melarang Mathematica untuk semua;) kerja yang baik, meskipun
Christopher Wirt