Ir al contenido principal

Máximos valores de una expresión aritmética

Las expresiones aritméticas generales se pueden definir usando el siguiente tipo de datos

   data Expr = C Int
             | X
             | S Expr Expr
             | R Expr Expr
             | P Expr Expr
             | E Expr Int
     deriving (Eq, Show)

Por ejemplo, la expresión

   3*x - (x+2)^7

se puede definir por

   R (P (C 3) X) (E (S X (C 2)) 7)

Definir la función

   maximo :: Expr -> [Int] -> (Int,[Int])

tal que maximo e xs es el par formado por el máximo valor de la expresión e para los puntos de xs y en qué puntos alcanza el máximo. Por ejemplo,

   λ> maximo (E (S (C 10) (P (R (C 1) X) X)) 2) [-3..3]
   (100,[0,1])

Soluciones

A continuación se muestran las soluciones en Haskell y las soluciones en Python.

Soluciones en Haskell

data Expr = C Int
          | X
          | S Expr Expr
          | R Expr Expr
          | P Expr Expr
          | E Expr Int
  deriving (Eq, Show)

maximo :: Expr -> [Int] -> (Int,[Int])
maximo e ns = (m,[n | n <- ns, valor e n == m])
  where m = maximum [valor e n | n <- ns]

valor :: Expr -> Int -> Int
valor (C x) _     = x
valor X     n     = n
valor (S e1 e2) n = valor e1 n + valor e2 n
valor (R e1 e2) n = valor e1 n - valor e2 n
valor (P e1 e2) n = valor e1 n * valor e2 n
valor (E e1 m1) n = valor e1 n ^ m1

Soluciones en Python

from dataclasses import dataclass


@dataclass
class Expr:
    pass

@dataclass
class C(Expr):
    x: int

@dataclass
class X(Expr):
    pass

@dataclass
class S(Expr):
    x: Expr
    y: Expr

@dataclass
class R(Expr):
    x: Expr
    y: Expr

@dataclass
class P(Expr):
    x: Expr
    y: Expr

@dataclass
class E(Expr):
    x: Expr
    y: int

def valor(e: Expr, n: int) -> int:
    match e:
        case C(a):
            return a
        case X():
            return n
        case S(e1, e2):
            return valor(e1, n) + valor(e2, n)
        case R(e1, e2):
            return valor(e1, n) - valor(e2, n)
        case P(e1, e2):
            return valor(e1, n) * valor(e2, n)
        case E(e1, m):
            return valor(e1, n) ** m
    assert False

def maximo(e: Expr, ns: list[int]) -> tuple[int, list[int]]:
    m = max((valor(e, n) for n in ns))
    return (m, [n for n in ns if valor(e, n) == m])