Advertisement
tomasfdel

Estructuras II TP 1

Apr 17th, 2018
364
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 13.58 KB | None | 0 0
  1. import Prelude
  2.  
  3. data NdTree p = Node (NdTree p) p (NdTree p) Int | Empty
  4.                 deriving (Eq, Ord, Show)
  5.                
  6. class Punto p where
  7.     dimension :: p -> Int
  8.     coord :: Int -> p -> Double
  9.     dist :: p -> p -> Double
  10.     -- Se crea una lista con las diferencias al cuadrado de todas las coordenadas.
  11.     -- Luego, se suman todos los elementos.
  12.     dist a b = foldl (+) 0 [((coord i a) - (coord i b)) ^ 2 | i <- [0 .. ((dimension a ) - 1)]]
  13.    
  14.    
  15. newtype Punto2d = P2d (Double, Double) deriving (Eq, Show)
  16. newtype Punto3d = P3d (Double, Double, Double) deriving (Eq, Show)
  17. type Rect = (Punto2d, Punto2d)
  18.  
  19.  
  20. instance Punto Punto2d where
  21.   dimension p = 2
  22.   coord 0 (P2d (x, y)) = x
  23.   coord 1 (P2d (x, y)) = y
  24.  
  25. instance Punto Punto3d where
  26.   dimension p = 3
  27.   coord 0 (P3d (x, y, z)) = x
  28.   coord 1 (P3d (x, y, z)) = y
  29.   coord 2 (P3d (x, y, z)) = z
  30.  
  31.  
  32. sortNuestro :: Punto p => Int -> [p] -> [p]
  33. sortNuestro _ [] = []
  34. sortNuestro c (x:xs) = sortNuestro c menores ++ [x] ++ sortNuestro c mayores
  35.     where cx = (coord c x)
  36.           menores = [a | a <- xs, (coord c a) <= cx]
  37.           mayores = [b | b <- xs, (coord c b) >  cx]
  38.          
  39.  
  40. armarArbol :: Punto p => [p] -> Int -> NdTree p
  41. -- Cuando una lista quede vacía, se construye una hoja.
  42. armarArbol [] _ = Empty
  43. -- En caso contrario, se procede a dividir el arreglo para construir un árbol no vacío.
  44. armarArbol (x:xs) h = let mitad = div (length (x:xs)) 2
  45.                           eje = mod h (dimension x) -- El eje a partir del cual se ordena al arreglo.
  46.                           xsOrdenado = sortNuestro eje (x:xs)
  47.                           mediana = xsOrdenado !! mitad -- Tomamos el valor de la mediana, y se revisa que
  48.                                                         -- todos los valores con una coordenada igual
  49.                                                         -- queden en el mismo subárbol.
  50.                           primeraMitad = takeWhile (\x -> (coord eje x) <= (coord eje mediana)) xsOrdenado
  51.                           pivot = last primeraMitad -- El nodo que se usará de raíz será el último punto que
  52.                                                     -- contenga la misma coordenada que la mediana
  53.                           segundaMitad = drop (length primeraMitad) xsOrdenado -- La segunda mitad es el resto del arreglo.
  54.                        -- Se construye el nodo, dejando la primera mitad como árbol izquierdo,
  55.                        -- la segunda mitad como árbol derecho y el pivot como dato.
  56.                        in Node
  57.                           (armarArbol (init primeraMitad) (h + 1))
  58.                           pivot
  59.                           (armarArbol segundaMitad (h + 1))
  60.                           eje
  61.  
  62.  
  63. fromList :: Punto p => [p] -> NdTree p
  64. -- Se llama a la función auxiliar de construcción, indicando que la altura del primer nodo es 0.
  65. fromList xs = armarArbol xs 0
  66.  
  67.  
  68. insertarAux :: Punto p => p -> NdTree p -> Int -> NdTree p
  69. -- Si se llega a una hoja, construimos el nodo con el valor correspondiente allí.
  70. insertarAux punto Empty h            = Node Empty punto Empty (mod h (dimension punto))
  71. -- Si no, se compara la coordenada correspondiente del valor a agregar con el nodo raíz,
  72. -- y se lo inserta de acuerdo a si es menor o mayor.
  73. insertarAux punto (Node i r d eje) h | (coord eje punto) <= (coord eje r) = Node (insertarAux punto i (h + 1) ) r d eje
  74.                                      | otherwise                          = Node i r (insertarAux punto d (h + 1) ) eje
  75.  
  76.  
  77. insertar :: Punto p => p -> NdTree p -> NdTree p
  78. -- Se llama a la función auxiliar de inserción, indicando que la altura del primer nodo es 0.
  79. insertar punto arbol = insertarAux punto arbol 0
  80.  
  81.  
  82. minDeATres :: Punto p => p -> p -> p -> Int -> p
  83. -- Devuelve el punto con menor coordenada de acuerdo a un eje.
  84. minDeATres x y z eje | coordX <= coordY && coordX <= coordZ = x
  85.                      | coordY <= coordX && coordY <= coordZ = y
  86.                      | otherwise                            = z
  87.                      where coordX = coord eje x
  88.                            coordY = coord eje y
  89.                            coordZ = coord eje z
  90.  
  91.  
  92. buscarMinAux :: Punto p => NdTree p -> Int -> p -> p
  93. -- Si se llega a una hoja, se devuelve como valor mínimo el posible valor actual.
  94. buscarMinAux Empty ejeComp posibleMin = posibleMin
  95. -- Si no, se buscan recursivamente los mínimos de ambos subárboles y se devuelve el menor entre ellos y el nodo raíz.
  96. -- Se tiene la salvedad de que si el eje de comparación coincide con el eje del nodo,
  97. -- no se busca en los dos subárboles, sino sólo en el izquierdo.
  98. buscarMinAux (Node i dato d eje) ejeComp posibleMin |  eje == ejeComp = if (coord ejeComp dato) <= (coord ejeComp minI) then dato else minI
  99.                                                     |  otherwise      = minDeATres (buscarMinAux i ejeComp posibleMin) dato (buscarMinAux d ejeComp posibleMin) ejeComp
  100.                                                     where minI = (buscarMinAux i ejeComp posibleMin)
  101.  
  102.  
  103. buscarMin :: Punto p => NdTree p -> Int -> p
  104. -- Se llama a la función auxiliar, indicando que el posible mínimo es la raíz del árbol.
  105. buscarMin raiz@(Node i dato d eje) ejeComp = buscarMinAux raiz ejeComp dato
  106.  
  107.  
  108. maxDeATres :: Punto p => p -> p -> p -> Int -> p
  109. -- Devuelve el punto con mayor coordenada de acuerdo a un eje.
  110. maxDeATres x y z eje | coordX >= coordY && coordX >= coordZ = x
  111.                      | coordY >= coordX && coordY >= coordZ = y
  112.                      | otherwise                            = z
  113.                      where coordX = coord eje x
  114.                            coordY = coord eje y
  115.                            coordZ = coord eje z
  116.                            
  117.                            
  118. buscarMaxAux :: Punto p => NdTree p -> Int -> p -> p
  119. -- Si se llega a una hoja, se devuelve como valor máximo el posible valor actual.
  120. buscarMaxAux Empty ejeComp posibleMax = posibleMax
  121. -- Si no, se buscan recursivamente los máximos de ambos subárboles y se devuelve el mayor entre ellos y el nodo raíz.
  122. -- Se tiene la salvedad de que si el eje de comparación coincide con el eje del nodo,
  123. -- no se busca en los dos subárboles, sino sólo en el derecho.
  124. buscarMaxAux (Node i dato d eje) ejeComp posibleMax |  eje == ejeComp = if (coord ejeComp dato) >= (coord ejeComp maxD) then dato else maxD
  125.                                                     |  otherwise = maxDeATres (buscarMaxAux i ejeComp posibleMax) dato (buscarMaxAux d ejeComp posibleMax) ejeComp
  126.                                                     where maxD = (buscarMaxAux d ejeComp posibleMax)
  127.  
  128. buscarMax :: Punto p => NdTree p -> Int -> p
  129. -- Se llama a la función auxiliar, indicando que el posible máximo es la raíz del árbol.
  130. buscarMax raiz@(Node i dato d eje) ejeComp = buscarMaxAux raiz ejeComp dato
  131.  
  132.  
  133. eliminar :: (Eq p, Punto p) => p -> NdTree p -> NdTree p
  134. -- Si se llega una hoja, no se modifica.
  135. eliminar punto Empty = Empty
  136. -- Si se llega a un nodo con hojas como hijos, se lo elimina si el dato coincide con el buscado.
  137. eliminar punto nodo@(Node Empty dato Empty _ ) = if punto == dato then Empty else nodo
  138. -- Si el nodo posee algún hijo no vacío, se compara su dato con el buscado.
  139. -- En caso de ser iguales, se busca el mínimo con respecto al eje del nodo en el subárbol derecho como reemplazo.
  140. -- Si éste fuera vacío, se busca el máximo en el izquierdo.
  141. -- Si el dato no es igual al buscado, se revisa el subárbol correspondiente al orden entre las coordenadas del dato y el buscado.
  142. eliminar punto (Node i dato d eje) | punto == dato                     = if d /= Empty
  143.                                                                              then (Node i candidatoD (eliminar candidatoD d) eje)
  144.                                                                              else (Node (eliminar candidatoI i) candidatoI d eje)
  145.                                    | coord eje punto <= coord eje dato = (Node (eliminar punto i) dato d eje)
  146.                                    | otherwise                         = (Node i dato (eliminar punto d) eje)
  147.                                    where candidatoD = buscarMin d eje
  148.                                          candidatoI = buscarMax i eje
  149.  
  150.  
  151. limites :: Rect -> Int -> (Double, Double)
  152. -- Dado un rectángulo y un eje, devuelve una tupla con los valores mínimo y máximo
  153. -- en ese eje que determinan los vértices de la diagonal.
  154. limites (P2d(x1,y1), P2d (x2,y2) ) 0 = if x1 <= x2 then (x1, x2) else (x2, x1)
  155. limites (P2d(x1,y1), P2d (x2,y2) ) 1 = if y1 <= y2 then (y1, y2) else (y2, y1)
  156.  
  157.  
  158. ortogonalSearch :: NdTree Punto2d -> Rect -> [Punto2d]
  159. -- Si se llega a una hoja, se devuelve una lista vacía.
  160. ortogonalSearch Empty _ = []
  161. -- Si no, se revisa el dato para ver si se lo debe agregar a la lista.
  162. ortogonalSearch (Node i dato d eje) rect
  163.                                          -- Si su coordenada está por debajo del límite inferior,
  164.                                          -- sólo se busca en su subárbol derecho.
  165.                                          | coordDato < lInf                          = ortogonalSearch d rect
  166.                                          -- Si su coordenada está por encima del límite superior,
  167.                                          -- sólo se busca en su subárbol izquierdo.
  168.                                          | coordDato > lSup                          = ortogonalSearch i rect
  169.                                          -- Si su coordenada está entre los valores de los límites,
  170.                                          -- se lo agrega a la lista si está entre los valores en el otro eje.
  171.                                          | coordDato2 >= lInf2 && coordDato2 <= lSup2 =  [dato] ++ busqHijos
  172.                                          -- Si no, sólo se devuelve la búsqueda en sus hijos.
  173.                                          | otherwise                                     = busqHijos
  174.                                          where
  175.                                                -- Límites inferior y superior del rectángulo en
  176.                                                -- el eje del nodo.      
  177.                                                (lInf, lSup) = limites rect eje
  178.                                                -- Límites inferior y superior del rectángulo en
  179.                                                -- el otro eje.
  180.                                                (lInf2, lSup2) = limites rect (mod (eje + 1) 2)
  181.                                                -- Coordenada del dato en el eje del nodo.
  182.                                                coordDato = coord eje dato
  183.                                                -- Coordenada del dato en el otro eje.
  184.                                                coordDato2 = coord (mod (eje + 1) 2) dato
  185.                                                -- Resultado de la búsqueda en ambos subárboles.
  186.                                                busqHijos = (ortogonalSearch i rect) ++ (ortogonalSearch d rect)
  187.  
  188.  
  189. -- ALGUNOS EJEMPLOS CON LOS QUE PROBAMOS LAS FUNCIONES
  190.  
  191. -- Lista de los nodos usados como ejemplo en los enunciados del Trabajo.
  192. listaEj = [P2d (2,3), P2d (5,4), P2d (9,6), P2d (4,7), P2d (8,1), P2d (7,2)]
  193. -- Arbol construido a partir de la lista de ejemplo.
  194. arbolEj = fromList listaEj
  195. -- Prueba de insertar un valor mayor a todos los existentes.
  196. arbolIns1 = insertar (P2d (100,100)) arbolEj
  197. -- Prueba de insertar luego un valor intermedio.
  198. arbolIns2 = insertar (P2d (4,8)) arbolIns1
  199.  
  200. -- Prueba de eliminar un dato inexistente.
  201. arbolDel1 = eliminar (P2d (66, 66)) arbolEj
  202. -- Prueba de eliminar una hoja.
  203. arbolDel2 = eliminar (P2d (2.0, 3.0)) arbolEj
  204. -- Prueba de eliminar un nodo con subárbol derecho vacío.
  205. arbolDel3 = eliminar (P2d (9, 6)) arbolEj
  206. -- Prueba de eliminar la raíz.
  207. arbolDel4 = eliminar (P2d (7, 2)) arbolEj
  208.  
  209. -- Rectángulo de prueba para la función de búsqueda.
  210. rectEj = ( (P2d (5,5)), (P2d (10,10)) )
  211. -- Prueba de búsqueda en el árbol del ejemplo.
  212. searchEj = ortogonalSearch arbolEj rectEj
  213.  
  214. -- Resultados de los ejemplos anteriores.
  215. {-
  216. NOTA: Intercalamos renglones entre valores de la estructura de la raíz para que queden con el formato:
  217. Node
  218.  Subárbol Izquierdo
  219.  Valor del Nodo
  220.  Subárbol Derecho
  221.  Eje
  222.  
  223. arbolEj =
  224. Node
  225. (Node (Node Empty (P2d (2.0,3.0)) Empty 0) (P2d (5.0,4.0)) (Node Empty (P2d (4.0,7.0)) Empty 0) 1)
  226. (P2d (7.0,2.0))
  227. (Node (Node Empty (P2d (8.0,1.0)) Empty 0) (P2d (9.0,6.0)) Empty 1)
  228. 0
  229.  
  230. arbolIns1 =
  231. Node
  232. (Node (Node Empty (P2d (2.0,3.0)) Empty 0) (P2d (5.0,4.0)) (Node Empty (P2d (4.0,7.0)) Empty 0) 1)
  233. (P2d (7.0,2.0))
  234. (Node (Node Empty (P2d (8.0,1.0)) Empty 0) (P2d (9.0,6.0)) (Node Empty (P2d (100.0,100.0)) Empty 0) 1)
  235. 0
  236.  
  237.  
  238. arbolIns2 =
  239. Node
  240. (Node (Node Empty (P2d (2.0,3.0)) Empty 0) (P2d (5.0,4.0)) (Node (Node Empty (P2d (4.0,8.0)) Empty 1) (P2d (4.0,7.0)) Empty 0) 1)
  241. (P2d (7.0,2.0))
  242. (Node (Node Empty (P2d (8.0,1.0)) Empty 0) (P2d (9.0,6.0)) (Node Empty (P2d (100.0,100.0)) Empty 0) 1)
  243. 0
  244.  
  245.  
  246. arbolDel1 == arbolEj =
  247. True
  248.  
  249.  
  250. arbolDel2 =
  251. Node
  252. (Node Empty (P2d (5.0,4.0)) (Node Empty (P2d (4.0,7.0)) Empty 0) 1)
  253. (P2d (7.0,2.0))
  254. (Node (Node Empty (P2d (8.0,1.0)) Empty 0) (P2d (9.0,6.0)) Empty 1)
  255. 0
  256.  
  257.  
  258. arbolDel3 =
  259. Node
  260. (Node (Node Empty (P2d (2.0,3.0)) Empty 0) (P2d (5.0,4.0)) (Node Empty (P2d (4.0,7.0)) Empty 0) 1)
  261. (P2d (7.0,2.0))
  262. (Node Empty (P2d (8.0,1.0)) Empty 1)
  263. 0
  264.  
  265.  
  266. arbolDel4 =
  267. Node
  268. (Node (Node Empty (P2d (2.0,3.0)) Empty 0) (P2d (5.0,4.0)) (Node Empty (P2d (4.0,7.0)) Empty 0) 1)
  269. (P2d (8.0,1.0))
  270. (Node Empty (P2d (9.0,6.0)) Empty 1)
  271. 0
  272.  
  273.  
  274. searchEj =
  275. [P2d (9.0,6.0)]
  276. -}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement