packages feed

yx (empty) → 0.0.1.0

raw patch · 6 files changed

+184/−0 lines, 6 filesdep +arraydep +basedep +bytestringsetup-changed

Dependencies added: array, base, bytestring, hspec, yx

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Matthieu Monsch (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Matthieu Monsch nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# yx
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Data/Geometry/YX.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE OverloadedStrings #-}++-- | A bitmap-friendly XY coordinate.+--+-- YX rather than XY since layout is row major (first row sorts before the+-- second, etc.).+module Data.Geometry.YX ( YX(..)+                        , rows+                        , up, left, right, down+                        , steps4, steps8+                        , byteStringToArray, arrayToByteString ) where++import Data.Array.IArray (IArray)+import qualified Data.Array.IArray as Array+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as BS+import Data.Ix (Ix)+import qualified Data.Ix as Ix+import Data.List (groupBy)++-- | A 2D coordinate.+--+-- YX implements 'Num'. Integers are converted to their diagonal equivalent+-- (for example @2@ becomes @YX 2 2@).+data YX = YX { x :: !Int, y :: !Int } deriving (Eq, Ord, Show)++lift1 :: (Int -> Int) -> YX -> YX+lift1 f (YX y1 x1) = YX (f y1) (f x1)++lift2 :: (Int -> Int -> Int) -> YX -> YX -> YX+lift2 f (YX y1 x1) (YX y2 x2) = YX (f y1 y2) (f x1 x2)++instance Num YX where+  (+) = lift2 (+)+  (*) = lift2 (*)+  abs = lift1 abs+  signum = lift1 signum+  fromInteger i = let i' = fromInteger i in YX i' i'+  negate = lift1 negate++instance Ix YX where+  range (YX yl xl, YX yu xu) =+    [ YX y x | y <- Ix.range (yl, yu), x <- Ix.range (xl, xu) ]+  index (YX yl xl, YX yu xu) (YX y x) =+    Ix.index (yl, yu) y * Ix.rangeSize (xl, xu) + Ix.index (xl, xu) x+  inRange (YX yl xl, YX yu xu) (YX y x) =+    Ix.inRange (yl, yu) y && Ix.inRange (xl, xu) x++-- | All coordinates, grouped by row.+rows :: (YX, YX) -> [[YX]]+rows = groupBy (\(YX y1 _) (YX y2 _) -> y1 == y2) . Ix.range++-- | Basic steps.+up, left, right, down :: YX+up = YX (-1) 0+left = YX 0 (-1)+right = YX 0 1+down = YX 1 0++-- | Ordered steps arrays.+steps4, steps8 :: [YX]+steps4 = [up, left, right, down]+steps8 = [up + left, up, up + right, left, right, down + left, down, down + right]++-- Parse newline delimited bytestring into an array.+byteStringToArray :: (IArray a e) => (Char -> Maybe e) -> ByteString -> Either String (a YX e)+byteStringToArray f bs = shape (BS.split '\n' bs) (-1) >>= materialize bs where+  shape [] (YX y x) = Right (YX y (max x 0))+  shape (row : rows) yx@(YX y x0)+    | null rows && BS.null row = shape [] yx -- Empty last row.+    | otherwise = let x = BS.length row - 1+                  in if x /= x0 && x0 >= 0+                    then Left $ "bad row lengths: " ++ show x ++ ", " ++ show x0+                    else shape rows (YX (y + 1) x)+  materialize bs yx = Array.listArray (0, yx) <$> elems bs+  elems = sequenceA . fmap parse . filter (/= '\n') . BS.unpack+  parse c = case f c of+    Just e -> Right e+    Nothing -> Left $ "unknown char: " ++ show c++-- | Reverse of `byteStringToArray`+arrayToByteString :: (IArray a e) => (e -> Char) -> a YX e -> ByteString+arrayToByteString f arr = BS.intercalate "\n" lines where+  lines = fmap (BS.pack . fmap (f . (arr Array.!))) . rows . Array.bounds $ arr
+ test/Spec.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE OverloadedStrings #-}++import qualified Data.Array.IArray as Array+import Data.Char (digitToInt)+import Data.Either (isLeft)+import Data.Geometry.YX (YX)+import qualified Data.Geometry.YX as YX+import Test.Hspec+import Test.Hspec.QuickCheck++main :: IO ()+main = hspec $ do+  describe "bytestring conversions" $ do+    it "should parse a simple square case" $ do+      let+        got = YX.byteStringToArray (Just . digitToInt) "12\n34\n"+        want = Array.listArray (0, 1) [1..4] :: Array.Array YX Int+      got `shouldBe` Right want+    it "fails on uneven row" $ do+      let got = YX.byteStringToArray Just "12\n3\n" :: Either String (Array.Array YX Char)+      isLeft got `shouldBe` True+    it "round trips" $ do+      let+        bs = "12\n34\n56"+        Right arr = YX.byteStringToArray Just bs :: Either String (Array.Array YX Char)+        bs' = YX.arrayToByteString id arr+      bs' `shouldBe` bs
+ yx.cabal view
@@ -0,0 +1,40 @@+name:                yx+version:             0.0.1.0+synopsis:            Row-major coordinates+description:         https://github.com/mtth/yx+homepage:            https://github.com/mtth/yx+license:             BSD3+license-file:        LICENSE+author:              Matthieu Monsch+maintainer:          matthieu.monsch@gmail.com+copyright:           2018 Matthieu Monsch+category:            Web+build-type:          Simple+extra-source-files:  README.md+cabal-version:       >=1.10++library+  hs-source-dirs:      src+  exposed-modules:     Data.Geometry.YX+  build-depends:       base >= 4.7 && < 5+                     , array >= 0.5+                     , bytestring >= 0.10+  default-language:    Haskell2010++test-suite yx-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , array >= 0.5+    , bytestring >= 0.10+    , hspec >=2.5 && <2.6+    , yx+  default-language: Haskell2010++source-repository head+  type:     git+  location: https://github.com/mtth/yx