packages feed

grid 2.0 → 2.1.1

raw patch · 4 files changed

+93/−13 lines, 4 filesdep +exact-combinatoricsdep ~test-framework-quickcheck2PVP ok

version bump matches the API change (PVP)

Dependencies added: exact-combinatorics

Dependency ranges changed: test-framework-quickcheck2

API changes (from Hackage documentation)

+ Math.Geometry.Grid: minimalPaths :: Grid g s x => x -> x -> g -> [[x]]
+ Math.Geometry.GridInternal: minimalPaths :: Grid g s x => x -> x -> g -> [[x]]
- Math.Geometry.Grid: class Eq x => Grid g s x | g -> s, g -> x where neighbours x g = filter (\ a -> distance x a g ≡ 1) $ indices g inGrid x g = x `elem` indices g viewpoint p g = map f (indices g) where f x = (x, distance p x g) tileCount = length . indices empty g = tileCount g ≡ 0 nonEmpty = not . empty edges g = nubBy sameEdge $ concatMap (`adjacentEdges` g) $ indices g
+ Math.Geometry.Grid: class Eq x => Grid g s x | g -> s, g -> x where neighbours x g = filter (\ a -> distance x a g ≡ 1) $ indices g inGrid x g = x `elem` indices g viewpoint p g = map f (indices g) where f x = (x, distance p x g) tileCount = length . indices empty g = tileCount g ≡ 0 nonEmpty = not . empty edges g = nubBy sameEdge $ concatMap (`adjacentEdges` g) $ indices g minimalPaths a b g | a ≡ b = [[a]] | distance a b g ≡ 1 = [[a, b]] | otherwise = map (a :) xs where xs = concatMap (\ x -> minimalPaths x b g) ys ys = filter f $ neighbours a g f x = distance x b g ≡ distance a b g - 1
- Math.Geometry.GridInternal: class Eq x => Grid g s x | g -> s, g -> x where neighbours x g = filter (\ a -> distance x a g ≡ 1) $ indices g inGrid x g = x `elem` indices g viewpoint p g = map f (indices g) where f x = (x, distance p x g) tileCount = length . indices empty g = tileCount g ≡ 0 nonEmpty = not . empty edges g = nubBy sameEdge $ concatMap (`adjacentEdges` g) $ indices g
+ Math.Geometry.GridInternal: class Eq x => Grid g s x | g -> s, g -> x where neighbours x g = filter (\ a -> distance x a g ≡ 1) $ indices g inGrid x g = x `elem` indices g viewpoint p g = map f (indices g) where f x = (x, distance p x g) tileCount = length . indices empty g = tileCount g ≡ 0 nonEmpty = not . empty edges g = nubBy sameEdge $ concatMap (`adjacentEdges` g) $ indices g minimalPaths a b g | a ≡ b = [[a]] | distance a b g ≡ 1 = [[a, b]] | otherwise = map (a :) xs where xs = concatMap (\ x -> minimalPaths x b g) ys ys = filter f $ neighbours a g f x = distance x b g ≡ distance a b g - 1

Files

grid.cabal view
@@ -1,5 +1,5 @@ name:           grid-version:        2.0+version:        2.1.1 synopsis:       Tools for working with regular grids\/graphs\/lattices. description:    Provides tools for working with regular arrangements                 of tiles, such as might be used in a board game or some@@ -29,7 +29,8 @@ test-suite grid-tests   type:            exitcode-stdio-1.0   build-depends:   base ==4.*,-                   test-framework-quickcheck2 == 0.2.*,+                   exact-combinatorics ==0.2.*,+                   test-framework-quickcheck2 == 0.3.*,                    QuickCheck == 2.4.*,                    test-framework == 0.*,                    grid,
src/Math/Geometry/Grid.hs view
@@ -89,4 +89,10 @@ >ghci> nonEmpty g >True +   Find all of the minimal paths between two points.++ghci> let g = hexHexGrid 3+ghci> minimalPaths (0,0) (2,-1) g+[[(0,0),(1,0),(2,-1)],[(0,0),(1,-1),(2,-1)]]+ -}
src/Math/Geometry/GridInternal.hs view
@@ -35,7 +35,7 @@     paraHexGrid   ) where -import Data.Eq.Unicode ((≡))+import Data.Eq.Unicode ((≡), (≠)) import Data.List (nub, nubBy) import Data.Ord.Unicode ((≤), (≥)) @@ -56,8 +56,8 @@   -- | @'neighbours' x g@ returns the indices of the tiles in the grid @g@   --   which are adjacent to the tile at @x@.   neighbours ∷ x → g → [x]-  neighbours x g = filter (\a -> distance x a g ≡ 1 ) $ indices g-  -- | @x `'inGrid'` g@ returns true if the index @x@ is contained within @g@,+  neighbours x g = filter (\a → distance x a g ≡ 1 ) $ indices g+  -- | @x 'inGrid' g@ returns true if the index @x@ is contained within @g@,   --   otherwise it returns false.   inGrid ∷ x → g → Bool   inGrid x g = x `elem` indices g@@ -82,12 +82,24 @@   --   pair of adjacent tiles.   edges ∷ g → [(x,x)]   edges g = nubBy sameEdge $ concatMap (`adjacentEdges` g) $ indices g+  -- | @'minimalPaths' a b@ returns a list of all minimal paths from +  --   @a@ to @b@. A path is a sequence of tiles, where each tile in the+  --   sequence is adjacent to the previous one. (Two tiles are adjacent+  --   if they share an edge.) If @a@ or @b@ are not contained+  --   within @g@, the result is undefined.+  minimalPaths ∷ x → x → g → [[x]]+  minimalPaths a b g | a ≡ b              = [[a]]+                     | distance a b g ≡ 1 = [[a,b]]+                     | otherwise          = map (a:) xs+    where xs = concatMap (\x → minimalPaths x b g) ys+          ys = filter f $ neighbours a g+          f x = distance x b g ≡ distance a b g - 1 -sameEdge :: Eq t => (t, t) -> (t, t) -> Bool-sameEdge (a,b) (c,d) = (a,b) == (c,d) || (a,b) == (d,c)+sameEdge ∷ Eq t ⇒ (t, t) → (t, t) → Bool+sameEdge (a,b) (c,d) = (a,b) ≡ (c,d) || (a,b) ≡ (d,c) -adjacentEdges :: Grid g s t => t -> g -> [(t, t)]-adjacentEdges i g = map (\j -> (i,j)) $ i `neighbours` g+adjacentEdges ∷ Grid g s t ⇒ t → g → [(t, t)]+adjacentEdges i g = map (\j → (i,j)) $ i `neighbours` g  -- -- Triangular tiles@@ -106,7 +118,7 @@         where z1 = triZ x1 y1               z2 = triZ x2 y2 -triNeighbours :: Grid g s (Int, Int) ⇒ (Int, Int) → g → [(Int, Int)]+triNeighbours ∷ Grid g s (Int, Int) ⇒ (Int, Int) → g → [(Int, Int)] triNeighbours (x,y) g = filter (`inGrid` g) xs     where xs | even y    = [(x-1,y+1), (x+1,y+1), (x+1,y-1)]              | otherwise = [(x-1,y-1), (x-1,y+1), (x+1,y-1)]@@ -213,7 +225,7 @@ instance Grid TorSquareGrid (Int, Int) (Int, Int) where   indices (TorSquareGrid _ xs) = xs   neighbours (x,y) (TorSquareGrid (r,c) _) = -    nub $ filter (\(xx,yy) → xx /= x || yy /= y) +    nub $ filter (\(xx,yy) → xx ≠ x || yy ≠ y)        [((x-1) `mod` c,y), (x,(y+1) `mod` r), ((x+1) `mod` c,y),          (x,(y-1) `mod` r)]   distance (x1, y1) (x2, y2) g@(TorSquareGrid (r,c) _) =
test/Math/Geometry/GridQC.hs view
@@ -11,6 +11,7 @@ import Data.Eq.Unicode ((≡), (≠)) import Data.List (nub, sort) import Data.Ord.Unicode ((≤))+import qualified Math.Combinatorics.Exact.Binomial as M (choose) import Test.Framework as TF (Test, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck @@ -64,9 +65,28 @@ prop_edges_are_adjacent g = property $ and $ map f $ edges g   where f (a, b) = isAdjacent a b g -isAdjacent :: Grid g s x => x -> x -> g -> Bool+isAdjacent ∷ Grid g s x ⇒ x → x → g → Bool isAdjacent a b g = (distance a b g) ≡ 1 +prop_minimal_paths_have_min_length ∷ Grid g s x ⇒ g → Int → Int → Property+prop_minimal_paths_have_min_length g i j = nonEmpty g ==> ns ≡ [d+1]+  where a = i `pointIn` g+        b = j `pointIn` g+        d = distance a b g+        ns = nub $ map length $ minimalPaths a b g++prop_minimal_paths_are_valid ∷ Grid g s x ⇒ g → Int → Int → Property+prop_minimal_paths_are_valid g i j = nonEmpty g ==> +    and $ map (subsequentTilesInPathAreAdjacent g) $ minimalPaths a b g+  where a = i `pointIn` g+        b = j `pointIn` g++subsequentTilesInPathAreAdjacent ∷ Grid g s x ⇒ g → [x] → Bool+subsequentTilesInPathAreAdjacent _ [] = True+subsequentTilesInPathAreAdjacent g [x] = x `elem` (indices g)+subsequentTilesInPathAreAdjacent g (a:b:xs) = +  isAdjacent a b g && subsequentTilesInPathAreAdjacent g (b:xs)+ -- -- Triangular grids with triangular tiles --@@ -198,6 +218,15 @@           | r ≡ 1 || c ≡ 1  = neighbourCount `elem` [1,2]           | otherwise       = neighbourCount `elem` [2,3,4] +prop_RectSquareGrid_num_min_paths_correct ∷ +  RectSquareGrid → Int → Int → Property+prop_RectSquareGrid_num_min_paths_correct g i j = nonEmpty g ==>+  length (minimalPaths a b g) ≡ M.choose (deltaX+deltaY) deltaX+    where a = i `pointIn` g+          b = j `pointIn` g+          deltaX = abs $ fst b - fst a+          deltaY = abs $ snd b - snd a+ -- -- Toroidal grids with square-ish tiles --@@ -355,6 +384,11 @@       ( prop_edges_cw_neighbours ∷ TriTriGrid → Int → Property),     testProperty "prop_edges_are_adjacent - TriTriGrid"       ( prop_edges_are_adjacent ∷ TriTriGrid → Property),+    testProperty "prop_minimal_paths_have_min_length - TriTriGrid"+      ( prop_minimal_paths_have_min_length ∷ +          TriTriGrid → Int → Int → Property),+    testProperty "prop_minimal_paths_are_valid - TriTriGrid"+      ( prop_minimal_paths_are_valid ∷ TriTriGrid → Int → Int → Property),     -- ParaTriGrid tests     testProperty "prop_ParaTriGrid_tile_count_correct"       prop_ParaTriGrid_tile_count_correct,@@ -374,6 +408,11 @@       ( prop_edges_cw_neighbours ∷ ParaTriGrid → Int → Property),     testProperty "prop_edges_are_adjacent - ParaTriGrid"       ( prop_edges_are_adjacent ∷ ParaTriGrid → Property),+    testProperty "prop_minimal_paths_have_min_length - ParaTriGrid"+      ( prop_minimal_paths_have_min_length ∷ +          ParaTriGrid → Int → Int → Property),+    testProperty "prop_minimal_paths_are_valid - ParaTriGrid"+      ( prop_minimal_paths_are_valid ∷ ParaTriGrid → Int → Int → Property),     -- RectSquareGrid tests     testProperty "prop_RectSquareGrid_tile_count_correct"       prop_RectSquareGrid_tile_count_correct,@@ -393,6 +432,13 @@       ( prop_edges_cw_neighbours ∷ RectSquareGrid → Int → Property),     testProperty "prop_edges_are_adjacent - RectSquareGrid"       ( prop_edges_are_adjacent ∷ RectSquareGrid → Property),+    testProperty "prop_minimal_paths_have_min_length - RectSquareGrid"+      ( prop_minimal_paths_have_min_length ∷ +          RectSquareGrid → Int → Int → Property),+    testProperty "prop_minimal_paths_are_valid - RectSquareGrid"+      ( prop_minimal_paths_are_valid ∷ RectSquareGrid → Int → Int → Property),+    testProperty "prop_RectSquareGrid_num_min_paths_correct"+      prop_RectSquareGrid_num_min_paths_correct,     -- TorSquareGrid tests     testProperty "prop_TorSquareGrid_tile_count_correct"       prop_TorSquareGrid_tile_count_correct,@@ -412,6 +458,11 @@       ( prop_edges_cw_neighbours ∷ TorSquareGrid → Int → Property),     testProperty "prop_edges_are_adjacent - TorSquareGrid"       ( prop_edges_are_adjacent ∷ TorSquareGrid → Property),+    testProperty "prop_minimal_paths_have_min_length - TorSquareGrid"+      ( prop_minimal_paths_have_min_length ∷ +          TorSquareGrid → Int → Int → Property),+    testProperty "prop_minimal_paths_are_valid - TorSquareGrid"+      ( prop_minimal_paths_are_valid ∷ TorSquareGrid → Int → Int → Property),     -- HexHexGrid tests     testProperty "prop_HexHexGrid_tile_count_correct"       prop_HexHexGrid_tile_count_correct,@@ -431,6 +482,11 @@       ( prop_edges_cw_neighbours ∷ HexHexGrid → Int → Property),     testProperty "prop_edges_are_adjacent - HexHexGrid"       ( prop_edges_are_adjacent ∷ HexHexGrid → Property),+    testProperty "prop_minimal_paths_have_min_length - HexHexGrid"+      ( prop_minimal_paths_have_min_length ∷ +          HexHexGrid → Int → Int → Property),+    testProperty "prop_minimal_paths_are_valid - HexHexGrid"+      ( prop_minimal_paths_are_valid ∷ HexHexGrid → Int → Int → Property),     -- ParaHexGrid tests     testProperty "prop_ParaHexGrid_tile_count_correct"       prop_ParaHexGrid_tile_count_correct,@@ -449,6 +505,11 @@     testProperty "prop_edges_cw_neighbours - ParaHexGrid"       ( prop_edges_cw_neighbours ∷ ParaHexGrid → Int → Property),     testProperty "prop_edges_are_adjacent - ParaHexGrid"-      ( prop_edges_are_adjacent ∷ ParaHexGrid → Property)+      ( prop_edges_are_adjacent ∷ ParaHexGrid → Property),+    testProperty "prop_minimal_paths_have_min_length - ParaHexGrid"+      ( prop_minimal_paths_have_min_length ∷ +          ParaHexGrid → Int → Int → Property),+    testProperty "prop_minimal_paths_are_valid - ParaHexGrid"+      ( prop_minimal_paths_are_valid ∷ ParaHexGrid → Int → Int → Property)  ]