forked from artemkonenko/fp-class
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass-02.hs
140 lines (117 loc) · 6.14 KB
/
class-02.hs
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
-- 1.1
-- Написать функцию, которая разбивает промежуток времени в секундах на часы, минуты и секунды.
-- Результат возвращать в виде кортежа из трёх элементов. Реализовать также обратное преобразование.
sec2hms :: Int -> (Int, Int, Int)
sec2hms a = (div a 3600, div (mod a 3600) 60, mod (mod a 3600) 60)
hms2sec :: (Int, Int, Int) -> Int
hms2sec (h, m, s) = h * 3600 + m * 60 + s
-- Реализовать с помощью hms2sec (здесь параметры заданы по отдельности)
hms2sec' :: Int -> Int -> Int -> Int
hms2sec' h m s = hms2sec (h, m, s)
-- должно быть True
test1 = and $ map (\x -> x == hms2sec (sec2hms x)) [1,10..10000]
-- 1.2
-- Написать функции, вычисляющие
-- а) длину отрезка по координатам его концов;
-- б) периметр и площадь треугольника по координатам вершин.
type Point = (Double, Double)
distance :: Point -> Point -> Double
distance (x1, y1) (x2, y2) = sqrt((x2 - x1)^2 + (y2 - y1)^2)
triangle :: Point -> Point -> Point -> (Double, Double)
triangle (x1, y1) (x2, y2) (x3, y3) = (p, s)
where
p = sum [distance (x1, y1) (x2, y2), distance (x2, y2) (x3, y3), distance (x1, y1) (x3, y3)]
s = ((x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3)) / 2
-- Во всех следующих заданиях использование стандартных функций обработки списков не допускается.
-- Все решения должны реализовываться рекурсивными функциями.
-- 2.1
-- Определить рекурсивную функцию, определяющую количество чётных элементов списка
nEven :: Integral a => [a] -> Int
nEven [] = 0
nEven (x:xs)
| even x = 1 + nEven xs
| otherwise = nEven xs
-- 2.2
-- Увеличить все элементы заданного списка в два раза.
-- Указание: в решении может понадобиться операция конструирования списка:
-- > 1 : [2,3,4]
-- [1,2,3,4]
doubleElems :: Num a => [a] -> [a]
doubleElems (xs) = map (*2) xs
-- 2.3
-- Дан список целых чисел. Сформировать новый список, содержащий только нечетные элементы исходного.
fltOdd :: Integral a => [a] -> [a]
fltOdd [] = []
fltOdd (x:xs)
| odd x = x : fltOdd xs
| otherwise = fltOdd xs
-- 2.4
-- Написать следующие функции обработки списков:
-- а) удалить все отрицательные элементы;
delNeg :: Integral a => [a] -> [a]
delNeg [] = []
delNeg (x:xs)
| x >= 0 = x : delNeg xs
| otherwise = delNeg xs
-- б) увеличить элементы с чётными значениями в два раза;
doubleEven :: Integral a => [a] -> [a]
doubleEven [] = []
doubleEven (x:xs)
| even x = x*2 : doubleEven xs
| otherwise = x : doubleEven xs
-- в) переставить местами чётные и нечётные по порядку следования элементы
-- (для списков нечётной длины отбрасывать последний элемент).
-- 2.5
-- Даны два списка целых чисел. Сформировать список, каждый элемент которого равен сумме
-- соответствующих элементов исходных списков. Предусмотреть ситуацию списков разной длины.
combine_plus :: [Integer] -> [Integer] -> [Integer]
combine_plus [] ys = ys
combine_plus xs [] = xs
combine_plus (x:xs) (y:ys) = x + y : combine_plus xs ys
-- 2.6
-- Даны два списка. Сформировать новый список, содержащий пары из соответствующих элементов
-- исходных списков. Хвост более длинного списка отбросить.
zip' :: [a] -> [b] -> [(a, b)]
zip' [] _ = []
zip' _ [] = []
zip' (x:xs) (y:ys) = (x, y) : zip' xs ys
-- 2.7
-- Написать функции, которые по заданному n возвращают список, состоящий из n первых натуральных чисел
-- а) в порядке убывания;
toTheBottom :: (Eq a, Num a) => a -> [a]
toTheBottom 0 = []
toTheBottom n = n : toTheBottom (n - 1)
-- б) в порядке возрастания.
toTheTop :: (Eq a, Num a) => a -> [a]
toTheTop 0 = []
toTheTop n = toTheTop (n - 1) ++ [n]
-- 2.8
-- Дан элемент типа a и список [a]. Вставить между всеми элементами списка заданный элемент.
insElem :: a -> [a] -> [a]
insElem _ [] = []
insElem _ [x] = [x]
insElem a (x:xs) = [x] ++ [a] ++ insElem a xs
-- 2.9
-- Написать функцию, которая разбивает список на два подсписка: элементы из начала списка,
-- совпадающие с первым элементом, и все остальные элементы, например:
-- [1,1,1,2,3,1] -> ([1,1,1], [2,3,1]).
--3
-- Даны типовые аннотации функций. Попытайтесь догадаться, что они делают, и напишите их
-- рекурсивные реализации (если вы можете предложить несколько вариантов, реализуйте все):
-- а) [a] -> Int -> a
findElem :: [a] -> Int -> a
findElem [] _ = error "Here is no element you're looking for"
findElem (x:xs) 0 = x
findElem (x:xs) a = findElem xs (a - 1)
-- б) Eq a => [a] -> a -> Bool
contains :: Eq a => [a] -> a -> Bool
contains [] _ = False
contains (x:xs) a
| x == a = True
| otherwise = contains xs a
-- в) [a] -> Int -> [a]
-- г) a -> Int -> [a]
-- д) [a] -> [a] -> [a]
-- е) Eq a => [a] -> [[a]]
-- ж) [a] -> [(Int, a)]
-- з) Eq a => [a] -> [a]