BEGIN {
token[0] = 0
ind = 0
print calc("9-3÷1/3+1")
print calc("1/2÷3/4÷5/6×7/8×10")
print calc("(1+5×(3+2)-2)÷4")
print calc("-1/12-2/12")
}
function gcd(m, n) {
return (n ? gcd(n, m % n) : m)
}
function lcm(m, n) {
return (m * n / gcd(m, n))
}
function setfrac(n, d, fac, newn, newd) {
if (n == 0){
return 0
}
if (d == 0){
return setfrac(n, 1)
}
fac = gcd(n, d)
newn = n / fac
newd = d / fac
if (newd < 0){
newn *= -1
newd *= -1
}
return ((newd == 1) ? newn : (newn "/" newd))
}
function reciprocalfrac(f, v) {
split(f, v, "/")
if (v[2] == 0){
v[2] = 1
}
return setfrac(v[2], v[1])
}
function multifrac(mf, nf, m, n) {
split(mf, m, "/")
if (m[2] == 0){
m[2] = 1
}
split(nf, n, "/")
if (n[2] == 0){
n[2] = 1
}
return setfrac(m[1] * n[1], m[2] * n[2])
}
function divfrac(mf, nf) {
if (nf == 0){
print "error: division by 0"
}
return multifrac(mf, reciprocalfrac(nf))
}
function addfrac(mf, nf, fac, m, n, newm, newn) {
split(mf, m, "/")
if (m[2] == 0){
m[2] = 1
}
split(nf, n, "/")
if (n[2] == 0){
n[2] = 1
}
fac = lcm(m[2], n[2])
newm = m[1] * fac / m[2]
newn = n[1] * fac / n[2]
return setfrac(newm + newn, fac)
}
function subfrac(mf, nf) {
return addfrac(mf, multifrac(nf, -1))
}
function accept(x) {
if (x == token[ind]){
ind++
return 1
}
return 0
}
function digit() {
if (accept("0")){
return 0
}
if (accept("1")){
return 1
}
if (accept("2")){
return 2
}
if (accept("3")){
return 3
}
if (accept("4")){
return 4
}
if (accept("5")){
return 5
}
if (accept("6")){
return 6
}
if (accept("7")){
return 7
}
if (accept("8")){
return 8
}
if (accept("9")){
return 9
}
return (-1)
}
function digits( sign, n, v) {
sign = 1
if (accept("-")){
sign = -1
}
n = digit()
if (n < 0){
print "error: expected digit"
}
while(1){
v = digit()
if (v < 0) break
n = n * 10 + v
}
return setfrac(sign * n)
}
function factor( n) {
if (accept("(")){
n = expression()
if (!accept(")")){
print "error: unmatched brackets"
}
return n
}
return digits()
}
function term( n) {
n = factor()
while(1){
if (accept("*")){
n = multifrac(n, factor())
continue
}
if (accept("/")){
n = divfrac(n, factor())
continue
}
break
}
return n
}
function multi_exp( n) {
n = term()
while(1){
if (accept("×")){
n = multifrac(n, term())
continue
}
if (accept("÷")){
n = divfrac(n, term())
continue
}
break
}
return n
}
function expression( n) {
n = multi_exp()
while(1){
if (accept("+")){
n = addfrac(n, multi_exp())
continue
}
if (accept("-")){
n = subfrac(n, multi_exp())
continue
}
break
}
return n
}
function trdigit(v) {
if (v == "0"){
return "0"
}
if (v == "1"){
return "1"
}
if (v == "2"){
return "2"
}
if (v == "3"){
return "3"
}
if (v == "4"){
return "4"
}
if (v == "5"){
return "5"
}
if (v == "6"){
return "6"
}
if (v == "7"){
return "7"
}
if (v == "8"){
return "8"
}
if (v == "9"){
return "9"
}
if (v == "-"){
return "-"
}
if (v == "/"){
return "/"
}
}
function fractostring(s, i, n, v, r) {
n = split(s, v, "")
r = ""
for(i = 1; i <= n; i++){
r = r trdigit(v[i])
}
return r
}
function calc(s, i, n) {
n = split(s, token, "")
token[n + 1] = "$"
ind = 1
return fractostring(expression())
}
QkVHSU4gewoJdG9rZW5bMF0gPSAwCglpbmQgPSAwCgoJcHJpbnQgY2FsYygi77yZ77yN77yTw7fvvJHvvI/vvJPvvIvvvJEiKQoJcHJpbnQgY2FsYygi77yR77yP77ySw7fvvJPvvI/vvJTDt++8le+8j++8lsOX77yX77yP77yYw5fvvJHvvJAiKQoJcHJpbnQgY2FsYygi77yI77yR77yL77yVw5fvvIjvvJPvvIvvvJLvvInvvI3vvJLvvInDt++8lCIpCglwcmludCBjYWxjKCLvvI3vvJHvvI/vvJHvvJLvvI3vvJLvvI/vvJHvvJIiKQp9CgpmdW5jdGlvbiBnY2QobSwgbikgewoJcmV0dXJuIChuID8gZ2NkKG4sIG0gJSBuKSA6IG0pCn0KCmZ1bmN0aW9uIGxjbShtLCBuKSB7CglyZXR1cm4gKG0gKiBuIC8gZ2NkKG0sIG4pKQp9CgpmdW5jdGlvbiBzZXRmcmFjKG4sIGQsICBmYWMsIG5ld24sIG5ld2QpIHsKCWlmIChuID09IDApewoJCXJldHVybiAwCgl9CglpZiAoZCA9PSAwKXsKCQlyZXR1cm4gc2V0ZnJhYyhuLCAxKQoJfQoKCWZhYyA9IGdjZChuLCBkKQoJbmV3biA9IG4gLyBmYWMKCW5ld2QgPSBkIC8gZmFjCglpZiAobmV3ZCA8IDApewoJCW5ld24gKj0gLTEKCQluZXdkICo9IC0xCgl9CgoJcmV0dXJuICgobmV3ZCA9PSAxKSA/IG5ld24gOiAobmV3biAiLyIgbmV3ZCkpCn0KCmZ1bmN0aW9uIHJlY2lwcm9jYWxmcmFjKGYsICB2KSB7CglzcGxpdChmLCB2LCAiLyIpCglpZiAodlsyXSA9PSAwKXsKCQl2WzJdID0gMQoJfQoKCXJldHVybiBzZXRmcmFjKHZbMl0sIHZbMV0pCn0KCmZ1bmN0aW9uIG11bHRpZnJhYyhtZiwgbmYsICBtLCBuKSB7CglzcGxpdChtZiwgbSwgIi8iKQoJaWYgKG1bMl0gPT0gMCl7CgkJbVsyXSA9IDEKCX0KCXNwbGl0KG5mLCBuLCAiLyIpCglpZiAoblsyXSA9PSAwKXsKCQluWzJdID0gMQoJfQoKCXJldHVybiBzZXRmcmFjKG1bMV0gKiBuWzFdLCBtWzJdICogblsyXSkKfQoKZnVuY3Rpb24gZGl2ZnJhYyhtZiwgbmYpIHsKCWlmIChuZiA9PSAwKXsKCQlwcmludCAiZXJyb3I6IGRpdmlzaW9uIGJ5IDAiCgkJZXhpdCAxCgl9CgoJcmV0dXJuIG11bHRpZnJhYyhtZiwgcmVjaXByb2NhbGZyYWMobmYpKQp9CgpmdW5jdGlvbiBhZGRmcmFjKG1mLCBuZiwgIGZhYywgbSwgbiwgbmV3bSwgbmV3bikgewoJc3BsaXQobWYsIG0sICIvIikKCWlmIChtWzJdID09IDApewoJCW1bMl0gPSAxCgl9CglzcGxpdChuZiwgbiwgIi8iKQoJaWYgKG5bMl0gPT0gMCl7CgkJblsyXSA9IDEKCX0KCglmYWMgPSBsY20obVsyXSwgblsyXSkKCW5ld20gPSBtWzFdICogZmFjIC8gbVsyXQoJbmV3biA9IG5bMV0gKiBmYWMgLyBuWzJdCgoJcmV0dXJuIHNldGZyYWMobmV3bSArIG5ld24sIGZhYykKfQoKZnVuY3Rpb24gc3ViZnJhYyhtZiwgbmYpIHsKCXJldHVybiBhZGRmcmFjKG1mLCBtdWx0aWZyYWMobmYsIC0xKSkKfQoKCmZ1bmN0aW9uIGFjY2VwdCh4KSB7CglpZiAoeCA9PSB0b2tlbltpbmRdKXsKCQlpbmQrKwoJCXJldHVybiAxCgl9CgoJcmV0dXJuIDAKfQoKZnVuY3Rpb24gZGlnaXQoKSB7CglpZiAoYWNjZXB0KCLvvJAiKSl7CgkJcmV0dXJuIDAKCX0KCWlmIChhY2NlcHQoIu+8kSIpKXsKCQlyZXR1cm4gMQoJfQoJaWYgKGFjY2VwdCgi77ySIikpewoJCXJldHVybiAyCgl9CglpZiAoYWNjZXB0KCLvvJMiKSl7CgkJcmV0dXJuIDMKCX0KCWlmIChhY2NlcHQoIu+8lCIpKXsKCQlyZXR1cm4gNAoJfQoJaWYgKGFjY2VwdCgi77yVIikpewoJCXJldHVybiA1Cgl9CglpZiAoYWNjZXB0KCLvvJYiKSl7CgkJcmV0dXJuIDYKCX0KCWlmIChhY2NlcHQoIu+8lyIpKXsKCQlyZXR1cm4gNwoJfQoJaWYgKGFjY2VwdCgi77yYIikpewoJCXJldHVybiA4Cgl9CglpZiAoYWNjZXB0KCLvvJkiKSl7CgkJcmV0dXJuIDkKCX0KCglyZXR1cm4gKC0xKQp9CgpmdW5jdGlvbiBkaWdpdHMoIHNpZ24sIG4sIHYpIHsKCXNpZ24gPSAxCglpZiAoYWNjZXB0KCLvvI0iKSl7CgkJc2lnbiA9IC0xCgl9CgoJbiA9IGRpZ2l0KCkKCWlmIChuIDwgMCl7CgkJcHJpbnQgImVycm9yOiBleHBlY3RlZCBkaWdpdCIKCQlleGl0IDEKCX0KCgl3aGlsZSgxKXsKCQl2ID0gZGlnaXQoKQoJCWlmICh2IDwgMCkgYnJlYWsKCQluID0gbiAqIDEwICsgdgoJfQoKCXJldHVybiBzZXRmcmFjKHNpZ24gKiBuKQp9CgpmdW5jdGlvbiBmYWN0b3IoIG4pIHsKCWlmIChhY2NlcHQoIu+8iCIpKXsKCQluID0gZXhwcmVzc2lvbigpCgkJaWYgKCFhY2NlcHQoIu+8iSIpKXsKCQkJcHJpbnQgImVycm9yOiB1bm1hdGNoZWQgYnJhY2tldHMiCgkJCWV4aXQgMQoJCX0KCQlyZXR1cm4gbgoJfQoKCXJldHVybiBkaWdpdHMoKQp9CgpmdW5jdGlvbiB0ZXJtKCBuKSB7CgluID0gZmFjdG9yKCkKCXdoaWxlKDEpewoJCWlmIChhY2NlcHQoIu+8iiIpKXsKCQkJbiA9IG11bHRpZnJhYyhuLCBmYWN0b3IoKSkKCQkJY29udGludWUKCQl9CgkJaWYgKGFjY2VwdCgi77yPIikpewoJCQluID0gZGl2ZnJhYyhuLCBmYWN0b3IoKSkKCQkJY29udGludWUKCQl9CgkJYnJlYWsKCX0KCglyZXR1cm4gbgp9CgpmdW5jdGlvbiBtdWx0aV9leHAoIG4pIHsKCW4gPSB0ZXJtKCkKCXdoaWxlKDEpewoJCWlmIChhY2NlcHQoIsOXIikpewoJCQluID0gbXVsdGlmcmFjKG4sIHRlcm0oKSkKCQkJY29udGludWUKCQl9CgkJaWYgKGFjY2VwdCgiw7ciKSl7CgkJCW4gPSBkaXZmcmFjKG4sIHRlcm0oKSkKCQkJY29udGludWUKCQl9CgkJYnJlYWsKCX0KCglyZXR1cm4gbgp9CgpmdW5jdGlvbiBleHByZXNzaW9uKCBuKSB7CgluID0gbXVsdGlfZXhwKCkKCXdoaWxlKDEpewoJCWlmIChhY2NlcHQoIu+8iyIpKXsKCQkJbiA9IGFkZGZyYWMobiwgbXVsdGlfZXhwKCkpCgkJCWNvbnRpbnVlCgkJfQoJCWlmIChhY2NlcHQoIu+8jSIpKXsKCQkJbiA9IHN1YmZyYWMobiwgbXVsdGlfZXhwKCkpCgkJCWNvbnRpbnVlCgkJfQoJCWJyZWFrCgl9CgoJcmV0dXJuIG4KfQoKZnVuY3Rpb24gdHJkaWdpdCh2KSB7CglpZiAodiA9PSAiMCIpewoJCXJldHVybiAi77yQIgoJfQoJaWYgKHYgPT0gIjEiKXsKCQlyZXR1cm4gIu+8kSIKCX0KCWlmICh2ID09ICIyIil7CgkJcmV0dXJuICLvvJIiCgl9CglpZiAodiA9PSAiMyIpewoJCXJldHVybiAi77yTIgoJfQoJaWYgKHYgPT0gIjQiKXsKCQlyZXR1cm4gIu+8lCIKCX0KCWlmICh2ID09ICI1Iil7CgkJcmV0dXJuICLvvJUiCgl9CglpZiAodiA9PSAiNiIpewoJCXJldHVybiAi77yWIgoJfQoJaWYgKHYgPT0gIjciKXsKCQlyZXR1cm4gIu+8lyIKCX0KCWlmICh2ID09ICI4Iil7CgkJcmV0dXJuICLvvJgiCgl9CglpZiAodiA9PSAiOSIpewoJCXJldHVybiAi77yZIgoJfQoJaWYgKHYgPT0gIi0iKXsKCQlyZXR1cm4gIu+8jSIKCX0KCWlmICh2ID09ICIvIil7CgkJcmV0dXJuICLvvI8iCgl9Cn0KCmZ1bmN0aW9uIGZyYWN0b3N0cmluZyhzLCAgaSwgbiwgdiwgcikgewoJbiA9IHNwbGl0KHMsIHYsICIiKQoKCXIgPSAiIgoJZm9yKGkgPSAxOyBpIDw9IG47IGkrKyl7CgkJciA9IHIgdHJkaWdpdCh2W2ldKQoJfQoKCXJldHVybiByCn0KCmZ1bmN0aW9uIGNhbGMocywgIGksIG4pIHsKCW4gPSBzcGxpdChzLCB0b2tlbiwgIiIpCgl0b2tlbltuICsgMV0gPSAi77yEIgoJaW5kID0gMQoKCXJldHVybiBmcmFjdG9zdHJpbmcoZXhwcmVzc2lvbigpKQp9Cg==