forked from artemkonenko/fp-class
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass-03.hs
150 lines (120 loc) · 7.62 KB
/
class-03.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
141
142
143
144
145
146
147
148
149
150
import Data.Char
import Data.List
{-
Явная рекурсия в решениях хотя и допускается, но не приветствуется. Старайтесь обходиться стандартными
функциями, используя при этом создание функций «на лету». Пытайтесь максимально упростить уже написанные
решения, применяя подходящие функции из модуля Data.List и любых других модулей. Перед выполнением заданий
изучите примеры из лекции по функциям высшего порядка.
-}
{-
1. Простейшие задачи на применение функций map и filter.
1.1 Преобразовать данный список целых чисел следующим образом:
-}
--a) увеличить все его элементы в два раза;
doubleElems :: Integral a => [a] -> [a]
doubleElems = map (*2)
--b) увеличить все его элементы с четными значениями в два раза;
doubleEvenElems :: Integral a => [a] -> [a]
doubleEvenElems = map (\x -> if even x then x * 2 else x)
--с) обнулить все его элементы с нечетными значениями;
turnToZeroOddElems :: Integral a => [a] -> [a]
turnToZeroOddElems = map (\x -> if odd x then 0 else x)
--d) удалить из него элементы, большие заданного числа k;
delMoreThanKElems :: Ord a => a -> [a] -> [a]
delMoreThanKElems k = filter (<= k)
--e) отфильтровать его, оставив в списке только отрицательные числа;
delPositiveElems :: Integral a => [a] -> [a]
delPositiveElems = filter (< 0)
--f) удалить из него все положительные чётные числа.
delPositiveEvenElems :: Integral a => [a] -> [a]
delPositiveEvenElems = filter (\n -> (n <= 0) || odd n)
{-
1.2 Дан список декартовых координат точек на плоскости (пар вещественных чисел).
Преобразовать его следующим образом:
-}
--a) отфильтровать список так, чтобы в нём остались точки из заданной координатной четверти;
coordinateQuarterFilter :: (Eq a, Num a, Num a1, Num a2, Ord a1, Ord a2) => a -> [(a1, a2)] -> [(a1, a2)]
coordinateQuarterFilter n = filter (\(x,y) -> if n == 1 then (x > 0) && (y > 0)
else if n == 2 then (x < 0) && (y > 0)
else if n == 3 then (x < 0) && (y < 0)
else if n == 4 then (x > 0) && (y < 0)
else error "It's so hard to find the quarter!")
--b) преобразовать декартовы координаты в полярные.
--1.3 Дан список слов.
--a) Преобразовать все слова к верхнему регистру.
f13a :: [String] -> [String]
f13a = map (map toUpper)
--b) Извлечь из него подсписок слов заданной длины.
f13b :: Int -> [String] -> [String]
f13b a = filter (\xs -> length xs == a)
--c) Извлечь из него подсписок слов, начинающихся с заданной буквы.
f13c :: Char -> [String] -> [String]
f13c a = filter (\xs -> head xs == a)
<<<<<<< HEAD
=======
{-
2. Формирование числовых последовательностей (iterate).
a) Список натуральных чисел, начиная с 0.
b) Список чётных чисел.
c) Список элементов последовательности: a_0=1, a_n=(1+a_{n-1})/2.
d) Список символов английского алфавита.
e) Список строк, представляющих n-значные двоичные числа.
-}
>>>>>>> upstream/master
--2. Формирование числовых последовательностей (iterate).
--a) Список натуральных чисел, начиная с 0.
nats :: [Integer]
nats = iterate (+1) 0
--b) Список чётных чисел.
evens :: [Integer]
evens = iterate (+2) 0
--c) Список элементов последовательности: a0=1, an=(1+an-1)/2.
listOfElems :: [Double]
listOfElems = iterate ((/ 2) . (+ 1)) 1
--d) Список символов английского алфавита.
chars :: [Char]
chars = take 26 $ iterate (chr . (+1) . ord) 'a'
--e) Список строк, представляющих n-значные двоичные числа.
--3. Группировка списков.
--a) Дан список символов. Сгруппировать подряд идущие символы по принципу: цифры — не цифры — ...
f3a :: [Char] -> [String]
f3a = groupBy (\x y -> isDigit x == isDigit y)
{-
b) Дан список пар вещественных чисел (координат точек на плоскости). Сгруппировать подряд идущие
координаты точек, лежащие в одной координатной четверти.
-}
f3b :: [(Double, Double)] -> [[(Double, Double)]]
f3b = groupBy (\(x1,y1) (x2,y2) -> ((x1 > 0) == (x2 > 0)) && ((y1 > 0) == (y2 > 0)))
{-
c) Дан список и ненулевое натуральное число n. Разбить список на подсписки длиной n каждый.
Последний подсписок может содержать менее n элементов.
-}
f3c :: [a] -> Int -> [[a]]
f3c xs n = map (take n) $ takeWhile (not . null) $ iterate (drop n) xs
{-
d) Дан список и ненулевые натуральные числа n и m. Разбить список на перекрывающиеся подсписки
длиной n элементов со сдвигом относительно предыдущего подсписка на m элементов.
-}
f3d :: [a] -> Int -> Int -> [[a]]
f3d xs n m = map (take n) $ takeWhile (not . null) $ iterate (drop m) xs
-- Должно быть True
test_f3d = f3d [1..10] 4 2 == [[1,2,3,4],[3,4,5,6],[5,6,7,8],[7,8,9,10],[9,10]]
--e) Дан список. Определить длину самого длинного подсписка, содержащего подряд идущие одинаковые элементы.
{-
4. Разные задачи.
a) Дан текст в виде строки символов, содержащий среди прочего числовые данные. Посчитать количество
всех упоминающихся в тексте чисел.
-}
f4a :: [Char] -> Int
f4a s = length $ filter (\a -> isDigit a) s
{-
b) Найти сумму всех чисел Фибоначчи, удовлетворяющих заданному предикату, в указанном промежутке
(например: все чётные от 1 до 106).
c) Дана строка текста и число n. Сформировать список, содержащий n самых часто используемых
в строке символов.
d) Дан список чисел. Сформировать список локальных максимумов исходного списка. Локальным максимумом
называется элемент, больший своих соседей.
-}
--e) Дан список. Продублировать все его элементы.
f4e :: [a] -> [a]
f4e = concat . map (\x -> [x,x])