Advertisement
Guest User

Untitled

a guest
Nov 20th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. Block :: {top, left, width, height}
  3.  
  4. BlockTree :: {block: Block, children: [BlockTree]}
  5.  
  6. blockTreeOfBlocks :: [Block] -> BlockTree
  7.  
  8. -- size block = block.height * block.width
  9.  
  10. -- within block1 block2 =
  11.     let beginX = block2.left
  12.         beginY = block2.top
  13.         endX   = beginX + block2.width
  14.         endY   = beginY + block2.height
  15.     in block1.top > beginY && (block1.top + block1.height) < endY
  16.     && block1.left > beginX && (block1.left + block1.width) < endX
  17.  
  18. -- blocksWithin blocks block = filter (\b -> b `within` block) blocks
  19.  
  20. -- determina se um bloco é filho de algum irmão.
  21. -- complexidade: O(n)
  22. let immediateChild child siblings =
  23.     and (map (\sibling -> not (child `within` sibling)) siblings)
  24.  
  25. -- divide uma lista de blocos em filhos diretos (aqueles que não são filhos de nenhum irmão)
  26. -- e filhos indiretos (aqueles que são). Esta função espera receber os blocos ordenados por tamanho
  27. -- por questão de otimização (um bloco não pode ser filho de um bloco menor do que ele)
  28. -- complexidade: O(n^2). O pior caso ocorre quando todos os blocos são filhos diretos.
  29. let partitionChildren children =
  30.     let partitionR children (immediates, nonImmediates) =
  31.         case children of
  32.             child :: rest -> if (child `immediateChild` immediates)
  33.                              then partitionR rest (child :: immediates, nonImmediates)
  34.                              else partitionR rest (immediates, child :: nonImmediates)
  35.             []            -> (immediates, nonImmediates)
  36.     in partitionR children ([], [])
  37.  
  38.  
  39. {-
  40.  recebe uma lista de blocos, uma lista de filhos diretos, e uma lista de filhos indiretos e monta
  41.  uma árvore. Para cada um dos filhos diretos, são determinados quais estão ou não contidos naquele filho,
  42.  e são divididos em filhos diretos e filhos indiretos para a nova chamada recursiva.
  43.  
  44.  A princípio, isso seria uma operação de custo N * M^2 sem contar a recursão,
  45.  onde N é o número de filhos diretos
  46.  e M o de filhos indiretos, mas quando o custo da operação de partição se aproxima de M^2 não há
  47.  chamada recursiva (porque todos os filhos são diretos). Ou seja, se o número de filhos da árvore é
  48.  alto, o custo em cada nível fica baixo e vice-versa. No caso de uma árvore binária, o custo fica
  49.  N em cada nível * log N níveis, ou seja N log N, e no caso de uma árvore com apenas um nível,
  50.  o custo tende a N^2. Nos casos intermediários, o custo fica entre N log N e N^2.
  51.  Portanto, podemos concluir que a complexidade desta operação é O(N^2).
  52. -}
  53. let blockTreeNode parent immediateChildrenBlocks nonImmediateChildrenBlocks =
  54.     let childrenTrees = map (\child ->
  55.             let childrenOfChild = (nonImmediateChildrenBlocks `blocksWithin` child) `sortBy` size
  56.                 (immediateChildrenOfChild, nonImmediateChildrenOfChild) = partitionChildren childrenOfChild
  57.             in blockTreeNode child immediateChildrenOfChild nonImmediateChildrenOfChild
  58.         ) immediateChildrenBlocks
  59.     in BlockTree parent childrenTrees
  60.  
  61. -- A função principal só inicia a recursão adicionando uma operação em tempo constante.
  62. -- Portanto, a complexidade total é O(N^2)
  63. let blockTreeOfBlocks blocks =
  64.     let (parent :: children) = blocks `sortBy` size
  65.         (immediateChildren, nonImmediateChildren) = partitionChildren children
  66.     in blockTreeNode parent immediateChildren nonImmediateChildren
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement