Notasi Awalan ke Notasi Postfix

19

Penafian: Tidak, ini bukan tantangan lelucon untuk membalik string.

Tugas

Hanya ada satu operasi untuk mendukung: pengurangan ( -).

Anda juga hanya memiliki dua atom untuk didukung: nol ( 0) dan satu ( 1).

Di sini, notasi awalan -ABsama dengan notasi postfix AB-, di mana Adan Badalah ekspresi.

Tugas Anda adalah (secara rekursif) mengubah ekspresi dalam notasi awalan menjadi yang setara dalam notasi postfix.

Definisi

Ekspresi dalam notasi awalan dihasilkan oleh tata bahasa berikut:

S > -SS
S > 0
S > 1

Ekspresi notasi postfix dihasilkan oleh tata bahasa berikut:

S > SS-
S > 0
S > 1

Contoh

Prefix notation:  --01-0-01
Parentheses:      -(-01)(-0(-01))
Convert:          (01-)(0(01-)-)-
Postfix notation: 01-001---

Aturan dan kebebasan

  • Anda dapat mengubah nama operasi dan atom ke karakter mana pun, asalkan konsisten.
  • Format input harus konsisten dengan format output (terlepas dari kenyataan bahwa input dalam notasi awalan dan output dalam notasi postfix).

Kasus cobaan

Input       Output
1           1
0           0
-01         01-
-10         10-
--01-0-01   01-001---

Kredit testcases ke Dada .

Biarawati Bocor
sumber
1
Bisakah Anda menambahkan beberapa test case lagi?
Shaggy
@ Shaggy, jenis tes apa yang Anda inginkan?
Leaky Nun
@ LeakyNun Apakah saya tetap bisa mengambil input dan output sebagai iterator, seperti yang saya lakukan di versi terbaru dari jawaban saya?
L3viathan
@ L3viathan kurasa begitu ...
Leaky Nun

Jawaban:

12

brainfuck , 32 byte

,[[->++++<<+>]>[[-]<<[.[-]<]]>,]

Cobalah online!

Saya digunakan @sebagai operasi, karena titik kode (64) nyaman. Ujuga dimungkinkan dengan jumlah byte yang sama, menggunakan 3 * 85 + 1 = 256 = 0.

Penjelasan

Rekaman itu digunakan sebagai tumpukan. Di setiap iterasi loop utama, penunjuk data mulai dua sel tepat di atas tumpukan.

,[                Take input and start main loop
  [->++++<<+>]    Push input, and compute 4*input
  >[              If 4*input is nonzero (and thus input is not @):
    [-]<<           Zero out this cell and move to top of stack
    [.[-]<]         Pop from stack and output until \0 is reached
  ]
  >,              Move pointer into the correct position.  If input was @, the earlier > pushed \0 onto the stack.
]
Nitrodon
sumber
6

Retina , 37 30 29 byte

M!`-*.
+m`^-(.*)¶(\d.*)
$1$2-

Cobalah online! Menyimpan 7 byte dengan menyadari bahwa istilah selalu dimulai dengan angka, jadi saya tidak perlu lagi membatasi kecocokan dengan yang terakhir -(sebelumnya hanya satu-satunya yang dijamin diikuti oleh dua istilah). Disimpan 1 byte dengan tidak meletakkan -pada baris mereka sendiri. Misalnya, -01menjadi -0¶1yang kemudian diganti dengan 01-. Sekarang, jika saya memiliki --010yaitu --0¶1¶0maka saya ingin mengubah batin -0¶1untuk 01-sehingga saya bisa mengganti -01-¶0dengan 01-0-, tetapi tidak benar-benar peduli yang mana dari kedua -s saya remove, jadi saya menghapus satu di awal baris, seperti itu lebih mudah untuk diuji.

Neil
sumber
Saya pikir ini adalah sesuatu Anda :)
Leo
@ Leo Tidak berfungsi secara umum, mis. -0-0-00Seharusnya menjadi 0000---.
Neil
Anda benar, maaf. Saya punya ide lain, tetapi ini sangat berbeda, jadi saya akan mempostingnya sebagai jawaban baru
Leo
1
@ Leo, saya sekarang menemukan sesuatu ...
Neil
1
@ Leo Dengan golf terbaru saya, kami terikat!
Neil
6

Haskell , 62 59 byte

f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
fst.f

Cobalah online! Penggunaan: fst.f $ "--01-0-01". 0dan 1dapat berupa karakter arbitrer yang lebih besar dari karakter tersebut -.

Sunting: -3 byte terima kasih kepada Zgarb!

Fungsi fsecara rekursif mem-parsing satu ekspresi dan mengembalikan tuple ekspresi ini dalam notasi postfix dan string lainnya, mengikuti tata bahasa sederhana yang darinya dapat dibangun ekspresi awalan yang valid:

<exp> ::= - <exp> <exp> | 0 | 1

Jika karakter pertama adari string input lebih besar dari -, kita berada pada ekspresi atom dan mengembalikan tupel string dengan karakter adan sisa string input.

Jika kita menemukan -, dua ekspresi perlu diuraikan. Ini dapat dicapai dengan (a,x)<-f rmendapatkan ekspresi pertama adan kemudian mengurai string sisanya xlagi (b,c)<-f xuntuk mendapatkan ekspresi kedua bdan string sisa terakhir c. (a,(b,c))<-f<$>f rtidak persis ini karena <$>pada tupel memetakan fungsi dua elemen kedua tupel sementara menjadi tiga byte lebih pendek dari (a,x)<-f r,(b,c)<-f x. Setelah mendapatkan kedua ekspresi dan sisanya string, ekspresi yang bersambung dan "-" ditambahkan: (a++b++"-",c).

Laikoni
sumber
1
Anda dapat menyimpan 3 byte dengan menggabungkan case:f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
Zgarb
@ Zgarb Terima kasih! Untuk beberapa alasan saya hanya mempertimbangkan f(x:r)|x<'0',(a,(b,c))<-f<$>f r=(a++b++"-",c)|1<3=([x],r)ketika saya mencari versi dengan kedua case yang digabungkan, yaitu byte yang lebih panjang.
Laikoni
5

Haskell, 54 byte

v f""=""
v f(a:s)=last(v.v:[id|a>'-'])((a:).f)s
h=v h

Fungsi vmengambil string dan fungsi, mengatur ulang sub-ekspresi awal, kemudian menerapkan fungsi ke sisa string sampai semuanya telah diatur ulang. Susunan panggilan dan argumen fungsi bersama-sama melacak ekspresi apa yang sedang diuraikan. Fungsi hmenjawab tantangan, dan hanya vdipanggil dengan sendirinya sebagai argumen pertama dummy.

faubi
sumber
1
Wow! (1) Itu baru 53, Anda tidak perlu menghitung baris terakhir. (2) Baris pertama dapat disingkat menjadi v f l=ljika Anda memindahkannya kedua.
Ørjan Johansen
1
Saya tidak berpikir Anda perlu mem-parsing lebih dari satu ekspresi keseluruhan, sehingga Anda dapat menyimpan byte dengan menggunakan fungsi anonim v id.
Ørjan Johansen
1
Sebenarnya baris pertama tidak pernah dipanggil pada input yang valid, jadi Anda bisa menghapusnya.
Ørjan Johansen
1
Membagi menjadi penjaga tampaknya mengalahkan lasttrik dengan satu byte.
Ørjan Johansen
4

Perl 5 , 57 byte

sub f{"@_"=~s/x((?0)|.)((?0)|.)/my$n=$2;f($1).f($n).x/re}

Saya menggunakan xsebagai operator alih-alih -(lihat tautan TryItOnline di bawah).

Cobalah online!

Penjelasan:
/x((?0)|.)((?0)|.)/ cocok dengan ekspresi penuh secara rekursif: a xdi awal, lalu ekspresi (?0)(itu panggilan rekursif) atau atom ( .), diikuti oleh ekspresi-atau-atom lain.
Maka saya perlu menyimpan ekspresi kedua / atom ( my$n=$2;) karena jika tidak, panggilan rekursif akan menimpanya.
Fungsi ini kemudian secara rekursif dipanggil pada ekspresi pertama ( f($1)), kemudian pada yang kedua f($n), dan xditambahkan di akhir ( .x).

Dada
sumber
4

Python 3, 117 112 105 100 98 76 62 61 59 byte

def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]

Changelog:

  • menghapus linebreak jika memungkinkan (-5 byte)
  • lambda bukannya fungsi penuh (-7 byte, terima kasih @Dada)
  • tidak lain (-5 byte, terima kasih @Leaky Nun)
  • batalkan golf yang terlalu bersemangat (-2 byte, terima kasih @Leaky Nun)
  • bekerja pada daftar global sebagai gantinya (-22 byte)
  • sebenarnya, mari kita bekerja pada iterator saja (-14 byte)
  • ubah !=ke >(-1 byte, disalin dari saran @ovs)
  • tipuan evaluasi malas (-2 byte, terima kasih @ovs)

Gunakan seperti ini:

>>> list(p(iter("--01-0-01")))
['0', '1', '-', '0', '0', '1', '-', '-', '-']
L3viathan
sumber
2
lambda x:p(x)[0]mungkin bisa menggantikan ffungsi Anda .
Dada
1
Anda tidak perlu else, metinks.
Leaky Nun
1
Apakah d="-"benar - benar menyimpan byte?
Leaky Nun
1
def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]untuk 59 byte
ovs
3

Pyth, 20 byte

L+&-hbTsyM.-Btbytbhb

Ini menciptakan fungsi yyang mengharapkan string sebagai parameter.

Cobalah online: Demonstrasi atau Test Suite

Penjelasan:

Fungsi yakan mem-parsing dan mengonversi ekspresi awalan pertama ke ekspresi postfix. Jadi jika disebut seperti y"10"itu akan kembali saja 1.

L+&-hbTsyM.-Btbytbhb
L                      define a function y(b), that returns:
   -hbT                   remove the chars "10" from the first char b
                          (T=10, and - will convert a number to a string)
  &                       if this gives the empty string (a falsy value)
 +                hb         then append b[0] to it and return it
                             (so this will parse a digit 0 or 1 from the string)
  &                       otherwise (the first char is a -)
               ytb           parse the first prefix expression from b[1:]
                             (recursive call)
          .-Btb              remove this parsed expression bifurcated from b[1:]
                             this gives a tuple [b[1:], b[1:] without first expr]
        yM                   parse and convert an expression from each one
       s                     join the results
 +                hb         and append the b[0] (the minus) to it and return
Jakube
sumber
2

Retina , 34 31 29 byte


;
-;
¶
+`¶(.+);(.+)
$1$2-
;

Cobalah online!

;digunakan untuk menunjukkan node, yang awalnya disusun oleh nomor tunggal dan kemudian tumbuh menjadi apa pun yang telah diuraikan. -diubah menjadi baris baru sehingga dengan.+ kita dapat mengambil apa pun yang tidak diparsing -.

Leo
sumber