Evaluación de cadenas con puntos

25

Escriba un programa que tome una cadena de longitud impar que contenga solo los caracteres .y :. Con la ayuda de una pila inicialmente vacía , genere un número a partir de esta cadena de la siguiente manera:

Para cada carácter c en la cadena (de izquierda a derecha) ...

  • Si c es .y la pila tiene menos de 2 elementos, presione 1 en la pila.
  • Si c es .y la pila tiene 2 o más elementos, saque los dos valores superiores de la pila y empuje su suma a la pila.
  • Si c es :y la pila tiene menos de 2 elementos, presione 2 en la pila.
  • Si c es :y la pila tiene 2 o más elementos, saque los dos valores superiores de la pila y empuje su producto a la pila.

El número resultante es el valor en la parte superior de la pila. Su programa debe imprimir este número en stdout (con una nueva línea final opcional).

(Un pequeño análisis muestra que solo queda un número a menos que la cadena tenga una longitud uniforme, por lo que los ignoramos. De hecho, la pila nunca tiene más de 2 elementos).

Por ejemplo, el número para ::...:.:.es 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

Como verificación de cordura, aquí están los números para todas las cadenas de longitud 1, 3 y 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

El programa más corto en bytes gana. Tiebreaker es una publicación anterior.

  • Puede suponer que la entrada siempre es válida, es decir, una cadena que solo contiene .y :cuya longitud es impar.
  • En lugar de escribir un programa, puede escribir una función que tome una cadena válida e imprima o devuelva el número generado.
Pasatiempos de Calvin
fuente
55
El mejor ecualizador minimalista de todos los tiempos.
dberm22

Respuestas:

13

CJam, 27 24 23 22 bytes

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

Muy claro. Uso la pila de CJam como la pila mencionada en la pregunta;)

Algoritmo

Primero veamos el código ASCII para .y :.

'.i ':ied

[46 58]

Dado que en CJam, el índice se ajusta, veamos si podemos usar estos valores directamente para obtener la operación deseada.

'.i4% ':i4%ed

[2 2]

Por lo tanto, no puedo simplemente usar los códigos ASCII en una cadena de operación de 4 longitudes. Probemos algunos otros valores.

'.i 10% ':i 10%ed

[6 8]

que en una cuerda de 4 longitudes se reduce a

[2 0]

Puedo usar esta operación mod 10 pero costará 2 bytes. Probemos otra cosa

'.i5% ':i5%ed

[1 3]

¡Bien !, ahora solo restamos 1 para la condición del tamaño de la pila para obtener los índices 0, 1, 2 and 3y usar una 5matriz de longitud ( "1+2* ") como un caso de cambio. El último espacio es solo un relleno para que sea de longitud 5. Esto es solo 1 byte adicional en comparación con la operación de modificación.

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

Pruébalo en línea aquí

1 byte guardado gracias a cosechy

Optimizador
fuente
1
¿Para qué hay espacio en la cadena de operaciones?
Peter Taylor
@PeterTaylor explicó en la publicación.
Optimizador
9

> <> (Pez) , 33 bytes

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

Bastante sencillo con pequeños trucos / optimizaciones.

Explicación:

  • Información: i= punto de código de la siguiente entrada de caracteres, -1si se alcanza el final de la entrada; a= 10; b= 11; )=>
  • ipunto de código de la primera entrada char,
  • b%1- top_of_stack mod 11 - 1máscaras 48 ('.') , 56 (':')para1 , 2
  • i:1+?\~n; si se alcanza el final de la entrada, imprima el último resultado y finalice
  • de otra manera:
  • b%1- entrada de máscara a 1 , 2
  • 0@empujar 0debajo del número dos
  • i5a*)lea la siguiente entrada y enmascarela para 0 , 1compararla con50
  • if 1( ':') multiplica los dos elementos superiores creando una pila [0 producto]
  • siempre agregue los dos elementos superiores creando pila [0 sum]o[0+product=product]
  • 40.saltar (bucle) de vuelta a la posición (4,0), nuestro punto 4,i:1+?\~n;
randomra
fuente
8

Haskell, 73 65 bytes

Una solución sencilla, utilizando el hecho de que la pila nunca tiene más de 2 elementos.

[x,y]#'.'=[x+y]
[x,y]#_=[x*y]
s#'.'=1:s
s#_=2:s
f=head.foldl(#)[]
alephalpha
fuente
5

C, 104 bytes

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;}

Bueno, esto es demasiado largo.

BrainSteel
fuente
5

Pyth, 25 24 bytes

eu?]?.xGHsGtG+GhHmqd\:zY

Tengo una idea al estudiar la solución de @ isaacg. Pero estoy usando una pila.

Demostración en línea o conjunto de pruebas

Explicación

Lo primero que hago es convertir la cadena de entrada en 0s y 1s. A "."se convierte en a 0, a ":"en a 1.

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

Luego reduzco esta lista de números:

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
fuente
4

JavaScript (ES6), 65

Solo usamos 2 celdas de nuestra pila.

Comience a poner un valor en s [0].
Luego, en cada posición impar (contando desde 0) en la cadena de entrada, ponga un valor en s [1].
En cada posición par, ejecute un cálculo (sumar o multiplicar) y almacenar el resultado en s [0].

Así que olvídate de la pila y usa solo 2 variables, a y b.

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

Una prueba rápida

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))
} 

Salida

"." 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
fuente
-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 al menos en mi borde que no funciona. for (i in s) proporciona propiedades adicionales además de índices
edc65
Me está funcionando en Firefox 37.0.2. Intenta ejecutarlo en una pestaña limpia del navegador. Parece StackExchange agrega propiedades adicionales a las cadenas (en stub.en.js)
nderscore
3

Pyth, 27 bytes

Jmhqd\:zu?*GhHteH+GhHctJ2hJ

¿Un montón? ¿Quién necesita una pila?

                       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.

Demostración.

isaacg
fuente
1
Genio. Y mientras tanto implementé una pila (32 bytes). :-(
Jakube
3

Retina , 105 75 73 bytes

Mi primer programa de retina! (Gracias a Martin Büttner por guardar 2 bytes, sin mencionar la invención del idioma en primer lugar).

Cada línea debe ir en un archivo separado; o puede ponerlos todos en un archivo y usar la -sbandera. La <empty>notación representa un archivo / línea vacío.

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

Inspirado por la respuesta de mbomb007 , pero adopto un enfoque algo diferente. Una diferencia importante es que construyo la pila frente a la cadena de puntos (con la parte superior de la pila hacia la derecha). Esto facilita la conversión de símbolos a los números correspondientes en el lugar. También lo uso en alugar de 1intercambiarlo solo al final, para evitar analizar la ambigüedad en secuencias como $1a. Si una respuesta como aaaaaaes aceptable como un número unario, las últimas dos líneas / archivos podrían eliminarse para guardar 4 bytes.

Explicación:

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

Coincide si hay 0 o 1 elementos en la pila ( (a+;)?) seguidos de un punto ( \.); si es así, reemplaza el punto con a;(es decir, empuja un 1).

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

Coincide si hay 0 o 1 elementos en la pila seguidos de dos puntos. Si es así, reemplaza el colon con aa;(es decir, empuja un 2).

;(a+;)\.
$1

Coincide si hay dos elementos en la pila seguidos de un punto. Elimina el punto y el punto y coma entre los elementos, y así los agrega.

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

Coincide si hay dos elementos en la pila, la parte superior de los cuales es un 2, seguido de dos puntos. Elimina los dos puntos y el 2 y repite el otro número dos veces, multiplicándolo así por 2.

)`;a;:
;

La expresión regular coincide si hay dos elementos en la pila, la parte superior de los cuales es un 1, seguido de dos puntos. Elimina los dos puntos y el 1, dejando el otro número sin cambios (es decir, multiplicado por 1).

)`indica el final de un ciclo. Si se realizó algún cambio en la cadena, el control vuelve a la parte superior del programa y ejecuta las sustituciones nuevamente. Si la cadena ha dejado de cambiar, hemos reemplazado todos los puntos y dos puntos, y todo lo que queda es la limpieza ...

;
<empty>

Elimina el punto y coma restante.

a
1

Transforma todas las a en 1. Nuevamente, si los números unarios pueden usar cualquier símbolo, este paso es innecesario.

DLosc
fuente
¿Se supone que el comienzo del ciclo es el primer archivo, entonces?
mbomb007
@ mbomb007 Sí. Lo había visto en los documentos, pero lo olvidé hasta que Martin me lo recordó. ;)
DLosc
2

Moho, 170 caracteres

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}

Más pruebas de que Rust es absolutamente terrible en el golf. Código completo sin golf:

#[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}

Aquí hay un truco interesante que utilicé en este. Puede eliminar un carácter en una instrucción if / else haciendo que devuelvan un valor que se descarta inmediatamente, lo que significa que solo necesita un punto y coma en lugar de dos.

Por ejemplo,

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

se puede cambiar a

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

que salva a un personaje al afeitarse un punto y coma.

Pomo de la puerta
fuente
2

Haskell, 88 81 79 Bytes

(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

Parece que alguien me dio en el blanco en una solución de Haskell, no solo eso, su solución es más corta que la mía. Eso es malo, pero no veo ninguna razón para no publicar lo que se me ocurrió.

ankh-morpork
fuente
2

APL (50)

Estoy en una gran desventaja aquí, porque APL no es un lenguaje basado en pila. Sin embargo, finalmente pude abusar de la reducción para acortar el programa.

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

La función interna toma un 'comando' a la izquierda y una pila a la derecha, y lo aplica, devolviendo la pila. La función externa lo reduce sobre la cadena, comenzando con una pila vacía.

Explicación:

  • (⌽⍵),⊂⍬: la lista inicial para reducir más. ⊂⍬es una lista vacía en caja, que representa la pila, (⌽⍵)es el reverso de la entrada. (La reducción se aplica de derecha a izquierda sobre la lista, por lo que la cadena se procesará de derecha a izquierda. Invertir la entrada de antemano hace que aplique los caracteres en el orden correcto).

  • {... }: la función interna. Toma la pila a la derecha, un personaje a la izquierda, y devuelve la pila modificada.

    • F←'.:'⍳⍺: el índice del carácter en la cadena .:, será 1 o 2 dependiendo del valor.
    • 2>⍴⍵:F,⍵: Si 2 es mayor que el tamaño actual de la pila, simplemente agregue el valor actual a la pila.
    • : de lo contrario,
      • 2↓⍵: elimina los dos elementos superiores de la pila
      • (... )/2↑⍵: reduce una función dada sobre ellos y agrégala a la pila.
      • ⍎F⌷'+×': la función es +(suma) o ×(multiplicación), seleccionada por F.
  • : finalmente, devuelve el elemento más alto en la pila

marinus
fuente
2

Ruby - 96 caracteres

La pieza interesante aquí es eval.

Aparte de eso, estoy asumiendo que después del primer carácter, la pila siempre irá 2, matemáticas, 2, matemáticas, ... Esto me permite usar menos código agarrando dos caracteres a la vez, nunca tengo que calcular averiguar si un personaje es matemático o número. Es posicional.

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

Sin golf:

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`
No es que Charles
fuente
2

TI-BASIC, 78 73 70 69 66 bytes

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 es bueno en líneas simples, porque el cierre de paréntesis es opcional; por el contrario, es un lenguaje pobre donde se requiere almacenar múltiples valores porque el almacenamiento en una variable requiere de dos a cuatro bytes de espacio. Por lo tanto, el objetivo es escribir tanto en cada línea como sea posible. TI-BASIC también es horrible (para un lenguaje tokenizado) en la manipulación de cadenas de cualquier tipo; incluso leer una subcadena es largo.

Los trucos incluyen:

  • int(e^([boolean]en lugar de 1+(boolean; ahorra un byte
  • Suma parcial de una lista en lugar de segmentación de la lista (lo que requeriría almacenar en una lista): ahorra 3 bytes
lirtosiast
fuente
Debería estar bien con la entrada de Ans, como ".:.":prgmDOTTY, guardar 4 bytes.
MI Wright
@Wright Uso Ans para almacenar el número en la pila.
lirtosiast
Me refería al principio: deshacerse de la línea 1 y cambiar la segunda línea a1+(":"=sub(Ans,1,1
MI Wright
1
Necesito usar Str1 en el bucle, donde se toma Ans, por lo que no puedo mantener la cadena en Ans. Almacenarlo en Str1 desde Ans no ahorrará espacio.
lirtosiast
1

Ir, 129 129 115 112 bytes

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)}

(un poco) no golfista:

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)
}

Pruébelo en línea aquí: http://play.golang.org/p/B3GZonaG-y

Kristoffer Sall-Storgaard
fuente
1

Pitón 3, 74

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

Primero transforma la lista de entrada en una secuencia de 1 y 2, tomando el primer valor como valor inicial x. Luego, saca dos elementos a la vez desde el frente s, toma el primer número y suma o multiplica con el número actual en función de si el segundo es 1 o 2.

xnor
fuente
1

bueno, esta es una operación tan fácil, sofisticada por el operador (intencionalmente)

es sólo ...

expresión entre paréntesis traducida en operación * / + postfix

Código: C (80 bytes)

int f(char*V){return*(V-1)?f(V-2)*(*V==58?*(V-1)/29:1)+(*V&4)/4**(V-1)/29:*V/29;}
  • esta función debería llamarse desde la cola de la cadena de esta manera: f (V + 10) donde V = ".: ..:.: .. ::"

entrada

longitud = 2n + 1 vector V de tipo char '.' o ':'

Salida

un entero k

Función

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

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


Simulación:

pruébalo aquí

Abr001am
fuente
¿Cómo puede suponer que el byte antes de la cadena ( *(V-1)) es cero?
nutki
cuando asigna un nuevo vector, su comienzo siempre comienza desde un segmento vacío, su final ES un carácter vacío
Abr001am
1

Retina, 181 135 129 bytes

Cada línea debe estar en un archivo separado. <empty>representa un archivo vacío La salida está en Unary.

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

Cuando ${0}1se usa, las llaves se separan $0del 1, de lo contrario, sería $01el primer grupo coincidente. Intenté usarlo $001, pero parece que esto no funciona en el sabor .NET de regex.

Editar: encontrado que $&es lo mismo que $0.

En pseudocódigo, esto sería esencialmente un ciclo do-while, como se ve a continuación. Presiono el primer número, luego repito: presiono el segundo número, elimino la operación (instrucción), hago matemáticas, elimino el op. Continuar en bucle. Tenga en cuenta que cuando aparece una operación, esto también eliminará el espacio después de que se hayan completado todas las instrucciones.

Comentado:

^\..*           # 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
fuente
Lo principal que estoy viendo en cuanto al golf son los patrones / pares de reemplazo como (:)(.*)-> $1$2, que estoy bastante seguro de que podría ser solo (:.*)-> $1(ya que mantiene los dos grupos en el mismo orden y no hace nada más con ellos) )
DLosc
Me inspiré e hice mi propia respuesta Retina. ¡Gracias por empujarme a descargar este interesante lenguaje!
DLosc
@DLosc Cool! Sí, en realidad no lo he descargado. Utilicé un probador de reemplazo de expresiones regulares en línea para cada reemplazo individual.
mbomb007
0

Python 3, 122 bytes

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])

Sin golf:

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])

En python, hace referencia al índice de una lista como esta:

list[index]

Puede poner un valor booleano en eso, Truees 1y Falsees 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] ]
                                                                      [_=='.']

Pruébalo en línea aquí

Tim
fuente
0

Perl, 77 bytes

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

expandido:

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

La @omatriz asigna dígitos a los operadores. Luego sustituimos pares de dígitos con el operador apropiado, reordenado a infijo. La expresión regular comienza por \Blo que no coincidimos con el primer personaje. El resultado de s///gnos dice cuántos padres abiertos necesitamos al principio. Luego, cuando hemos reunido la expresión infija completa, podemos evaluarla. (Retirareval si desea ver la expresión en su lugar).

Aquí está el arnés de prueba que utilicé para verificar los resultados:

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

La entrada es la lista de expresiones dotty y sus valores (provistos en la pregunta) y la salida es pares de {real, esperado}.

Toby Speight
fuente