避免重复Haskell

时间:2017-04-24 18:37:35

标签: algorithm haskell tuples

学生们成对地做项目。

规则:不允许任何人独自工作;每个项目都由两名学生完成。没有两个学生可以在一个以上的项目上合作。

每个项目由执行项目的两名学生的姓名和标记(0到100之间的整数)组成。

我正在编写一个名为legalCourse的函数,该函数将CourseData作为参数并返回Bool。返回 True如果课程数据是“合法的”,则表示它不包含上面列出的各种错误。对于所有剩余的功能。 样本输出:

*legalCourse [("John","Mary",75)]
True
* legalCourse [("John","John",75)]
False
* legalCourse [("John","Mary",75),("Peter","Paul",90),("John","Mary",90)]
False
* legalCourse [("John","Mary",75),("Peter","Paul",90),("Mary","John",90)]
False
*Assignment2> legalCourse [("John","Mary",75),("Peter","Paul",90),("Mary","Fred",90)]
True

代码:

type CourseData = [(String, String, Int)]
legalCourse :: CourseData -> Bool
legalCourse course = legal1 course && legal2 course
where
    -- legal1 course means the course does not contain any projects like ("David","David",90)
    legal1 [] = True
    legal1 ((name1,name2,_):moreGroups) = name1 /= name2 && legal1 moreGroups
    -- hasPair course name1 name2 means the course has a project done by name1 and name2
    -- (in either order)
    hasPair [] _ _ = False
    hasPair ((a,b,_):moreGroups) name1 name2 =
        (a == name1 && b == name2) || (a == name2 && b == name1) || hasPair moreGroups name1 name2
    -- legal2 course means the course does not contain two projects done by the same
    -- pair of students (regardless of order)
    legal2 [] = True
    legal2 [_] = True
    legal2 ((name1,name2,_):moreProjects) = 
        not (hasPair moreProjects name1 name2) && legal2 moreProjects

我不理解hasPairlegal2,这部分是怎样的

hasPair ((a,b,_):moreGroups) name1 name2 =
    (a == name1 && b == name2) || (a == name2 && b == name1) || hasPair moreGroups name1 name2

避免同一对人做项目?

4 个答案:

答案 0 :(得分:2)

hasPair在第一个参数中搜索与其下两个参数匹配的对。

空对列表没有与其他参数匹配的对,无论它们是什么。

hasPair [] _ _ = False

包含学生对(a, b, _)和更多对moreGroups的列表将与学生对name1name2匹配,如果...

hasPair ((a,b,_):moreGroups) name1 name2 =

学生abname1name2。这可能以任何顺序发生。

    (a == name1 && b == name2) || (a == name2 && b == name1) || ...

或者,如果剩余的一个群组是name1name2

    ... hasPair moreGroups name1 name2

hasPair并不确定没有任何小组在做任何两个项目,但在考虑单个项目时,可以使用它来确保&#39 ;没有其他项目由同一组完成。

答案 1 :(得分:1)

hasPair xs name1 name2检查列表xs中是否有3个元组,其中前两个元素为name1name2,但不按此顺序排列。 legal2对每个项目组应用相同的检查,但这样每个项目对只会被检查一次。我认为' hasPair'使用类型签名可以更容易理解函数。在这里(我认为),更清楚地定义了这个功能:

hasPair :: Eq a => [(a, a, b)] -> a -> a -> Bool
hasPair []               _  _  = False
hasPair ((x1, x2, _):xs) y1 y2
  | x1 == y1 && x2 == y2 = True
  | x1 == y2 && x2 == y1 = True
  | otherwise            = hasPair xs y1 y2

答案 2 :(得分:0)

import Data.Set (Set,fromList)

data CourseData = CourseData String String Int deriving Show

制作忽略成绩的EqOrd个实例,并期望已对学生姓名进行排序。

instance Eq CourseData where
  (==) (CourseData a b _) (CourseData a' b' _) = a == a' && b == b'

instance Ord CourseData where
  compare (CourseData a b _) (CourseData a' b' _) = compare a a' `mappend` compare b b'

无法做出错误的" CourseData通过对名称进行排序。

mkCourseData :: String -> String -> Int -> CourseData
mkCourseData a b = case compare a b of
  -- Make sure the greater element is to the right
  GT -> CourseData b a
  _ -> CourseData a b

正如您所看到的,这会使Set CourseData符合您的规则:

test :: Set CourseData
test = fromList [mkCourseData "a" "b" 1,mkCourseData "b" "a" 2] 

这出现在fromList [CourseData "a" "b" 2]

答案 3 :(得分:0)

另一种成分替代

import Data.List(sort,group)

legalCourse = null . filter (>1) . map length . group . sort . map dictOrder
         where dictOder (x,y,_) = if (x<y) then (x,y) else (y,x)