Last active
August 29, 2023 20:32
-
-
Save lazamar/305e8808f8975258f6acea4d20fd3405 to your computer and use it in GitHub Desktop.
Solution to nested-map-reduce-traversal challenge.
This file contains hidden or 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
{- This is a solution to https://github.com/josevalim/nested-map-reduce-traversal | |
without using explicit accumulators. | |
You can run it with: | |
$ ghc Main.hs && ./Main | |
Which outputs: | |
Numbered 0 ("One",[Numbered 0 "A",Numbered 1 "B"]) | |
Numbered 1 ("Two",[Numbered 2 "C",Numbered 3 "D",Numbered 4 "E"]) | |
Numbered 2 ("Three",[Numbered 0 "F",Numbered 1 "G"]) | |
Numbered 3 ("Four",[]) | |
Numbered 4 ("Five",[Numbered 0 "H"]) | |
-} | |
module Main where | |
import Data.List (tails) | |
type SectionTitle = String | |
type Lesson = String | |
data Section = Section | |
{ title :: SectionTitle | |
, reset_lesson_position :: Bool | |
, lessons :: [Lesson] | |
} | |
deriving Show | |
data Numbered a = Numbered Int a | |
deriving Show | |
type Result = (SectionTitle, [Numbered Lesson]) | |
main = putStrLn $ unlines $ map show $ | |
numberIt | |
[ Section "One" True ["A", "B"] | |
, Section "Two" False ["C", "D", "E"] | |
, Section "Three" True ["F", "G"] | |
, Section "Four" False [] | |
, Section "Five" True ["H"] | |
] | |
numberIt :: [Section] -> [Numbered Result] | |
numberIt = numbered . concatMap numberLessons . spans | |
where | |
-- stretches where lessons should be sequentially numbered | |
spans :: [Section] -> [[Section]] | |
spans sections = | |
map (\(x:xs) -> x : takeWhile (not . reset_lesson_position) xs) $ | |
filter (reset_lesson_position . head) $ | |
filter (not . null) $ | |
tails sections | |
numberLessons :: [Section] -> [Result] | |
numberLessons sections = map groupBy (map title sections) | |
where | |
groupBy title = (title, map snd $ filter ((== title) . fst) annotated) | |
annotated :: [(SectionTitle, Numbered Lesson)] | |
annotated = uncurry zip $ fmap numbered $ unzip $ concatMap annotate sections | |
annotate :: Section -> [(SectionTitle, Lesson)] | |
annotate (Section title _ lessons) = map (title,) lessons | |
numbered :: [a] -> [Numbered a] | |
numbered xs = zipWith Numbered [0..] xs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment