first try
This commit is contained in:
@@ -0,0 +1,169 @@
|
|||||||
|
module Card where
|
||||||
|
|
||||||
|
import Data.List
|
||||||
|
import Utils
|
||||||
|
|
||||||
|
data Type = Seven
|
||||||
|
| Eight
|
||||||
|
| Nine
|
||||||
|
| Queen
|
||||||
|
| King
|
||||||
|
| Ten
|
||||||
|
| Ace
|
||||||
|
| Jack
|
||||||
|
deriving (Eq, Ord, Show, Enum)
|
||||||
|
|
||||||
|
countType :: Type -> Int
|
||||||
|
countType Ace = 11
|
||||||
|
countType Ten = 10
|
||||||
|
countType King = 4
|
||||||
|
countType Queen = 3
|
||||||
|
countType Jack = 2
|
||||||
|
countType _ = 0
|
||||||
|
|
||||||
|
data Colour = Diamonds
|
||||||
|
| Hearts
|
||||||
|
| Spades
|
||||||
|
| Clubs
|
||||||
|
deriving (Eq, Ord, Show, Enum, Read)
|
||||||
|
|
||||||
|
data Card = Card Type Colour
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
countCard :: Card -> Int
|
||||||
|
countCard (Card t _) = countType t
|
||||||
|
|
||||||
|
count :: [Card] -> Int
|
||||||
|
count = sum . map countCard
|
||||||
|
|
||||||
|
data Team = Team | Single
|
||||||
|
deriving (Show, Eq, Ord, Enum)
|
||||||
|
|
||||||
|
data Space = Table | Hand1 | Hand2 | Hand3 | WonTeam | WonSingle | SkatP
|
||||||
|
deriving (Show, Eq, Ord, Enum)
|
||||||
|
|
||||||
|
teamPile :: Team -> Space
|
||||||
|
teamPile Team = WonTeam
|
||||||
|
teamPile Single = WonSingle
|
||||||
|
|
||||||
|
playerHand :: Index -> Space
|
||||||
|
playerHand One = Hand1
|
||||||
|
playerHand Two = Hand2
|
||||||
|
playerHand Three = Hand3
|
||||||
|
|
||||||
|
playerOfHand :: Space -> Index
|
||||||
|
playerOfHand Hand1 = One
|
||||||
|
playerOfHand Hand2 = Two
|
||||||
|
playerOfHand Hand3 = Three
|
||||||
|
|
||||||
|
data CardS = CardS { getCard :: Card
|
||||||
|
, getSpace :: Space
|
||||||
|
, getOwner :: Space }
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
moveCard :: Card -> Space -> [CardS] -> [CardS]
|
||||||
|
moveCard card sp cards = map f cards
|
||||||
|
where f c = if card == getCard c then c { getSpace = sp } else c
|
||||||
|
|
||||||
|
findCards :: Space -> [CardS] -> [Card]
|
||||||
|
findCards sp cards = foldr f [] cards
|
||||||
|
where f (CardS c s _) cs
|
||||||
|
| s == sp = c : cs
|
||||||
|
| otherwise = cs
|
||||||
|
|
||||||
|
data Index = One | Two | Three
|
||||||
|
deriving (Show, Ord, Eq, Enum)
|
||||||
|
|
||||||
|
next :: Index -> Index
|
||||||
|
next One = Two
|
||||||
|
next Two = Three
|
||||||
|
next Three = One
|
||||||
|
|
||||||
|
prev :: Index -> Index
|
||||||
|
prev One = Three
|
||||||
|
prev Two = One
|
||||||
|
prev Three = Two
|
||||||
|
|
||||||
|
data Player = Player { team :: Team
|
||||||
|
, index :: Index }
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
data Players = Players Player Player Player
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
player :: Players -> Index -> Player
|
||||||
|
player (Players p _ _) One = p
|
||||||
|
player (Players _ p _) Two = p
|
||||||
|
player (Players _ _ p) Three = p
|
||||||
|
|
||||||
|
type Hand = [Card]
|
||||||
|
|
||||||
|
equals :: Colour -> Maybe Colour -> Bool
|
||||||
|
equals col (Just x) = col == x
|
||||||
|
equals col Nothing = True
|
||||||
|
|
||||||
|
isTrump :: Colour -> Card -> Bool
|
||||||
|
isTrump trumpCol (Card tp col)
|
||||||
|
| tp == Jack = True
|
||||||
|
| otherwise = col == trumpCol
|
||||||
|
|
||||||
|
effectiveColour :: Colour -> Card -> Colour
|
||||||
|
effectiveColour trumpCol card@(Card _ col) =
|
||||||
|
if trump then trumpCol else col
|
||||||
|
where trump = isTrump trumpCol card
|
||||||
|
|
||||||
|
isAllowed :: Colour -> Maybe Colour -> Hand -> Card -> Bool
|
||||||
|
isAllowed trumpCol turnCol cs card =
|
||||||
|
if col `equals` turnCol
|
||||||
|
then True
|
||||||
|
else not $ any (\ca -> effectiveColour trumpCol ca `equals` turnCol && ca /= card) cs
|
||||||
|
where col = effectiveColour trumpCol card
|
||||||
|
|
||||||
|
putAt :: Space -> Card -> CardS
|
||||||
|
putAt sp c = CardS c sp sp
|
||||||
|
|
||||||
|
distribute :: [Card] -> [CardS]
|
||||||
|
distribute cards = map (putAt Hand1) hand1
|
||||||
|
++ map (putAt Hand2) hand2
|
||||||
|
++ map (putAt Hand3) hand3
|
||||||
|
++ map (putAt SkatP) skt
|
||||||
|
where round1 = chunksOf 3 (take 9 cards)
|
||||||
|
skt = take 2 $ drop 9 cards
|
||||||
|
round2 = chunksOf 4 (take 12 $ drop 11 cards)
|
||||||
|
round3 = chunksOf 3 (take 9 $ drop 23 cards)
|
||||||
|
hand1 = concatMap (!! 0) [round1, round2, round3]
|
||||||
|
hand2 = concatMap (!! 1) [round1, round2, round3]
|
||||||
|
hand3 = concatMap (!! 2) [round1, round2, round3]
|
||||||
|
|
||||||
|
playersFromTable :: Players -> [CardS] -> [Player]
|
||||||
|
playersFromTable ps = map (player ps . playerOfHand . getOwner)
|
||||||
|
|
||||||
|
-- TESTING VARS
|
||||||
|
|
||||||
|
c1 :: Card
|
||||||
|
c1 = Card Jack Spades
|
||||||
|
|
||||||
|
c2 :: Card
|
||||||
|
c2 = Card Ace Diamonds
|
||||||
|
|
||||||
|
c3 :: Card
|
||||||
|
c3 = Card Queen Diamonds
|
||||||
|
|
||||||
|
c4 :: Card
|
||||||
|
c4 = Card Queen Hearts
|
||||||
|
|
||||||
|
c5 :: Card
|
||||||
|
c5 = Card Jack Clubs
|
||||||
|
|
||||||
|
h1 :: Hand
|
||||||
|
h1 = [c1,c2,c3,c4,c5]
|
||||||
|
|
||||||
|
allCards :: [Card]
|
||||||
|
allCards = [ Card t c | t <- tps, c <- cols ]
|
||||||
|
where tps = [Seven .. Jack]
|
||||||
|
cols = [Diamonds .. Clubs]
|
||||||
|
|
||||||
|
distributePutSkat :: [Card] -> [CardS]
|
||||||
|
distributePutSkat cards = foldr (\c m -> moveCard c WonSingle m) distributed skt
|
||||||
|
where distributed = distribute cards
|
||||||
|
skt = findCards SkatP distributed
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Control.Monad.State
|
||||||
|
|
||||||
|
import Card
|
||||||
|
import Skat
|
||||||
|
import Reizen
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
env <- reizen
|
||||||
|
(sgl, tm) <- evalStateT runGame env
|
||||||
|
putStrLn $ "Single player has " ++ show sgl ++ " points."
|
||||||
|
putStrLn $ "Team has " ++ show tm ++ " points."
|
||||||
+203
@@ -0,0 +1,203 @@
|
|||||||
|
module Operations where
|
||||||
|
|
||||||
|
import Control.Monad.State
|
||||||
|
import System.Random (newStdGen, randoms)
|
||||||
|
import Data.List
|
||||||
|
import Data.Ord
|
||||||
|
|
||||||
|
import Card
|
||||||
|
import Skat
|
||||||
|
import Utils (shuffle)
|
||||||
|
|
||||||
|
compareCards :: Colour
|
||||||
|
-> Maybe Colour
|
||||||
|
-> Card
|
||||||
|
-> Card
|
||||||
|
-> Ordering
|
||||||
|
compareCards _ _ (Card Jack col1) (Card Jack col2) = compare col1 col2
|
||||||
|
compareCards trumpCol turnCol c1@(Card tp1 col1) c2@(Card tp2 col2) =
|
||||||
|
case compare trp1 trp2 of
|
||||||
|
EQ ->
|
||||||
|
case compare (col1 `equals` turnCol)
|
||||||
|
(col2 `equals` turnCol) of
|
||||||
|
EQ -> compare tp1 tp2
|
||||||
|
v -> v
|
||||||
|
v -> v
|
||||||
|
where trp1 = isTrump trumpCol c1
|
||||||
|
trp2 = isTrump trumpCol c2
|
||||||
|
|
||||||
|
sortCards :: Colour -> Maybe Colour -> [Card] -> [Card]
|
||||||
|
sortCards trumpCol turnCol cs = sortBy (compareCards trumpCol turnCol) cs
|
||||||
|
|
||||||
|
compareRender :: Card -> Card -> Ordering
|
||||||
|
compareRender (Card t1 c1) (Card t2 c2) = case compare c1 c2 of
|
||||||
|
EQ -> compare t1 t2
|
||||||
|
v -> v
|
||||||
|
|
||||||
|
sortRender :: [Card] -> [Card]
|
||||||
|
sortRender = sortBy compareRender
|
||||||
|
|
||||||
|
-- | finishes the calculation of a match
|
||||||
|
turning :: Index -> Skat (Int, Int)
|
||||||
|
turning n = undefined
|
||||||
|
|
||||||
|
turn2 :: Index -> Skat (Int, Int)
|
||||||
|
turn2 n = do
|
||||||
|
t <- table
|
||||||
|
ps <- gets players
|
||||||
|
let p = player ps n
|
||||||
|
hand <- cardsAt (playerHand $ index p)
|
||||||
|
if length hand == 0
|
||||||
|
then countGame
|
||||||
|
else case length t of
|
||||||
|
0 -> play p >> turn2 (next n)
|
||||||
|
1 -> do
|
||||||
|
modify (setTurnColour . f . head $ t)
|
||||||
|
play p
|
||||||
|
turn2 (next n)
|
||||||
|
2 -> play p >> evaluateTable >>= turn2
|
||||||
|
3 -> evaluateTable >>= turn2
|
||||||
|
where f (Card _ col) = Just col
|
||||||
|
|
||||||
|
simulate :: Team -> Index -> Skat (Int, Int)
|
||||||
|
simulate team n = do
|
||||||
|
t <- table
|
||||||
|
ps <- gets players
|
||||||
|
let p = player ps n
|
||||||
|
hand <- cardsAt (playerHand $ index p)
|
||||||
|
if length hand == 0
|
||||||
|
then countGame
|
||||||
|
else case length t of
|
||||||
|
0 -> playOpen team p >> simulate team (next n)
|
||||||
|
1 -> do
|
||||||
|
modify (setTurnColour . f . head $ t)
|
||||||
|
playOpen team p
|
||||||
|
simulate team (next n)
|
||||||
|
2 -> playOpen team p >> evaluateTable >>= simulate team
|
||||||
|
3 -> evaluateTable >>= simulate team
|
||||||
|
where f (Card _ col) = Just col
|
||||||
|
|
||||||
|
evaluateTable :: Skat Index
|
||||||
|
evaluateTable = do
|
||||||
|
trumpCol <- gets trumpColour
|
||||||
|
turnCol <- gets turnColour
|
||||||
|
t <- table
|
||||||
|
ts <- tableS
|
||||||
|
ps <- gets players
|
||||||
|
let psOrdered = playersFromTable ps ts
|
||||||
|
l = zip psOrdered t
|
||||||
|
g a b = compareCards trumpCol turnCol (snd a) (snd b)
|
||||||
|
(winner, _) = last (sortBy g l)
|
||||||
|
pile = teamPile $ team winner
|
||||||
|
forM t (\c -> move c pile)
|
||||||
|
modify $ setTurnColour Nothing
|
||||||
|
return $ index winner
|
||||||
|
|
||||||
|
countGame :: Skat (Int, Int)
|
||||||
|
countGame = do
|
||||||
|
sgl <- count <$> cardsAt WonSingle
|
||||||
|
tm <- count <$> cardsAt WonTeam
|
||||||
|
return (sgl, tm)
|
||||||
|
|
||||||
|
turn :: Index -> Skat Index
|
||||||
|
turn n = do
|
||||||
|
ps <- gets players
|
||||||
|
let p1 = player ps n
|
||||||
|
p2 = player ps (next n)
|
||||||
|
p3 = player ps (next $ next n)
|
||||||
|
c1@(Card _ col) <- play p1
|
||||||
|
modify $ setTurnColour (Just col)
|
||||||
|
c2 <- play p2
|
||||||
|
c3 <- play p3
|
||||||
|
trumpCol <- gets trumpColour
|
||||||
|
turnCol <- gets turnColour
|
||||||
|
let l = zip3 [p1, p2, p3] [c1, c2, c3] [n, next n, next $ next n]
|
||||||
|
g a b = compareCards trumpCol turnCol (f a) (f b)
|
||||||
|
(winner, _, idx) = last (sortBy g l)
|
||||||
|
pile = teamPile $ team winner
|
||||||
|
move c1 pile
|
||||||
|
move c2 pile
|
||||||
|
move c3 pile
|
||||||
|
modify $ setTurnColour Nothing
|
||||||
|
return idx
|
||||||
|
where f (_, x, _) = x
|
||||||
|
|
||||||
|
play :: Player -> Skat Card
|
||||||
|
play p = do
|
||||||
|
table <- table
|
||||||
|
turnCol <- gets turnColour
|
||||||
|
trump <- gets trumpColour
|
||||||
|
hand <- cardsAt (playerHand $ index p)
|
||||||
|
let card = playCard p table hand trump turnCol
|
||||||
|
move card Table
|
||||||
|
return card
|
||||||
|
|
||||||
|
playOpen :: Team -> Player -> Skat Card
|
||||||
|
playOpen team p = do
|
||||||
|
card <- playCardOpenAI team p
|
||||||
|
move card Table
|
||||||
|
return card
|
||||||
|
|
||||||
|
-- | cheating AI that knows all cards (open play)
|
||||||
|
playCardOpenAI :: Team -> Player -> Skat Card
|
||||||
|
playCardOpenAI team p = do
|
||||||
|
table <- table
|
||||||
|
turnCol <- gets turnColour
|
||||||
|
trump <- gets trumpColour
|
||||||
|
hand <- cardsAt (playerHand $ index p)
|
||||||
|
let possible = filter (isAllowed trump turnCol hand) hand
|
||||||
|
ownResult = if team == Single then fst else snd
|
||||||
|
ownIdx = index p
|
||||||
|
results <- forM possible (\card -> do
|
||||||
|
move card Table
|
||||||
|
val <- ownResult <$> simulate team ownIdx
|
||||||
|
move card (playerHand $ index p)
|
||||||
|
return (val, card))
|
||||||
|
return $ snd $ maximumBy (comparing fst) results
|
||||||
|
|
||||||
|
playCard :: Player
|
||||||
|
-> [Card]
|
||||||
|
-> [Card]
|
||||||
|
-> Colour
|
||||||
|
-> Maybe Colour
|
||||||
|
-> Card
|
||||||
|
playCard p table hand trump turnCol = head possible
|
||||||
|
where possible = filter (isAllowed trump turnCol hand) hand
|
||||||
|
|
||||||
|
runGame :: Skat (Int, Int)
|
||||||
|
runGame = do
|
||||||
|
foldM_ (\i _ -> turn i) One [1..10]
|
||||||
|
sgl <- fmap count $ cardsAt WonSingle
|
||||||
|
tm <- fmap count $ cardsAt WonTeam
|
||||||
|
return (sgl, tm)
|
||||||
|
|
||||||
|
shuffleCards :: IO [Card]
|
||||||
|
shuffleCards = do
|
||||||
|
gen <- newStdGen
|
||||||
|
return $ shuffle gen allCards
|
||||||
|
|
||||||
|
-- TESTING VARS
|
||||||
|
|
||||||
|
env :: SkatEnv
|
||||||
|
env = SkatEnv cards Nothing Spades playersExamp
|
||||||
|
where hand1 = take 10 allCards
|
||||||
|
hand2 = take 10 $ drop 10 allCards
|
||||||
|
hand3 = take 10 $ drop 20 allCards
|
||||||
|
skt = drop 30 allCards
|
||||||
|
cards = map (putAt Hand1) hand1
|
||||||
|
++ map (putAt Hand2) hand2
|
||||||
|
++ map (putAt Hand3) hand3
|
||||||
|
++ map (putAt WonSingle) skt
|
||||||
|
|
||||||
|
playersExamp :: Players
|
||||||
|
playersExamp = Players (Player Team One) (Player Team Two) (Player Single Three)
|
||||||
|
|
||||||
|
shuffledEnv :: IO SkatEnv
|
||||||
|
shuffledEnv = do
|
||||||
|
cards <- shuffleCards
|
||||||
|
return $ SkatEnv (distribute cards) Nothing Spades playersExamp
|
||||||
|
|
||||||
|
shuffledEnv2 :: IO SkatEnv
|
||||||
|
shuffledEnv2 = do
|
||||||
|
cards <- shuffleCards
|
||||||
|
return $ SkatEnv (distributePutSkat cards) Nothing Spades playersExamp
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
module Reizen where
|
||||||
|
|
||||||
|
import Skat
|
||||||
|
import Card
|
||||||
|
import Utils
|
||||||
|
import Operations
|
||||||
|
import Render
|
||||||
|
|
||||||
|
data Reizer = Reizer Index [Card]
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
getHand :: Index -> [Reizer] -> [Card]
|
||||||
|
getHand n rs = let (Reizer _ h) = head $ filter (\(Reizer i cs) -> i == n) rs
|
||||||
|
in h
|
||||||
|
|
||||||
|
goWith :: [Card] -> Int -> IO Bool
|
||||||
|
goWith cs n = query $ "Go with " ++ show n
|
||||||
|
|
||||||
|
goUp :: [Card] -> Int -> IO Int
|
||||||
|
goUp cs n = query $ "Go up " ++ show n
|
||||||
|
|
||||||
|
askColour :: [Card] -> IO Colour
|
||||||
|
askColour cs = render (sortRender cs) >> query "Trump should be:"
|
||||||
|
|
||||||
|
askSkat :: [Card] -> IO (Card, Card)
|
||||||
|
askSkat cs_ = do
|
||||||
|
let cs = sortRender cs_
|
||||||
|
render cs
|
||||||
|
(n1, n2) <- query "Drop two cards:"
|
||||||
|
if n1 < length cs && n2 < length cs && n1 >= 0 && n2 >= 0 && n1 /= n2
|
||||||
|
then return (cs !! n1, cs !! n2)
|
||||||
|
else askSkat cs
|
||||||
|
|
||||||
|
reizen :: IO SkatEnv
|
||||||
|
reizen = do
|
||||||
|
cs <- shuffleCards
|
||||||
|
let cards = distribute cs
|
||||||
|
p1 = Reizer One $ findCards Hand1 cards
|
||||||
|
p2 = Reizer Two $ findCards Hand2 cards
|
||||||
|
p3 = Reizer Three $ findCards Hand3 cards
|
||||||
|
skt = findCards SkatP cards
|
||||||
|
(winner1, new) <- combat p2 p1 0
|
||||||
|
(Reizer idx _, _) <- combat p3 winner1 new
|
||||||
|
let ps = Players (Player (if idx == One then Single else Team) One)
|
||||||
|
(Player (if idx == Two then Single else Team) Two)
|
||||||
|
(Player (if idx == Three then Single else Team) Three)
|
||||||
|
sglHand = playerHand idx
|
||||||
|
cards' = foldr (\c css -> moveCard c sglHand css) cards skt
|
||||||
|
trumpCol <- askColour (findCards sglHand cards')
|
||||||
|
(s1, s2) <- askSkat (findCards sglHand cards')
|
||||||
|
let cards'' = moveCard s2 WonSingle (moveCard s1 WonSingle cards')
|
||||||
|
return $ SkatEnv cards'' Nothing trumpCol ps
|
||||||
|
|
||||||
|
combat :: Reizer -> Reizer -> Int -> IO (Reizer, Int)
|
||||||
|
combat r2@(Reizer p2 h2) r1@(Reizer p1 h1) start = do
|
||||||
|
-- advantage for h1 (being challenged)
|
||||||
|
putStrLn $ "Player " ++ show p2 ++ " challenging " ++ show p1
|
||||||
|
putStrLn $ "Player " ++ show p2 ++ "'s turn"
|
||||||
|
new <- goUp h2 start
|
||||||
|
if new > start
|
||||||
|
then do
|
||||||
|
putStrLn $ "Player " ++ show p2 ++ " goes up to " ++ show new
|
||||||
|
putStrLn $ "Player " ++ show p1 ++ "'s turn"
|
||||||
|
yes <- goWith h1 new
|
||||||
|
if yes then combat r2 r1 new
|
||||||
|
else do
|
||||||
|
putStrLn $ "Player " ++ show p1 ++ " gives up"
|
||||||
|
putStrLn $ "Player " ++ show p2 ++ " wins"
|
||||||
|
return (r2, new)
|
||||||
|
else do
|
||||||
|
putStrLn $ "Player " ++ show p2 ++ " gives up"
|
||||||
|
putStrLn $ "Player " ++ show p1 ++ " wins"
|
||||||
|
return (r1, start)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
module Render where
|
||||||
|
|
||||||
|
import Card
|
||||||
|
import Operations
|
||||||
|
import Data.List
|
||||||
|
|
||||||
|
render :: [Card] -> IO ()
|
||||||
|
render = putStrLn . intercalate "\n" . zipWith (\n c -> show n ++ ") " ++ show c) [0..]
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
module Skat where
|
||||||
|
|
||||||
|
import Card
|
||||||
|
import Control.Monad.State
|
||||||
|
import Control.Monad.Reader
|
||||||
|
import Data.List
|
||||||
|
|
||||||
|
data SkatEnv = SkatEnv { cards :: [CardS]
|
||||||
|
, turnColour :: Maybe Colour
|
||||||
|
, trumpColour :: Colour
|
||||||
|
, players :: Players }
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
type Skat = StateT SkatEnv IO
|
||||||
|
|
||||||
|
table :: Skat [Card]
|
||||||
|
table = gets cards >>= return . foldr f []
|
||||||
|
where f (CardS c Table _) cs = c : cs
|
||||||
|
f _ cs = cs
|
||||||
|
|
||||||
|
tableS :: Skat [CardS]
|
||||||
|
tableS = gets cards >>= return . foldr f []
|
||||||
|
where f c@(CardS _ Table _) cs = c : cs
|
||||||
|
f _ cs = cs
|
||||||
|
|
||||||
|
move :: Card -> Space -> Skat ()
|
||||||
|
move card sp = do
|
||||||
|
cs <- gets cards
|
||||||
|
let cs' = moveCard card sp cs
|
||||||
|
modify (\env -> env { cards = cs' })
|
||||||
|
|
||||||
|
cardsAt :: Space -> Skat [Card]
|
||||||
|
cardsAt sp = gets cards >>= return . findCards sp
|
||||||
|
|
||||||
|
setTurnColour :: Maybe Colour -> SkatEnv -> SkatEnv
|
||||||
|
setTurnColour col sk = sk { turnColour = col }
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
module Utils where
|
||||||
|
|
||||||
|
import System.Random
|
||||||
|
import Text.Read
|
||||||
|
|
||||||
|
shuffle :: StdGen -> [a] -> [a]
|
||||||
|
shuffle g xs = shuffle' (randoms g) xs
|
||||||
|
|
||||||
|
shuffle' :: [Int] -> [a] -> [a]
|
||||||
|
shuffle' _ [] = []
|
||||||
|
shuffle' (i:is) xs = let (firsts, rest) = splitAt (1 + i `mod` length xs) xs
|
||||||
|
in (last firsts) : shuffle' is (init firsts ++ rest)
|
||||||
|
|
||||||
|
chunksOf :: Int -> [a] -> [[a]]
|
||||||
|
chunksOf n [] = []
|
||||||
|
chunksOf n xs = take n xs : chunksOf n (drop n xs)
|
||||||
|
|
||||||
|
query :: Read a => String -> IO a
|
||||||
|
query s = do
|
||||||
|
putStrLn s
|
||||||
|
l <- fmap readMaybe getLine
|
||||||
|
case l of
|
||||||
|
Just x -> return x
|
||||||
|
Nothing -> query s
|
||||||
Reference in New Issue
Block a user