-
Notifications
You must be signed in to change notification settings - Fork 12
Lab1 Rudnevskiy #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ import Data.Word (Word8) | |
|
|
||
| -- используйте сопоставление с образцом | ||
| xor :: Bool -> Bool -> Bool | ||
| xor x y = error "todo" | ||
| xor x y = if x == y then False else True | ||
|
|
||
| -- max3 x y z находит максимум из x, y и z | ||
| -- max3 1 3 2 == 3 | ||
|
|
@@ -17,9 +17,11 @@ xor x y = error "todo" | |
| -- median3 1 3 2 == 2 | ||
| -- median3 5 2 5 == 5 | ||
| max3, median3 :: Integer -> Integer -> Integer -> Integer | ||
| max3 x y z = error "todo" | ||
|
|
||
| median3 x y z = error "todo" | ||
| max3 x y z = max (max x y) z -- if z >= a then z else a where {a = x >= y then z else y} | ||
| median3 x y z | (min x z <= y) && (y <= max x z) = y --sum | ||
| | (min y z <= x) && (x <= max y z) = x | ||
| | (min x y <= z) && (z <= max x y) = z | ||
| | otherwise = error "the median has not been calculated" | ||
|
|
||
| -- Типы данных, описывающие цвета в моделях | ||
| -- RGB (https://ru.wikipedia.org/wiki/RGB), компоненты от 0 до 255 | ||
|
|
@@ -37,7 +39,17 @@ data CMYK = CMYK { cyan :: Double, magenta :: Double, yellow :: Double, black :: | |
| -- Заметьте, что (/) для Int не работает, и неявного преобразования Int в Double нет. | ||
| -- Это преобразование производится с помощью функции fromIntegral. | ||
| rbgToCmyk :: RGB -> CMYK | ||
| rbgToCmyk color = error "todo" | ||
| rbgToCmyk (RGB 0 0 0) = CMYK 0.0 0.0 0.0 1.0 | ||
| rbgToCmyk color = cmyk_color where | ||
| r = fromIntegral(red color) / 255.0 | ||
| g = fromIntegral(green color) / 255.0 | ||
| b = fromIntegral(blue color) / 255.0 | ||
| k = (min (min (1.0 - r) (1.0 - g)) (1.0 - b)) | ||
| c = (1.0 - r - k) / (1.0 - k) | ||
| m = (1.0 - g - k) / (1.0 - k) | ||
| y = (1.0 - b - k) / (1.0 - k) | ||
| cmyk_color = CMYK c m y k | ||
|
|
||
|
|
||
| -- geomProgression b q n находит n-й (считая с 0) член | ||
| -- геометрической прогрессии, нулевой член которой -- b, | ||
|
|
@@ -47,7 +59,9 @@ rbgToCmyk color = error "todo" | |
| -- используйте рекурсию | ||
| -- не забудьте случаи n < 0 и n == 0. | ||
| geomProgression :: Double -> Double -> Integer -> Double | ||
| geomProgression b q n = error "todo" | ||
| geomProgression b q n | (n == 0) = b | ||
| | n < 0 = error "n must be a natural number: n >= 2" | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Почему >= 2?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лишнее условие. Я хотел поставить условие неотрицательности, но здесь достаточно n > 0 |
||
| | n > 0 = q * geomProgression b q (n - 1) | ||
|
|
||
| -- coprime a b определяет, являются ли a и b взаимно простыми | ||
| -- (определение: Целые числа называются взаимно простыми, | ||
|
|
@@ -63,5 +77,17 @@ geomProgression b q n = error "todo" | |
| -- (или div, mod, divMod в зависимости от того, как | ||
| -- обрабатываете отрицательные числа) | ||
| -- https://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html | ||
| {- euclidAlgorithm :: Integer -> Integer -> Integer | ||
| euclidAlgorithm x 0 = x | ||
| euclidAlgorithm x y = euclidAlgorithm y (mod x y) -} | ||
|
|
||
|
|
||
| coprime :: Integer -> Integer -> Bool | ||
| coprime a b = error "todo" | ||
| coprime a b = | ||
| let | ||
| euclidAlgorithm :: Integer -> Integer -> Integer | ||
| euclidAlgorithm x 0 = x | ||
| euclidAlgorithm x y = euclidAlgorithm y (mod x y) | ||
| in | ||
| if ((a * b) == 0) then error "ZeroException" else if euclidAlgorithm a b == 1 then True else False | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. -1 и -1 взаимно простые?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Взаимно простые, но функция выдает ошибку. Связано это, предположительно, с особенностями обработки отрицательных чисел функцией mod. Возможное решение - брать от чисел их модули (что-то вроде функции abc в стандартных математических пакетах). |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,33 +1,53 @@ | ||
| module Lists where | ||
|
|
||
| -- вектор задаётся списком координат | ||
| newtype Point = Point [Double] deriving (Eq, Show, Read) | ||
| data Point = Point {coords :: [Double]} deriving (Eq, Show, Read) | ||
|
|
||
| --{coords :: [Double]} | ||
|
|
||
| -- distance x y находит расстояние между двумя точками в n-мерном | ||
| -- пространстве. Если число координат точек разное, сообщите об ошибке. | ||
| -- distance (Point [1.0, 0.0]) (Point [0.0, 1.0]) == sqrt 2.0 | ||
| -- distance (Point [0.0, 0.0]) (Point [0.0, 1.0]) == 1.0 | ||
|
|
||
| -- используйте рекурсию и сопоставление с образцом | ||
| distance :: Point -> Point -> Double | ||
| distance x y = error "todo" | ||
|
|
||
| distance, abnormDistance :: Point -> Point -> Double | ||
|
|
||
| abnormDistance p1 p2 | ||
| | not (length (coords p1) == length (coords p2)) = error "DifferentDimensionError" | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Такая проверка будет медленной и делаться у вас на каждом шаге рекурсии. Видно ли, как её можно избежать? И во вторую очередь, как можно поменять тип
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Проверку можно сделать отдельно, через сопоставление с образцом (?)
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Идея в том, что если длины не равны, то вы можете всё равно начинать рекурсию. Просто тогда на каком-то будущем шаге окажется, что одна сторона пустая, а другая нет. И выкидывать это ошибку лучше именно на том шаге. |
||
| | (null (coords p1) && null (coords p2)) = 0 | ||
| | otherwise = ((head (coords p2)) - (head (coords p1)))^2 + abnormDistance (Point(tail (coords p1))) (Point(tail (coords p2))) | ||
|
|
||
| distance fstCoord sndCoords = sqrt $ (abnormDistance fstCoord sndCoords) | ||
|
|
||
| -- intersect xs ys возвращает список, содержащий общие элементы двух списков. | ||
| -- intersect [1, 2, 4, 6] [5, 4, 2, 5, 7] == [2, 4] (или [4, 2]!) | ||
| -- intersect [1, 2, 4, 6] [3, 5, 7] == [] | ||
|
|
||
| -- используйте рекурсию и сопоставление с образцом | ||
| intersect :: [Integer] -> [Integer] -> [Integer] | ||
| intersect xs ys = error "todo" | ||
| --intersect [] _ = [] | ||
| --intersect _ [] = [] | ||
| -- intersect xs ys = [x | x <- xs, any ((==) x) ys] | ||
| intersect xs ys | (null xs || null ys) = [] | ||
| | otherwise = [x | x <- xs, any ((==) x) ys] | ||
|
|
||
| -- zipN принимает список списков и возвращает список, который состоит из | ||
| -- списка их первых элементов, списка их вторых элементов, и так далее. | ||
| -- zipN [[1, 2, 3], [4, 5, 6], [7, 8, 9]] == [[1, 4, 7], [2, 5, 8], [3, 6, 9]] | ||
| -- zipN [[1, 2, 3], [4, 5], [6]] == [[1, 4, 6], [2, 5], [3]] | ||
| zipN :: [[a]] -> [[a]] | ||
| zipN xss = error "todo" | ||
|
|
||
| -- Нижеперечисленные функции можно реализовать или рекурсивно, или с помощью | ||
| zipN :: (Num a) => [[a]] -> [[a]] | ||
| zipN ((x:xs):xss) = (x : zipN' xss) : zipN (helper xs xss) where | ||
| zipN' ((a:as):ass) = a : zipN' ass | ||
| zipN' _ = [] | ||
| helper [] ((b:bs):bss) = bs : helper [] bss | ||
| helper b_b ((b:bs):bss) = b_b : (bs : helper [] bss) | ||
| helper _ _ = [] | ||
| zipN _ = [] | ||
|
|
||
|
|
||
| -- Нижеперечисленные функции можно реализовать или рекурсивно, или с помощью | ||
| -- стандартных функций для работы со списками (map, filter и т.д.) | ||
| -- Попробуйте оба подхода! Хотя бы одну функцию реализуйте обоими способами. | ||
|
|
||
|
|
@@ -38,32 +58,65 @@ zipN xss = error "todo" | |
| -- findLast (> 0) [-1, 2, -3, 4] == Just 4 | ||
| -- find (> 0) [-1, -2, -3] == Nothing | ||
| find, findLast :: (a -> Bool) -> [a] -> Maybe a | ||
| find f xs = error "todo" | ||
| findLast f xs = error "todo" | ||
|
|
||
| {- find f [] = Nothing | ||
| find f xs = Just (head (filter f xs)) -} | ||
|
|
||
| find f [] = Nothing | ||
| find f xs | ||
| | (f (head xs)) = Just (head xs) | ||
| | not (f (head xs)) && (not (null (tail xs))) = find f (tail xs) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно записать через if: if (f (head xs)) then Just (head xs) else find f (tail xs)
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да, так тоже можно. |
||
| | null (tail xs) = Nothing | ||
|
|
||
| findLast f x | (length (filter f x)) > 0 = Just $ last (filter f x) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут формально получается, что
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно создать список элементов x, таких, что: filter f x > 0 , затем извлечь из него последний элемент
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я имел в виду просто вынести |
||
| | otherwise = Nothing | ||
|
|
||
| -- mapFuncs принимает список функций fs и возвращает список результатов | ||
| -- применения всех функций из fs к x. | ||
| -- mapFuncs [\x -> x*x, (1 +), \x -> if even x then 1 else 0] 3 == [9, 4, 0] | ||
| mapFuncs :: [a -> b] -> a -> [b] | ||
| mapFuncs fs x = error "todo" | ||
| mapFuncs [] _ = [] | ||
| mapFuncs fs x = [(f x) | f <- fs] | ||
|
|
||
| -- satisfiesAll принимает список предикатов (функций, возвращающих Bool) preds | ||
| -- и возвращает True, если все они выполняются (т.е. возвращают True) для x. | ||
| -- Полезные стандартные функции: and, all. | ||
| -- satisfiesAll принимает список предикатов (функций, возвращающих Bool) preds | ||
| -- и возвращает True, если все они выполняются | ||
| -- (т.е. возвращают True) для x. Полезные стандартные функции: and, all. | ||
| -- satisfiesAll [even, \x -> x rem 5 == 0] 10 == True | ||
| -- satisfiesAll [] 4 == True (кстати, почему?) | ||
| -- satisfiesAll [] 4 == True (кстати, почему?). Потому что в пустом списке нет предикатов, возвращающих True, а значит ни один предикат не будет применён к аргументам | ||
| satisfiesAll :: [a -> Bool] -> a -> Bool | ||
| satisfiesAll preds x = error "todo" | ||
| satisfiesAll [] _ = True | ||
| satisfiesAll preds x | ||
| | all (True ==) (mapFuncs preds x) = True | ||
| | any (False ==) (mapFuncs preds x) = False | ||
| | otherwise = False | ||
|
Comment on lines
+90
to
+91
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Как упростить?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. написать что-то в духе if (all (True ==) (mapFuncs preds x)) else False
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут имелось в виду, что если два условия с одинаковым результатом, и последнее |
||
|
|
||
| -- Непустой список состоит из первого элемента (головы) | ||
| -- непустой список состоит из первого элемента (головы) | ||
| -- и обычного списка остальных элементов | ||
| -- Например, NEL 1 [2, 3] соотвествует списку [1, 2, 3], а NEL 1 [] -- списку [1]. | ||
| data NEL a = NEL a [a] deriving (Eq, Show, Read) | ||
|
|
||
| -- Запишите правильный тип (т.е. такой, чтобы функция имела результат для любых аргументов | ||
| -- без вызовов error) и реализуйте функции на NEL, аналогичные tail, last и zip | ||
| -- запишите правильный тип (т.е. такой, чтобы функция имела результат для любых аргументов) | ||
| -- и реализуйте функции на NEL, аналогичные tail, last и zip | ||
| -- tailNel :: NEL a -> ??? | ||
| -- lastNel :: NEL a -> ??? | ||
| -- zipNel :: NEL a -> NEL b -> ??? | ||
| -- listToNel :: [a] -> ??? | ||
| -- nelToList :: NEL a -> ??? | ||
|
|
||
| tailNel :: NEL a -> [a] | ||
| tailNel (NEL x xs) = xs | ||
|
|
||
| lastNel :: NEL a -> a | ||
| lastNel (NEL x xs) | ||
| | null xs = x | ||
| | (not (null xs)) = last xs | ||
|
|
||
| listToNel :: [a] -> NEL a | ||
| listToNel (x:xs) = NEL x xs | ||
|
|
||
| nelToList :: NEL a -> [a] | ||
| nelToList (NEL x xs) = x : xs | ||
|
|
||
|
|
||
| zipNel :: NEL a -> NEL b -> NEL (a,b) | ||
| zipNel a b = listToNel $ zip (nelToList a) (nelToList b) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Возможный ли это случай?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
По идее, первые три условия покрывают все возможные случаи. Последний был приведен по большей части для сохранения стиля написания охранных условий (насколько я понял, otherwise прописывается в большинстве случаев).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Да, но поэтому можно уже третий случай сделать
otherwise.