PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/sandbox.hs

http://github.com/jneira/haskell-desk
Haskell | 577 lines | 264 code | 85 blank | 228 comment | 31 complexity | b611848fd6fb16d48f957960cf9eecc1 MD5 | raw file
  1. {-# LANGUAGE DatatypeContexts #-}
  2. module Sandbox where
  3. -- Ejemplos y ejercicios siguiendo el libro: "Programacion Funcional" de Jeroem Fokker
  4. -- http://people.cs.uu.nl/jeroen/
  5. -- Algunas de las soluciones copiadas de ALBERTO RODRIGUEZ CALVO-}
  6. import Data.List as List
  7. import Data.Array as Array
  8. import Data.Char
  9. import Data.Ord
  10. import Control.Monad.Writer
  11. fac n = product [1..n]
  12. comb n k = fac n / (fac k * fac (n-k))
  13. n !^! k=comb n k
  14. formulaWhere a b c = [(-b+d)/n, (-b-d)/n ]
  15. where d= sqrt (b*b-4.0*a*c)
  16. n= 2.0*a
  17. facrec n |n==0 = 1
  18. |n>0 = n * fac (n-1)
  19. --Ejemplos de patrones en la declaracion (destructuracion en la llamada)
  20. facrec2 0 = 1
  21. --facrec2 (n+1)=(n+1)*fac n
  22. {-Es posible crear listas de funciones, si estas funciones (como numeros, valores booleanos y listas) son de un
  23. mismo tipo, es posible hacer listas de funciones.
  24. :type [sin,cos,tan]-}
  25. {-Esta permitido escribir el tipo de una funcion en el
  26. programa. La definicion de funcion se realizarla de la siguiente forma:-}
  27. mysum :: [Int] -> Int
  28. mysum [] = 0
  29. mysum (x:xs) = x + mysum xs
  30. {-Aunque la declaracion del tipo es superflua, tiene dos ventajas:
  31. * se comprueba si la funcion tiene el tipo que esta declarado.
  32. * la declaracion del tipo ayuda a entender la funcion.-}
  33. add5 :: [Int] -> [Int]
  34. add5 [] = []
  35. add5 (x:xs) = (x+5):add5(xs)
  36. add6 :: Int -> Int
  37. add6 n = n+6
  38. lpad :: Int -> Char -> [Char] -> [Char]
  39. lpad 0 c cad = cad
  40. lpad n c cad = lpad (n-1) c (c:cad)
  41. {- Ejercicio 1.1.
  42. Escriba una funcion que cuente cuantos numeros negativos existen en una lista.-}
  43. countNeg0 xs = foldl (\x y -> if y<0 then x+1 else x) 0 xs
  44. countNeg1 xs=sum [1 | x <- xs,x<0]
  45. countNeg2 [] = 0
  46. countNeg2 (h:t) | h < 0 = 1 + countNeg2 t
  47. | otherwise = countNeg2 t
  48. {- Ejercicio 1.2
  49. Escriba una funcion diag que tenga una lista de caracteres como parametro
  50. y que de como resultado los caracteres
  51. en una diagonal.-}
  52. diag str=putStrLn $ reduce 0 str
  53. where reduce n []=""
  54. reduce n (h:t)= replicate n ' '
  55. ++ [h] ++ reduce (n+1) t
  56. {- Ejercicio 1.3
  57. Escriba una funcion cuadrado que dada una lista de caracteres, presente tantas
  58. copias de esta serie de caracteres (cada copia en una nueva linea), de manera
  59. que el numero de las letras en horizontal sea igual al numero de las letras
  60. que hay verticalmente. Tenga en cuenta que una cadena de caracteres es en realidad
  61. una lista de caracteres -}
  62. cuadrado str= putStrLn.unlines $ replicate (length str) str
  63. {- Ejercicio 1.4
  64. Escriba una funcion dividir, de manera que dada una lista de caracteres de como
  65. resultado otra lista, pero ahora dividida en lineas. Cada vez que haya dos
  66. caracteres seguidos que sean iguales se insertar en el resultado una
  67. nueva linea (entre los dos caracteres iguales) -}
  68. dividir lst=let line x (h:t) |x==h=x:'\n':h:t
  69. |otherwise=x:h:t
  70. f (h:t)=foldr line [last (h:t)] $ init (h:t)
  71. f []=[]
  72. in putStrLn $ f lst
  73. {- Ejercicio 3.1
  74. Escriba una funcion aproxseno que, dados dos numeros eps y x
  75. (el primero mayor que 0, el segundo cualquiera),
  76. de como resultado el numero y con la propiedad de que
  77. | sin x - y | < eps
  78. Use la siguiente regla matematica:
  79. (-1)^n * x ^(2*n+1) /(fromIntegral $ fac (2*n+1))
  80. Escriba dos veces una definicion para aproxseno:
  81. una vez usando la funcion iterate y otra con until.
  82. -}
  83. aproxseno x eps = head $ until (\(y:_)-> abs (sin x-y) < eps)
  84. (\(fst:snd:tail) -> fst+snd:tail)
  85. $ termsTaylor x
  86. termsTaylor x= map (term x) [0..]
  87. term x n= (-1)^n * x ^(2*n+1) /(fromIntegral $ fac (2*n+1))
  88. aproxseno2 x eps= head $ dropWhile (\y-> abs (sin x-y) >= eps)
  89. $ map head $ iterate (\(fst:snd:tail) -> fst+snd:tail)
  90. $ termsTaylor x
  91. {- Ejercicio 3.4
  92. ¿Que funcion f y que lista a cumplen la siguiente regla?
  93. map (+1) . reverse = foldl f a -}
  94. assert 3.4 f lst=(map (+ 1).reverse $ lst)
  95. == (f lst)
  96. test 3.41 = assert 3.4 (foldl (\a b->b+1:a) []) [0,1,2,3]
  97. {- Ejercicio 3.5
  98. Defina una funcion esta que controle si existe cierto elemento en una lista de elementos. Defina la funcion de las
  99. siguientes maneras:
  100. 1 Tome todos los elementos iguales al elemento buscado y coloque estos en una lista. Compruebe despues si
  101. esta lista esta vacia o no.
  102. 2 Haga una nueva lista en la que todos los elementos iguales al elemento buscado sean reemplazados por 1 y los
  103. otros elementos por 0. Sume los elementos de la lista resultante y compruebe si el resultado es igual a 0 o no.
  104. 3 Compruebe para cada elemento si es igual al elemento buscado o no. Despues compruebe si uno de estos tests
  105. devolvio True.-}
  106. esta 0 x lst = not.null.(filter (== x)) $ lst
  107. esta 1 x lst = 0 < (sum $ map (\y->if y==x then 1 else 0) lst)
  108. esta 2 x lst = or $ map (== x) lst
  109. esta 3 x lst = any (== x) lst
  110. {-Ejercicio 3.6
  111. Escriba una funcion posiciones que devuelva una lista de indices de las posiciones de un elemento determinado en
  112. una lista de elementos.
  113. Por ejemplo:
  114. ? posiciones 4 [1,4,3,7,4,2]
  115. [2,5]
  116. ? posiciones [3,5] [[3,6],[2,5]]
  117. [] -}
  118. posiciones x lst= let acc (i,is) y | x==y = (i+1,is++[i])
  119. | otherwise=(i+1,is)
  120. in snd $ foldl acc (0,[]) lst
  121. {-Ejercicio 3.7
  122. Escriba una funcion ndedc (numero de elementos distintos creciente), que dada una lista no decreciente de numeros,
  123. decida cuantos numeros distintos hay en la lista.
  124. Use el dato de que la lista esta ordenada.-}
  125. ndedc:: (Eq a) => [a] -> Int
  126. ndedc lista = let norep [] n=[n]
  127. norep (x:xs) n | x == n = x:xs
  128. | otherwise = n:x:xs
  129. in length $ foldl norep [] lista
  130. {-Ejercicio 3.8
  131. Escriba una funcion nded (numero de elementos distintos), que, dada una lista cualquiera de numeros, devuelva
  132. cuantos numeros distintos existen en la lista.
  133. Una posibilidad de resolver este problema es contar solamente la primera ocurrencia de cada numero en la lista.
  134. -}
  135. nded :: (Eq a)=>[a]->Int
  136. nded = length.nub
  137. nded2::(Eq a)=>[a]->Int
  138. nded2 = let cont (x,xs) y | elem y xs = (x,xs)
  139. | otherwise = (x+1,y:xs)
  140. in fst .(foldl cont (0,[]))
  141. {-Ejercicio 3.9
  142. Escriba una funcion segmento, que, dados una lista xs y dos numeros i y j, devuelva una sublista de xs desde el
  143. indice i+1 hasta el indice j.
  144. No se puede usar el operador !!.
  145. Antes de contestar esta pregunta, se debe especificar que pasa si j <= i, j > #xs y si i > #s.-}
  146. segmento2 i j lst
  147. | j > (length lst)=segmento i (length lst) lst
  148. | i>=j = segmento j i lst
  149. | otherwise= let acc (c,xs) x | c>=i && c<=j = (c+1,xs++[x])
  150. | otherwise = (c+1,xs)
  151. in snd $ foldl acc (0,[]) lst
  152. segmento:: Int -> Int -> [a] -> [a]
  153. segmento i j lista | i >= j = segmento2 j i lista
  154. | i < 0=segmento2 0 j lista
  155. | j > l=segmento2 i l lista
  156. | otherwise=take (j-i) (drop i lista)
  157. where l=length lista
  158. {-Ejercicio 3.10
  159. Escriba una funcion esSegmento, que, dadas dos listas xs y ys devuelva True si xs es segmento de ys,
  160. y False si no.
  161. Una lista xs es sublista de ys cuando ys = hs ++ xs ++ ts, con hs, ts listas de cero o mas elementos.
  162. Se puede usar la funcion segmento del ejercicio anterior.-}
  163. esSegmento xs ys
  164. | length xs > length ys = False
  165. | h1==h2 && xs == take (length xs) ys = True
  166. | otherwise = esSegmento xs t2
  167. where (h1:_,h2:t2)=(xs,ys)
  168. esSegmento2 xs ys | length xs > (length ys) = False
  169. | xs == take (length xs) ys = True
  170. | otherwise = esSegmento2 xs (tail ys)
  171. {-Ejercicio 3.11
  172. Escriba una funcion scdosa (sigue concatenando los dos anteriores), que, dadas dos listas xs y ys
  173. del mismo tipo, devuelva una lista infinita de listas, con las siguientes propiedades:
  174. *Los primeros dos elementos son respectivamente xs y ys.
  175. *Para cada n > 0 el n+2-esimo elemento es la concatenacion del n-esimo elemento con el n+1-esimo elemento.
  176. Use la funcion iterate.-}
  177. scdosa xs ys =xs:(map last $ iterate (\lst -> lst++[(last.init $ lst) ++ (last lst)]) [xs,ys])
  178. -- La buena
  179. acdosa2 xs ys = map fst $ iterate (\(xs,ys)->(ys,xs++ys)) (xs, ys)
  180. {-Ejercicio 3.12
  181. Escriba una funcion sssp (sigue sumando el segmento previo), que, dada una lista finita de numeros ns con un
  182. tamaño k > 0, devuelva una lista infinita ms que cumpla con las siguientes propiedades:
  183. * ns = take k ms
  184. * Para todo n >= k : ms!!(n+1) = (sum . drop (n-k) . take n) ms
  185. Por ejemplo:
  186. sssp [0,0,1] = [0,0,1,1,2,4,7,13,24,44..
  187. Use la funcion iterate.-}
  188. sssp lst = let k=length lst
  189. f xs=let n=length xs
  190. in xs++[(sum.drop(n-k).take n) xs]
  191. in init lst ++ (map last $ iterate f lst)
  192. sssp2:: [Int] -> [Int]
  193. sssp2 xs = xs ++ map fst ( iterate f (sum xs, xs) )
  194. where f (suma, y:ys) = (sum zs, zs) where zs = ys ++ [suma]
  195. -- La buena
  196. sssp3 ns = map head (iterate f ns)
  197. where f ns = (tail ns) ++ [sum ns]
  198. {-Ejercicio 3.13
  199. Escriba una funcion elimDobles, que, dada una lista (que puede ser infinita), devuelva una nueva lista, con solamente
  200. una ocurrencia de cada elemento de la lista original. El problema en este ejercicio es que la lista puede ser infinita.
  201. Por eso, no puede usar las funciones foldr y foldl.-}
  202. elimDobles []=[]
  203. elimDobles (x:xs) = x:(elimDobles (filter (/=x) xs))
  204. {-Ejercicio 3.14
  205. Un valor x se denomina extremo interno con indice i en la lista xs, si i es un indice con las siguientes propiedades:
  206. 1 < i < length xs
  207. xs!!i = x
  208. existen una j y una k , con j < i y k > i con xs!!j /= x y xs!!k /= x
  209. la mayor j (j < i) y la menor k (k > i) con xs!!j /= x y xs!!k /= x cumplen con la condicion que
  210. o xs!!j > x y xs!!k > x
  211. o xs!!j < x y xs!!k < x
  212. Dos extremos internos con indices i y j en una lista son vecinos si no existe otro extremo con indice k y i < k < j
  213. o j < k < i.
  214. Escriba una funcion extremos, que calcule los extremos internos de una lista.
  215. Use la funcion foldl.-}
  216. -- La mia
  217. extremos [h]= []
  218. extremos [h,t]=[]
  219. extremos (h:t)=
  220. let f (acc,p) x
  221. | x>p && (head acc)>p ||
  222. x<p && (head acc)<p=(p:acc,x)
  223. | otherwise= (acc,x)
  224. in init.fst $ foldl f ([h],h) t
  225. extremos1 [h]= []
  226. extremos1 [h,t]=[]
  227. extremos1 (h:t)=let f (acc,p) x = (acc++e,x)
  228. where e | x>p && (last acc)>p ||
  229. x<p && (last acc)<p=[p]
  230. | otherwise=[]
  231. in tail.fst $ foldl f ([h],h) t
  232. --Otra
  233. extremos2:: [Int] -> [Int]
  234. extremos2 lista = fst (foldl f ([], []) lista)
  235. where f ([], []) n = ([], [n])
  236. f (extremos, (y:ys)) n | ys == [] && y == n =(extremos, (y:ys ))
  237. | ys == [] && y /= n =(extremos, (y:[n]))
  238. | head ys == n =(extremos, (y:ys))
  239. | (y < head ys)==((head ys) < n)=(extremos, y:[n])
  240. | otherwise =(extremos ++ [head ys], (head ys):[n])
  241. {-Ejercicio 3.15
  242. Escriba una funcion distanciaExtr que calcule la maxima distancia entre dos extremos vecinos. (Ver el ejercicio
  243. 3.14 para la definicion de extremos.) Si no existen dos extremos vecinos en la lista, entonces el resultado sera 0.-}
  244. distanciaExtr (h:t)=
  245. let f ((i,max),(acc,p)) x
  246. | x>p && (head acc)>p ||
  247. x<p && (head acc)<p=((0,max'),(p:acc,x))
  248. | otherwise= ((i',max),(acc,x))
  249. where i'=i+1
  250. max' | max<0=0 | i'>max=i'
  251. |otherwise=max
  252. in snd.fst $ foldl f ((0,-1),([h],h)) t
  253. -- Entendi mal no es la distancia segun el indice del extremo sino la diferencia entre valores:
  254. distanciaExtr2:: [Int] -> Int
  255. distanciaExtr2 lista = maxDif (extremos lista)
  256. -- Maxima diferencia absoluta entre dos elementos consecutivos
  257. maxDif:: [Int] -> Int
  258. maxDif (x:xs) | length (x:xs) < 2=0
  259. | otherwise=fst ( foldl f (0, x) xs )
  260. where f (a, b) n=( max (abs(b-n))a, n )
  261. {-Ejercicio 3.16
  262. Escriba una funcion recursiva sc (sublistas crecientes), que, dada una lista, devuelva una lista de listas que existan
  263. en todas las sublistas no decrecientes de la lista. Escriba tambien una definicion de sc usando foldr.
  264. Por ejemplo:
  265. ? sc [6,1,4,8] = [[],[6],[1],[1,4],[4],
  266. [1,4,8],[4,8],[1,8],[6,8],[8]]-}
  267. sc lista = combinacion lista
  268. where combinacion [] = []
  269. combinacion (x:xs) = combinacion xs
  270. ++ (combina x $ combinacion xs)
  271. combina elemento [] = [[elemento]]
  272. combina elemento (x:xs) | x == [] = combina elemento xs
  273. | elemento <=head x=(elemento:x):(combina elemento xs )
  274. | otherwise=combina elemento xs
  275. --Solucion con foldr
  276. sc2:: [Int] -> [[Int]]
  277. sc2 lista = foldr f [] lista
  278. where f elemento xs = xs ++ (combina elemento xs)
  279. {-Ejercicio 3.17
  280. Escriba una funcion dividir, que, dados una lista no decreciente xs y un elemento x, devuelva una tupla de dos
  281. listas (ys,zs), con xs = ys ++ zs, donde todos los elementos de ys sean menores o iguales que x, y todos los
  282. elementos de zs sean mayores que x.
  283. Escriba una funcion insertar, que, dados una lista no decreciente ys y un elemento y, devuelva una lista no
  284. decreciente igual a ys mas el elemento y insertado en el lugar correspondiente.
  285. dividir :: a -> [a] -> ([a],[a])-}
  286. x <=: (h:t) = null t || h>x
  287. dividir2 x xs= (takeWhile (x>=) xs,dropWhile (x>=) xs)
  288. dividir3 :: (Ord a)=>a -> [a] -> ([a],[a])
  289. dividir3 x xs=until ((x <=:).snd) (\(ys,(h:t))->(ys++[h],t)) ([],xs)
  290. dividir4 x xs=span (x>=) xs
  291. insertar x xs=let (ys,zs)=dividir2 x xs
  292. in ys++(x:zs)
  293. {-Ejercicio 3.18
  294. Escriba una funcion unico, que, dada una lista devuelva una lista que contenga exactamente los elementos que se
  295. encuentran solamente una vez en la lista dada. Por ejemplo:
  296. "Cuales son las letras unicas en esta frase?"
  297. "oicf?" -}
  298. strt="Cuales son las letras unicas en esta frase?"
  299. unico str=let low=map toLower str;nuby=nub low
  300. in nuby\\(low\\nuby)
  301. unico1 []=[]
  302. unico1 ls=let low=map toLower ls
  303. f acc []=acc
  304. f acc (h:t)
  305. |elem h t =f acc flt
  306. |otherwise=f (acc++[h]) flt
  307. where flt=filter (/= h) t
  308. in f [] low
  309. unico2=concat.(filter ((== 1).length)).group.sort.(map toLower)
  310. {-Ejercicio 3.19
  311. a. Escriba una funcion segcrec (segmentos crecientes), que dada una lista, devuelva una lista de listas que cumpla
  312. con las siguientes condiciones:
  313. la concatenacion de los elementos en el resultado devuelve la lista original
  314. todos los elementos del resultado son listas no decrecientes y tampoco son vacias
  315. por cada segmento no decreciente ys de la lista dada, existe un elemento en el resultado del cual ys es
  316. un segmento
  317. La definicion de segcrec debe ser en base a foldl o foldr.
  318. b. De tambien una definicion recursiva de segcrec.
  319. Ejemplo:
  320. ? segcrec [1,2,3,4,2,3,5,6,4,8,3,2]
  321. [[1,2,3,4],[2,3,5,6],[4,8],[3],[2]]-}
  322. lst 3.19=[1,2,3,4,2,3,5,6,4,8,3,2]
  323. segrec []=[]
  324. segrec (h:t)=let f lst x | x>=(last.last$lst)=(init lst)++[last lst++[x]]
  325. | otherwise=lst++[[x]]
  326. in foldl f [[h]] t
  327. segrec1 lst=let f x []=[[x]]
  328. f x (h':t') | x<(head h') = (x:h'):t'
  329. | otherwise=[x]:(h':t')
  330. in foldr f [] $ lst
  331. segrec2 []=[]
  332. segrec2 [h]=[[h]]
  333. segrec2 (h:h':t)|h>h'=[h]:next
  334. |otherwise=(h:(head next)):(tail next)
  335. where next=segrec2 $ h':t
  336. {-Ejercicio 3.20
  337. Escriba una funcion recursiva esSubLista, que, dadas dos listas, devuelva True si la segunda lista es una sublista
  338. de la primera, y False si no. Decimos que ys es una sublista de la lista xs si existe una lista creciente de numeros
  339. positivos is, con ys = [xs!!i|i<-is]. Ejemplos:
  340. ? esSubLista "muchisimo" "uso"
  341. True
  342. ? esSubLista [1,4,2,5,7] [4,7]
  343. True
  344. ? esSubLista [1,4,2,5,7] [2,1]
  345. False
  346. -- Useful tips -}
  347. esSubLista xs []=True
  348. esSubLista [] ys=False
  349. esSubLista (h:t) (h':t')
  350. | (h:t)==(h':t')=True
  351. | h==h'=esSubLista (h:t) t'
  352. | otherwise = esSubLista t (h':t')
  353. {-Ejercicio 3.21
  354. Escriba una funcion partir, que, dados un predicado p y una lista xs, devuelva una tupla de listas (ys,zs) en tal
  355. forma que ys contenga todos los elementos de xs, que cumplan con la condicion p, y en zs el resto de los elementos
  356. de xs. Por ejemplo:
  357. ? partir digit "a1!,bc4"
  358. ("14","a!,bc")
  359. Es posible escribir una definicion simple y correcta:
  360. partir p xs = (filter p xs, filter (not.p) xs)
  361. Pero, en este ejercicio queremos practicar el uso de las funciones fold. Entonces, debes dar una definicion en base
  362. a foldr o foldl.-}
  363. -- Esta funcion es una generalizacion del ejercicio 3.17 y se pueden trasladar las soluciones
  364. -- directamente poniendo el predicado como parametro
  365. partir=span
  366. partir1 pred xs= (takeWhile pred xs,dropWhile pred xs)
  367. partir2 pred xs=until (pred.head.snd) (\(ys,(h:t))->(ys++[h],t)) ([],xs)
  368. --Pero nos la piden con foldl y/o foldr
  369. partirL pred xs=let nxt (xs,ys) x
  370. | pred x=(xs,ys++[x])
  371. | otherwise =(xs++[x],ys)
  372. in foldl nxt ([],[]) xs
  373. partirR pred xs=let nxt x (xs,ys) |pred x=(xs,x:ys)
  374. |otherwise=(x:xs,ys)
  375. in foldr nxt ([],[]) xs
  376. {-Ejercicio 3.22
  377. Escriba las funciones sumar, multiplicar, restar y dividir para numeros complejos. Un numero complejo es de la
  378. forma a + bi, con a, b numeros reales, y i un numero con la propiedad: i2 = -1. Para la funcion dividirCompl
  379. puede ser util primero derivar una formula para 1/a+bi . Para esto, puedes calcular los valores de x e y en la ecuacion
  380. (a + bi)*(x + yi) = (1 + 0i).-}
  381. -- Mezcla de la libreria de Haskell complex y la funcion de division de Alberto
  382. infix 6 :+
  383. data (RealFloat a) => Complex a = !a :+ !a deriving (Eq,Read,Show)
  384. instance (RealFloat a) => Num (Complex a) where
  385. (x:+y) + (x':+y') = (x+x') :+ (y+y')
  386. (x:+y) - (x':+y') = (x-x') :+ (y-y')
  387. (x:+y) * (x':+y') = (x*x'-y*y') :+ (x*y'+y*x')
  388. abs z = undefined
  389. signum z = undefined
  390. fromInteger n = fromInteger n :+ 0
  391. dividirCompl:: Complex Float-> Complex Float-> Complex Float
  392. dividirCompl (x:+y) (x':+y') = (x:+y) * ((x'/div):+(-y'/div))
  393. where div = x'*x' + y'*y'
  394. {-Ejercicio 3.23
  395. En sistemas de numeracion en base k (con k un numero entero y k > 1), un numero puede ser representado por una
  396. lista de numeros, todos menores que k y mayores o iguales a cero.
  397. En el sistema de numeracion en base 10 (k = 10), la lista [9,8,4] representa el numero 984 (9*100+8*10+4*1).
  398. En el sistema de numeracion en base tres (k = 3), la lista [2,0,1] representa el numero 19 (2*9+0*3+1*1).
  399. Escriba una funcion listaAnumero, que, dados un numero k y una lista ms de numeros m (0 <= m < k), devuelva el
  400. numero representado por la lista en el sistema de numeracion en base 10.
  401. Defina la funcion en base a foldl.-}
  402. listaNum k xs= let f (acc,0) x =(acc+x,0)
  403. f (acc,i) x =(acc+(x*k^i),i-1)
  404. in fst $ foldl f (0,(length xs)-1) xs
  405. {-Ejercicio 3.24
  406. Podemos cambiar la representacion de numeros en un sistema de numeracion en base k que esta descrita en el
  407. ejercicio 3.23 por una representacion en que esta el numero al reves. Entonces, en este caso, el numero 984 en el
  408. sistema de numeracion es representado por la lista [4,8,9].
  409. Escriba una funcion listaAnumeroR que haga lo mismo que la funcion listaAnumero, pero ahora con la representacion al reves.
  410. Defina la funcion en base a foldr.-}
  411. listaNumR k xs=let f x (acc,0)=(acc+x,0)
  412. f x (acc,i)=(acc+(x*k^i),i-1)
  413. in fst $ foldr f (0,(length xs)-1) xs
  414. -- Solucion mas elegante de Xavier Garcia Buils
  415. porKmas k m n = m*k+n
  416. listaAnumero k = foldl (porKmas k) 0
  417. listaAnumeroR k = foldr (flip $ porKmas k) 0
  418. {-Ejercicio 3.25
  419. Escriba una funcion multiplicar, que, dados un numero positivo menor que 10 m y una lista de numeros ns, que
  420. representa un numero n como esta descrito en el ejercicio 3.24, devuelva una lista que represente la multiplicacion
  421. n*m, tambien segun la representacion descrita en el ejercicio anterior. Puede suponer que trabajamos en un sistema
  422. de numeracion en base 10. Ejemplos:
  423. ? multiplicar 3 [4,8,9]
  424. [2,5,9,2]
  425. ? multiplicar 5 [9,9,9,1,4,6]
  426. [5,9,9,9,0,2,3]
  427. Una solucion podria ser: cambiar el numero representado en la lista por un numero entero y despues multiplicar.
  428. Esta solucion no se permite, porque, en este caso, no se pueden multiplicar numeros que sean muy grandes (la
  429. maquina acepta solamente numeros enteros hasta cierto limite). Por eso, debe aplicar otro sistema de multiplicar,
  430. por ejemplo el sistema que consiste en multiplicar numero por numero y guardar cada vez el resto. En este caso,
  431. trabaja con un par de valores: los numeros del resultado ya calculados y el resto de la ultima multiplicacion. Use
  432. foldr o foldl.-}
  433. x % y = (div x y,mod x y)
  434. mult x xs=let m (acc,r) y=
  435. let (d,r')=(y*x+r)%10
  436. in (r':acc,d)
  437. in uncurry (flip (:)) $ foldl m ([],0) xs
  438. multR2 x xs=let m y (acc,r)=
  439. let (d,r')=(y*x+r)%10
  440. in (r':acc,d)
  441. in uncurry (flip(:)) $ foldr m ([],0) xs
  442. {-Como podemos ver de varios ejercicios hay un patron comun en varios de ellos: fold con una tupla que
  443. consiste un acumulador y tarnformar una lista en otra (map) COmo para casi cada patron hay un funcion de
  444. orden superior para evitar repeticiones en este caso es mapAccumR y mapAccumL. Podemos reescribir la ultima
  445. de mis soluciones:-}
  446. multR x xs=uncurry (:) $ mapAccumR (\r y->(y*x+r)%10) 0 xs
  447. {-Ejercicio 3.26
  448. Escriba una funcion multip que haga lo mismo que la funcion multiplicar descrita en el ejercicio 3.25, pero ahora
  449. multiplique dos listas en la representacion especial, y no (como en el ejercicio anterior), un numero entero menor
  450. que 10 con una lista en la representacion especial. Por ejemplo:
  451. ? multip [1,3] [4,8,9]
  452. [6,3,9,3]
  453. Es util usar la funcion multip y escribir una funcion sumar mas. La funcion sumar debe sumar dos numeros
  454. representados en listas como en los anteriores ejercicios.-}
  455. mas= (uncurry (:)).
  456. (mapAccumR (\r x->(x+r)%10) 0).
  457. (map sum).transpose
  458. multp xs ys=let r0 i=replicate i 0
  459. acc i n=(i+1,r0(length xs-i)++(multR n ys)++r0 i)
  460. in mapAccumR acc 0 xs --mal
  461. infix 8 $>
  462. --($>) :: a-> [(a->b)] -> [b]
  463. fs $> x = map ($ x) fs
  464. -- Monads
  465. tellMe :: Int -> Writer String Int
  466. tellMe x= do
  467. let y ="2" -- <- getLine
  468. tell $ "You have written:" ++ y
  469. let r=x+(read y :: Int)
  470. tell $ "The result is:" ++ show r
  471. return r
  472. arbol' n = [if c == n + q
  473. then '\n'
  474. else if c <= n - q
  475. then ' '
  476. else '*' |
  477. q <- [1 .. n], c <- [1 .. n + q]]
  478. arbol'' n = unlines [r (n-x) ' ' ++ r (2*x-1) '*' |x<-[1..n]]
  479. where r=replicate
  480. -- Genera los INFINITOS árboles de Navidad
  481. bosque=a["*"] where a x=x:a (map (' ':) x ++ [replicate (1+2*length x) '*'])
  482. -- Para tomar un árbol concreto, basta referenciarlo por su índice
  483. arbol=(!!)bosque
  484. -- Para imprimirlo
  485. talar=putStrLn.unlines.arbol
  486. bosque'=iterate(\x->map(' ':)x++[replicate(1+2*length x) '*'])["*"]
  487. --bosque=a["*"]where a x=x:a(map(' ':)x++[take(1+2*length x)$repeat '*'])
  488. minSubsetSum'=head.sortBy(comparing length).filter(\s->s/=[] && sum s==0).subsequences
  489. vigenere m c=zipWith f m $ cycle c
  490. where f x y=chr $ (g x + g y - 130) `mod` 26 + 65;g=ord.toUpper
  491. f x=x+1
  492. g x y=(f x) + (f y)