1
0
mirror of https://github.com/robonen/fp-haskell.git synced 2026-03-20 10:54:40 +00:00

Initial commit

This commit is contained in:
2023-05-02 21:10:55 +07:00
commit 69c53a7949
11 changed files with 293 additions and 0 deletions

17
src/1a/1a.hs Normal file
View File

@@ -0,0 +1,17 @@
-- На вход функции подается два числовых списка [a1, a2, …,an]
-- и [b1, b2, …, bn]. Функция должна формировать новый
-- список [min(a1,b1), min(a2,b2), …, min(an,bn)].
mmin :: Ord a => a -> a -> a
mmin x y = if x < y then x else y
minList :: [Int] -> [Int] -> [Int]
minList [] _ = []
minList _ [] = []
minList (x:xs) (y:ys) = mmin x y : minList xs ys
main :: IO ()
main = do
let a = [0, 5, 10, 3]
let b = [5, 1, 3]
print $ minList a b

18
src/1b/1b.hs Normal file
View File

@@ -0,0 +1,18 @@
-- Напишите функцию, зависящую от двух аргументов x и y,
-- удаляющую все вхождения x в список y. Х может быть атомом или списком.
removeElem :: Eq a => a -> [a] -> [a]
removeElem _ [] = []
removeElem y (x:xs)
| x == y = removeElem y xs
| otherwise = x : removeElem y xs
removeAll :: Eq a => [a] -> [a] -> [a]
removeAll [] x = x
removeAll (y:ys) x = removeAll ys (removeElem y x)
main :: IO ()
main = do
let x = [1, 2, 3, 4, 5, 6, 7]
print $ removeAll [3] x
print $ removeAll [2, 5] x

12
src/2a/2a.hs Normal file
View File

@@ -0,0 +1,12 @@
-- Напишите функцию (f s n), которая из двухуровневого
-- списка чисел s создает новый одноуровневый список квадратов
-- чисел, исключив все элементы исходного списка s, которые
-- меньше заданного числа n.
f :: [[Int]] -> Int -> [Int]
f s n = [x*x | xs <- s, x <- xs, x >= n]
main :: IO ()
main = do
let s = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print $ f s 5

12
src/2b/2b.hs Normal file
View File

@@ -0,0 +1,12 @@
-- Определите функцию (f a n), которая от двух числовых
-- аргументов строит следующий список:
-- [a, a*(a+1),a*(a+1)*(a+2),…,a*(a+1)*(a+2)*…*(a+n)].
f :: Int -> Int -> [Int]
f a n = scanl (*) a $ take n [a+1..]
main :: IO ()
main = do
let a = 2
let n = 5
print $ f a n

62
src/3/3.hs Normal file
View File

@@ -0,0 +1,62 @@
-- Определите тип данных для хранения следующей информации по
-- футбольным командам: название команды; информация по
-- результатам сыгранных игр [(x1,y1), (x2,y2), …], где каждый
-- кортеж это информация по отдельной игре и xi количество
-- забитых голов, yi количество пропущенных голов. Определить
-- для этого типа функцию сравнения == класса Eq, а также функции
-- <, <= класса Ord, сравнивая команды по количеству набранных
-- очков (выигрыш=3, ничья=1), если у двух команд равное
-- количество набранных очков, то дальше сравнивают разницу между
-- количеством забитых и количеством пропущенных голов.
import Data.List (sortBy)
data FootballTeam = FootballTeam {
teamName :: String,
gameResults :: [(Int, Int)]
} deriving (Show)
instance Eq FootballTeam where
team1 == team2 = team1Score == team2Score && team1Diff == team2Diff
where
team1Score = calculateScore team1
team2Score = calculateScore team2
team1Diff = calculateGoalDifference team1
team2Diff = calculateGoalDifference team2
instance Ord FootballTeam where
compare team1 team2
| team1Score < team2Score = LT
| team1Score > team2Score = GT
| team1Diff < team2Diff = LT
| team1Diff > team2Diff = GT
| otherwise = EQ
where
team1Score = calculateScore team1
team2Score = calculateScore team2
team1Diff = calculateGoalDifference team1
team2Diff = calculateGoalDifference team2
calculateScore :: FootballTeam -> Int
calculateScore team = sum [3 | (x, y) <- gameResults team, x > y] + sum [1 | (x, y) <- gameResults team, x == y]
calculateGoalDifference :: FootballTeam -> Int
calculateGoalDifference team = sum [x - y | (x, y) <- gameResults team]
main :: IO ()
main = do
let teams = [FootballTeam "Team1" [(2, 1), (1, 1), (0, 1)], -- score: 4, diff: 0
FootballTeam "Team2" [(1, 2), (3, 1), (2, 2)], -- score: 4, diff: 1
FootballTeam "Team3" [(1, 1), (2, 2), (3, 3)]] -- score: 3, diff: 0
putStr "Sorted teams: "
print $ map teamName $ sortBy compare teams
let team1 = FootballTeam "Team1" [(2, 1), (1, 1), (0, 1)] -- score: 4, diff: 0
let team2 = FootballTeam "Team2" [(2, 1), (1, 1), (0, 1)] -- score: 4, diff: 0
let team3 = FootballTeam "Team3" [(2, 1), (2, 1), (0, 1)] -- score: 4, diff: 1
putStr "Equal team1 and team2: "
print $ team1 == team2
putStr "Equal team1 and team3: "
print $ team1 == team3

68
src/4/4.hs Normal file
View File

@@ -0,0 +1,68 @@
-- В файлах хранится информация об актерах и фильмах в следующем
-- виде: актер(<фамилия>,<название_фильма>),
-- фильм(<название_фильма>,<жанр>,<год_выпуска>). Написать
-- программу, формирующую список актеров по жанрам (если актер
-- снимался в фильмах разных жанров, то определять его жанр исходя
-- из максимального количества ролей в фильмах одного жанра).
import Text.Regex.Posix
import Data.List (nubBy, maximumBy, group, sort)
import Data.Ord (comparing)
import System.Directory (getCurrentDirectory)
data Actor = Actor {
name :: String,
movieTitle :: String
} deriving (Show)
data Movie = Movie {
title :: String,
genre :: String,
year :: String
} deriving (Show)
--parseActorsTest :: String -> [[String]]
--parseActorsTest content = content =~ actorRegex :: [[String]]
-- where actorRegex = "actor\\(([^,]+),([^\\)]+)\\)"
parseActors :: String -> [Actor]
parseActors content = map (\x -> Actor (x !! 1) (x !! 2)) (content =~ actorRegex :: [[String]])
where actorRegex = "actor\\(([^,]+),([^\\)]+)\\)"
parseMovies :: String -> [Movie]
parseMovies content = map (\x -> Movie (x !! 1) (x !! 2) (x !! 3)) (content =~ movieRegex :: [[String]])
where movieRegex = "movie\\(([^,]+),([^,]+),([^\\)]+)\\)"
actorsWithMoviesTitle :: [Actor] -> [(Actor, [String])]
actorsWithMoviesTitle actors =
[(actor, [title | movie <- movies, let title = movieTitle movie]) |
actor <- uniqueActors,
let movies = filter (\movie -> name actor == name movie) actors]
where uniqueActors = nubBy (\x y -> name x == name y) actors
joinMoviesWithActors :: [Movie] -> [(Actor, [String])] -> [(Actor, [Movie])]
joinMoviesWithActors movies actors =
[(actor, [movie | movie <- movies, title movie `elem` movieTitles]) | (actor, movieTitles) <- actors]
mostCommonGenre :: [Movie] -> String
mostCommonGenre = head . maximumBy (comparing length) . group . sort . map genre
mostPopularGenreByActor :: [(Actor, [Movie])] -> [(Actor, String)]
mostPopularGenreByActor = map (\(a, ms) -> (a, mostCommonGenre ms))
main :: IO ()
main = do
content <- readFile "src/4/data.txt"
-- print $ parseActorsTest content
let actors = parseActors content
movies = parseMovies content
acWithMovieTitles = actorsWithMoviesTitle actors
acWithMovies = joinMoviesWithActors movies acWithMovieTitles
mostPopularGenre = mostPopularGenreByActor acWithMovies
putStrLn "Most popular genre by actor:"
mapM_ (\x -> putStrLn $ name (fst x) ++ " - " ++ snd x) mostPopularGenre

47
src/4/4.old.hs Normal file
View File

@@ -0,0 +1,47 @@
import Text.Regex.Posix
import Data.List (nubBy, maximumBy, group, sort)
import Data.Ord (comparing)
data Actor = Actor {
name :: String,
movieTitle :: String
} deriving (Show)
data Movie = Movie {
title :: String,
genre :: String,
year :: String
} deriving (Show)
parseActors :: String -> [Actor]
parseActors content = map (\x -> Actor (x !! 1) (x !! 2)) (content =~ actorRegex :: [[String]])
where actorRegex = "actor\\(([^,]+),([^\\)]+)\\)"
parseMovies :: String -> [Movie]
parseMovies content = map (\x -> Movie (x !! 1) (x !! 2) (x !! 3)) (content =~ movieRegex :: [[String]])
where movieRegex = "movie\\(([^,]+),([^,]+),([^\\)]+)\\)"
actorsWithMoviesTitle :: [Actor] -> [(Actor, [String])]
actorsWithMoviesTitle actors = uniqueActors
where uniqueActors = nubBy (\x y -> name (fst x) == name (fst y)) actorsWithMovies
actorsWithMovies = map (\x -> (x, map movieTitle (filter (\y -> name x == name y) actors))) actors
joinMoviesWithActors :: [Movie] -> [(Actor, [String])] -> [(Actor, [Movie])]
joinMoviesWithActors movies actors = map (\x -> (fst x, map (\y -> head (filter (\z -> title z == y) movies)) (snd x))) actors
mostPopularGenreByActor :: [(Actor, [Movie])] -> [(Actor, String)]
mostPopularGenreByActor actorsWithMovies = map (\x -> (fst x, mostCommonGenre (snd x))) actorsWithMovies
where mostCommonGenre movies = head $ maximumBy (\x y -> compare (length x) (length y)) $ group $ sort $ map genre movies
main :: IO ()
main = do
content <- readFile "data.txt"
let actors = parseActors content
movies = parseMovies content
ac = actorsWithMoviesTitle actors
acWithMovies = joinMoviesWithActors movies ac
mostPopularGenre = mostPopularGenreByActor acWithMovies
putStrLn "Most popular genre by actor:"
mapM_ (\x -> putStrLn $ name (fst x) ++ " - " ++ snd x) mostPopularGenre

11
src/4/data.txt Normal file
View File

@@ -0,0 +1,11 @@
actor(ivanov,movie1)
actor(ivanov,movie2)
actor(ivanov,movie3)
actor(petrov,movie4)
actor(sidrov,movie1)
movie(movie1,action,2000)
movie(movie2,comedy,2005)
movie(movie3,action,2010)
movie(movie4,drama,2020)
movie(movie5,action,2021)