Movimientos en el plano
Se consideran el tipo de las posiciones del plano definido por
| 1 2 3 4 5 6 |    type Posicion = (Int,Int)    <7p y el tipo de las direcciones definido por <pre lang="text">    data Direccion = Izquierda | Derecha | Arriba | Abajo      deriving Show | 
Definir las siguientes funciones
| 1 2 3 |    opuesta     :: Direccion -> Direccion    movimiento  :: Posicion -> Direccion -> Posicion    movimientos :: Posicion -> [Direccion] -> Posicion | 
tales que
- opuesta des la dirección opuesta de- d. Por ejemplo,
| 1 |      opuesta Izquierda == Derecha | 
- movimiento p des la posición reultante de moverse, desde la posición- p, un paso en la dirección- d. Por ejemplo,
| 1 2 |      movimiento (2,5) Arriba          == (2,6)      movimiento (2,5) (opuesta Abajo) == (2,6) | 
- movimientos p dses la posición obtenida aplicando la lista de movimientos según las direcciones de- dsa la posición- p. Por ejemplo,
| 1 |      movimientos (2,5)  [Arriba, Izquierda] == (1,6) | 
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | type Posicion = (Int,Int) data Direccion = Izquierda | Derecha | Arriba | Abajo   deriving Show -- Definición de opuesta -- ===================== opuesta :: Direccion -> Direccion opuesta Izquierda = Derecha opuesta Derecha   = Izquierda opuesta Arriba    = Abajo opuesta Abajo     = Arriba -- 1ª definición de movimiento -- =========================== movimiento1 :: Posicion -> Direccion -> Posicion movimiento1 (x,y) Izquierda = (x-1,y) movimiento1 (x,y) Derecha   = (x+1,y) movimiento1 (x,y) Arriba    = (x,y+1) movimiento1 (x,y) Abajo     = (x,y-1) -- 2ª definición de movimiento -- =========================== movimiento2 :: Posicion -> Direccion -> Posicion movimiento2 (x,y) d =   case d of     Izquierda -> (x-1,y)     Derecha   -> (x+1,y)     Arriba    -> (x,y+1)     Abajo     -> (x,y-1) -- 1ª definición de movimientos -- ============================ movimientos1 :: Posicion -> [Direccion] -> Posicion movimientos1 p []     = p movimientos1 p (d:ds) = movimientos1 (movimiento1 p d) ds -- 2ª definición de movimientos -- ============================ movimientos2 :: Posicion -> [Direccion] -> Posicion movimientos2 = foldl movimiento1 | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | from enum import Enum from functools import reduce Posicion = tuple[int, int] Direccion = Enum('Direccion', ['Izquierda', 'Derecha', 'Arriba', 'Abajo']) # 1ª definición de opuesta # ======================== def opuesta1(d: Direccion) -> Direccion:     if d == Direccion.Izquierda:         return Direccion.Derecha     if d == Direccion.Derecha:         return Direccion.Izquierda     if d == Direccion.Arriba:         return Direccion.Abajo     if d == Direccion.Abajo:         return Direccion.Arriba     assert False # 2ª definición de opuesta # ======================== def opuesta2(d: Direccion) -> Direccion:     match d:         case Direccion.Izquierda:             return Direccion.Derecha         case Direccion.Derecha:             return Direccion.Izquierda         case Direccion.Arriba:             return Direccion.Abajo         case Direccion.Abajo:             return Direccion.Arriba     assert False # 1ª definición de movimiento # =========================== def movimiento1(p: Posicion, d: Direccion) -> Posicion:     (x, y) = p     if d == Direccion.Izquierda:         return (x - 1, y)     if d == Direccion.Derecha:         return (x + 1, y)     if d == Direccion.Arriba:         return (x, y + 1)     if d == Direccion.Abajo:         return (x, y - 1)     assert False # 2ª definición de movimiento # =========================== def movimiento2(p: Posicion, d: Direccion) -> Posicion:     (x, y) = p     match d:         case Direccion.Izquierda:             return (x - 1, y)         case Direccion.Derecha:             return (x + 1, y)         case Direccion.Arriba:             return (x, y + 1)         case Direccion.Abajo:             return (x, y - 1)     assert False # 1ª definición de movimientos # ============================ def movimientos1(p: Posicion, ds: list[Direccion]) -> Posicion:     if not ds:         return p     return movimientos1(movimiento1(p, ds[0]), ds[1:]) # 2ª definición de movimientos # ============================ def movimientos2(p: Posicion, ds: list[Direccion]) -> Posicion:     return reduce(movimiento1, ds, p) |