aboutsummaryrefslogtreecommitdiff
path: root/challenge-074/jeongoon/haskell/ch-1.hs
blob: 34b45fd2d46e2565c9ef17d53a7115601eeb38ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}
import Options.Generic
import JRandomList
import Data.List ( sort, unfoldr )

import Data.Maybe
import System.Random ( randoms, randomR, randomRs, newStdGen, StdGen )

{- Tested with:
runhaskell -i. ch-1.hs 10
-}

-- Solution
getMajor []   = (-1)
getMajor [x]  =  x
getMajor list = case (last.processMajor.sort) list of
                  Nothing  -> (-1)
                  Just (x) ->   x
  where
    majlen = (length list) `div` 2
    processMajor list@(l:ls) = unfoldr recordMajor ( ( l, 1), ls )
    recordMajor ( (x, cnt), ls )
      | null ls    = Nothing                                 -- edge case
      | x == y     = if cnt == majlen
                    then Just( Just x, ( (x ,succ cnt), [] ) ) -- major found
                    else Just ( Nothing, ((x, succ cnt), ys) )
      | otherwise = Just ( Nothing, ( (y, 1), ys ) )
        where y = head ls; ys = tail ls;

{- Comment: probably I could use `(filter f).group.sort' approach
            but I still want to study more about haskell. -}

-- Testing
aSample size seed =
  let majEnsured = head ( randoms seed :: [Bool] )
      halfSize   = size `div` 2
      lo = 0
      hi = size -1
      ( majNum, seed' ) = randomR ( lo, hi ) seed
      majCnt  = fst $ if majEnsured then randomR ( halfSize+1, size-1 ) seed'
                      else randomR ( 0, halfSize ) seed'
      majList = replicate majCnt majNum
      rstList = take (size - majCnt) (randomRs (lo, hi) seed)
      majInfo = if majEnsured then Just ( majNum, majCnt ) else Nothing
  in
    ( majInfo, shuffleByPickingAll ( majList ++ rstList ) seed )

validateSizeIO :: (Ord a, Show a) => a -> a -> IO a
validateSizeIO def given = do
  if given < def then
    putStrLn ( "Given size is too short: " ++ (show given)
               ++ ": using default size: " ++ (show def) )
    >> return def
    else putStrLn( "Given Size:" ++ (show given) )
    >> return given

main = do
  args <- getRecord "Challenge #074 - Task #1"
  let defS = 2
      sStr = show ( args :: Int )
      s = read sStr :: Int
      getSize = validateSizeIO defS s in
    do
      size <- getSize;
      seed <- newStdGen;
      let ex = aSample size seed
          majorInfoExist = isJust( fst ex )
          majorNum   = (fst.fromJust) (fst ex)
          solution = getMajor (snd ex)
        in do
        -- XXX: even though I didn't intend to make majority number
        --      random list still could contain a majority number
        putStr $ "Input: " ++
          (if majorInfoExist then "Major = " ++ show majorNum
           else "*Maybe* No Major" ) ++ ": "
        print $ snd ex
        putStr   "Output: "
        print $ solution