ALPII Práctica 3 Bernardo García Fuentes 1
Ej. 1................................................................................................. modulus :: [Float] -> Float modulus = sqrt.sum.map square square :: Float -> Float square x = x^2 vmod :: [[Float]] -> [Float] vmod [] = [] vmod (v:vs) = modulus v : vmod vs {- smap 0 f = map f smap (n+1) f = map (smap n f) No se puede tipear la funcion smap en haskell por que su tipo depende de su argumento, en este caso, de (n+1). El caso base de smap devuelve una funcion g :: [a] -> [a] Si n = 0 smap devuelve g :: [[a]] -> [[a]] Si n = 1 smap devuelve g :: [[[a]]] -> [[[a]]] y asi sucesivamente. -} Ej. 2................................................................................................. hd :: [a] -> a hd (x:xs) = x tl :: [a] -> [a] tl (x:xs) = xs pred :: Int -> Int pred (x + 1) = x Ej. 3................................................................................................. ---> pred 0 Program error: pattern match failure: pred 0 Produce error por que no esta definida la funcion pred para un n tal que n+1 = 0 pred 0 = x falta de pattern matching (no esta definida para algun n tal que n+1=0) bottom ---> tl [pred 0] [] Devuelve la lista vacia por que la lista que se le pasa a tl es (x:xs) = (pred 0:[]) 1
tl [pred 0] = x notacion tl (pred 0:[]) = x def de tl [] ---> hd (tl [pred 0]) Program error: pattern match failure: hd [] hd(tl [pred 0]) = x notacion hd(tl (pred 0:[]) = x def de tl hd([]) = x falta de PM -> indefinido bottom Ej. 4................................................................................................. data Color = C Int Int Int deriving Show mezclar :: Color -> Color -> Color mezclar (C r1 g1 b1) (C r2 g2 b2) = C ((r1 + r2) div 2) ((g1 + g2) div 2) ((b1 + b2) div 2) Ej. 5................................................................................................. data DigBin = Cero Uno deriving (Show, Eq) {- 0 + 0 = 0 0 + 1 = 1 1 + 0 = 1 1 + 1,Acarreo 0 = 0, Acarreo 1 1 + 1,Acarreo 1 = 1, Acarreo 1 Por ej: 111 -> Acarreo 1010 1111 ---- 11001 -} -- Suma basica de binarios suma :: DigBin -> DigBin -> DigBin suma Cero Cero = Cero suma Cero Uno = Uno suma Uno Cero = Uno suma Uno Uno = Cero -- Producto Modulo 2 pmod2 :: DigBin -> DigBin -> DigBin 2
pmod2 Cero Cero = Cero pmod2 Cero Uno = Cero pmod2 Uno Cero = Cero pmod2 Uno Uno = Uno -- Esta funcion suma numeros binarios con el bit menos significativo como -- el primer elemento de la lista type NumBin = [DigBin] sumab_rev :: NumBin -> NumBin -> NumBin sumab_rev x y = suma x y Cero -- Las demas no las defino xq no tengo ganas. -- Ahora usando la convencion standard, donde el primer elemento de la lista es el -- bit mas significativo. -- Como la suma es de derecha a izquierda primero doy vuelta el orden de la lista -- si no empieza sumando del bit mas significativo al menos significativo y es al -- reves. Antes de devolverla vuelvo a dar vuelta el resultado para que se pueda -- leer como numbero binario. sumab :: NumBin -> NumBin -> NumBin sumab x y length x == length y = reverse(suma (reverse x) (reverse y) Cero) otherwise = error("los numeros binarios no tienen la misma cantidad de bits") suma :: NumBin -> NumBin -> DigBin -> NumBin suma [] [] acarreo acarreo == Cero = [] acarreo == Uno = Uno:[] suma [] (x:xs) acarreo = suma (x:xs) [] acarreo suma (x:xs) [] acarreo x == Cero && acarreo == Cero = Cero :(suma xs [] Cero) x == Uno && acarreo == Cero = Uno :(suma xs [] Cero) x == Cero && acarreo == Uno = Cero :(suma xs [] Uno) x == Uno && acarreo == Uno = Cero :(suma xs [] Uno) suma (x:xs) (y:ys) acarreo x == Cero && y == Cero && acarreo == Cero = Cero :(suma xs ys Cero) x == Cero && y == Uno && acarreo == Cero = Uno :(suma xs ys Cero) x == Uno && y == Cero && acarreo == Cero = Uno :(suma xs ys Cero) x == Cero && y == Cero && acarreo == Uno = Uno :(suma xs ys Cero) x == Cero && y == Uno && acarreo == Uno = Cero :(suma xs ys Uno) x == Uno && y == Cero && acarreo == Uno = Cero :(suma xs ys Uno) x == Uno && y == Uno && acarreo == Cero = Cero :(suma xs ys Uno) x == Uno && y == Uno && acarreo == Uno = Uno :(suma xs ys Uno) prodx2 :: NumBin -> NumBin prodx2 x = sumab x x {- Vamos a usar la resta, sumando el complemento a 2: El complemento a 1 de un valor binario se obtiene invirtiendo el estado 3
de todas sus cifras, incluyendo los ceros a la izquierda hasta completar la capacidad del registro. Por ejemplo, el valor 10011 en un registro de 8 bits (cifras) será 00010011 y su complemento a 1 será 11101100. El complemento a 2 de un valor binario se obtiene sumando 1 al complemento a 1. Por ejemplo, el complemento a 2 de 10011 (el mismo anterior) será 11101100 + 1 = 11101101. Cómo restar sumando: El complemento a 2 de un número binario se puede considerar directamente su equivalente negativo. Por lo tanto, para hacer la resta a - b = x? basta con calcular el resultado "x" (sin olvidar el tama~no del registro que se utilice) como: x = a + (complemento a 2 de b) Utilizando el Complemento a dos. La resta de dos números binarios puede obtenerse sumando al minuendo el complemento a dos del sustraendo. Veamos algunos ejemplos: Hagamos la siguiente resta, 91-46 = 45, en binario: 1011011 1011011-0101110 C246 = 1010010 +1010010 -------- -------- 0101101 10101101 En el resultado nos sobra un bit, que se desborda por la izquierda. Pero, como el número resultante no puede ser más largo que el minuendo, el bit sobrante se desprecia. -} complemento_1 :: NumBin -> NumBin complemento_1 [] = [] complemento_1 (x:xs) x == Cero = Uno : complemento_1 xs x == Uno = Cero : complemento_1 xs complemento_2 :: NumBin -> NumBin complemento_2 x = sumab (complemento_1 x) (binunoconzeros (length x)) -- Esta funcion genera el numero binario uno de n bits [Cero,Cero,...,Uno] -- para poder hacer el complemento a 2 binunoconzeros :: Int -> NumBin binunoconzeros 1 = [Uno] binunoconzeros n = Cero : binunoconzeros (n-1) restab :: NumBin -> NumBin -> NumBin restab x y length(sumab x (complemento_2 y)) > length x = tail(sumab x (complemento_2 y)) otherwise = sumab x (complemento_2 y) -- La division x 2 es un shift a la derecha, descartando el ultimo bit -- 1010 / 2 = 0101 cocientebx2 :: NumBin -> NumBin cocientebx2 x = Cero : reverse(tail(reverse x)) 4
-- El resto de la division x 2 es el bit que desapareceria si hiciesemos -- un shift a la derecha restococientebx2 :: NumBin -> DigBin restococientebx2 x = head(reverse x) Ej. 6................................................................................................. -- Defino los Bags como una lista de tuplas -- [(elemento, Numero de apariciones de un elemento)] type Bag a = [(a,int)] --list2bag :: [a] -> Bag a list2bag [] = [] list2bag (x:xs) = baginsert x (list2bag xs) --baginsert :: a -> Bag a -> Bag a baginsert a [] = [(a,1)] baginsert a ((b,n):xs) = if a == b then (b,n+1):xs else (b,n):baginsert a xs bagempty x = if x == [] then True else False bagcar [] = 0 bagcar ((b,n):xs) = n + bagcar xs bagelem a [] = False bagelem a ((b,n):xs) = if a == b then True else bagelem a xs bagocurr a [] = False bagocurr (a,n) ((b,m):xs) = if a == b && n==m then True else bagocurr (a,n) xs bagequal [] [] = True bagequal _ [] = False bagequal [] _ = False bagequal ((a,n):xs) ((b,m):ys) = if a==b && n==m then True && bagequal xs ys else False bagsubbag [] [] = True bagsubbag _ [] = False bagsubbag [] _ = True bagsubbag ((a,n):xs) ((b,m):ys) = if a==b && n<=m then True && bagsubbag xs ys else bagsubbag ((a,n):xs) ys bagminenbag [] [] = 0 bagminenbag _ [] = 0 bagminenbag [] _ = 0 bagminenbag [(a,n)] ((b,m):ys) = if a==b then min n m else bagminenbag [(a,n)] ys baginter [] _ = [] baginter ((a,n):xs) ((b,m):ys) = if x > 0 then (a, x):baginter xs ((b,m):ys) 5
else baginter xs ((b,m):ys) where x = bagminenbag [(a,n)] ((b,m):ys) insertnveces a 1 ys = baginsert a ys insertnveces a n ys = baginsert a (insertnveces a (n-1) ys) bagsum [] ys = ys bagsum ((a,n):xs) ys = bagsum xs (insertnveces a n ys) bagdelete _ [] = [] bagdelete (a,n) ((b,m):ys) a/=b = (b,m):bagdelete (a,n) ys a==b && n>=m = ys a==b && n<m = (b,m-n):ys 6