RosettaCodeData/Task/Range-consolidation/Haskell/range-consolidation.hs
2023-07-01 13:44:08 -04:00

85 lines
1.7 KiB
Haskell

import Data.List (intercalate, maximumBy, sort)
import Data.Ord (comparing)
------------------- RANGE CONSOLIDATION ------------------
consolidated :: [(Float, Float)] -> [(Float, Float)]
consolidated = foldr go [] . sort . fmap ab
where
go xy [] = [xy]
go xy@(x, y) abetc@((a, b) : etc)
| y >= b = xy : etc
| y >= a = (x, b) : etc
| otherwise = xy : abetc
ab (a, b)
| a <= b = (a, b)
| otherwise = (b, a)
--------------------------- TEST -------------------------
tests :: [[(Float, Float)]]
tests =
[ [],
[(1.1, 2.2)],
[(6.1, 7.2), (7.2, 8.3)],
[(4, 3), (2, 1)],
[(4, 3), (2, 1), (-1, -2), (3.9, 10)],
[(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)]
]
main :: IO ()
main =
putStrLn $
tabulated
"Range consolidations:"
showPairs
showPairs
consolidated
tests
-------------------- DISPLAY FORMATTING ------------------
tabulated ::
String ->
(a -> String) ->
(b -> String) ->
(a -> b) ->
[a] ->
String
tabulated s xShow fxShow f xs =
let w =
length $
maximumBy
(comparing length)
(xShow <$> xs)
rjust n c s = drop (length s) (replicate n c <> s)
in unlines $
s :
fmap
( ((<>) . rjust w ' ' . xShow)
<*> ((" -> " <>) . fxShow . f)
)
xs
showPairs :: [(Float, Float)] -> String
showPairs xs
| null xs = "[]"
| otherwise =
'[' :
intercalate
", "
(showPair <$> xs)
<> "]"
showPair :: (Float, Float) -> String
showPair (a, b) =
'(' :
showNum a
<> ", "
<> showNum b
<> ")"
showNum :: Float -> String
showNum n
| 0 == (n - fromIntegral (round n)) = show (round n)
| otherwise = show n