Utils.hs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. module Utils where
  2. import Data.Function
  3. import Data.Maybe
  4. import Data.Ratio
  5. import Data.List
  6. import Data.Char
  7. import Debug.Trace
  8. import Text.Printf
  9. (|>) = (&)
  10. (!?) :: [a] -> Int -> Maybe a
  11. l !? i
  12. | i >= (length l) = Nothing
  13. | i == 0 = car l
  14. | otherwise = cdr l >>= \x -> x !? (i-1)
  15. c2i :: Char -> Maybe Int
  16. c2i c = if cv < 48 || cv > 57
  17. then Nothing
  18. else Just (cv - 48)
  19. where cv = ord c
  20. car :: [a] -> Maybe a
  21. car [] = Nothing
  22. car [x] = Just x
  23. car (x:_) = Just x
  24. cdr :: [a] -> Maybe [a]
  25. cdr [] = Nothing
  26. cdr [_] = Just []
  27. cdr (_:xs) = Just xs
  28. run_maybe :: Maybe a -> (a -> b) -> Maybe b
  29. run_maybe x f = case x of
  30. Nothing -> Nothing
  31. Just x -> Just (f x)
  32. to_maybe :: (a -> b) -> (a -> Maybe b)
  33. to_maybe f = \x -> Just (f x)
  34. compareLength :: [a] -> Int -> Ordering
  35. compareLength l s
  36. | len == s = EQ
  37. | len > s = LT
  38. | len < s = GT
  39. where len = length l
  40. combinations2 :: [a] -> [b] -> [(a, b)]
  41. combinations2 x y = go' x y 0 0
  42. where
  43. go' :: [a] -> [b] -> Int -> Int -> [(a, b)]
  44. go' x y xi yi
  45. | compareLength x xi == EQ = go' x y 0 (yi+1)
  46. | compareLength y yi == EQ = []
  47. | otherwise = [((x !! xi), (y !! yi))] ++ go' x y (xi+1) yi
  48. combinations3 :: [a] -> [b] -> [c] -> [(a, b, c)]
  49. combinations3 x y z = go' x y z 0 0 0
  50. where
  51. go' :: [a] -> [b] -> [c] -> Int -> Int -> Int -> [(a, b, c)]
  52. go' x y z xi yi zi
  53. | compareLength x xi == EQ = go' x y z 0 (yi+1) zi
  54. | compareLength y yi == EQ = go' x y z 0 0 (zi+1)
  55. | compareLength z zi == EQ = []
  56. | otherwise = [((x !! xi), (y !! yi), (z !! zi))] ++ go' x y z (xi+1) yi zi
  57. data Direction = DUp | DDown | DLeft | DRight | DUpRight | DUpLeft | DDownRight | DDownLeft deriving Show
  58. allDirection :: [Direction]
  59. allDirection = [DUp, DDown, DLeft, DRight, DUpRight, DUpLeft, DDownRight, DDownLeft]
  60. data Point = Point { x :: Int, y :: Int } deriving Show
  61. point_next_dir :: Point -> Direction -> Point
  62. point_next_dir p d =
  63. case d of
  64. DUp -> Point ((x p)-1) (y p)
  65. DDown -> Point ((x p)+1) (y p)
  66. DLeft -> Point (x p) ((y p)-1)
  67. DRight -> Point (x p) ((y p)+1)
  68. DUpRight -> Point ((x p)-1) ((y p)+1)
  69. DUpLeft -> Point ((x p)-1) ((y p)-1)
  70. DDownRight -> Point ((x p)+1) ((y p)+1)
  71. DDownLeft -> Point ((x p)+1) ((y p)-1)
  72. type Matrix a = [[a]]
  73. matrix_n_rows :: Matrix a -> Int
  74. matrix_n_rows m = length m
  75. matrix_n_cols :: Matrix a -> Maybe Int
  76. matrix_n_cols m = car m >>= to_maybe length
  77. matrix_get :: Matrix a -> Int -> Int -> Maybe a
  78. matrix_get m x y = m !? x >>= \z -> z !? y
  79. matrix_get_n :: Matrix a -> Int -> Direction -> Point -> Maybe [a]
  80. matrix_get_n m a d p = go' m a d p 0
  81. where
  82. go' :: Matrix a -> Int -> Direction -> Point -> Int -> Maybe [a]
  83. go' m a d p c
  84. | c == a = Just []
  85. | otherwise = case matrix_get m (x p) (y p) of
  86. Nothing -> Nothing
  87. Just z -> go' m a d (point_next_dir p d) (c+1) >>= \w -> Just ([z] ++ w)
  88. coalesce2 :: Maybe a -> Maybe a -> a -> a
  89. coalesce2 x y d = coalesce1 y (coalesce1 x d)
  90. coalesce1 :: Maybe a -> a -> a
  91. coalesce1 (Just x) _ = x
  92. coalesce1 (Nothing) d = d
  93. bigger :: (a -> Int) -> [a] -> a
  94. bigger f xs = xs !! i where li = map f xs
  95. i = fromJust $ elemIndex (maximum li) li
  96. data Tri a = EmptyTri | Node a (Tri a) (Tri a)
  97. deriving Show
  98. triLeft :: Tri a -> Tri a
  99. triLeft EmptyTri = EmptyTri
  100. triLeft (Node _ l _) = l
  101. triRight :: Tri a -> Tri a
  102. triRight EmptyTri = EmptyTri
  103. triRight (Node _ _ r) = r
  104. triVal :: Tri a -> Maybe a
  105. triVal EmptyTri = Nothing
  106. triVal (Node x _ _) = Just x
  107. triValDef :: a -> Tri a -> a
  108. triValDef d EmptyTri = d
  109. triValDef _ (Node x _ _) = x
  110. triVal' :: Tri a -> a
  111. triVal' (Node x _ _) = x
  112. triParseString :: String -> Tri Int
  113. triParseString s = lines s |> map words |> map (map read) |> go' 0
  114. where
  115. go' :: Int -> [[Int]] -> Tri Int
  116. go' _ [] = EmptyTri
  117. go' i [x] = Node (x !! i) EmptyTri EmptyTri
  118. go' i (x:xs) = Node (x !! i) (go' (i+0) xs) (go' (i+1) xs)
  119. tri2UnsortedList :: Int -> Tri a -> [a]
  120. tri2UnsortedList _ (EmptyTri) = []
  121. tri2UnsortedList td t = go' t 0
  122. where
  123. go' (EmptyTri) _ = []
  124. go' (Node x l r) d
  125. | d == td = []
  126. | otherwise = [x] ++ go' l (d+1) ++ go' r (d+1)
  127. type Day = Int
  128. type Month = Int
  129. monthNumOfDay :: Year -> Month -> Int
  130. monthNumOfDay yyyy 2 = if (yearIsLeap yyyy) then 29 else 28
  131. monthNumOfDay _ 4 = 30
  132. monthNumOfDay _ 6 = 30
  133. monthNumOfDay _ 9 = 30
  134. monthNumOfDay _ 11 = 30
  135. monthNumOfDay _ mm = 31
  136. type Year = Int
  137. yearIsLeap :: Year -> Bool
  138. yearIsLeap yyyy = (mody 4) && ((not (mody 100)) || (mody 400))
  139. where mody = \x -> mod yyyy x == 0
  140. data Date = Date Year Month Day
  141. deriving (Show, Eq)
  142. dateDay :: Date -> Day
  143. dateDay (Date _ _ dd) = dd
  144. dateNextDay :: Date -> Date
  145. dateNextDay (Date yyyy mm dd)
  146. | dd == (monthNumOfDay yyyy mm) = dateNextMonth (Date yyyy mm 1)
  147. | otherwise = (Date yyyy mm (dd+1))
  148. dateNextMonth :: Date -> Date
  149. dateNextMonth (Date yyyy 12 dd) = dateNextYear (Date yyyy 1 dd)
  150. dateNextMonth (Date yyyy mm dd) = (Date yyyy (mm+1) dd)
  151. dateNextYear :: Date -> Date
  152. dateNextYear (Date yyyy mm dd) = (Date (yyyy+1) mm dd)
  153. data Weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
  154. deriving (Show, Enum, Eq)
  155. weekdayNext :: Weekday -> Weekday
  156. weekdayNext Sunday = Monday
  157. weekdayNext x = succ x
  158. weekdayOfDate :: Date -> Weekday
  159. weekdayOfDate tD = go' (Date 1900 1 1) (iterate weekdayNext Monday)
  160. where
  161. go' :: Date -> [Weekday] -> Weekday
  162. go' d (x:xs)
  163. | d == tD = x
  164. | otherwise = go' (dateNextDay d) xs
  165. factorial :: Integer -> Integer
  166. factorial 0 = 0
  167. factorial 1 = 1
  168. factorial x = x * factorial (x-1)
  169. divs :: Int -> [Int]
  170. divs 0 = []
  171. divs 1 = [1]
  172. divs x = filter (\x' -> (mod x x') == 0) (take (x-1) (iterate (+1) 1))
  173. flattenTupleList :: [(a, a)] -> [a]
  174. flattenTupleList [] = []
  175. flattenTupleList [(x, y)] = [x, y]
  176. flattenTupleList ((x, y):xs) = [x, y] ++ (flattenTupleList xs)
  177. mapi :: (Int -> a -> b) -> [a] -> [b]
  178. mapi _ [] = []
  179. mapi f l = go' l 0
  180. where go' [] _ = []
  181. go' [x] i = [f i x]
  182. go' (x:xs) i = [f i x] ++ go' xs (i+1)
  183. splitByChar :: Char -> String -> [String]
  184. splitByChar c s = go' (elemIndex c s) s
  185. where go' :: Maybe Int -> String -> [String]
  186. go' (Nothing) s = [s]
  187. go' (Just i) s = [b] ++ go' (elemIndex c a) a
  188. where
  189. (b, aRaw) = splitAt i s
  190. a = tail aRaw
  191. tracePPId :: Show a => [a] -> [a]
  192. tracePPId l = if (go' l 0) then [] else l
  193. where
  194. go' :: Show a => [a] -> Int -> Bool
  195. go' [] _ = False
  196. go' (x:xs) i = trace (printf "%5d -> %s" i (show x)) (go' xs (i+1))
  197. slice :: Int -> Int -> [a] -> [a]
  198. slice b s l = drop b l |> take s
  199. howManyFit :: Int -> Int -> Int
  200. --howManyFit x y | trace (printf "howManyFit %3d %3d" x y) False = undefined
  201. howManyFit x y = if w == 0
  202. then 1
  203. else (if w > 0
  204. then 1 + (howManyFit x w)
  205. else 0)
  206. where w = y-x
  207. tW f (x:xs) = case f x of
  208. True -> tW f xs
  209. False -> x
  210. longDiv :: Ratio Int -> String
  211. longDiv r = if dn == nmRaw then "1" else pred ++ (go' nm False 5000)
  212. where
  213. nmRaw = numerator r
  214. dn = denominator r
  215. hMInc = iterate (+1) 1 |> tW (\x -> (howManyFit dn (nmRaw*(10^x))) == 0)
  216. nm = nmRaw * (10^hMInc)
  217. pred = case hMInc of
  218. 1 -> "0."
  219. 2 -> "0.0"
  220. 3 -> "0.00"
  221. 4 -> "0.000"
  222. _ -> ""
  223. go' :: Int -> Bool -> Int -> [Char]
  224. go' 0 _ _ = []
  225. go' _ _ 0 = []
  226. go' x z n
  227. -- | trace (printf "go' %3d %3d | hmf -> %3d" x n hmf) False = undefined
  228. | hmf == 0 && z = ['0'] ++ (go' x False (n-1))
  229. | otherwise = if hmf == 0
  230. then go' (x * 10) True (n)
  231. else [(intToDigit hmf)] ++ (go' (x-(dn*hmf)) False (n-1))
  232. where hmf = howManyFit dn x
  233. isPrime :: Int -> Bool
  234. isPrime x = (divs x) == [1]
  235. addResult :: (a -> b) -> a -> (a, b)
  236. addResult f x = (x, f x)
  237. mapFindMaxInitial :: Ord b => (a -> b) -> [a] -> a
  238. mapFindMaxInitial f l = map (addResult f) l |> maximumBy (\a b -> compare (snd a) (snd b)) |> fst
  239. dup :: a -> (a,a)
  240. dup x = (x, x)