Оцінка дужок і дужок як цілих чисел


20

Напишіть програму, яка містить рядок із чотирьох символів, ()[]що задовольняє цим точкам:

  • Кожна ліва дужка (має відповідні праві дужки ).
  • Кожна ліва дужка [має відповідну праву дужку ].
  • Збігання пар дужок і дужок не буде перетинатися. наприклад [(]), недійсний, оскільки відповідні дужки не містяться повністю в дужках, що відповідають, а також навпаки.
  • Перший і останній символи - це відповідна пара дужок або дужок. Так ([]([]))і [[]([])]справедливі , але []([])це не так .

( Граматика для формату введення є <input> ::= [<input>*] | (<input>*).)

Кожна пара відповідних дужок і дужок оцінює невід'ємне ціле число:

  • Значення пар усередині відповідних дужок підсумовуються . Порожній збіг ()має значення 0.
  • Значення пар у відповідних дужках всі множать . Порожній збіг []має значення 1.

( Сума або добуток одного числа - це те саме число.)

Наприклад, ([](())([][])[()][([[][]][][])([][])])можна розбити і оцінити як 9:

([](())([][])[()][([[][]][][])([][])])    <input>
(1 (0 )(1 1 )[0 ][([1 1 ]1 1 )(1 1 )])    <handle empty matches>
(1 0   2     0   [(1     1 1 )2     ])    <next level of matches>
(1 0   2     0   [3           2     ])    <and the next>
(1 0   2     0   6                   )    <and the next>
9                                         <final value to output>

Ще один приклад:

[([][][][][])([][][])([][][])(((((([][]))))))]    <input>
[(1 1 1 1 1 )(1 1 1 )(1 1 1 )((((((1 1 ))))))]
[5           3       3       (((((2     )))))]
[5           3       3       ((((2       ))))]
[5           3       3       (((2         )))]
[5           3       3       ((2           ))]
[5           3       3       (2             )]
[5           3       3       2               ]
90                                                <output>

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

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


Попросити від імені подання Python на роз'яснення: Програма лише, чи добре / функції / повернути значення?
Sp3000

Тоді може бути добре відредагувати питання. У попередньому запитанні мені сказали, що функції недійсні, якщо в запитанні написано "написати програму".
Рето Кораді

Відповіді:


11

CJam, 23

q"])(""1]:*0]:+["4/ers~

З великими кредитами Деннісу! Спробуйте в Інтернеті

Пояснення:

Програма перетворює вхід у вираз CJam, а потім оцінює його.
[…]стає […1]:*(додайте 1 і помножте)
(…)стає […0]:+(додайте 0 і додайте)

q              read input
"])("          characters we want to replace
"1]:*0]:+["    replacement strings, concatenated
4/             split into strings of length 4: ["1]:*" "0]:+" "["]
er             replace (transliterate) the 3 characters with the 3 strings
s              convert the result (mixed characters and strings) to string
~              evaluate

1
Транслітерація економить 4 байти:q"])(""1]:*0]:+["4/ers~
Dennis

2
@Dennis whaaa! Це божевільно, ти можеш це зробити ??
адіцу

3
Ви мене питаєте ? : P
Dennis

4
@Dennis Як би творець CJam знав про існування такої функції ??
Оптимізатор

8

Лист звичайний - 98

(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
  1. Замінити (на(+
  2. Замінити [на(*
  3. Замінити ]на)
  4. Читати з рядка
  5. Евал

Це вимагає cl-ppcreзавантаження бібліотеки в поточне зображення.

Пояснення

Функції *і +є VARIADIC і повернути їх нейтральне значення , коли не дали ніяких аргументів. Для ваших прикладів оцінюваною формою lisp є такі:

(+ (*) (+ (+)) (+ (*) (*)) (* (+)) (* (+ (* (*) (*)) (*) (*)) (+ (*) (*))))
=> 9

і

(* (+ (*) (*) (*) (*) (*)) (+ (*) (*) (*)) (+ (*) (*) (*))
   (+ (+ (+ (+ (+ (+ (*) (*))))))))
=> 90

Без регулярних виразів - 183 байти

(lambda(s)(do(r(x(coerce s'list))c)((not x)(eval(read-from-string(coerce(reverse r)'string))))(setq c(pop x))(push(case c(#\[ (push #\* r)#\()(#\] #\))(#\( (push #\+ r) #\()(t c))r)))

C'mon, Lisp - 16 байт (експериментально)

+((<r*([<r)]<rRE

Інші мови настільки лаконічні, що я спокушаюся скласти свою власну мову для гольфу на основі Common Lisp для коротших маніпуляцій із струнами. В даний час немає специфікації, а функція eval наступна:

(defun cmon-lisp (expr &rest args)
  (apply
   (lambda (s)
     (let (p q)
       (loop for c across expr
             do (case c
                  (#\< (push (pop p) q))
                  (#\r
                   (let ((a1 (coerce q 'string)) (a2 (coerce p 'string)))
                     (setf p nil
                           q nil
                           s
                             (cl-ppcre:regex-replace-all
                              (cl-ppcre:quote-meta-chars a1) s a2))))
                  (#\R
                   (setf s
                           (if (string= s "")
                               nil
                               (read-from-string s))))
                  (#\E (setf s (eval s)))
                  (t (push c p))))
       s))
   args))

Тести:

(cmon-lisp "+((<r*([<r)]<rRE" "([] [] ([] []))")
=> 4
  • є неявний аргумент, який називається sі двома стеками, pі q.
  • символів у вихідному коді висуваються на p.
  • <: спливає з pі підштовхує до q.
  • r: замінює s(повинен бути рядок) з символів у qна символи p; результат зберігається в s; pі qспорожняються.
  • R: читати з рядка s, зберігати результат у змінній s.
  • E: форма eval s, результат зберігання в s.

1
Смішно, як lisp використовується для того, щоб робити щось із дужками.
Сид Керкхов

@SydKerckhove Ваш коментар просто змушує мене думати про відповідну відповідь Clojure. Дуже дякую!
coredump

6

Pyth, 35 34 33 байт

L?*F+1yMbqb+YbsyMbyvsXzJ"])"+R\,J

Демонстрація.

1 байт завдяки @Jakube.

Почнемо з розбору вхідних даних. Формат введення близький до Python, але не зовсім. Нам потрібні коми після кожної групи, що скористався дужкою, або з дужкою. Кома в кінці загранованої групи непотрібна, але нешкідлива. Для цього ми використовуємо цей код:

vsXzJ"])"+R\,J
  X               Translate
   z              in the input
     "])"         the characters "])"
    J             which we will save to J to
             J    J
         +R\,     with each character mapped to itself plus a ",".
 s                Combine the list to a string.
v                  Evaluate as a Python literal.

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

Тепер, коли рядок розбирається, ми повинні знайти його значення. Це робиться за допомогою визначеної користувачем функції y, яка викликається на проаналізованому об'єкті. функція визначається наступним чином:

L?*F+1yMbqb+YbsyMb
L                     Define a function, y(b), which returns the following:
 ?       qb+Yb        We form a ternary whose condition is whether the input, b,
                      equals the inputplus the empty list, Y. This is true if
                      and only if b is a list.
      yMb             If so, we start by mapping y over every element of b.
  *F+1                We then take the product of these values. The +1 ensures
                      that the empty list will return 1.
                yMb   Otherwise, we start by mapping y over every element of b.
               s      Then, we sum the results.

@Jakube Правильно, одинарне підсумовування не має ефекту.
isaacg

3

Emacs lisp, 94

Формат виглядає дуже пихатим, тому я подумав, що просте перетворення може спрацювати:

(defun e()(format-replace-strings'(("("."(+")("["."(*")("]".")")))(eval(read(buffer-string))))

Проміжний формат виглядає приблизно так (наприклад, у запитанні):

(+(*)(+(+))(+(*)(*))(*(+))(*(+(*(*)(*))(*)(*))(+(*)(*))))

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

Дегольфований та інтерактивний для вас задоволення від гри:

(defun paren_eval()
  (interactive "*")
  (format-replace-strings '(("(" . "(+")
                            ("[" . "(*")
                            ("]" . ")")))
  (eval (read (buffer-string)))
)

Я мав би прочитати уважніше - рішення Common Lisp використовує точно такий же підхід!
Toby Speight

1
Нам потрібно більше відповідей Emacs Lisp !. До речі, я не рахував, але ви можете трохи більше пограти, скориставшись лямбдаю, взявши рядок як параметр і видаливши interactive (замість буферного рядка, використовуйте read-from-string).
coredump

2

Сітківка , 111 байт

[\([](1+x)[]\)]
$1
\[]
1x
\(\)
x
(\[a*)1(?=1*x1*x)
$1a
a(?=a*x(1*)x)
$1
(\[1*x)1*x
$1
)`(\(1*)x(?=1*x)
$1
[^1]
<empty line>

Дає вихід уніар.

Кожен рядок повинен мати свій власний файл, але ви можете запустити код як один файл із -sпрапором. Наприклад:

> retina -s brackets <input_1
111111111

Пояснення надходить пізніше.


2

Java, 349 символів

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

import java.util.*;class K{int a=0,b;String c;public static void main(String[]a){K b=new K();b.c=a[0];System.out.print(b.a());}int a(){switch(c.charAt(a++)){case'(':b=0;for(int a:b())b+=a;break;case'[':b=1;for(int a:b())b*=a;}a++;return b;}List<Integer>b(){List d=new ArrayList();char c;while((c=this.c.charAt(a))!=']'&&c!=')')d.add(a());return d;}}

Розширено:

import java.util.*;

class K {
    int a =0, b;
    String c;
    public static void main(String[] a){
        K b = new K();
        b.c = a[0];
        System.out.print(b.a());
    }
    int a(){
        switch (c.charAt(a++)){
            case '(':
                b =0;
                for (int a : b())
                    b += a;
                break;
            case '[':
                b =1;
                for (int a : b())
                    b *= a;
        }
        a++;
        return b;
    }
    List<Integer> b(){
        List d = new ArrayList();
        char c;
        while ((c= this.c.charAt(a)) != ']' && c != ')')
            d.add(a());
        return d;
    }
}

2

Перл 5, 108

Виконано як перекладач, а не переписуйте та оцінюйте. Не чудове показ, але все-таки весело писати.

push@s,/[[(]/?[(ord$_&1)x2]:do{($x,$y,$z,$t)=(@{pop@s},@{pop@s});
[$t?$x*$z:$x+$z,$t]}for<>=~/./g;say$s[0][0]

Без гольфу:

# For each character in the first line of stdin
for (<> =~ /./g) {
    if ($_ eq '[' or $_ eq '(') {
        # If it's an opening...
        # ord('[') = 91 is odd, ord('(') = 40 is even
        push @stack, [ ( ord($_) & 1) x 2 ];
        # so we will push [1, 1] on the stack for brackets and [0, 0] for parens.
        # one of these is used as the flag for which operator the context is, and
        # the other is used as the initial (identity) value.
    } else {
        # otherwise, assume it's a closing
        ($top_value, $top_oper) = @{ pop @stack };
        ($next_value, $next_oper) = @{ pop @stack };
        # merge the top value with the next-to-top value according to the
        # next-to-top operator. The top operator is no longer used.
        $new_value = $next_oper
            ? $top_value * $next_value
            : $top_value + $next_value
        push @stack, [ $new_value, $next_oper ];
    }
}

say $stack[0][0]; # print the value remaining on the stack.

2

Пітона, 99

Я спробував різні методи, але найкоротший, який я міг отримати, був, в основному, лише заміною та eval. Я був приємно здивований, коли виявив, що можу залишити всі сліди ,, оскільки Python може розібратися, [1,2,]а остання кома в кінці просто вміщує всю справу в кортеж. Тільки інші не просто частина буде цілком ord(c)%31%7відокремити з різних символів (це має значення 2, 3, 1, 0для (, ), [, ]відповідно)

F=lambda s:eval(''.join(["],1),","reduce(int.__mul__,[","sum([","]),"][ord(c)%31%7]for c in s))[0]

1
Це не працює як програма, чи не так? Питання задає програму, тому я не думаю, що надання функції відповідає вимогам. Принаймні, це те, про що люди говорили мені востаннє, коли я подав функцію, коли в запитанні було сказано "програма". :)
Рето Коради

1

Ява, 301

дещо інший підхід, ніж відповідь TheNumberOne, хоча мій також має рекурсивний характер. Введення береться з командного рядка. При видаленні символів, які більше не потрібні, метод void зберігає кілька байтів.

enum E{I;String n;public static void main(String[]r){I.n=r[0];System.out.print(I.e());}int e(){int v=0;if(n.charAt(0)=='('){for(s("(");n.charAt(0)!=')';)v+=e();s(")");}else if(n.charAt(0)=='['){v=1;for(s("[");n.charAt(0)!=']';)v*=e();s("]");}return v;}void s(String c){n=n.substring(1+n.indexOf(c));}}

розширено:

enum EvaluatingParenthesesAndBrackets{
    AsIntegers;
    String input;
    public static void main(String[]args){
        AsIntegers.input=args[0];
        System.out.print(AsIntegers.evaluate());
    }
    int evaluate(){
        int value=0;
        if(input.charAt(0)=='('){
            for(substringAfterChar("(");input.charAt(0)!=')';)
                value+=evaluate();
            substringAfterChar(")");
        }
        else if(input.charAt(0)=='['){
            value=1;
            for(substringAfterChar("[");input.charAt(0)!=']';)
                value*=evaluate();
            substringAfterChar("]");
        }
        return value;
    }
    void substringAfterChar(String character){
        input=input.substring(1+input.indexOf(character));
    }
}

1

Пітон, 117 110 109 байт

def C(s,p=[0]):
 m=r=s[p[0]]=='[';p[0]+=1
 while s[p[0]]in'[(':t=C(s,p);r=r*t*m+(r+t)*(1-m)
 p[0]+=1;return r

Один із аспектів, з якими я боровся, полягає в тому, що функція в основному має два повернені значення: продукт / сума та нове положення в рядку. Але мені потрібна функція, яка повертає лише результат, тому повернення кортежу не працює. Ця версія використовує аргумент "посилання" (список з одним елементом), щоб повернути позицію назад з функції.

У мене є скорочена версія (103 байти), яка використовує глобальну змінну для позиції. Але це спрацює лише на перший дзвінок. А функція, яка працює лише один раз, здається трохи рибкою. Не впевнений, чи допустимо це для коду гольфу.

Алгоритм - це пряма рекурсія. Я спробував ряд варіантів виразу, який оновлює продукт / суму. Я придумав кілька версій, які були точно однакової довжини, але жодна з них не була коротшою.

Я начебто очікував, що підхід, який перетворює це на вираження, яке оцінюється, ймовірно, виграє. Але, як кажуть: "Ітерація є людиною, щоб повторити божественне".


Функції тепер явно дозволені :)
Захоплення Кальвіна

@ Calvin'sHobbies У мене є питання про правила, про які я взагалі цікавився, але це може зіграти тут: Якщо рішення реалізується як функція, чи означає це, що функцію можна викликати не один раз за один проміжок? Наприклад, якщо б вона використовувала глобальну змінну, яка ініціалізується правильно лише під час першого дзвінка, це було б ... неправильно?
Рето Кораді

@Retro Я б сказав, так, це неправильно. Функція повинна працювати будь-яку кількість разів, не повторюючи її.
Захоплення Кальвіна

1

Clojure - 66 байт

Зауважте, що ([] (()) ([] []) [()] [([[] []] [] []) ([] [])])це дійсна форма Clojure. Так:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • Це анонімна функція, яка бере рядок, читає його та передає g.
  • Локальна gфункція застосовується +або *до результату виклику gпіделементів його аргументів.
  • Основний випадок рекурсії є трохи тонким: він досягається, коли xв порожній послідовності; (map g x)повертає nilта applyповертає нейтральне значення для операції.

0

JavaScript (ES6), 116 байт

s=>+[...s].reduce((t,c)=>((x=c==']')||c==')'?t[1].push(t.shift().reduce((a,b)=>x?a*b:a+b,+x)):t.unshift([]),t),[[]])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.