Оценка строк Дотти

25

Напишите программу, которая принимает строку нечетной длины, содержащую только символы .и :. С помощью изначально пустого стека сгенерируйте число из этой строки следующим образом:

Для каждого символа c в строке (идущего слева направо) ...

  • Если c есть, .а в стеке менее 2 элементов, нажмите 1 в стеке.
  • Если с есть .и стек имеет 2 или более элементов, поп два значения из стека и подтолкнуть их сумму на стек.
  • Если c есть, :а в стеке менее 2 элементов, нажмите 2 в стеке.
  • Если с это :и стек имеет 2 или более элементов, поп два значения из стека и толкать их продукт в стек.

Полученное число является значением в верхней части стека. Ваша программа должна напечатать этот номер на стандартный вывод (с дополнительным завершающим переводом строки).

(Небольшой анализ показывает, что остается только одно число, если строка не имеет четной длины, поэтому мы игнорируем их. На самом деле в стеке никогда не бывает более 2 элементов.)

Например, число для ::...:.:.9:

  2   1   2   2    /______ stack just after the character below is handled
2 2 4 4 5 5 7 7 9  \
: : . . . : . : .  <-- string, one character at a time

В качестве проверки работоспособности, вот числа для всех строк длины 1, 3 и 5:

. 1
: 2
... 2
..: 1
.:. 3
.:: 2
:.. 3
:.: 2
::. 4
::: 4
..... 3
....: 2
...:. 4
...:: 4
..:.. 2
..:.: 1
..::. 3
..::: 2
.:... 4
.:..: 3
.:.:. 5
.:.:: 6
.::.. 3
.::.: 2
.:::. 4
.:::: 4
:.... 4
:...: 3
:..:. 5
:..:: 6
:.:.. 3
:.:.: 2
:.::. 4
:.::: 4
::... 5
::..: 4
::.:. 6
::.:: 8
:::.. 5
:::.: 4
::::. 6
::::: 8

Самая короткая программа в байтах побеждает. Tiebreaker - более ранний пост.

  • Вы можете предполагать, что ввод всегда действителен, то есть строка, содержащая только .и :длина которой нечетна.
  • Вместо написания программы вы можете написать функцию, которая принимает допустимую строку и печатает или возвращает сгенерированное число.
Кальвин Хобби
источник
5
Лучший минималистский эквалайзер.
dberm22

Ответы:

13

CJam, 27 24 23 22 байта

q{i]_,+~3<-"1+2* "=~}/

Довольно прямо вперед. Я использую стек CJam в качестве стека, упомянутого в вопросе;)

Алгоритм

Сначала давайте посмотрим на код ASCII для .и :.

'.i ':ied

[46 58]

Поскольку в CJam индекс оборачивается, давайте посмотрим, сможем ли мы использовать эти значения напрямую, чтобы получить желаемую операцию.

'.i4% ':i4%ed

[2 2]

Поэтому я не могу просто использовать коды ASCII в строке операции длиной 4. Давайте попробуем некоторые другие значения

'.i 10% ':i 10%ed

[6 8]

который на 4-х струнной длине сводится к

[2 0]

Я могу использовать эту операцию мода 10, но это будет стоить 2 байта. Давайте попробуем что-нибудь еще

'.i5% ':i5%ed

[1 3]

Хорошо, теперь мы просто вычитаем 1 для условия размера стека, чтобы получить индексы, 0, 1, 2 and 3и используем 5массив length ( "1+2* ") в качестве регистра переключателя. Последний пробел - это просто заполнитель для длины 5. Это всего лишь 1 дополнительный байт по сравнению с операцией моддинга.

q{                  }/    e# parse each input character in this loop
  i]                      e# convert '. or ': into ASCII code and wrap everything
                          e# in stack in an array
    _,+                   e# Copy the stack array, take its length and add the length to
                          e# the stack array 
       ~3<                e# unwrap the stack array and check if stack size is less than 3
                          e# 3 because either . or : is also on stack
          -               e# subtract 0 or 1 based on above condition from ASCII code
           "1+2* "        e# string containing the operation to perform
                  =~      e# chose the correct operation and evaluate it

Попробуйте онлайн здесь

1 байт сохранен благодаря cosechy

оптимизатор
источник
1
Для чего нужно пространство в строке операций?
Питер Тейлор
@PeterTaylor объяснил в посте.
Оптимизатор
9

> <> (Рыба) , 33 байта

ib%1-i:1+?\~n;
5a*)?*+40.\b%1-0@i

Довольно просто с небольшими хитростями / оптимизациями.

Объяснение:

  • Информация: i= кодовая точка следующего входного символа, -1если достигнут конец ввода; a= 10; b= 11; )знак равно>
  • iкодовая точка первого входного символа,
  • b%1- top_of_stack mod 11 - 1маски 48 ('.') , 56 (':')для1 , 2
  • i:1+?\~n; если достигнут конец ввода, выведите последний результат и завершите
  • иначе:
  • b%1- маска ввода для 1 , 2
  • 0@нажмите 0под два числа
  • i5a*)прочитайте следующий ввод и замаскируйте его для 0 , 1сравнения с50
  • if 1( ':') умножить верхние два элемента, создавая стек [0 product]
  • всегда добавить два верхних элементов стека , создавая либо [0 sum]или[0+product=product]
  • 40.прыжок (цикл) обратно в положение (4,0), наша точка 4,i:1+?\~n;
randomra
источник
8

Haskell, 73 65 байт

Простое решение, использующее тот факт, что стек никогда не имеет более 2 элементов.

[x,y]#'.'=[x+y]
[x,y]#_=[x*y]
s#'.'=1:s
s#_=2:s
f=head.foldl(#)[]
alephalpha
источник
5

C 104 байта

k[2],n;f(char*c){for(n=0;*c;)k[n]=*c++-58?n>1?n=0,*k+k[1]:1:n>1?n=0,*k*k[1]:2,k[1]=n++?k[1]:0;return*k;}

Ну, это слишком долго.

BrainSteel
источник
5

Pyth, 25 24 байта

eu?]?.xGHsGtG+GhHmqd\:zY

Получил идею, изучив решение @ isaacg. Но я использую стек.

Онлайн-демонстрация или тестовый набор

объяснение

Первое, что я делаю, это преобразовываю входную строку в 0 и 1. А "."превращается в 0, ":"в в 1.

mqd\:z   map each char d of input to (d == ":")

Тогда я уменьшу этот список чисел:

eu?]?.xGHsGtG+GhHmqd\:zY
 u                     Y   start with the empty stack G = []
                           for each H in (list of 0s and 1s), update G:
                              G = 
    ?.xGHsG                      product of G if H != 0 else sum of G
   ]                             wrapped in a list 
  ?        tG                 if G has more than 1 element else
             +GhH                G + (H + 1)
e                         take the top element of the stack
Jakube
источник
4

JavaScript (ES6), 65

Мы используем только 2 ячейки нашего стека.

Начните помещать значение в s [0].
Затем в каждой нечетной позиции (считая от 0) во входной строке поместите значение в s [1].
В каждой четной позиции выполните calc (сложение или умножение) и сохраните результат в s [0].

Так что забудьте о стеке и используйте только 2 переменные, a и b.

f=s=>[...s].map((c,i)=>(c=c>'.',i&1?b=1+c:i?c?a*=b:a+=b:a=1+c))|a

Быстрый тест

for(i=0;i<128;i++)
{
  b=i.toString(2).replace(/./g,v=>'.:'[v]).slice(1)
  if(b.length&1) console.log(b,f(b))
} 

Выход

"." 1
":" 2
"..." 2
"..:" 1
".:." 3
".::" 2
":.." 3
":.:" 2
"::." 4
":::" 4
"....." 3
"....:" 2
"...:." 4
"...::" 4
"..:.." 2
"..:.:" 1
"..::." 3
"..:::" 2
".:..." 4
".:..:" 3
".:.:." 5
".:.::" 6
".::.." 3
".::.:" 2
".:::." 4
".::::" 4
":...." 4
":...:" 3
":..:." 5
":..::" 6
":.:.." 3
":.:.:" 2
":.::." 4
":.:::" 4
"::..." 5
"::..:" 4
"::.:." 6
"::.::" 8
":::.." 5
":::.:" 4
"::::." 6
":::::" 8
edc65
источник
-2:f=s=>[(c=s[i]>'.',i&1?b=1+c:+i?c?a*=b:a+=b:a=1+c)for(i in s)]|a
nderscore
@nderscore по крайней мере на моем браузере, который не работает. for (i in s) дает дополнительные свойства помимо индексов
edc65
это работает для меня в Firefox 37.0.2. Попробуйте запустить его в чистой вкладке браузера. Кажется, stackexchange добавляет дополнительные свойства к строкам (в stub.en.js)
nderscore
3

Pyth, 27 байт

Jmhqd\:zu?*GhHteH+GhHctJ2hJ

Стек? Кому нужен стек

                       Implicit: z is the input string.
Jmhqd\:z               Transform the string into a list, 1 for . and 2 for :
                       Store it in J.
u            ctJ2hJ     Reduce over pairs of numbers in J, with the
                       first entry as initial value.
 ?    teH               Condition on whether the second number is 1 or 2.
  *GhH                  If 1, update running total to prior total times 1st num.
         +GhH           If 2, update running total to prior total plus 1nd num.

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

isaacg
источник
1
Genius. А между тем я реализовал стек (32 байта). :-(
Якуб
3

Retina , 105 75 73 байта

Моя первая программа Retina! (Спасибо Мартину Бюттнеру за то, что он сэкономил 2 байта, не говоря уже о изобретении языка в первую очередь.)

Каждая строка должна идти в отдельном файле; или вы можете поместить их все в один файл и использовать -sфлаг. <empty>Обозначение представляет собой пустой файл / строку.

^(a+;)?\.
$1a;
^(a+;)?:
$1aa;
;(a+;)\.
$1
(a+);aa;:
$1$1;
)`;a;:
;
;
<empty>
a
1

Вдохновлен ответом mbomb007 , но я использую несколько иной подход. Одно из основных отличий состоит в том, что я строю стек перед точечной строкой (вершина стека обращена вправо). Это позволяет легко конвертировать символы в соответствующие номера на месте. Я также использую aвместо того 1, чтобы заменить его только в конце, чтобы избежать разбора неоднозначности в таких последовательностях, как $1a. Если подобный ответ aaaaaaприемлем в качестве унарного числа, последние две строки / файлы можно исключить, чтобы сэкономить 4 байта.

Объяснение:

^(a+;)?\.
$1a;

Соответствует, если в стеке 0 или 1 элементов, (a+;)?за которыми следует точка ( \.); если это так, он заменяет период на a;(т.е. помещает 1).

^(a+;)?:(.*)
$1aa;$2

Соответствует, если в стеке 0 или 1 элементов, за которыми следует двоеточие. Если это так, он заменяет двоеточие на aa;(то есть толкает 2).

;(a+;)\.
$1

Соответствует, если в стеке есть два элемента, за которыми следует точка. Удаляет точку и точку с запятой между элементами, тем самым добавляя их.

(a+);aa;:
$1$1;

Соответствует, если в стеке есть два элемента, верхний из которых - 2, за которым следует двоеточие. Удаляет двоеточие и 2 и повторяет другое число дважды, умножая его на 2.

)`;a;:
;

Регулярное выражение совпадает, если в стеке есть два элемента, верхняя часть которых - 1, за которым следует двоеточие. Удаляет двоеточие и 1, оставляя другое число без изменений (т. Е. Умножается на 1).

)`указывает на конец цикла. Если в строку были внесены какие-либо изменения, элемент управления возвращается в начало программы и снова выполняет подстановки. Если строка перестала меняться, мы заменили все точки и двоеточия, и все, что осталось, это очистить ...

;
<empty>

Удаляет оставшуюся точку с запятой.

a
1

Превращает все а в 1. Опять же, если для одинарных чисел разрешено использовать любой символ, этот шаг не требуется.

DLosc
источник
Предполагается, что начало цикла является первым файлом?
mbomb007
@ mbomb007 Да. Я видел это в документах, но забыл, пока Мартин не напомнил мне об этом. ;)
DLosc
2

Ржавчина, 170 символов

fn f(s:String)->i32{let(mut a,mut b)=(-1,-1);for c in s.chars(){if b!=-1{a=match c{'.'=>a+b,':'=>a*b,_=>0};b=-1}else{b=match c{'.'=>1,':'=>2,_=>0};if a==-1{a=b;b=-1}};}a}

Еще одно доказательство того, что Руст абсолютно ужасен в игре в гольф. Полный негольфированный код:

#[test]
fn it_works() {
    assert_eq!(dotty_ungolfed("::...:.:.".to_string()), 9);
    assert_eq!(f("::...:.:.".to_string()), 9);
}

fn dotty_ungolfed(program: String) -> i32 {
    let (mut a, mut b) = (-1, -1);
    for ch in program.chars() {
        if b != -1 {
            a = match ch { '.' => a + b, ':' => a * b, _ => panic!() };
            b = -1;
        } else {
            b = match ch { '.' => 1, ':' => 2, _ => panic!() };
            if a == -1 { a = b; b = -1; }
        }
    }
    a
}

fn f(s:String)->i32{let(mut a,mut b)=(-1,-1);for c in s.chars(){if b!=-1{a=match c{'.'=>a+b,':'=>a*b,_=>0};b=-1}else{b=match c{'.'=>1,':'=>2,_=>0};if a==-1{a=b;b=-1}};}a}

Вот интересный трюк, который я использовал в этом. Вы можете сбрить символ в операторе if / else, заставив его вернуть значение, которое немедленно отбрасывается, что означает, что вам нужно только одну точку с запятой вместо двух.

Например,

if foo {
    a = 42;
} else {
    doSomething(b);
}

может быть изменен на

if foo {
    a = 42
} else {
    doSomething(b)
};

который сохраняет характер, сбривая точку с запятой.

Дверная ручка
источник
2

Haskell, 88 81 79 байт

(h:t)![p,q]|h=='.'=t![p+q]|1<2=t![p*q]
(h:t)!s|h=='.'=t!(1:s)|1<2=t!(2:s)
_!s=s

Кажется, что кто-то превзошел меня до уровня решения Haskell, и не только это, их решение короче моего. Это плохо, но я не вижу причин, чтобы не публиковать то, что я придумал.

Анк-Морпорка
источник
2

APL (50)

Я нахожусь в невыгодном положении, потому что APL не является языком, основанным на стеке. Я, наконец, начал сокращать злоупотребления, чтобы сократить программу.

{⊃{F←'.:'⍳⍺⋄2>⍴⍵:F,⍵⋄((⍎F⌷'+×')/2↑⍵),2↓⍵}/(⌽⍵),⊂⍬}

Внутренняя функция берет «команду» слева и стек справа и применяет ее, возвращая стек. Внешняя функция уменьшает его над строкой, начиная с пустого стека.

Объяснение:

  • (⌽⍵),⊂⍬: начальный список, чтобы уменьшить более. ⊂⍬является пустым списком в штучной упаковке, который представляет стек, (⌽⍵)является обратной стороной ввода. (Сокращение применяется справа налево над списком, поэтому строка будет обрабатываться справа налево. Реверсирование ввода заранее позволяет применять символы в правильном порядке.)

  • {... }: внутренняя функция. Он берет стек справа, символ слева и возвращает модифицированный стек.

    • F←'.:'⍳⍺: индекс символа в строке .:, это будет 1 или 2 в зависимости от значения.
    • 2>⍴⍵:F,⍵: Если 2 больше текущего размера стека, просто добавьте текущее значение в стек.
    • : иначе,
      • 2↓⍵: удалить два верхних элемента из стека
      • (... )/2↑⍵: уменьшить заданную функцию над ними и добавить ее в стек.
      • ⍎F⌷'+×': функция либо +(сложение), либо ×(умножение), выбрана с помощью F.
  • : наконец, вернуть самый верхний элемент в стеке

Мэринус
источник
2

Рубин - 96 символов

Сорта интересный кусок здесь eval .

Кроме того, я делаю предположение, что после первого символа в стеке всегда будет 2, math, 2, math, .... Это позволяет мне использовать меньше кода, получая два символа одновременно - мне никогда не придется вычислять вне зависимости от того, является ли символ математикой или числом. Это позиционно.

x,m=$<.getc>?.?2:1
(b,f=m.split //
b=b>?.?2:1
x=f ?eval("x#{f>?.??*:?+}b"):b)while m=gets(2)
p x

Ungolfed:

bottom_of_stack = $<.getc > '.' ? 2 : 1 # if the first char is ., 1, else 2
two_dots = nil
while two_dots = gets(2) do # get the next 2 chars
  number_char, math_char = two_dots.split //
  number = number_char > '.' ? 2 : 1
  if math_char
    math = math_char > '.' ? '*' : '+'
    # so bottom_of_stack = bottom_of_stack + number ...
    # or bottom_of_stack = bottom_of_stack * number
    bottom_of_stack = eval("bottom_of_stack #{math} number")
  else
    # if there's no math_char, it means that we're done and 
    # number is the top of the stack
    # we're going to print bottom_of_stack, so let's just assign it here
    bottom_of_stack = number
  end
end
p bottom_of_stack  # always a number, so no need for `puts`
Не тот Чарльз
источник
2

TI-BASIC, 78 73 70 69 66 байтов

Input Str1
int(e^(1=inString(Str1,":
For(A,2,length(Str1),2
Ans+sum({Ans-2,1,1,0},inString("::..:",sub(Str1,A,2
End
Ans

TI-BASIC хорош в однострочниках, потому что закрывающие скобки не обязательны; и наоборот, это плохой язык, в котором требуется сохранение нескольких значений, поскольку хранение в переменной занимает от двух до четырех байтов. Поэтому цель состоит в том, чтобы написать как можно больше в каждой строке. TI-BASIC также ужасен (для языка токенов) при любых манипуляциях со строками; даже чтение подстроки занимает много времени.

Трюки включают в себя:

  • int(e^([boolean] вместо того 1+(boolean ; сохраняет один байт
  • Частичная сумма списка вместо среза списка (что потребовало бы сохранения в списке): экономит 3 байта
lirtosiast
источник
Вы должны быть в порядке, принимая входные данные от Ans, например ".:.":prgmDOTTY, сохраняя 4 байта.
МИ Райт
@ Право Я использую Ans, чтобы сохранить номер в стеке.
lirtosiast
В начале я имел в виду - избавиться от строки 1 и изменить вторую строку на1+(":"=sub(Ans,1,1
MI Wright
1
Мне нужно использовать Str1 в цикле, где берется Ans, поэтому я не могу оставить строку в Ans. Хранение его на Str1 от Ans не сэкономит места.
lirtosiast
1

Идти, 129 115 112 байт

func m(s string){a,b:=0,0;for c,r:=range s{c=int(r/58);if b>0{a=a*b*c+(a+b)*(c^1);b=0}else{b,a=a,c+1}};print(a)}

(отчасти) разгневанный

func m(s string){
    // Our "stack"
    a, b := 0, 0
    // abusing the index asignment for declaring c
    for c, r := range s {
        // Ascii : -> 58, we can now use bit fiddeling
        c = int(r / 58)
        if b > 0 {
            // if r is :, c will be 1 allowing a*b to pass through, c xor 1 will be 0
            // if r is ., c xor 1 will be 1 allowing a+b to pass through
            a = a*b*c + (a+b)*(c^1)
            b = 0
        } else {
            b, a = a, c+1 // Since we already know c is 0 or 1
        }
    }
    print(a)
}

Попробуйте онлайн здесь: http://play.golang.org/p/B3GZonaG-y

Кристоффер Салл-Сторгард
источник
1

Python 3, 74

x,*s=[1+(c>'.')for c in input()]
while s:a,b,*s=s;x=[x*a,x+a][-b]
print(x)

Сначала преобразует входной список в последовательность из 1 и 2, принимая первое значение в качестве начального значения x. Затем снимает два элемента одновременно с передней части s, беря первое число и добавляя или умножая его на текущее число, основываясь на том, равен ли второй 1 или 2.

XNOR
источник
1

ну это так просто операция, сложная опера (намеренно)

просто ...

выражение в скобках переведено в постфиксную операцию * / +

Код: C (80 байт)

int f(char*V){return*(V-1)?f(V-2)*(*V==58?*(V-1)/29:1)+(*V&4)/4**(V-1)/29:*V/29;}
  • эта функция должна вызываться из хвоста строки следующим образом: f (V + 10) где V = ".: ..:.: .. ::"

вход

длина = 2n + 1 вектор V типа char '.' или ':'

Выход

целое число k

функция

  • k = (V [1] op (V [3]) V [2]) op (V [5]) V [4] ....

  • op (x): (x = '.') -> +, (x = ':') -> *


Моделирование:

попробуйте здесь

Abr001am
источник
Как вы можете предположить, что байт перед строкой ( *(V-1)) равен нулю?
Nutki
когда вы размещаете новый вектор, его начало всегда начинается с пустого сегмента, его конец она IS пустой символ
Abr001am
1

Сетчатка, 181 135 129 байт

Каждая строка должна быть в отдельном файле. <empty>представляет пустой файл. Выход в Унарном.

^\..*
$&1;
^:.*
$&11;
^.
<empty>
(`^\..*
$&1
^:.*
$&11
^.(.*?1+;1+)
$1
^(\..*);(1+)
$1$2;
;1$
;
^(:.*?)(1+).*
$1$2$2;
)`^.(.*?1+;)
$1
;
<empty>

Когда ${0}1используется, фигурные скобки отделяются $0от 1, в противном случае это была бы $011-я подходящая группа. Я пытался использовать $001, но это, похоже, не работает в. NET вкус регулярных выражений.

Изменить: Найдено, что так $&же, как $0.

В псевдокоде это, по сути, будет цикл do-while, как показано ниже. Я нажимаю первый номер, затем зацикливаю: нажимаю второй номер, убираю операцию (инструкцию), делаю математику, убираю оп. Продолжайте цикл. Обратите внимание, что когда операция прерывается, это также удалит пробел после выполнения всех инструкций.

комментарии:

^\..*           # Push if .
$&1;
^:.*            # Push if :
$&11;
^.              # Pop op
<empty>


(`^\..*         # Loop, Push #
$&1
^:.*
$&11
^.(.*?1+;1+)    # Pop op
$1


^(\..*);(1+)    # Add if . (move ;)
$1$2;
;1$          # If mul by 1, remove
;
^(:.*?)(1+).*   # Mul if : (double)
$1$2$2;
)`^.(.*?1+;)    # Pop op, End Loop (clean up)
$1
;               # Remove semicolon
<empty>
mbomb007
источник
Главное, что я вижу в гольфе - это пары шаблон / замена, такие как (:)(.*)-> $1$2, что, я уверен, может быть просто (:.*)-> $1(поскольку вы держите две группы в одном порядке и больше ничего с ними не делаете ).
DLosc
Я вдохновился и сделал свой собственный ответ Retina. Спасибо, что подтолкнули меня к загрузке этого интересного языка!
DLosc
@DLosc Круто! Да, я на самом деле не загрузил его. Я использовал онлайн тестер замены регулярных выражений для каждой отдельной замены.
mbomb007
0

Python 3, 122 байта

x=input()
l=[0,0]
for _ in x:
 t=len(l)-2<2
 l=[[[0,0,l[-2]*l[-1]],l+[2]][t],[[0,0,sum(l)],l+[1]][t]][_=='.']
print(l[-1])

Ungolfed:

x = input()
l = []
for i in x:
    if i == '.':
        if len(l) < 2: 
            l+=[1]        #True, True = 1,1
        else:
            l=[sum(l)]    #True, True = 1,0
    else:
        if len(l)<2:
            l+=[2]        #False, True = 0,1
        else:
            l=[l[0]*l[1]] #False, False = 0,0
print (l[0])

В python вы ссылаетесь на индекс списка следующим образом:

list[index]

Вы можете поместить логическое значение в это, Trueесть 1и Falseесть 0.

# t is True if the length is less than 2, else false.

l=[ 

  # |------- Runs if char is : -------|
  # |------- l<2 -------| |- l>=2 -|

    [ [ 0,0, l[-2]*l[-1] ], l+[2] ] [t],

                                      # |---- Runs if char is . ----| 
                                      # |--- l<2 ---|  |- l>=2 -|

                                        [ [0,0, sum(l)], l+[1] ] [t] ]
                                                                      [_=='.']

Попробуйте онлайн здесь

Тим
источник
0

Perl, 77 байт

@o=(0,'+','*');sub d{$_=shift;y/.:/12/;eval'('x s!\B(.)(.)!"$o[$2]$1)"!ge.$_}

расширен:

@o=(0, '+', '*');
sub d{
    $_=shift;
    y/.:/12/;
    eval '(' x s!\B(.)(.)!"$o[$2]$1)"!ge.$_
}

@oМассив отображает цифры для операторов. Затем мы заменяем пары цифр соответствующим оператором, переставленным в infix. Регулярное выражение начинается с \Bтого, что мы не сопоставляем самого первого символа. Результат s///gговорит нам, сколько открытых паренов нам нужно в начале. Затем, когда мы собрали полное инфиксное выражение, мы можем его оценить. (Удалите, evalесли хотите вместо этого увидеть выражение).

Вот тестовый жгут, который я использовал для проверки результатов:

while(<>) {
    my ($a, $b) = m/(.*) (.*)/;
    print d($a), " $b\n";
}

Входные данные представляют собой список выражений точек и их значений (приведены в вопросе), а выходные данные представляют собой пары {фактические, ожидаемые}.

Тоби Спейт
источник