Konversi dari Infix Notation ke Prefix Notation

12

Diberikan ekspresi aritmatika, yang dapat mencakup tanda kurung ( ()), eksponen ( ^), pembagian ( /) dan perkalian ( *), penambahan ( +) dan pengurangan ( -) (dalam urutan operasi itu), seperti

a ^ (2 / 3) * 9 * 3 - 4 * 6

menghasilkan ekspresi yang sama dalam notasi awalan.

(- (* (* (^ a (/ 2 3)) 9) 3) (* 4 6))

Spasi bersifat opsional dalam input maupun output. Anda dapat mengasumsikan bahwa semua operator asosiatif kiri dan bahwa semua angka dalam ekspresi adalah bilangan bulat satu digit (yaitu [0-9]).

Ini adalah tantangan kode golf, sehingga solusi terpendek menang.

Peter Olson
sumber
1
Apakah + dan - prioritas yang sama, atau + lebih tinggi dari -? Yaitu, apakah 3+4-5+6 = (((3+4)-5)+6)atau ((3+4)-(5+6))?
Keith Randall
Juga, Anda meninggalkan divisi dalam daftar operasi Anda.
PhiNotPi
Apakah tanda kurung opsional dalam hasil?
Ali1S232
@KeithRandall *dan /memiliki prioritas yang sama, seperti halnya +amd -.
Peter Olson
@ Tidak, tidak.
Peter Olson

Jawaban:

13

Ruby 1.9 - 134

%w[** / * + -].map{|o|String.send(:define_method,o){|n|"(#{o=='**'??^:o} #{self} #{n})"}}
puts eval gets.gsub(/\w/,'?\0').gsub ?^,'**'

Cukup jahat, tetapi berhasil:

$ echo 'a ^ (2 / 3) * 9 * 3 - 4 * 6' | ruby sol.rb
(- (* (* (^ a (/ 2 3)) 9) 3) (* 4 6))
eregon
sumber
3

Python, 222 karakter

class A:
 def __init__(s,x):s.v=x
for x in('pow^','mul*','div/','add+','sub-'):exec('A.__'+x[:3]+'__=lambda s,y:A("('+x[3]+'"+s.v+y.v+")")')
import re
print eval(re.sub('(\\w)','A("\\1")',raw_input().replace('^','**'))).v

Mirip dengan Ruby, kecuali Python tidak membiarkan Anda mendefinisikan ulang operasi global, hanya operasi kelas.

Keith Randall
sumber
2

Perl 6 (146 | 150)

Cara termudah untuk melakukan ini adalah dengan hanya menukar subrutin yang mengimplementasikan operator untuk yang baru.

sub infix:«+»   ($a,$b) { "(+ $a $b)" }
sub infix:«-»   ($a,$b) { "(- $a $b)" }
sub infix:«*»   ($a,$b) { "(* $a $b)" }
sub infix:['/'] ($a,$b) { "(/ $a $b)" } # stupid highlighter
sub infix:«**»  ($a,$b) { "(^ $a $b)" }

# currently there seems to be a bug that
# prevents this from modifying the parser correctly
# probably because there is already a different operator with this name
# which has nothing to do with exponentiation
my &infix:«^» := &[**];

say 'a' ** (2 / 3) * 9 * 3 - 4 * 6;
# (- (* (* (^ a (/ 2 3)) 9) 3) (* 4 6))␤

Jumlah minimum absolut byte untuk melakukannya dengan cara ini adalah:

sub infix:<+>{"(+ $^a $^b)"}␤  #   29
sub infix:<->{"(- $^a $^b)"}␤  # + 29
sub infix:<*>{"(* $^a $^b)"}␤  # + 29
sub infix:<**>{"(^ $^a $^b)"}␤ # + 30
sub infix:</>{"(/ $^a $^b)"}␤  # + 29

146 byte, meskipun lebih masuk akal untuk menghitung grapheme di Perl 6.

Ini mengasumsikan bahwa " output ekspresi yang sama dalam notasi awalan " hanya bisa merujuk ke hasil ekspresi, belum tentu output dari program.

Anda harus menambahkan say di depan ekspresi untuk mendapatkan program untuk mencetaknya ke STDOUT. (150 byte)

Brad Gilbert b2gills
sumber
0

Unix TMG , 189 byte

p:ignore(<< >>)parse(e);e:q(t,a);t:q(x,m);x:q(r,h);q:proc(x,y)x k:y/d x={<(>2 3 1<)>}b\k;r:o(!<<+-*/^()>>)|<(>e<)>;a:o(<<+->>);m:o(<<*/>>);h:o(<<^>>);o:proc(n)smark any(n)scopy;d:;b:bundle;

Solusinya hampir langsung dari manual untuk bahasa tersebut, dengan hanya bermain golf dasar.

Diperluas:

prog:  ignore(<< >>) parse(expr);
expr:  q(term, addop);
term:  q(fact, mulop);
fact:  q(prim, expop);
q:     proc(x,y) x k: y/done x ={ <(> 2 3 1 <)> } b\k;
prim:  op(!<<+-*/^()>>) | <(> expr <)>;
addop: op(<<+->>);
mulop: op(<<*/>>);
expop: op(<<^>>);
op:    proc(n) smark any(n) scopy;
done:  ;
b:     bundle;
Andriy Makukha
sumber