Guest User

Untitled

a guest
Jan 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.11 KB | None | 0 0
  1. {- Author: Grigory Shepelev.; Github: @altjsus; E-mail: altjsus@gmail.com -}
  2. import Data.List
  3. import Data.Ord
  4. import Data.Maybe
  5.  
  6. import Control.Monad
  7. import System.Random
  8.  
  9. import Fake hiding (shuffle)
  10. import Fake.Provider.Person.EN_US
  11.  
  12. data Sex = Male | Female deriving (Eq, Show) -- Yep, that's true
  13. data Virtue = Intelligence | Appearence | Kindness deriving (Eq, Show, Enum)
  14. type Preferences = [Virtue]
  15. data Parameter = Parameter{
  16. virtue :: Virtue,
  17. value :: Int
  18. } deriving (Eq, Show)
  19. type Parameters = [Parameter]
  20.  
  21. data Person = Person{
  22. name :: String,
  23. sex :: Sex,
  24. preferences :: Preferences,
  25. parameters :: Parameters,
  26. partner :: Maybe Person
  27. } deriving (Eq, Show)
  28.  
  29.  
  30. {-| Shuffles given array -}
  31. shuffle :: [a] -> IO [a]
  32. shuffle [] = return []
  33. shuffle xs = do
  34. randomPosition <- getStdRandom (randomR (0, length xs - 1))
  35. let (left, (a:right)) = splitAt randomPosition xs
  36. fmap (a:) (shuffle (left ++ right))
  37.  
  38. {-| Sorts parameters by preferences and results values of given parameters -}
  39. parametersByPreferencesVector :: Parameters -> Preferences -> [Int]
  40. parametersByPreferencesVector parameters preferences = map ( \x -> value $ parameters !! ( fromJust $ elemIndex x $ map virtue parameters ) ) preferences
  41.  
  42. {-| Creates rating by given parameters array. In given case return sum of products elements of the parameters vector on their index. Example: [6, 2, 1] -> 18 + 4 + 1 -> 23 -}
  43. rate :: [Int] -> Int
  44. rate array =
  45. sum $ map ( \x -> (length array - x) * array!!x ) [0..length array - 1]
  46.  
  47. {-| Combines parametersByPreferencesVector and rate. Given an instance of Person (judge) and the one who'll be rated (person) calculates rating of person based on judge's preferences and person parameters -}
  48. defaultRateFunction :: Person -> Person -> Int
  49. defaultRateFunction judge person = rate $ parametersByPreferencesVector (parameters person) (preferences judge)
  50.  
  51. {-| Generates random name (module Fake), based on sex -}
  52. generateNameBasedOnSex :: Sex -> Maybe (IO String)
  53. generateNameBasedOnSex sex
  54. | sex == Male = Just $ nameGen maleName
  55. | sex == Female = Just $ nameGen femaleName
  56. | otherwise = Nothing
  57. where nameGen x = fmap T.unpack $ generate x
  58.  
  59. {-| Creates instance of Person structure with given sex but random name, parameters and preferences -}
  60. generateRandomPerson :: Sex -> IO (Maybe Person)
  61. generateRandomPerson sex =
  62. case generateNameBasedOnSex sex of
  63. Nothing -> return Nothing
  64. Just value -> do
  65. name <- value
  66. preferences <- shuffle allVirtues
  67. parametersValues <- sequence $ replicate (length allVirtues) $ randomRIO (1 :: Int , 10 :: Int)
  68. return $ Just $ Person name sex preferences (parametersFromValues parametersValues) Nothing
  69. where
  70. allVirtues = [Intelligence ..]
  71. parametersFromValues parametersValues = map (\x -> Parameter (fst x) (snd x) ) $ zip allVirtues parametersValues
  72.  
  73. {-| Man makes an engagement proposal for the woman and if she don't have partner — she replies positively (True) and if she does, if new partner's rating is larger than the old one's — returns True and if it does not — returns False -}
  74. proposal :: Person -> Person -> Bool
  75. proposal male female
  76. | isNothing (partner female) = True
  77. | defaultRateFunction female male > defaultRateFunction female (fromJust $ partner female) = True
  78. | otherwise = False
  79.  
  80. {-| Man makes a proposal for each woman in females untill he'll find the one who'll reply positively. Assumed that there are at least one of this type in the array -}
  81. findTheBride :: Person -> [Person] -> Person
  82. findTheBride male females
  83. | proposal male (head females) == True = head females
  84. | otherwise = findTheBride male (tail females)
  85.  
  86. {-| Results list of women sorted by preferences of man by defaultRateFunction -}
  87. personalRating :: Person -> [Person] -> [Person]
  88. personalRating x ys = sortBy (comparing (\y -> defaultRateFunction x y)) ys
  89.  
  90. {-| Takes an array of array of femalse and retruns a list of females, each of whom has a partner. Pairings satisfy stability rule. -}
  91. marrige :: [Person] -> [Person] -> [Person]
  92. marrige males females
  93. | sm == [] = females
  94. | isNothing ex =
  95. marrige
  96. ([fsm {partner = Just fsmPartner}] ++ delete fsm males)
  97. ([fsmPartner {partner = Just fsm}] ++ delete fsmPartner females)
  98. | otherwise =
  99. marrige
  100. ([fsm {partner = Just fsmPartner}] ++ [(fromJust ex) {partner = Nothing}] ++ delete fsm (delete (fromJust ex) males))
  101. ([fsmPartner {partner = Just fsm}] ++ delete fsmPartner females)
  102. where
  103. sm = filter (\x -> partner x == Nothing) males -- Single males
  104. fsm = head sm -- Fist single male
  105. fsmPartner = findTheBride fsm (personalRating fsm females) -- Fist single male's partner
  106. ex = partner fsmPartner -- Partner's ex (Maybe)
  107.  
  108. main :: IO()
  109. main = do
  110. let n = 5
  111. males <- sequence $ replicate n $ generateRandomPerson Male -- creates an array of n'th random Males
  112. females <- sequence $ replicate n $ generateRandomPerson Female -- creates an array of n'th random Females
  113. print $ marrige (catMaybes males) (catMaybes females)
Add Comment
Please, Sign In to add comment