Last active
August 29, 2015 14:10
-
-
Save nomeata/5dc2ea606e45d98ea67e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE TupleSections #-} | |
module SeqCP where | |
import Data.Sequence | |
import Prelude hiding (drop, take, length, splitAt) | |
import Test.QuickCheck ((===), (==>), Property, Positive(..)) | |
data CPs x y = | |
Empty | | |
SingleCP x (Seq y) | | |
CPs (Seq x) (Seq y) !Int {- beginning column -} !Int {- last column -} | |
deriving Show | |
createCPs :: Seq x -> Seq y -> CPs x y | |
createCPs xs ys = CPs xs ys 0 (length ys - 1) | |
lengthCPs :: CPs x y -> Int | |
lengthCPs Empty = 0 | |
lengthCPs (SingleCP x ys) = length ys | |
lengthCPs (CPs xs ys fc lc) = (length xs - 1) * length ys - fc + lc + 1 | |
-- Smart constructor | |
mkCPs :: Seq x -> Seq y -> Int -> Int -> CPs x y | |
mkCPs xs ys fc lc | |
| length xs == 0 || length ys == 0 | |
= Empty | |
| length xs == 1 | |
= SingleCP (xs `index` 0) (drop fc $ take (lc+1) $ ys) | |
| otherwise | |
= CPs xs ys fc lc | |
splitCPs:: Int -> CPs x y -> (CPs x y, CPs x y) | |
splitCPs n cps | n <= 0 | |
= ( Empty, cps ) | |
splitCPs n (CPs xs ys fc lc) | length xs == 0 || length ys == 0 | |
= ( Empty, Empty ) | |
splitCPs n cp | n >= lengthCPs cp | |
= ( cp, Empty ) | |
splitCPs n (SingleCP x ys) | |
= ( SingleCP x ys1, SingleCP x ys2 ) | |
where (ys1, ys2) = splitAt n ys | |
splitCPs n (CPs xs ys fc lc) | |
= ( mkCPs (take r_end xs) ys fc c_end | |
, mkCPs (drop r_begin xs) ys c_begin lc | |
) | |
where | |
-- Coordinates of the beginning of the second chunk | |
r_begin = (n + fc) `div` length ys -- number of rows that do not go into the second chunk | |
c_begin = (n + fc) `mod` length ys | |
-- Coordinates of the end of the first chunk | |
r_end | c_begin == 0 = r_begin -- cut nicely along rows, keep the other rows | |
| otherwise = r_begin + 1 -- we need to keep one row in both chunks | |
c_end = (c_begin - 1) `mod` length ys | |
getSingletonCPs :: CPs x y -> (x, Seq y) | |
getSingletonCPs (SingleCP x ys) = (x, ys) | |
pairsCP :: CPs x y -> Seq (x,y) | |
pairsCP Empty | |
= empty | |
pairsCP (SingleCP x ys) | |
= fmap (x,) ys | |
pairsCP (CPs xs ys fc lc) | |
= (fmap (xs `index` 0,) $ drop fc $ ys) >< pairsCP (mkCPs (drop 1 xs) ys 0 lc) | |
test_splitCPs :: [Int] -> [Char] -> Positive Int -> Positive Int -> Positive Int -> Property | |
test_splitCPs xs ys (Positive n) (Positive m) (Positive k) | |
= n < length ys' ==> | |
m < length ys' ==> | |
(if length xs' == 1 then n < m else True) ==> | |
pairsCP cp === (pairsCP cp1 >< pairsCP cp2) | |
where | |
xs' = fromList xs | |
ys' = fromList ys | |
cp = mkCPs xs' ys' n m | |
(cp1, cp2) = splitCPs k cp |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment