Укресліть вираз виразом


20

Нещодавно я писав новою мовою , щоб уникнути необхідності обробляти порядок операцій , я просто скористався дужкою кожного виразу належним чином, щоб уникнути цього цілком.

Оскільки в дужках знаходяться char-коди 40-41, ваш код повинен бути якомога коротшим.


Приклади

1+2*3
(1+(2*3))

2*(3+4)
(2*(3+4))

2*3/4+3
(((2*3)/4)+3)

342*32/8
((342*32)/8)

Правила

Єдині операції, з якими вам потрібно буде впоратися, це: *(множення), /(ділення), +(додавання) та -(віднімання).

  • Порядок операцій є:
    • Парентез
    • Множення, ділення
    • Складання, віднімання
  • Вам слід віддати перевагу ліворуч праворуч
  • Число введення завжди буде додатними цілими числами (див. Бонуси)

Бонуси

-20%, якщо ви обробляєте заперечення:

3+-5
(3+(-5))

-5%, якщо ви можете розмістити пробіли всередині входу:

3  + 4
(3+4)

-10%, якщо ви можете обробляти десяткові знаки на вході:

1+.12
(1+.12)
1+0.21/3
(1+(0.21/3))

500 баунті: якщо вам вдасться написати відповідь у Без назви / Блоки


25
"Оскільки в дужках знаходяться графічні коди 40-41, ваш код повинен бути якомога коротшим." Гаразд, тепер ти просто смішний. ; P
ETHproductions

3
І це простіше, ніж позначення префіксів (польських), бо?
wizzwizz4

3
Можливий дублікат .
недолік

8
@flawr Я це бачив, але це дуже відрізняється тим, що в цьому питанні ви виводите всі способи думки в виразі. Тут ви повинні взяти до уваги порядок операцій, які, на мою думку, є суттєвою різницею, оскільки код не може бути тривіально модифікований для цього виклику
Downgoat

3
Важливий тестовий випадок: 1+2+3+4(які певні рішення можуть бути використані в дужках ((1+2)+(3+4)))
Мартін Ендер

Відповіді:


2

Пітон, 153 * 0,9 = 137,7 байт

def p(e):
 for o in"+-*/":
    for i,c in enumerate(e):
        if(c==o)*(0==sum([(d=="(")-(d==")")for d in e[:i]])):return"("+p(e[:i])+o+p(e[i+1:])+")"
 return e

Ця програма обробляє десяткове введення.

Другий рядок починається з пробілу, другий починається з вкладки, третій - з двома вкладками, а третій - з пробілом. Це зберегло один байт. Ось шістнадцятковий ( xxdpp):

0000000: 6465 6620 7028 6529 3a0a 2066 6f72 206f  def p(e):. for o
0000010: 2069 6e22 2b2d 2a2f 223a 0a09 666f 7220   in"+-*/":..for 
0000020: 692c 6320 696e 2065 6e75 6d65 7261 7465  i,c in enumerate
0000030: 2865 293a 0a09 0969 6628 633d 3d6f 292a  (e):...if(c==o)*
0000040: 2830 3d3d 7375 6d28 5b28 643d 3d22 2822  (0==sum([(d=="("
0000050: 292d 2864 3d3d 2229 2229 666f 7220 6420  )-(d==")")for d 
0000060: 696e 2065 5b3a 695d 5d29 293a 7265 7475  in e[:i]])):retu
0000070: 726e 2228 222b 7028 655b 3a69 5d29 2b6f  rn"("+p(e[:i])+o
0000080: 2b70 2865 5b69 2b31 3a5d 292b 2229 220a  +p(e[i+1:])+")".
0000090: 2072 6574 7572 6e20 650a                  return e.

Ось програма, яку я використовував для тестування: (Збережіть програму вище як paren.py)

import paren

cases = {
        "2+3*4": "(2+(3*4))", 
        "(2+3)*4": "((2+3)*4)", 
        "1+2+3+4": "(1+(2+(3+4)))", 
        "3/2+5": "((3/2)+5)", 
        "1+2-3": "(1+(2-3))", 
        "2-1+2": "((2-1)+2)",
        "3+-5": "(3+(-5))",
        "1+.12": "(1+.12)",
        "1+0.21/3": "(1+(0.21/3))",
}


for num, case in enumerate(cases):
    print "\n\n\033[1m\033[38;5;14mCase #%d: %s" % (num + 1, case)
    result = paren.p(case)
    print "\033[38;5;4mParenthesize returned: %s" % (result)
    solution = cases[case]
    if result == solution:
        print "\033[38;5;76mCorrect!"
    else:
        print "\033[38;5;9mNot correct!"

Переконайтеся, що ваш термінал використовує \033[38;5;<COL>mкод евакуації кольорів.


* четвертий з пробілом?
Елемент118

1
Ця програма не робить prefer to go left-right. Спробуйте тестовий випадок 3 в ОП, ваш результат невірний. Це може бути справжньою проблемою, наприклад, з цілою арифметикою ((2*(3/4))+3)(((2*3)/4)+3)
:!

1
@ user12365 Не використовуючи цілу арифметику (наприклад, в C або C ++) 3/4 == 0, тому ((2 * (3/4)) + 3) дорівнює 3, а (((2 * 3) / 4) + 3) є 4
edc65

3

JavaScript (ES6) 179 (263 -20% -5% -10%)

(x,W=[],Q=['('],z=1,w=v='',h=p=>'*/+-))('.indexOf(p)|1,C=n=>{for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;z&&Q.push(q,n)})=>(x+')').replace(/[\d.]+|\S/g,t=>t>'('?t>')'?~h(t)?z?(w+='('+t,v+=')'):C(t,z=1):W=[w+t+v,...W,z=w=v='']:C(t,z=0):z=Q.push(t))&&W[0]

Оскільки інші два відповіді наразі обидві неправильні, я опублікую свою. Це варіант аналізу синтаксичного аналізатора, який я використовував тут і тут, і деінде. Подивіться там для більш детальних пояснень алгоритму.

Це досить громіздко, але це має працювати.

Фрагмент тесту

f=(x,W=[],Q=['('],z=1,w=v='',h=p=>'*/+-))('.indexOf(p)|1,C=n=>{for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;z&&Q.push(q,n)})=>(x+')').replace(/[\d.]+|\S/g,t=>t>'('?t>')'?~h(t)?z?(w+='('+t,v+=')'):C(t,z=1):W=[w+t+v,...W,z=w=v='']:C(t,z=0):z=Q.push(t))&&W[0]

// More readable
x=(x,W=[],Q=['('],z=1,w=v='',
  h=p=>'*/+-))('.indexOf(p)|1,
  C=n=>{
    for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;
    z&&Q.push(q,n)
  }
)=>(
  (x+')')
  .replace(/[\d.]+|\S/g,t=> 
       t>'('    
       ?t>')'
       ?~h(t)
       ?z
       ?(w+='('+t,v+=')')
       :C(t,z=1)
       :W=[w+t+v,...W,z=w=v=''] // overfill W to save 2 chars ()
       :C(t,z=0)
       :z=Q.push(t)
  ),
  W[0]
)

console.log=(...x)=>O.textContent+=x.join` `+'\n'

// TEST
;[
  ['1+2*3','(1+(2*3))'],['2*(3+4)','(2*(3+4))'],['2*3/4+3','(((2*3)/4)+3)'],['342*32/8','((342*32)/8)'],
  ['3+-5','(3+(-5))'],['-3+-4*7','((-3)+((-4)*7))'], // bonus 20%
  ['3  + 4','(3+4)'], // bonus 5%
  ['1+.12','(1+.12)'],['1+0.21/3','(1+(0.21/3))'] // bonus 10%
].forEach(t=>{var k=t[1],i=t[0],r=f(i); console.log(i+' : '+r+(r==k? ' OK':' Fail expecting '+k))})
<pre id=O></pre>


1

Пітон, 241 * 0,8 * 0,95 * 0,9 = 164,84 символів

Я використовую бібліотеку ast (Абстрактні синтаксичні дерева) та дікт про заміну рядків домашнього алфавіту. Заміна струни коштує багато, але бонус допомагає утримувати оцінку дещо низькою. Можливо, (частина заміни струни) можна буде додатково пограти в гольф.

Зауважте, що це рішення додає додатковий набір дужок навколо кожного числа, але я думаю, що це в дусі питання

import ast;def p(e):
 r,s={"Module([":"",")])":"","Expr(":"","BinOp":"","Num":"",", Add(), ":"+",", Sub(), ":"-",", Div(), ":"/",", Mult(), ":"*"},ast.dump(ast.parse(e),annotate_fields=False)
 for f,t in r.iteritems():s=s.replace(f,t)
 return s

Тестовий набір:

cases = {
    "2+3*4", 
    "(2+3)*4", 
    "1+2+3+4", 
    "3/2+5", 
    "1+2-3", 
    "2-1+2",
    "3+-5",
    "1+.12",
    "1+0.21/3"
}

for num,case in enumerate(cases):
    result = p(case)
    print "Case {}: {:<16} evaluates to: {}".format(num+1,case,result)

Вихід з тестового набору:

Case 1: 3+-5             evaluates to: ((3)+(-5))
Case 2: 3/2+5            evaluates to: (((3)/(2))+(5))
Case 3: 2+3*4            evaluates to: ((2)+((3)*(4)))
Case 4: 1+2+3+4          evaluates to: ((((1)+(2))+(3))+(4))
Case 5: 1+0.21/3         evaluates to: ((1)+((0.21)/(3)))
Case 6: (2+3)*4          evaluates to: (((2)+(3))*(4))
Case 7: 2-1+2            evaluates to: (((2)-(1))+(2))
Case 8: 1+.12            evaluates to: ((1)+(0.12))
Case 9: 1+2-3            evaluates to: (((1)+(2))-(3))

Відсутній import astу вашому коді
edc65

І це не правильний спосіб нарахування відсотків премії. Якщо ви отримуєте знижку в 50%, а крім того ще 50%, ви не платите 0. Ваш рахунок повинен бути 157,32 (щось більше після додавання рядка імпорту). Це хороший результат - я підкажу, якщо ви виправте
edc65

Гарна думка. Додано імпорт. 241 символ зараз. Не знаю, як нарахувати бонус. Якщо я правильно зрозумів ваш коментар правильно, порядок , в якому бонусна віднімають питання ...
agtoever

Бонус не віднімається (це множення) і порядок не має значення. 241 * (1-20%) * (1-5%) * (1-10%) => 241 * 0,8 * 0,95 * 0,9 => 164,84
edc65

@ edc65 Ага. Правильно. Не думав прямо. Спасибі.
agtoever
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.