{-
File: strategies.hs
Author: Max Levatich
-}

import System.Environment
import Data.Maybe
import Control.Parallel.Strategies hiding (evalList, using)
import Control.DeepSeq

-- Find sudoku.hs and sudoku17.1000.txt here:
-- https://github.com/simonmar/parconc-examples/archive/master.tar.gz
import Sudoku

-- For kmeans:
-- https://github.com/simonmar/parconc-examples/archive/master.tar.gz
-- stack install monad-par
-- stack install normaldistribution

-- Generate samples:
-- stack ghc -- -O2 -Wall GenSamples.hs
-- ./GenSamples 5 50000 100000 1010

-- Generate image (requires gnuplot):
-- gnuplot -e 'set terminal png;set nokey;plot "points"' > points.png

-- Run kmeans on samples:
-- stack ghc -- -O2 -Wall -threaded -rtsopts kmeans.hs
-- Sequential: ./kmeans seq
-- Parallel with 50 chunks: ./kmeans strat 50 +RTS ...



-- evalList :: Strategy a -> ([a] -> Eval [a])
evalList :: Strategy a -> Strategy [a]
evalList _ []     = return []
evalList s (x:xs) = do
    x'  <- s x
    xs' <- evalList s xs
    return (x':xs')

-- parList :: Strategy a -> [a] -> Eval [a]
-- parList s = evalList (rparWith s)

-- seqList :: [a] -> Eval [a]
-- seqList = evalList seq

-- dynamicParMap :: (a -> b) -> [a] -> Eval [b]
-- dynamicParMap f xs = parList $ map f xs

using :: a -> Strategy a -> a
x `using` s = runEval $ s x

-- Run parallel sudoku solver:
-- ./strategies sudoku17.1000.txt +RTS ...
main :: IO ()
main = do 
    [f] <- getArgs
    puzzles <- lines <$> readFile f

    -- Attempt 1: serial
    -- let solutions = map solve puzzles

    -- Attempt 2: static partitioning
    -- let (as,bs) = splitAt (length puzzles `div` 2) puzzles
    --     solutions = runEval $ do
    --         as' <- rpar $ force $ map solve as
    --         bs' <- rpar $ force $ map solve bs
    --         rseq as'
    --         rseq bs'
    --         return $ as' ++ bs'

    -- Attempt 3: dynamic partitioning
    -- let solutions = runEval $ dynamicParMap solve puzzles

    -- Attempt 4: extracting the strategy! Note the similarity to the serial version
    let solutions = map solve puzzles `using` parList rseq

    print $ length $ filter isJust solutions