Compare commits
37 Commits
third-lab
...
58aefa43c5
| Author | SHA1 | Date | |
|---|---|---|---|
| 58aefa43c5 | |||
| 93bb0f247c | |||
| 5700d5892a | |||
| f92d91571a | |||
| 1c7c0a0fd6 | |||
| de9d8681f3 | |||
| 92e1cb96ea | |||
| 5921d5f9d4 | |||
| 65bb51146d | |||
| d89e7f09e7 | |||
| cf58fc9634 | |||
| 3692629264 | |||
| 1a45ec2330 | |||
| 70d1742368 | |||
| c66352d500 | |||
| 917341a8c8 | |||
| 2867c80305 | |||
| a5b624a333 | |||
| 4bcec8060d | |||
| 4982ace7a6 | |||
| 14d853c878 | |||
| de4bfa4f84 | |||
| 25a5646093 | |||
| 9e3e5cda0c | |||
| a3061e6678 | |||
| f05a39da06 | |||
| 7ccdb8346e | |||
| 1aa359b5c1 | |||
| 69e7f5537a | |||
| 2ad9d5d784 | |||
| 9f7e34f7cd | |||
| ddabccfd2b | |||
| bfa7c918b2 | |||
| b816f9f17c | |||
| d8db6809e4 | |||
| 09b722a8eb | |||
| 66279d0ff4 |
4
coursework/part1/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.stack-work/
|
||||
*~
|
||||
!task_part1.txt
|
||||
!expressions.txt
|
||||
11
coursework/part1/CHANGELOG.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Changelog for `part1`
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to the
|
||||
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 0.1.0.0 - YYYY-MM-DD
|
||||
26
coursework/part1/LICENSE
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright 2024 Author name here
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
coursework/part1/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# part1
|
||||
2
coursework/part1/Setup.hs
Normal file
@@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
12
coursework/part1/app/Main.hs
Normal file
@@ -0,0 +1,12 @@
|
||||
module Main (main) where
|
||||
|
||||
import Lib
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
putStrLn "Введите имя файла:" >>
|
||||
getLine >>= \fileName ->
|
||||
readFile fileName >>= \content ->
|
||||
let expressions = lines content in
|
||||
putStrLn $ concatMap processExpression expressions
|
||||
|
||||
6
coursework/part1/expressions.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
100 * 100
|
||||
40 + 30
|
||||
50 / 2
|
||||
5 / 2
|
||||
62 - 32
|
||||
78 - 500
|
||||
59
coursework/part1/package.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
name: part1
|
||||
version: 0.1.0.0
|
||||
github: "githubuser/part1"
|
||||
license: BSD-3-Clause
|
||||
author: "Author name here"
|
||||
maintainer: "example@example.com"
|
||||
copyright: "2024 Author name here"
|
||||
|
||||
extra-source-files:
|
||||
- README.md
|
||||
- CHANGELOG.md
|
||||
|
||||
# Metadata used when publishing your package
|
||||
# synopsis: Short description of your package
|
||||
# category: Web
|
||||
|
||||
# To avoid duplicated efforts in documentation and dealing with the
|
||||
# complications of embedding Haddock markup inside cabal files, it is
|
||||
# common to point users to the README.md file.
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/part1#readme>
|
||||
|
||||
dependencies:
|
||||
- base >= 4.7 && < 5
|
||||
|
||||
ghc-options:
|
||||
- -Wall
|
||||
- -Wcompat
|
||||
- -Widentities
|
||||
- -Wincomplete-record-updates
|
||||
- -Wincomplete-uni-patterns
|
||||
- -Wmissing-export-lists
|
||||
- -Wmissing-home-modules
|
||||
- -Wpartial-fields
|
||||
- -Wredundant-constraints
|
||||
|
||||
library:
|
||||
source-dirs: src
|
||||
|
||||
executables:
|
||||
part1-exe:
|
||||
main: Main.hs
|
||||
source-dirs: app
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- part1
|
||||
|
||||
tests:
|
||||
part1-test:
|
||||
main: Spec.hs
|
||||
source-dirs: test
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- part1
|
||||
67
coursework/part1/part1.cabal
Normal file
@@ -0,0 +1,67 @@
|
||||
cabal-version: 2.2
|
||||
|
||||
-- This file has been generated from package.yaml by hpack version 0.37.0.
|
||||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: part1
|
||||
version: 0.1.0.0
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/part1#readme>
|
||||
homepage: https://github.com/githubuser/part1#readme
|
||||
bug-reports: https://github.com/githubuser/part1/issues
|
||||
author: Author name here
|
||||
maintainer: example@example.com
|
||||
copyright: 2024 Author name here
|
||||
license: BSD-3-Clause
|
||||
license-file: LICENSE
|
||||
build-type: Simple
|
||||
extra-source-files:
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://github.com/githubuser/part1
|
||||
|
||||
library
|
||||
exposed-modules:
|
||||
Lib
|
||||
other-modules:
|
||||
Paths_part1
|
||||
autogen-modules:
|
||||
Paths_part1
|
||||
hs-source-dirs:
|
||||
src
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
default-language: Haskell2010
|
||||
|
||||
executable part1-exe
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_part1
|
||||
autogen-modules:
|
||||
Paths_part1
|
||||
hs-source-dirs:
|
||||
app
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
, part1
|
||||
default-language: Haskell2010
|
||||
|
||||
test-suite part1-test
|
||||
type: exitcode-stdio-1.0
|
||||
main-is: Spec.hs
|
||||
other-modules:
|
||||
Paths_part1
|
||||
autogen-modules:
|
||||
Paths_part1
|
||||
hs-source-dirs:
|
||||
test
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
, part1
|
||||
default-language: Haskell2010
|
||||
104
coursework/part1/src/Lib.hs
Normal file
@@ -0,0 +1,104 @@
|
||||
{-# LANGUAGE InstanceSigs #-}
|
||||
|
||||
module Lib (
|
||||
processExpression
|
||||
) where
|
||||
|
||||
import Control.Applicative (Alternative(..))
|
||||
import Data.Char (digitToInt, isDigit)
|
||||
|
||||
|
||||
newtype Parser tok a =
|
||||
Parser { runParser :: [tok] -> Maybe ([tok], a)}
|
||||
|
||||
instance Functor (Parser tok) where
|
||||
fmap :: (a -> b) -> Parser tok a -> Parser tok b
|
||||
fmap g (Parser p) = Parser f where
|
||||
f xs = case p xs of
|
||||
Nothing -> Nothing
|
||||
Just (cs, c) -> Just (cs, g c)
|
||||
|
||||
instance Applicative (Parser tok) where
|
||||
pure :: a -> Parser tok a
|
||||
pure x = Parser $ \toks -> Just (toks, x)
|
||||
|
||||
(<*>) :: Parser tok (a -> b) -> Parser tok a -> Parser tok b
|
||||
Parser u <*> Parser v = Parser f where
|
||||
f xs = case u xs of
|
||||
Nothing -> Nothing
|
||||
Just (xs', g) -> case v xs' of
|
||||
Nothing -> Nothing
|
||||
Just (xs'', x) -> Just (xs'', g x)
|
||||
|
||||
instance Alternative (Parser tok) where
|
||||
empty :: Parser tok a
|
||||
empty = Parser $ \_ -> Nothing
|
||||
|
||||
(<|>) :: Parser tok a -> Parser tok a -> Parser tok a
|
||||
Parser u <|> Parser v = Parser f where
|
||||
f xs = case u xs of
|
||||
Nothing -> v xs
|
||||
z -> z
|
||||
|
||||
satisfy :: (tok -> Bool) -> Parser tok tok
|
||||
satisfy pr = Parser f where
|
||||
f (c:cs) | pr c = Just (cs, c)
|
||||
f _ = Nothing
|
||||
|
||||
char :: Char -> Parser Char Char
|
||||
char c = satisfy (== c)
|
||||
|
||||
digit :: Parser Char Char
|
||||
digit = satisfy isDigit
|
||||
|
||||
skipSpaces :: Parser Char String
|
||||
skipSpaces = many (char ' ')
|
||||
|
||||
number :: Parser Char Int
|
||||
number = skipSpaces *> (strToInt <$> some digit)
|
||||
where
|
||||
strToInt = foldl (\acc x -> acc * 10 + digitToInt x) 0
|
||||
|
||||
data Operation = Add | Sub | Mul | Div deriving Show
|
||||
|
||||
operationToString :: Operation -> String
|
||||
operationToString op = case op of
|
||||
Add -> "+"
|
||||
Sub -> "-"
|
||||
Mul -> "*"
|
||||
Div -> "/"
|
||||
|
||||
operationToOperator :: Operation -> (Int -> Int -> Int)
|
||||
operationToOperator op = case op of
|
||||
Add -> (+)
|
||||
Sub -> (-)
|
||||
Mul -> (*)
|
||||
Div -> div
|
||||
|
||||
|
||||
operation :: Parser Char Operation
|
||||
operation = skipSpaces *> (
|
||||
char '+' *> pure Add <|>
|
||||
char '-' *> pure Sub <|>
|
||||
char '*' *> pure Mul <|>
|
||||
char '/' *> pure Div
|
||||
)
|
||||
|
||||
expression :: Parser Char (Int, Operation, Int)
|
||||
expression = (,,) <$> number <*> operation <*> number <* skipSpaces
|
||||
|
||||
calculateExpression :: (Int, Operation, Int) -> Int
|
||||
calculateExpression (a, op, b) = (operationToOperator op) a b
|
||||
|
||||
processExpression :: String -> String
|
||||
processExpression s = case runParser expression s of
|
||||
Nothing -> err
|
||||
Just (cs, (a, op, b)) -> case cs of
|
||||
[] ->
|
||||
show a ++ " " ++
|
||||
operationToString op ++ " " ++
|
||||
show b ++ " = " ++
|
||||
show (calculateExpression (a, op, b)) ++ "\n"
|
||||
_ -> err
|
||||
where
|
||||
err = error $ "Не удалось прочитать выражение: \"" ++ s ++ "\""
|
||||
67
coursework/part1/stack.yaml
Normal file
@@ -0,0 +1,67 @@
|
||||
# This file was automatically generated by 'stack init'
|
||||
#
|
||||
# Some commonly used options have been documented as comments in this file.
|
||||
# For advanced use and comprehensive documentation of the format, please see:
|
||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||
|
||||
# A 'specific' Stackage snapshot or a compiler version.
|
||||
# A snapshot resolver dictates the compiler version and the set of packages
|
||||
# to be used for project dependencies. For example:
|
||||
#
|
||||
# snapshot: lts-22.28
|
||||
# snapshot: nightly-2024-07-05
|
||||
# snapshot: ghc-9.6.6
|
||||
#
|
||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||
#
|
||||
# snapshot: ./custom-snapshot.yaml
|
||||
# snapshot: https://example.com/snapshots/2024-01-01.yaml
|
||||
snapshot:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
|
||||
# User packages to be built.
|
||||
# Various formats can be used as shown in the example below.
|
||||
#
|
||||
# packages:
|
||||
# - some-directory
|
||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||
# subdirs:
|
||||
# - auto-update
|
||||
# - wai
|
||||
packages:
|
||||
- .
|
||||
# Dependency packages to be pulled from upstream that are not in the snapshot.
|
||||
# These entries can reference officially published versions as well as
|
||||
# forks / in-progress versions pinned to a git hash. For example:
|
||||
#
|
||||
# extra-deps:
|
||||
# - acme-missiles-0.3
|
||||
# - git: https://github.com/commercialhaskell/stack.git
|
||||
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||
#
|
||||
# extra-deps: []
|
||||
|
||||
# Override default flag values for project packages and extra-deps
|
||||
# flags: {}
|
||||
|
||||
# Extra package databases containing global packages
|
||||
# extra-package-dbs: []
|
||||
|
||||
# Control whether we use the GHC we find on the path
|
||||
# system-ghc: true
|
||||
#
|
||||
# Require a specific version of Stack, using version ranges
|
||||
# require-stack-version: -any # Default
|
||||
# require-stack-version: ">=3.1"
|
||||
#
|
||||
# Override the architecture used by Stack, especially useful on Windows
|
||||
# arch: i386
|
||||
# arch: x86_64
|
||||
#
|
||||
# Extra directories used by Stack for building
|
||||
# extra-include-dirs: [/path/to/dir]
|
||||
# extra-lib-dirs: [/path/to/dir]
|
||||
#
|
||||
# Allow a newer minor version of GHC than the snapshot specifies
|
||||
# compiler-check: newer-minor
|
||||
13
coursework/part1/stack.yaml.lock
Normal file
@@ -0,0 +1,13 @@
|
||||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/lock_files
|
||||
|
||||
packages: []
|
||||
snapshots:
|
||||
- completed:
|
||||
sha256: 08bd13ce621b41a8f5e51456b38d5b46d7783ce114a50ab604d6bbab0d002146
|
||||
size: 720271
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
original:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
10
coursework/part1/task_part1.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Часть 1
|
||||
Написать синтаксический анализатор (парсер), разбирающий строки, прочитанные
|
||||
из текстового файла .txt. Файл должен содержать значения и бинарные операции.
|
||||
|
||||
Значения: целые числа в десятичной системе счисления
|
||||
|
||||
Бинарные операции: сложение, вычитание, умножение, деление
|
||||
|
||||
Пример строки в файле: 234 * 43. Вычислить проанализированное выражение, вывести
|
||||
его результат вычисления на экран. Пользователь вводит название файла.
|
||||
2
coursework/part1/test/Spec.hs
Normal file
@@ -0,0 +1,2 @@
|
||||
main :: IO ()
|
||||
main = putStrLn "Test suite not yet implemented"
|
||||
4
coursework/part2/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.stack-work/
|
||||
*~
|
||||
!task_part2.txt
|
||||
!text.txt
|
||||
11
coursework/part2/CHANGELOG.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Changelog for `part2`
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to the
|
||||
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 0.1.0.0 - YYYY-MM-DD
|
||||
26
coursework/part2/LICENSE
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright 2024 Author name here
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
coursework/part2/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# part2
|
||||
2
coursework/part2/Setup.hs
Normal file
@@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
15
coursework/part2/app/Main.hs
Normal file
@@ -0,0 +1,15 @@
|
||||
module Main (main) where
|
||||
|
||||
import Lib
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
putStrLn "Введите имя файла:" >>
|
||||
getLine >>= \fileName ->
|
||||
readFile fileName >>= \content ->
|
||||
let sentences = splitText content in
|
||||
let dict = buildDictionary sentences in
|
||||
saveDictionary "dict.txt" dict >>
|
||||
putStrLn "Введите слово или пару слов:" >>
|
||||
getLine >>= \input ->
|
||||
processInput dict input
|
||||
62
coursework/part2/package.yaml
Normal file
@@ -0,0 +1,62 @@
|
||||
name: part2
|
||||
version: 0.1.0.0
|
||||
github: "githubuser/part2"
|
||||
license: BSD-3-Clause
|
||||
author: "Author name here"
|
||||
maintainer: "example@example.com"
|
||||
copyright: "2024 Author name here"
|
||||
|
||||
extra-source-files:
|
||||
- README.md
|
||||
- CHANGELOG.md
|
||||
|
||||
# Metadata used when publishing your package
|
||||
# synopsis: Short description of your package
|
||||
# category: Web
|
||||
|
||||
# To avoid duplicated efforts in documentation and dealing with the
|
||||
# complications of embedding Haddock markup inside cabal files, it is
|
||||
# common to point users to the README.md file.
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/part2#readme>
|
||||
|
||||
dependencies:
|
||||
- base >= 4.7 && < 5
|
||||
- containers
|
||||
- random
|
||||
- unescaping-print
|
||||
|
||||
ghc-options:
|
||||
- -Wall
|
||||
- -Wcompat
|
||||
- -Widentities
|
||||
- -Wincomplete-record-updates
|
||||
- -Wincomplete-uni-patterns
|
||||
- -Wmissing-export-lists
|
||||
- -Wmissing-home-modules
|
||||
- -Wpartial-fields
|
||||
- -Wredundant-constraints
|
||||
|
||||
library:
|
||||
source-dirs: src
|
||||
|
||||
executables:
|
||||
part2-exe:
|
||||
main: Main.hs
|
||||
source-dirs: app
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- part2
|
||||
|
||||
tests:
|
||||
part2-test:
|
||||
main: Spec.hs
|
||||
source-dirs: test
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- part2
|
||||
76
coursework/part2/part2.cabal
Normal file
@@ -0,0 +1,76 @@
|
||||
cabal-version: 2.2
|
||||
|
||||
-- This file has been generated from package.yaml by hpack version 0.37.0.
|
||||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: part2
|
||||
version: 0.1.0.0
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/part2#readme>
|
||||
homepage: https://github.com/githubuser/part2#readme
|
||||
bug-reports: https://github.com/githubuser/part2/issues
|
||||
author: Author name here
|
||||
maintainer: example@example.com
|
||||
copyright: 2024 Author name here
|
||||
license: BSD-3-Clause
|
||||
license-file: LICENSE
|
||||
build-type: Simple
|
||||
extra-source-files:
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://github.com/githubuser/part2
|
||||
|
||||
library
|
||||
exposed-modules:
|
||||
Lib
|
||||
other-modules:
|
||||
Paths_part2
|
||||
autogen-modules:
|
||||
Paths_part2
|
||||
hs-source-dirs:
|
||||
src
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
, containers
|
||||
, random
|
||||
, unescaping-print
|
||||
default-language: Haskell2010
|
||||
|
||||
executable part2-exe
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_part2
|
||||
autogen-modules:
|
||||
Paths_part2
|
||||
hs-source-dirs:
|
||||
app
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
, containers
|
||||
, part2
|
||||
, random
|
||||
, unescaping-print
|
||||
default-language: Haskell2010
|
||||
|
||||
test-suite part2-test
|
||||
type: exitcode-stdio-1.0
|
||||
main-is: Spec.hs
|
||||
other-modules:
|
||||
Paths_part2
|
||||
autogen-modules:
|
||||
Paths_part2
|
||||
hs-source-dirs:
|
||||
test
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
, containers
|
||||
, part2
|
||||
, random
|
||||
, unescaping-print
|
||||
default-language: Haskell2010
|
||||
73
coursework/part2/src/Lib.hs
Normal file
@@ -0,0 +1,73 @@
|
||||
module Lib where
|
||||
|
||||
import Data.Char (isLetter, toLower)
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Map as Map
|
||||
import Data.List (nub, tails)
|
||||
import System.IO
|
||||
import System.Random (StdGen, randomR, newStdGen) -- mkStdGen
|
||||
import UnescapingPrint (ushow)
|
||||
|
||||
|
||||
splitText :: String -> [[String]]
|
||||
splitText text = filter (not . null) $ map (processSentence . words) (splitSentences text)
|
||||
where
|
||||
splitSentences :: String -> [String]
|
||||
splitSentences [] = []
|
||||
splitSentences s =
|
||||
let (sentence, rest) = break isSeparator s
|
||||
rest' = dropWhile isSeparator rest
|
||||
in if null sentence
|
||||
then splitSentences rest'
|
||||
else sentence : splitSentences rest'
|
||||
|
||||
isSeparator :: Char -> Bool
|
||||
isSeparator c = c `elem` ".!?;:()"
|
||||
|
||||
processSentence :: [String] -> [String]
|
||||
processSentence = filter (not . null) . map cleanWord
|
||||
|
||||
cleanWord :: String -> String
|
||||
cleanWord = map toLower . filter isLetter
|
||||
|
||||
buildDictionary :: [[String]] -> Map String [String]
|
||||
buildDictionary sentences =
|
||||
let bigrams = [ (w1, w2) | s <- sentences, (w1:w2:_) <- tails s ]
|
||||
trigrams = [ (w1, w2, w3) | s <- sentences, (w1:w2:w3:_) <- tails s ]
|
||||
singleKeys = foldr (\(w1, w2) acc -> Map.insertWith (++) w1 [w2] acc) Map.empty bigrams
|
||||
singleKeys' = foldr (\(w1, w2, w3) acc -> Map.insertWith (++) w1 [w2 ++ " " ++ w3] acc) singleKeys trigrams
|
||||
doubleKeys = foldr (\(w1, w2, w3) acc -> Map.insertWith (++) (w1 ++ " " ++ w2) [w3] acc) Map.empty trigrams
|
||||
combined = Map.unionWith (++) singleKeys' doubleKeys
|
||||
in Map.map nub combined
|
||||
|
||||
saveDictionary :: FilePath -> Map String [String] -> IO ()
|
||||
saveDictionary filePath dict = withFile filePath WriteMode $ \h ->
|
||||
mapM_ (\(k,v) -> hPutStrLn h $ ushow k ++ ": " ++ ushow v) (Map.toList dict)
|
||||
|
||||
generatePhrase :: Map String [String] -> String -> StdGen -> [String]
|
||||
generatePhrase dict start initGenState =
|
||||
-- let (len, initGenState') = (2 :: Int, initGenState)
|
||||
let (len, initGenState') = randomR (2,15 :: Int) initGenState
|
||||
in reverse $ gp start [] len initGenState'
|
||||
where
|
||||
gp :: String -> [String] -> Int -> StdGen -> [String]
|
||||
gp key acc n genState
|
||||
| n <= 0 = acc
|
||||
| otherwise =
|
||||
case Map.lookup key dict of
|
||||
Nothing -> acc
|
||||
Just [] -> acc
|
||||
Just vals ->
|
||||
let (i, newGenState) = randomR (0, length vals - 1) genState
|
||||
next = vals !! i
|
||||
in
|
||||
gp next (next:acc) (n - length (words next)) newGenState
|
||||
|
||||
processInput :: Map String [String] -> String -> IO ()
|
||||
processInput dict input =
|
||||
if Map.member input dict then
|
||||
-- let gen = mkStdGen 42 in
|
||||
newStdGen >>= \gen ->
|
||||
putStrLn $ unwords $ generatePhrase dict input gen
|
||||
else
|
||||
putStrLn "Нет в словаре"
|
||||
69
coursework/part2/stack.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
# This file was automatically generated by 'stack init'
|
||||
#
|
||||
# Some commonly used options have been documented as comments in this file.
|
||||
# For advanced use and comprehensive documentation of the format, please see:
|
||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||
|
||||
# A 'specific' Stackage snapshot or a compiler version.
|
||||
# A snapshot resolver dictates the compiler version and the set of packages
|
||||
# to be used for project dependencies. For example:
|
||||
#
|
||||
# snapshot: lts-22.28
|
||||
# snapshot: nightly-2024-07-05
|
||||
# snapshot: ghc-9.6.6
|
||||
#
|
||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||
#
|
||||
# snapshot: ./custom-snapshot.yaml
|
||||
# snapshot: https://example.com/snapshots/2024-01-01.yaml
|
||||
snapshot:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
|
||||
# User packages to be built.
|
||||
# Various formats can be used as shown in the example below.
|
||||
#
|
||||
# packages:
|
||||
# - some-directory
|
||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||
# subdirs:
|
||||
# - auto-update
|
||||
# - wai
|
||||
packages:
|
||||
- .
|
||||
# Dependency packages to be pulled from upstream that are not in the snapshot.
|
||||
# These entries can reference officially published versions as well as
|
||||
# forks / in-progress versions pinned to a git hash. For example:
|
||||
#
|
||||
# extra-deps:
|
||||
# - acme-missiles-0.3
|
||||
# - git: https://github.com/commercialhaskell/stack.git
|
||||
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||
#
|
||||
extra-deps:
|
||||
- unescaping-print-0.1@sha256:12774feb474d20ac3041d577b6307730c7376127f59bc79612d599a56d5009d8,1397
|
||||
allow-newer: true
|
||||
|
||||
# Override default flag values for project packages and extra-deps
|
||||
# flags: {}
|
||||
|
||||
# Extra package databases containing global packages
|
||||
# extra-package-dbs: []
|
||||
|
||||
# Control whether we use the GHC we find on the path
|
||||
# system-ghc: true
|
||||
#
|
||||
# Require a specific version of Stack, using version ranges
|
||||
# require-stack-version: -any # Default
|
||||
# require-stack-version: ">=3.1"
|
||||
#
|
||||
# Override the architecture used by Stack, especially useful on Windows
|
||||
# arch: i386
|
||||
# arch: x86_64
|
||||
#
|
||||
# Extra directories used by Stack for building
|
||||
# extra-include-dirs: [/path/to/dir]
|
||||
# extra-lib-dirs: [/path/to/dir]
|
||||
#
|
||||
# Allow a newer minor version of GHC than the snapshot specifies
|
||||
# compiler-check: newer-minor
|
||||
20
coursework/part2/stack.yaml.lock
Normal file
@@ -0,0 +1,20 @@
|
||||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/lock_files
|
||||
|
||||
packages:
|
||||
- completed:
|
||||
hackage: unescaping-print-0.1@sha256:12774feb474d20ac3041d577b6307730c7376127f59bc79612d599a56d5009d8,1397
|
||||
pantry-tree:
|
||||
sha256: b32edaf8cdef31ef02a0363e629ddf4949a6490777a6a797617f5dd376a46fce
|
||||
size: 371
|
||||
original:
|
||||
hackage: unescaping-print-0.1@sha256:12774feb474d20ac3041d577b6307730c7376127f59bc79612d599a56d5009d8,1397
|
||||
snapshots:
|
||||
- completed:
|
||||
sha256: 08bd13ce621b41a8f5e51456b38d5b46d7783ce114a50ab604d6bbab0d002146
|
||||
size: 720271
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
original:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
56
coursework/part2/task_part2.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
Часть 2
|
||||
|
||||
Написать синтаксический анализатор разбирающий текст и генератор
|
||||
продолжения текста по введенному слову. Для этого выполнить следующие
|
||||
задачи:
|
||||
|
||||
1. Прочитать текст из файла, указываемого пользователем. Синтаксически
|
||||
проанализировать текст согласно правилам: слова состоят только из букв;
|
||||
предложения состоят только из слов и разделены символами: .!?;:().
|
||||
Разбить текст на предложения. Удалить все символы пунктуации и цифры
|
||||
из слов и предложений.
|
||||
|
||||
2. Составить модель N-грамм. Использовать модель биграмм и триграмм.
|
||||
По списку предложений составить словарь. Ключами являются: одно слово,
|
||||
либо пара слов. Значениями в словаре является список всех уникальных
|
||||
возможных продолжений триграммы (т.е. список пар слов или одиночных
|
||||
слов). Словарь сохранить в файл .txt.
|
||||
|
||||
Пример текста и словаря на его основе:
|
||||
|
||||
Текст: [a b, c d e! b c d? e b c# a ^d. a f; f.]
|
||||
|
||||
Словарь:
|
||||
[
|
||||
"a": ["b", "d", "f", "b c"];
|
||||
"b": ["c", "c d"];
|
||||
"c": ["d", "a", "d e", "a d"];
|
||||
"d": ["e"];
|
||||
"e": ["b", "b c"];
|
||||
"a b" : ["c"];
|
||||
"b c" : ["d", "a"];
|
||||
"c d": ["e"];
|
||||
"e b" : ["c"];
|
||||
"c a": ["d"];
|
||||
"f": []
|
||||
]
|
||||
|
||||
3. Реализовать взаимодействие с пользователем. Пользователь вводит одно
|
||||
слово или пару слов. Программа возвращает строку случайной длины в
|
||||
диапазоне от 2 до 15 слов, если задаваемого пользователем слова нет в
|
||||
ключах словаря, выдавать соответствующее сообщение. Фраза составляется
|
||||
путем добавления случайного слова (или пары) из списка значений текущего
|
||||
слова-ключа (или пары-ключа), до тех пор, пока либо не будет сформировано
|
||||
предложение нужной длины, либо не будет достигнут ключ, у которого нет
|
||||
значений.
|
||||
|
||||
4. Организовать диалог двух моделей N-грамм созданных на двух разных
|
||||
текстах. Тексты для второй модели выбрать самостоятельно. Пользователь
|
||||
задает начальное слово (или пару) и глубину М сообщений, которыми
|
||||
обмениваются модели. Ответ модели основывается на последнем слове из
|
||||
предложения оппонента (если последнее слово отсутствует в словаре, то
|
||||
предпоследнее и т.д. пока не будет найдено подходящее слово или не
|
||||
закончится предложение оппонента)
|
||||
|
||||
Автор текстов:
|
||||
Чехов, Антон Павлович
|
||||
2
coursework/part2/test/Spec.hs
Normal file
@@ -0,0 +1,2 @@
|
||||
main :: IO ()
|
||||
main = putStrLn "Test suite not yet implemented"
|
||||
17
coursework/part2/text.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ண<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>⨫<EFBFBD><E2A8AB><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>⥫<EFBFBD>: <20><><EFBFBD><EFBFBD> ⮫<><E2AEAB><EFBFBD><EFBFBD>, <20><>㣮<EFBFBD> ⮭<><E2AEAD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ⮫쪮 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>, <20><>᭨<EFBFBD><E1ADA8><EFBFBD><EFBFBD>, <20><><EFBFBD> ᯥ<><E1AFA5><EFBFBD> <20><>譨. <20><>嫮 <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ᮬ <20> 䫥<>-<2D>'<27>࠭<EFBFBD><E0A0AD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> ⮫쪮 <20><><EFBFBD> <20><>襫 <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>祭 祬<><E7A5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 㧫<><E3A7AB><EFBFBD> <20> <20><><EFBFBD>⮭<EFBFBD><E2AEAD><EFBFBD><EFBFBD>. <20><>嫮 <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>稭<EFBFBD><E7A8AD> <20> <20><>䥩<EFBFBD><E4A5A9><EFBFBD> <20><>饩. <20><>-<2D><> <20><><EFBFBD> ᯨ<><E1AFA8> <20>룫<EFBFBD><EBA3AB>뢠<EFBFBD><EBA2A0> <20>㤥<EFBFBD>쪠<EFBFBD> <20><><EFBFBD>騭<EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>த<EFBFBD><E0AEA4><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD><EFBFBD>, <20> <20><>᮪<EFBFBD><E1AEAA> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>७<EFBFBD><E0A5AD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD>.
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD>! - <20><>᪫<EFBFBD><E1AAAB><EFBFBD><EFBFBD><EFBFBD> ⮫<><E2AEAB><EFBFBD><EFBFBD>, 㢨<><E3A2A8><EFBFBD> ⮭<><E2AEAD><EFBFBD><EFBFBD>.- <20><> <20><> <20><><EFBFBD>? <20><><EFBFBD><EFBFBD><EFBFBD>稪 <20><><EFBFBD>! <20><><EFBFBD><EFBFBD>쪮 <20><><EFBFBD>, <>쪮 <20><><EFBFBD>!
|
||||
- <20><><EFBFBD><EFBFBD>誨! - <20><>㬨<EFBFBD><E3ACA8><EFBFBD> ⮭<><E2AEAD><EFBFBD>.- <20><><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>⢠! <20><><EFBFBD>㤠 <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>⥫<EFBFBD> <20><EFBFBD><E0AEA5><EFBFBD>⭮ <20><><EFBFBD><EFBFBD><EFBFBD>맠<EFBFBD><EBA7A0><EFBFBD><EFBFBD> <20> <20><><EFBFBD>६<EFBFBD><E0A5AC><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><>㣠 <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <>. <20><><EFBFBD> <20>뫨 <20><><EFBFBD><EFBFBD>⭮ <20>襫<EFBFBD><E8A5AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>! - <20><>砫 ⮭<><E2AEAD><EFBFBD> <20><> <20><><EFBFBD>맠<EFBFBD><EBA7A0><EFBFBD>.- <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD> <20><><EFBFBD><EFBFBD>ਧ! <20><>, <20><> <20><><EFBFBD><EFBFBD>廊 <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>襭쪮! <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>ᠢ<EFBFBD><E1A0A2>, <20><><EFBFBD> <20> <20><><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><>训<EFBFBD><E8AEAD> <20> 饣<><E9A5A3><EFBFBD>! <20><> <20><>, <20><>ᯮ<EFBFBD><E1AFAE>! <20><>, <20><><EFBFBD> <20><> <20><>? <20><><EFBFBD><EFBFBD><EFBFBD>? <20><><EFBFBD><EFBFBD><EFBFBD>? <20> 㦥 <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>㨧<EFBFBD>, <20><EFBFBD><E0AEA6><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>業<EFBFBD><E6A5AD><EFBFBD>... <20><><EFBFBD><EFBFBD>࠭<EFBFBD><E0A0AD>... <20> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD>, <20><>䠭<EFBFBD><E4A0AD><EFBFBD>, <20>祭<EFBFBD><E7A5AD> III <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD>, <20><>䠭<EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>⢠! <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>稫<EFBFBD><E7A8AB><EFBFBD>!
|
||||
<EFBFBD><EFBFBD>䠭<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>㬠<EFBFBD> <20> <20><><EFBFBD><EFBFBD> 蠯<><E8A0AF>.
|
||||
- <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>稫<EFBFBD><E7A8AB><EFBFBD>! - <20>த<EFBFBD><E0AEA4><EFBFBD><EFBFBD><EFBFBD> ⮭<><E2AEAD><EFBFBD>.- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> ⥡<> <20>ࠧ<EFBFBD><E0A0A7><EFBFBD><EFBFBD>? <20><><EFBFBD><EFBFBD> <20>ࠧ<EFBFBD><E0A0A7><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⮬ <20><> <20><>, <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><E0AEA6>, <20> <20><><EFBFBD><EFBFBD> <20>䨠<EFBFBD><E4A8A0>⮬ <20><> <20><>, <20><><EFBFBD> <20> <><EFA1A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD>. <20><>-<2D><>... <20><><EFBFBD>쬨 <20>뫨! <20><> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><>䠭<EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... <20> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><EFBFBD><E0AEA6><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>業<EFBFBD><E6A5AD><EFBFBD>... <20><><EFBFBD><EFBFBD>࠭<EFBFBD><E0A0AD>.
|
||||
<EFBFBD><EFBFBD>䠭<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>㬠<EFBFBD> <20> <20><><EFBFBD><EFBFBD>⠫<EFBFBD><E2A0AB> <20><> ᯨ<><E1AFA8> <20><><EFBFBD><EFBFBD>.
|
||||
- <20><>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>? - <20><><EFBFBD><EFBFBD>ᨫ ⮫<><E2AEAB><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>থ<EFBFBD><E0A6A5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><>㣠.- <20><>㦨<EFBFBD><E3A6A8> <20><><EFBFBD>? <20><><EFBFBD><EFBFBD>㦨<EFBFBD><E3A6A8><EFBFBD>?
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>᪨<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 㦥 <20><><EFBFBD>ன <20><><EFBFBD> <20> <20>⠭<EFBFBD><EFBFBD><E1ABA0> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>宥... <20><>, <20><> <20><><EFBFBD> <20> <20><><EFBFBD>! <20><><EFBFBD><EFBFBD> <20>ப<EFBFBD> <20><><EFBFBD>모 <20><><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD>ᨣ<EFBFBD><E1A8A3><EFBFBD> <20>ਢ<EFBFBD>⭮ <20><> <20><>ॢ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>. <20>⫨<EFBFBD><E2ABA8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ᨣ<EFBFBD><E1A8A3><EFBFBD>! <20><> <20>㡫<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20>த<EFBFBD><E0AEA4>. <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>, ⮬<>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>㯪<EFBFBD>. <20><EFBFBD><E0AEA1><EFBFBD>塞<EFBFBD><EFA5AC> <20><><EFBFBD>-<2D><><EFBFBD>. <20><>㦨<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD>⠬<EFBFBD><E2A0AC><EFBFBD><EFBFBD>, <20> ⥯<><E2A5AF><EFBFBD> <20> <20><>ॢ<EFBFBD><E0A5A2><EFBFBD><EFBFBD> <20>⮫<EFBFBD><E2AEAB><EFBFBD>砫쭨<E7A0AB><ECADA8><EFBFBD> <20><> ⮬<> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>㦨<EFBFBD><E3A6A8>. <20><>, <20> <20><> <20><><EFBFBD>? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 㦥 <20><><EFBFBD><EFBFBD>᪨<EFBFBD>? <20>?
|
||||
- <20><><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,- ᪠<><E1AAA0><EFBFBD> ⮫<><E2AEAB><EFBFBD><EFBFBD>.- <20> 㦥 <20><> ⠩<><E2A0A9><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>㦨<EFBFBD><E3A6A8><EFBFBD>... <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <><E1AAAE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD>ਢ<EFBFBD><E0A8A2><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>砩襩 <20><>롪<EFBFBD><EBA1AA>; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD>믠<EFBFBD><EBAFA0><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD> <20><> <20>ꥦ<EFBFBD><EAA5A6><EFBFBD><EFBFBD>, ᣮࡨ<E1A3AE><E0A1A8><EFBFBD>, <20>㧨<EFBFBD><E3A7A8><EFBFBD>... <20><><EFBFBD> 祬<><E7A5AC><EFBFBD><EFBFBD><EFBFBD>, 㧫<> <20> <20><><EFBFBD>⮭<EFBFBD><E2AEAD> <20>ꥦ<EFBFBD><EAA5A6><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>騫<EFBFBD><E9A8AB><EFBFBD>... <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>த<EFBFBD><E0AEA4> <20><><EFBFBD><EFBFBD> <20>⠫ <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <20><>䠭<EFBFBD><E4A0AD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD>⥣<EFBFBD><E2A5A3><EFBFBD> <20><><EFBFBD> <20>㣮<EFBFBD><E3A3AE><EFBFBD> <><E1A2AE><EFBFBD> <20>㭤<EFBFBD><E3ADA4><EFBFBD>...
|
||||
- <20>, <20><><EFBFBD><EFBFBD> <20>ॢ<EFBFBD><E0A5A2>室<EFBFBD>⥫<EFBFBD><E2A5AB>⢮... <20>祭<EFBFBD> <20><><EFBFBD><EFBFBD>⭮-<2D>! <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> ᪠<><E1AAA0><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>⢠ <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><>諨 <20> ⠪<><E2A0AA> <20><><EFBFBD>쬮<EFBFBD><ECACAE>-<2D>! <20><>-<2D><>-<2D>.
|
||||
- <20><>, <20><><EFBFBD><EFBFBD><EFBFBD>! - <20><><EFBFBD><EFBFBD><EFBFBD>騫<EFBFBD><E9A8AB> ⮫<><E2AEAB><EFBFBD><EFBFBD>.- <20><><EFBFBD> 祣<> <20><><EFBFBD><EFBFBD> ⮭? <20><> <20> ⮡<><E2AEA1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>⢠ - <20> <20> 祬<> <20><><EFBFBD> <20><><EFBFBD> 稭<><E7A8AD><EFBFBD><EFBFBD><EFBFBD>⠭<EFBFBD><E2A0AD>!
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... <20><><EFBFBD> <20><>-<2D>...- <20><><EFBFBD><EFBFBD>娪<EFBFBD><E5A8AA> ⮭<><E2AEAD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20>ꥦ<EFBFBD><EAA5A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.- <20><><EFBFBD><EFBFBD><EFBFBD>⨢<EFBFBD><E2A8A2> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>襣<EFBFBD> <20>ॢ<EFBFBD><E0A5A2>室<EFBFBD>⥫<EFBFBD><E2A5AB>⢠... <20>த<EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>⥫쭮<E2A5AB> <20><><EFBFBD><EFBFBD><EFBFBD>... <20><><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD><EFBFBD> <20>ॢ<EFBFBD><E0A5A2>室<EFBFBD>⥫<EFBFBD><E2A5AB>⢮, <20><><EFBFBD> <20><><EFBFBD> <20><>䠭<EFBFBD><E4A0AD><EFBFBD>... <20><><EFBFBD><EFBFBD> <20>㨧<EFBFBD>, <20><><EFBFBD><EFBFBD>࠭<EFBFBD><E0A0AD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ࠧ<EFBFBD><E0A0A7>...
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>⥫ <20>뫮 <20><><EFBFBD>ࠧ<EFBFBD><E0A0A7><EFBFBD> <20><><EFBFBD>-<2D><>, <20><> <20><> <20><><EFBFBD><EFBFBD> <20> ⮭<><E2AEAD><EFBFBD><EFBFBD> <20>뫮 <20><><EFBFBD><EFBFBD>ᠭ<EFBFBD> <20>⮫쪮 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <><E1ABA0><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>⥫쭮<E2A5AB> <20><><EFBFBD><E1ABAE>, <20><><EFBFBD> ⠩<><E2A0A9><EFBFBD><EFBFBD> ᮢ<>⭨<EFBFBD><E2ADA8> <20><><EFBFBD>譨<EFBFBD><E8ADA8>. <20><> <20>⢥<EFBFBD><E2A2A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> ⮭<><E2AEAD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD>頭<EFBFBD><E9A0AD> <20><><EFBFBD><EFBFBD>.
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ᥬ <20>㫮<EFBFBD><E3ABAE>饬 <20> <20><><EFBFBD><EFBFBD>娪<EFBFBD><E5A8AA>, <20><><EFBFBD> <20><>⠥<EFBFBD>: <<<3C><>-<2D><>-<2D><>>>. <20><><EFBFBD><EFBFBD> <20><>롭㫠<EBA1AD><E3ABA0>. <20><>䠭<EFBFBD><E4A0AD><EFBFBD> <20><>ભ<EFBFBD><E0AAAD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><EFBFBD><E0AEAD> <20><>ࠦ<EFBFBD><E0A0A6>. <20><><EFBFBD> <20> <20>뫨 <20><><EFBFBD><EFBFBD>⭮ <20>襫<EFBFBD><E8A5AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
@@ -22,6 +22,8 @@ main = do
|
||||
|
||||
let sourceTextPath = "resources/biography.txt"
|
||||
let sourceImagePath = "resources/david.bmp"
|
||||
let alphabetPath = "tmp/alphabet.txt"
|
||||
let encryptedTextPath = "tmp/biography_encrypted.txt"
|
||||
let encodedImagePath = "tmp/david_" ++ show bitsPerByte ++ "_" ++ show caesarShift ++ ".bmp"
|
||||
let decodedTextPath = "tmp/biography.txt"
|
||||
|
||||
@@ -32,8 +34,12 @@ main = do
|
||||
putStrLn "\nШифрование текста"
|
||||
let alphabet = createAlphabetFromText inputText
|
||||
putStrLn $ "Размер алфавита: " ++ show (length alphabet)
|
||||
writeFile alphabetPath alphabet
|
||||
putStrLn $ "Алфавит сохранён в файл \"" ++ alphabetPath ++ "\""
|
||||
let encryptedText = encryptCaesar alphabet caesarShift inputText
|
||||
putStrLn $ "10 символов шифра: \"" ++ take 10 encryptedText ++ "\""
|
||||
writeFile encryptedTextPath encryptedText
|
||||
putStrLn $ "Зашифрованный текст сохранён в файл \"" ++ encryptedTextPath ++ "\""
|
||||
let encryptedTextBits = textToBits encryptedText
|
||||
putStrLn $ "10 битов шифра: \"" ++ show (take 10 $ VU.toList encryptedTextBits) ++ "\""
|
||||
|
||||
@@ -52,6 +58,8 @@ main = do
|
||||
saveBmpImage encodedImagePath (ImageRGB8 resultImage)
|
||||
putStrLn $ "Изображение сохранено по пути: \"" ++ encodedImagePath ++ "\""
|
||||
|
||||
putStrLn $ "\nЧтение алфавита из файла \"" ++ alphabetPath ++ "\""
|
||||
alphabetFromFile <- readFile alphabetPath
|
||||
|
||||
putStrLn "\nДекодирование текста из изображения"
|
||||
case extractShift encodedImagePath of
|
||||
@@ -67,7 +75,7 @@ main = do
|
||||
putStrLn $ "10 битов шифра: \"" ++ show (take 10 $ VU.toList bits) ++ "\""
|
||||
let encryptedTextFromImage = takeWhile (/= '\NUL') (bitsToText bits)
|
||||
putStrLn $ "10 символов шифра: \"" ++ take 10 encryptedTextFromImage ++ "\""
|
||||
let decryptedText = decryptCaesar alphabet extractedCaesarShift encryptedTextFromImage
|
||||
let decryptedText = decryptCaesar alphabetFromFile extractedCaesarShift encryptedTextFromImage
|
||||
putStrLn $ "10 символов текста: \"" ++ take 10 decryptedText ++ "\""
|
||||
writeFile decodedTextPath decryptedText
|
||||
putStrLn $ "Текст сохранён по пути: \"" ++ decodedTextPath ++ "\""
|
||||
|
||||
BIN
lab3/report/img/david_2_20.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
lab3/report/img/david_3_20.jpg
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
lab3/report/img/david_5_20.jpg
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
lab3/report/img/david_6_20.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 38 KiB |
@@ -210,7 +210,7 @@
|
||||
|
||||
\subsection{Кодирование и декодирование текста с помощью шифра Цезаря}
|
||||
|
||||
Код функций для кодирования и декодирования текста с помощью шифра Цезаря представлен в листинге~\ref{lst:encrypt-caesar}. Функция \texttt{encryptCaesar} принимает алфавит в виде списка символов, смещение и сам текст, а возвращает зашифрованный текст. В её коде используется вспомогательная функция \texttt{indexOf}. Функция принимает список и элемент списка, а возвращает индекс этого элемента. Для создания алфавита используется функция \texttt{createAlphabetFromText}. Она принимает текст, а возвращает алфавит, который в нём используется, в виде списка символов. Для декодирования текста используется функция \texttt{decryptCaesar}, которая, по-сути, является лишь обёрткой над функцией \texttt{encryptCaesar}, так как процесс кодирования осуществляется почти так же как и декодирования. Функция \texttt{decryptCaesar} принимает на вход алфавит, смещение и закодированный текст, а возвращает декодированный текст.
|
||||
Код функций для кодирования и декодирования текста с помощью шифра Цезаря представлен в листинге~\ref{lst:encrypt-caesar}. Функция \texttt{encryptCaesar} принимает алфавит в виде списка символов, смещение и сам текст, а возвращает зашифрованный текст. В её коде используется вспомогательная функция \texttt{indexOf}. Функция принимает список и элемент списка, а возвращает индекс этого элемента. Для создания алфавита используется функция \texttt{createAlphabetFromText}. Она принимает текст, а возвращает алфавит, который в нём используется, в виде списка символов. Для декодирования текста используется функция \texttt{decryptCaesar}, которая, по-сути, является лишь обёрткой над функцией \texttt{encryptCaesar}, так как процесс кодирования осуществляется почти так же как и декодирования. Функция \texttt{decryptCaesar} принимает на вход алфавит, смещение и закодированный текст, а возвращает декодированный текст. Алфавит сохраняется в отдельный файл и должен передаваться вместе с зашифрованным текстом, чтобы этот текст можно было дешифровать.
|
||||
|
||||
\begin{lstlisting}[caption={Функции для кодирования и декодирования текста с помощью шифра Цезаря.}, label={lst:encrypt-caesar}]
|
||||
encryptCaesar :: [Char] -> Int -> String -> String
|
||||
@@ -239,6 +239,31 @@ decryptCaesar alphabet shift =
|
||||
alphabetLength = length alphabet
|
||||
\end{lstlisting}
|
||||
|
||||
Пример закодированного с помощью шифра Цезаря текста биографии Дэвида Дойча для смещения 5 представлен ниже.
|
||||
|
||||
\noindent
|
||||
\texttt{
|
||||
uiHF rWtFaga.ruabYgo;r3qkrNuCLS59Grcm.lrDwrvinrDJRBTrFgrirM.FYFg;rs;ngFo\\
|
||||
FgYriYrY;arAlFHa.gFYnrmerCdem. Ur9arFgrirHFgFYFlhrs.meaggm.rFlrY;aruasi.\\
|
||||
YQalYrmerIYmQForil r)iga.r8;ngFogriYrY;ar5alY.arem.r(bilYbQr5mQsbYiYFmlr\\
|
||||
N5(5TrFlrY;ar5ti.al mlr)icm.iYm.nrmerY;arAlFHa.gFYnrmerCdem. Ur9arsFmlaa\\
|
||||
.a rY;areFat rmerpbilYbQromQsbYiYFmlrcnrem.QbtiYFlhrir ago.FsYFmlrem.rir\\
|
||||
pbilYbQrSb.FlhrQio;Flayrigr,attrigrgsaoFenFlhrilrithm.FY;Qr agFhla rYmr.\\
|
||||
blrmlrirpbilYbQromQsbYa.Ur9arFgrirs.msmlalYrmerY;arQiln,m.t grFlYa.s.aYi\\
|
||||
YFmlrmerpbilYbQrQao;ilFogU1uabYgo;r,igrcm.lrYmrirxa,Fg;reiQFtnrFlr9iFeiy\\
|
||||
r-g.iatrmlrDwrvinrDJRByrY;argmlrmerCg2i.ril rSF2HiruabYgo;Ur-lr)ml mlyru\\
|
||||
iHF riYYal a rEalaHir9mbgargo;mmtrFlr5.Fo2ta,mm rN;Fgrsi.alYgrm,la ril r\\
|
||||
.ilrY;arItQir.agYib.ilYrmlr5.Fo2ta,mm rM.mi ,inTyremttm,a rcnrPFttFiQrWt\\
|
||||
tFgrko;mmtrFlr9Fh;hiYarcaem.ar.ai FlhrOiYb.itrkoFaloagriYr5ti.ar5mttahay\\
|
||||
r5iQc.F haril rYi2Flhr8i.Yr---rmerY;arviY;aQiYFoitrS.FsmgUr9ar,alYrmlrYm\\
|
||||
rPmtegmlr5mttahayrCdem. rem.r;Fgr moYm.iYarFlrY;am.aYFoitrs;ngFogyricmbY\\
|
||||
rpbilYbQreFat rY;am.nrFlrob.Ha rgsioaYFQayrgbsa.HFga rcnruallFgrkoFiQiri\\
|
||||
l r8;FtFsr5il atigU19Fgr,m.2rmlrpbilYbQrithm.FY;Qgrcahilr,FY;rirDJwRrsis\\
|
||||
a.yrtiYa.radsil a rFlrDJJzritmlhr,FY;rqFo;i. rxmfgiyrYmrs.m boarY;aruabY\\
|
||||
go;xmfgirithm.FY;QyrmlarmerY;areF.gYradiQstagrmerirpbilYbQrithm.FY;QrY;i\\
|
||||
YrFgradsmlalYFittnreigYa.rY;ilrilnrsmggFctar aYa.QFlFgYForotiggFoitrithm\\
|
||||
.FY;QU}
|
||||
|
||||
|
||||
\subsection{Представление текста в виде последовательности бит}
|
||||
|
||||
@@ -339,7 +364,7 @@ extractShift path =
|
||||
|
||||
\newpage
|
||||
\section {Результаты работы программы}
|
||||
При успешном завершении программа создаёт два файла: файл изображения с закодированных текстом и текстовый файл с декодированным текстом.
|
||||
При успешном завершении программа создаёт четыре файла: файл изображения с закодированных текстом, текстовый файл с закодированным текстом, текстовый файл с алфавитом и текстовый файл с декодированным текстом.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
@@ -352,32 +377,64 @@ extractShift path =
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.3\linewidth]{img/david_1_20.jpg}
|
||||
\includegraphics[width=0.33\linewidth]{img/david_1_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (1 бит).}
|
||||
\label{fig:david1}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.3\linewidth]{img/david_4_20.jpg}
|
||||
\includegraphics[width=0.33\linewidth]{img/david_2_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (2 бит).}
|
||||
\label{fig:david2}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.33\linewidth]{img/david_3_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (3 бит).}
|
||||
\label{fig:david3}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.33\linewidth]{img/david_4_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (4 бит).}
|
||||
\label{fig:david4}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.3\linewidth]{img/david_7_20.jpg}
|
||||
\includegraphics[width=0.33\linewidth]{img/david_5_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (5 бит).}
|
||||
\label{fig:david5}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.33\linewidth]{img/david_6_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (6 бит).}
|
||||
\label{fig:david6}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.33\linewidth]{img/david_7_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (7 бит).}
|
||||
\label{fig:david7}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.3\linewidth]{img/david_8_20.jpg}
|
||||
\includegraphics[width=0.33\linewidth]{img/david_8_20.jpg}
|
||||
\caption{Изображение с зашифрованными данными (8 бит).}
|
||||
\label{fig:david8}
|
||||
\end{figure}
|
||||
|
||||
\newpage
|
||||
\phantom{text}
|
||||
\newpage
|
||||
\phantom{text}
|
||||
\newpage
|
||||
На Рис.~\ref{fig:david1}-\ref{fig:david8} представлены результирующие изображения с разным количеством бит, отведённых под зашифрованные данные.
|
||||
|
||||
|
||||
3
lab4/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.stack-work/
|
||||
*~
|
||||
!task.txt
|
||||
11
lab4/CHANGELOG.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Changelog for `lab4`
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to the
|
||||
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 0.1.0.0 - YYYY-MM-DD
|
||||
26
lab4/LICENSE
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright 2024 Author name here
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
lab4/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# lab4
|
||||
2
lab4/Setup.hs
Normal file
@@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
14
lab4/app/Main.hs
Normal file
@@ -0,0 +1,14 @@
|
||||
module Main (main) where
|
||||
|
||||
import Lib
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn $ "Примеры работы `isCongruent`"
|
||||
putStrLn $ "isCongruent 10 12 2: " ++ show (isCongruent 10 12 2)
|
||||
putStrLn $ "isCongruent 10 11 2: " ++ show (isCongruent 10 11 2)
|
||||
|
||||
putStrLn $ "\nПример работы `filterByPredicate`"
|
||||
let predicate x = x > 5
|
||||
putStrLn $ "filterByPredicate (>5) [1, 6, 3, 7, 2]: "
|
||||
++ show (filterByPredicate predicate [1 :: Int, 6, 3, 7, 2])
|
||||
68
lab4/lab4.cabal
Normal file
@@ -0,0 +1,68 @@
|
||||
cabal-version: 2.2
|
||||
|
||||
-- This file has been generated from package.yaml by hpack version 0.37.0.
|
||||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: lab4
|
||||
version: 0.1.0.0
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/lab4#readme>
|
||||
homepage: https://github.com/githubuser/lab4#readme
|
||||
bug-reports: https://github.com/githubuser/lab4/issues
|
||||
author: Author name here
|
||||
maintainer: example@example.com
|
||||
copyright: 2024 Author name here
|
||||
license: BSD-3-Clause
|
||||
license-file: LICENSE
|
||||
build-type: Simple
|
||||
extra-source-files:
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://github.com/githubuser/lab4
|
||||
|
||||
library
|
||||
exposed-modules:
|
||||
Lib
|
||||
other-modules:
|
||||
Paths_lab4
|
||||
autogen-modules:
|
||||
Paths_lab4
|
||||
hs-source-dirs:
|
||||
src
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
default-language: Haskell2010
|
||||
|
||||
executable lab4-exe
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_lab4
|
||||
autogen-modules:
|
||||
Paths_lab4
|
||||
hs-source-dirs:
|
||||
app
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
, lab4
|
||||
default-language: Haskell2010
|
||||
|
||||
test-suite lab4-test
|
||||
type: exitcode-stdio-1.0
|
||||
main-is: Spec.hs
|
||||
other-modules:
|
||||
Paths_lab4
|
||||
autogen-modules:
|
||||
Paths_lab4
|
||||
hs-source-dirs:
|
||||
test
|
||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
QuickCheck
|
||||
, base >=4.7 && <5
|
||||
, lab4
|
||||
default-language: Haskell2010
|
||||
60
lab4/package.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
name: lab4
|
||||
version: 0.1.0.0
|
||||
github: "githubuser/lab4"
|
||||
license: BSD-3-Clause
|
||||
author: "Author name here"
|
||||
maintainer: "example@example.com"
|
||||
copyright: "2024 Author name here"
|
||||
|
||||
extra-source-files:
|
||||
- README.md
|
||||
- CHANGELOG.md
|
||||
|
||||
# Metadata used when publishing your package
|
||||
# synopsis: Short description of your package
|
||||
# category: Web
|
||||
|
||||
# To avoid duplicated efforts in documentation and dealing with the
|
||||
# complications of embedding Haddock markup inside cabal files, it is
|
||||
# common to point users to the README.md file.
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/lab4#readme>
|
||||
|
||||
dependencies:
|
||||
- base >= 4.7 && < 5
|
||||
|
||||
ghc-options:
|
||||
- -Wall
|
||||
- -Wcompat
|
||||
- -Widentities
|
||||
- -Wincomplete-record-updates
|
||||
- -Wincomplete-uni-patterns
|
||||
- -Wmissing-export-lists
|
||||
- -Wmissing-home-modules
|
||||
- -Wpartial-fields
|
||||
- -Wredundant-constraints
|
||||
|
||||
library:
|
||||
source-dirs: src
|
||||
|
||||
executables:
|
||||
lab4-exe:
|
||||
main: Main.hs
|
||||
source-dirs: app
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- lab4
|
||||
|
||||
tests:
|
||||
lab4-test:
|
||||
main: Spec.hs
|
||||
source-dirs: test
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- lab4
|
||||
- QuickCheck
|
||||
5
lab4/report/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
**/*
|
||||
!.gitignore
|
||||
!report.tex
|
||||
!img
|
||||
!img/*
|
||||
BIN
lab4/report/img/main.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
lab4/report/img/test.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
341
lab4/report/report.tex
Normal file
@@ -0,0 +1,341 @@
|
||||
\documentclass[a4paper, final]{article}
|
||||
%\usepackage{literat} % Нормальные шрифты
|
||||
\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта
|
||||
\usepackage{tabularx}
|
||||
\usepackage[T2A]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[russian]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry}
|
||||
\usepackage{ragged2e} %для растягивания по ширине
|
||||
\usepackage{setspace} %для межстрочного интервала
|
||||
\usepackage{moreverb} %для работы с листингами
|
||||
\usepackage{indentfirst} % для абзацного отступа
|
||||
\usepackage{moreverb} %для печати в листинге исходного кода программ
|
||||
\usepackage{pdfpages} %для вставки других pdf файлов
|
||||
\usepackage{tikz}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{afterpage}
|
||||
\usepackage{longtable}
|
||||
\usepackage{float}
|
||||
|
||||
|
||||
|
||||
% \usepackage[paper=A4,DIV=12]{typearea}
|
||||
\usepackage{pdflscape}
|
||||
% \usepackage{lscape}
|
||||
|
||||
\usepackage{array}
|
||||
\usepackage{multirow}
|
||||
|
||||
\renewcommand\verbatimtabsize{4\relax}
|
||||
\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге
|
||||
\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице
|
||||
\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы
|
||||
\usepackage{listings} %листинги
|
||||
\usepackage{xcolor} % цвета
|
||||
\usepackage{hyperref}% для гиперссылок
|
||||
\usepackage{enumitem} %для перечислений
|
||||
|
||||
% Настраиваем листинги, чтобы они использовали счётчик figure
|
||||
% \AtBeginDocument{
|
||||
% \renewcommand{\thelstlisting}{\thefigure} % Листинги используют тот же счетчик, что и рисунки
|
||||
% \renewcommand{\lstlistingname}{Рис.} % Меняем подпись на "Рисунок"
|
||||
% }
|
||||
|
||||
% Автоматически увеличиваем счетчик figure перед каждым листингом
|
||||
% \let\oldlstlisting\lstlisting
|
||||
% \renewcommand{\lstlisting}[1][]{%
|
||||
% \refstepcounter{figure}% Увеличиваем счетчик figure
|
||||
% \oldlstlisting[#1]% Вызываем оригинальную команду lstlisting
|
||||
% }
|
||||
|
||||
\newcommand{\specialcell}[2][l]{\begin{tabular}[#1]{@{}l@{}}#2\end{tabular}}
|
||||
|
||||
|
||||
\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях
|
||||
|
||||
\hypersetup{colorlinks,
|
||||
allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные)
|
||||
|
||||
% подгружаемые языки — подробнее в документации listings (это всё для листингов)
|
||||
\lstloadlanguages{ Haskell}
|
||||
% включаем кириллицу и добавляем кое−какие опции
|
||||
\lstset{tabsize=2,
|
||||
breaklines,
|
||||
basicstyle=\footnotesize,
|
||||
columns=fullflexible,
|
||||
flexiblecolumns,
|
||||
numbers=left,
|
||||
numberstyle={\footnotesize},
|
||||
keywordstyle=\color{blue},
|
||||
inputencoding=cp1251,
|
||||
extendedchars=true
|
||||
}
|
||||
\lstdefinelanguage{MyC}{
|
||||
language=Haskell,
|
||||
% ndkeywordstyle=\color{darkgray}\bfseries,
|
||||
% identifierstyle=\color{black},
|
||||
% morecomment=[n]{/**}{*/},
|
||||
% commentstyle=\color{blue}\ttfamily,
|
||||
% stringstyle=\color{red}\ttfamily,
|
||||
% morestring=[b]",
|
||||
% showstringspaces=false,
|
||||
% morecomment=[l][\color{gray}]{//},
|
||||
keepspaces=true,
|
||||
escapechar=\%,
|
||||
texcl=true
|
||||
}
|
||||
|
||||
\textheight=24cm % высота текста
|
||||
\textwidth=16cm % ширина текста
|
||||
\oddsidemargin=0pt % отступ от левого края
|
||||
\topmargin=-1.5cm % отступ от верхнего края
|
||||
\parindent=24pt % абзацный отступ
|
||||
\parskip=5pt % интервал между абзацами
|
||||
\tolerance=2000 % терпимость к "жидким" строкам
|
||||
\flushbottom % выравнивание высоты страниц
|
||||
|
||||
|
||||
% Настройка листингов
|
||||
\lstset{
|
||||
language=Haskell,
|
||||
extendedchars=\true,
|
||||
inputencoding=utf8,
|
||||
keepspaces=true,
|
||||
captionpos=t,
|
||||
}
|
||||
|
||||
\begin{document} % начало документа
|
||||
|
||||
|
||||
|
||||
% НАЧАЛО ТИТУЛЬНОГО ЛИСТА
|
||||
\begin{center}
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\
|
||||
федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]}
|
||||
\normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt]
|
||||
\normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt]
|
||||
\normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\
|
||||
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\large{Отчет по лабораторной работе №4}\\
|
||||
\large{по дисциплине}\\
|
||||
\large{<<Функциональное программирование>>}\\
|
||||
\large{Вариант 12}\\
|
||||
\hfill \break
|
||||
|
||||
% \hfill \break
|
||||
% \hfill \break
|
||||
\end{center}
|
||||
|
||||
\small{
|
||||
\begin{tabular}{lrrl}
|
||||
\!\!\!Студент, & \hspace{2cm} & & \\
|
||||
\!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\
|
||||
\!\!\!Преподаватель,\\ \hspace{-5pt}к. т. н., доц. & \hspace{2cm} & \underline{\hspace{3cm}} & Моторин Д. Е. \\\\
|
||||
&&\hspace{4cm}
|
||||
\end{tabular}
|
||||
\begin{flushright}
|
||||
<<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2024г.
|
||||
\end{flushright}
|
||||
}
|
||||
|
||||
\hfill \break
|
||||
% \hfill \break
|
||||
\begin{center} \small{Санкт-Петербург, 2024} \end{center}
|
||||
\thispagestyle{empty} % выключаем отображение номера для этой страницы
|
||||
|
||||
% КОНЕЦ ТИТУЛЬНОГО ЛИСТА
|
||||
\newpage
|
||||
|
||||
\tableofcontents
|
||||
|
||||
|
||||
\newpage
|
||||
\section {Постановка задачи}
|
||||
Для выполнения лабораторной работы необходимо было сделать следующее. Создать проект в \texttt{stack}. Функции записать в библиотеку \texttt{Lib.hs} и ограничить доступ к вспомогательным функциям. Тесты записать в \texttt{Spec.hs}.
|
||||
|
||||
\textbf{Функция 1:} Напишите функцию проверки равенства по модулю \texttt{isCongruent :: Int -> Int -> Int -> Bool}, которая проверяет, равны ли два числа по модулю третьего числа. Используя \texttt{QuickCheck}, проверьте следующие свойства:
|
||||
\begin{enumerate}
|
||||
\item Если два числа равны по модулю, то их разность делится на модуль:
|
||||
\texttt{isCongruent a b m == (modulus (a - b) m == 0)}.
|
||||
\item Равенство по модулю является симметричным:
|
||||
\texttt{isCongruent a b m == isCongruent b a m}.
|
||||
\item Если одно число равно другому, то они равны по любому модулю:
|
||||
если \texttt{a == b}, то \texttt{isCongruent a b m == True}.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Функция 2:} Напишите функцию \texttt{filterByPredicate :: (a -> Bool) -> [a] -> [a]}, которая фильтрует элементы списка по заданному предикату. Используя \texttt{QuickCheck}, проверьте следующие свойства:
|
||||
\begin{enumerate}
|
||||
\item Все элементы результата удовлетворяют предикату: для каждого элемента \texttt{x} из результата должно выполняться условие: \texttt{predicate x == True}.
|
||||
\item Длина результата не превышает длину исходного списка:
|
||||
\texttt{length (filterByPredicate predicate xs) <= length xs}.
|
||||
\item Если предикат всегда возвращает \texttt{True}, то результат совпадает с исходным списком:
|
||||
если \texttt{predicate x == True} для всех \texttt{x}, то \texttt{filterByPredicate predicate xs == xs}.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\newpage
|
||||
\section {Особенности реализации}
|
||||
\subsection{Функция isCongruent}
|
||||
|
||||
Код функции для проверки числовой конгруэнтности представлен в листинге~\ref{lst:is-congruent}. Функция \texttt{isCongruent} принимает три числа: \texttt{a}, \texttt{b} и \texttt{d}. Она возвращает \texttt{True}, если остатки от деления \texttt{a} и \texttt{b} на \texttt{d} равны, и \texttt{False} в противном случае.
|
||||
|
||||
\begin{lstlisting}[caption={Функция для проверки числовой конгруэнтности.}, label={lst:is-congruent}]
|
||||
isCongruent :: Int -> Int -> Int -> Bool
|
||||
isCongruent a b d = a `mod` d == b `mod` d
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Функция filterByPredicate}
|
||||
|
||||
Код функции для фильтрации элементов списка на основе предиката представлен в листинге~\ref{lst:filter-by-predicate}. Функция \texttt{filterByPredicate} принимает предикат (\texttt{predicate}) и список (\texttt{[a]}). Она возвращает новый список, содержащий только те элементы исходного списка, для которых предикат возвращает \texttt{True}.
|
||||
|
||||
\begin{lstlisting}[caption={Функция для фильтрации списка по предикату.}, label={lst:filter-by-predicate}]
|
||||
filterByPredicate :: (a -> Bool) -> [a] -> [a]
|
||||
filterByPredicate _ [] = []
|
||||
filterByPredicate predicate (x:xs)
|
||||
| predicate x = x : filteredTail
|
||||
| otherwise = filteredTail
|
||||
where
|
||||
filteredTail = filterByPredicate predicate xs
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{Тесты для функции isCongruent}
|
||||
|
||||
Для тестирования функции \texttt{isCongruent} использовались свойства, проверяемые с использованием библиотеки QuickCheck. Ниже приведены описания тестов, представленных в листинге~\ref{lst:congruent-tests}.
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{propCongruentDifference}: Проверяет, что два числа конгруэнтны по модулю \texttt{m}, если и только если разность этих чисел делится на \texttt{m} без остатка.
|
||||
\item \texttt{propCongruentSymmetric}: Проверяет симметричность конгруэнтности, то есть, если \texttt{a} конгруэнтно \texttt{b}, то \texttt{b} конгруэнтно \texttt{a}.
|
||||
\item \texttt{propCongruentEqualNumbers}: Проверяет, что любое число \texttt{a} всегда конгруэнтно самому себе по любому ненулевому модулю.
|
||||
\end{itemize}
|
||||
|
||||
\begin{lstlisting}[caption={Тесты для функции \texttt{isCongruent} с использованием QuickCheck.}, label={lst:congruent-tests}]
|
||||
propCongruentDifference :: Int -> Int -> Int -> Property
|
||||
propCongruentDifference a b m =
|
||||
m /= 0 ==> isCongruent a b m == ((a - b) `mod` m == 0)
|
||||
|
||||
propCongruentSymmetric :: Int -> Int -> Int -> Property
|
||||
propCongruentSymmetric a b m =
|
||||
m /= 0 ==> isCongruent a b m == isCongruent b a m
|
||||
|
||||
propCongruentEqualNumbers :: Int -> Int -> Property
|
||||
propCongruentEqualNumbers a m =
|
||||
m /= 0 ==> isCongruent a a m == True
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{Тесты для функции filterByPredicate}
|
||||
|
||||
Для тестирования функции \texttt{filterByPredicate} использовались свойства, проверяемые с использованием библиотеки QuickCheck. Описание тестов приведено в листинге~\ref{lst:filter-tests}.
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{propFilterByPredicateSatisfiesPredicate}: Проверяет, что все элементы результирующего списка удовлетворяют переданному предикату.
|
||||
\item \texttt{propFilterByPredicateLength}: Проверяет, что длина результирующего списка не превышает длину исходного списка.
|
||||
\item \texttt{propFilterByPredicateAlwaysTrue}: Проверяет, что если предикат всегда возвращает \texttt{True}, результирующий список совпадает с исходным.
|
||||
\end{itemize}
|
||||
|
||||
\begin{lstlisting}[caption={Тесты для функции \texttt{filterByPredicate} с использованием QuickCheck.}, label={lst:filter-tests}]
|
||||
propFilterByPredicateSatisfiesPredicate :: Fun Int Bool -> [Int] -> Bool
|
||||
propFilterByPredicateSatisfiesPredicate (Fun _ predicate) xs =
|
||||
all predicate (filterByPredicate predicate xs)
|
||||
|
||||
propFilterByPredicateLength :: Fun Int Bool -> [Int] -> Bool
|
||||
propFilterByPredicateLength (Fun _ predicate) xs =
|
||||
length (filterByPredicate predicate xs) <= length xs
|
||||
|
||||
propFilterByPredicateAlwaysTrue :: [Int] -> Bool
|
||||
propFilterByPredicateAlwaysTrue xs =
|
||||
filterByPredicate (\_ -> True) xs == xs
|
||||
\end{lstlisting}
|
||||
|
||||
В листинге~\ref{lst:broken1} представлена реализация функции \texttt{filterByPredicate}, которая не пройдёт ни один из перечисленных тестов. А в листинге~\ref{lst:broken2} представлена реализация, которая не пройдёт два из трёх тестов, первый и третий.
|
||||
|
||||
\begin{lstlisting}[caption={Пример реализации функции filterByPredicate, которая не пройдёт ни один тест.}, label={lst:broken1}]
|
||||
filterByPredicate :: (a -> Bool) -> [a] -> [a]
|
||||
filterByPredicate _ [] = []
|
||||
filterByPredicate predicate (x:xs)
|
||||
| not $ predicate x = x : x : filteredTail
|
||||
| otherwise = x : x : filteredTail
|
||||
where
|
||||
filteredTail = filterByPredicate predicate xs
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{lstlisting}[caption={Пример реализации функции filterByPredicate, которая не пройдёт первый и третий тесты.}, label={lst:broken2}]
|
||||
filterByPredicate :: (a -> Bool) -> [a] -> [a]
|
||||
filterByPredicate _ [] = []
|
||||
filterByPredicate predicate (x:xs)
|
||||
| not $ predicate x = x : filteredTail
|
||||
| otherwise = filteredTail
|
||||
where
|
||||
filteredTail = filterByPredicate predicate xs
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Запуск тестов}
|
||||
|
||||
Для выполнения всех тестов в проекте создан файл \texttt{Spec.hs}, в котором определена функция \texttt{main}. Она последовательно запускает все тесты, используя библиотеку \texttt{QuickCheck}. Код функции \texttt{main} приведён в листинге~\ref{lst:test-main}.
|
||||
|
||||
Функция \texttt{quickCheck} используется для автоматического тестирования свойств. Она генерирует случайные входные данные, проверяет выполнение свойства на каждом из них и сообщает о результатах. В случае провала теста \texttt{quickCheck} предоставляет пример данных, на которых свойство не выполняется.
|
||||
|
||||
Для сборки проекта и выполнения всех тестов достаточно выполнить команду \texttt{stack test}.
|
||||
|
||||
\begin{lstlisting}[caption={Функция \texttt{main} для запуска тестов.}, label={lst:test-main}]
|
||||
main :: IO ()
|
||||
main = do
|
||||
quickCheck propCongruentDifference
|
||||
quickCheck propCongruentSymmetric
|
||||
quickCheck propCongruentEqualNumbers
|
||||
|
||||
quickCheck propFilterByPredicateSatisfiesPredicate
|
||||
quickCheck propFilterByPredicateLength
|
||||
quickCheck propFilterByPredicateAlwaysTrue
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
|
||||
\newpage
|
||||
\section {Результаты работы программы}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.6\linewidth]{img/main.png}
|
||||
\caption{Результаты работы программы.}
|
||||
\label{fig:main}
|
||||
\end{figure}
|
||||
|
||||
Сама программа лишь выводит примеры работы функций \texttt{isCongruent} и \texttt{filterByPredicate}. Результаты её запуска представлены на Рис.~\ref{fig:main}.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.6\linewidth]{img/test.png}
|
||||
\caption{Результаты запуска тестов.}
|
||||
\label{fig:test}
|
||||
\end{figure}
|
||||
|
||||
Результаты запуска тестов с помощью команды \texttt{stack test} представлены на Рис.~\ref{fig:test}.
|
||||
|
||||
|
||||
|
||||
\newpage
|
||||
\section*{Заключение}
|
||||
\addcontentsline{toc}{section}{Заключение}
|
||||
В данной работе был создан проект с использованием \texttt{stack}, включающий разработку и тестирование двух функций: проверки равенства по модулю и фильтрации списка по предикату. Для каждой функции были написаны три теста. Тесты запускаются на сгенерированных данных с помощью \texttt{QuickCheck}. Они подтверждают корректность реализации этих функций. В ходе выполнения лабораторной работы были получены базовые знания об автоматическом тестировании программ, написанных на языке Haskell.
|
||||
|
||||
|
||||
\newpage
|
||||
\section*{Список литературы}
|
||||
\addcontentsline{toc}{section}{Список литературы}
|
||||
|
||||
\vspace{-1.5cm}
|
||||
\begin{thebibliography}{0}
|
||||
\bibitem{JuicyPixels}
|
||||
Hackage -- QuickCheck: Automatic testing of Haskell programs, URL: \url{https://hackage.haskell.org/package/QuickCheck}, Дата обращения: 19.11.2024
|
||||
\end{thebibliography}
|
||||
\end{document}
|
||||
16
lab4/src/Lib.hs
Normal file
@@ -0,0 +1,16 @@
|
||||
module Lib
|
||||
( isCongruent,
|
||||
filterByPredicate
|
||||
) where
|
||||
|
||||
isCongruent :: Int -> Int -> Int -> Bool
|
||||
isCongruent a b d = a `mod` d == b `mod` d
|
||||
|
||||
|
||||
filterByPredicate :: (a -> Bool) -> [a] -> [a]
|
||||
filterByPredicate _ [] = []
|
||||
filterByPredicate predicate (x:xs)
|
||||
| predicate x = x : filteredTail
|
||||
| otherwise = filteredTail
|
||||
where
|
||||
filteredTail = filterByPredicate predicate xs
|
||||
67
lab4/stack.yaml
Normal file
@@ -0,0 +1,67 @@
|
||||
# This file was automatically generated by 'stack init'
|
||||
#
|
||||
# Some commonly used options have been documented as comments in this file.
|
||||
# For advanced use and comprehensive documentation of the format, please see:
|
||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||
|
||||
# A 'specific' Stackage snapshot or a compiler version.
|
||||
# A snapshot resolver dictates the compiler version and the set of packages
|
||||
# to be used for project dependencies. For example:
|
||||
#
|
||||
# snapshot: lts-22.28
|
||||
# snapshot: nightly-2024-07-05
|
||||
# snapshot: ghc-9.6.6
|
||||
#
|
||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||
#
|
||||
# snapshot: ./custom-snapshot.yaml
|
||||
# snapshot: https://example.com/snapshots/2024-01-01.yaml
|
||||
snapshot:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
|
||||
# User packages to be built.
|
||||
# Various formats can be used as shown in the example below.
|
||||
#
|
||||
# packages:
|
||||
# - some-directory
|
||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||
# subdirs:
|
||||
# - auto-update
|
||||
# - wai
|
||||
packages:
|
||||
- .
|
||||
# Dependency packages to be pulled from upstream that are not in the snapshot.
|
||||
# These entries can reference officially published versions as well as
|
||||
# forks / in-progress versions pinned to a git hash. For example:
|
||||
#
|
||||
# extra-deps:
|
||||
# - acme-missiles-0.3
|
||||
# - git: https://github.com/commercialhaskell/stack.git
|
||||
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||
#
|
||||
# extra-deps: []
|
||||
|
||||
# Override default flag values for project packages and extra-deps
|
||||
# flags: {}
|
||||
|
||||
# Extra package databases containing global packages
|
||||
# extra-package-dbs: []
|
||||
|
||||
# Control whether we use the GHC we find on the path
|
||||
# system-ghc: true
|
||||
#
|
||||
# Require a specific version of Stack, using version ranges
|
||||
# require-stack-version: -any # Default
|
||||
# require-stack-version: ">=3.1"
|
||||
#
|
||||
# Override the architecture used by Stack, especially useful on Windows
|
||||
# arch: i386
|
||||
# arch: x86_64
|
||||
#
|
||||
# Extra directories used by Stack for building
|
||||
# extra-include-dirs: [/path/to/dir]
|
||||
# extra-lib-dirs: [/path/to/dir]
|
||||
#
|
||||
# Allow a newer minor version of GHC than the snapshot specifies
|
||||
# compiler-check: newer-minor
|
||||
13
lab4/stack.yaml.lock
Normal file
@@ -0,0 +1,13 @@
|
||||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/lock_files
|
||||
|
||||
packages: []
|
||||
snapshots:
|
||||
- completed:
|
||||
sha256: 08bd13ce621b41a8f5e51456b38d5b46d7783ce114a50ab604d6bbab0d002146
|
||||
size: 720271
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
original:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
|
||||
BIN
lab4/task.jpg
Normal file
|
After Width: | Height: | Size: 162 KiB |
19
lab4/task.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Практическое задание 4. Тестирование в Haskell
|
||||
№ 12
|
||||
|
||||
Создать проект в stack. Функции записать в библиотеку Lib.hs и ограничить доступ к вспомогательным функциям. Тесты записать в Spec.hs.
|
||||
|
||||
Функция 1: Напишите функцию проверки равенства по модулю isCongruent :: Int -> Int -> Int -> Bool, которая проверяет, равны ли два числа по модулю третьего числа. Используя QuickCheck, проверьте следующие свойства:
|
||||
|
||||
1. Если два числа равны по модулю, то их разность делится на модуль:
|
||||
isCongruent a b m == (modulus (a - b) m == 0).
|
||||
2. Равенство по модулю является симметричным:
|
||||
isCongruent a b m == isCongruent b a m.
|
||||
3. Если одно число равно другому, то они равны по любому модулю:
|
||||
если a == b, то isCongruent a b m == True.
|
||||
|
||||
Функция 2: Напишите функцию filterByPredicate :: (a -> Bool) -> [a] -> [a], которая фильтрует элементы списка по заданному предикату. Используя QuickCheck, проверьте следующие свойства:
|
||||
|
||||
1. Все элементы результата удовлетворяют предикату: для каждого элемента x из результата должно выполняться условие: predicate x == True.
|
||||
2. Длина результата не превышает длину исходного списка: length (filterByPredicate predicate xs) <= length xs.
|
||||
3. Если предикат всегда возвращает True, то результат совпадает с исходным списком: если predicate x == True для всех x, то filterByPredicate predicate xs == xs.
|
||||
43
lab4/test/Spec.hs
Normal file
@@ -0,0 +1,43 @@
|
||||
import Test.QuickCheck
|
||||
import Lib
|
||||
|
||||
-- Если два числа равны по модулю, то их разность делится на модуль
|
||||
propCongruentDifference :: Int -> Int -> Int -> Property
|
||||
propCongruentDifference a b m =
|
||||
m /= 0 ==> isCongruent a b m == ((a - b) `mod` m == 0)
|
||||
|
||||
-- Равенство по модулю является симметричным
|
||||
propCongruentSymmetric :: Int -> Int -> Int -> Property
|
||||
propCongruentSymmetric a b m =
|
||||
m /= 0 ==> isCongruent a b m == isCongruent b a m
|
||||
|
||||
-- Если одно число равно другому, то они равны по любому модулю
|
||||
propCongruentEqualNumbers :: Int -> Int -> Property
|
||||
propCongruentEqualNumbers a m =
|
||||
m /= 0 ==> isCongruent a a m == True
|
||||
|
||||
|
||||
-- Все элементы результата удовлетворяют предикату
|
||||
propFilterByPredicateSatisfiesPredicate :: Fun Int Bool -> [Int] -> Bool
|
||||
propFilterByPredicateSatisfiesPredicate (Fun _ predicate) xs =
|
||||
all predicate (filterByPredicate predicate xs)
|
||||
|
||||
-- Длина результата не превышает длину исходного списка
|
||||
propFilterByPredicateLength :: Fun Int Bool -> [Int] -> Bool
|
||||
propFilterByPredicateLength (Fun _ predicate) xs =
|
||||
length (filterByPredicate predicate xs) <= length xs
|
||||
|
||||
-- Если предикат всегда возвращает True, то результат совпадает с исходным списком
|
||||
propFilterByPredicateAlwaysTrue :: [Int] -> Bool
|
||||
propFilterByPredicateAlwaysTrue xs =
|
||||
filterByPredicate (\_ -> True) xs == xs
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
quickCheck propCongruentDifference
|
||||
quickCheck propCongruentSymmetric
|
||||
quickCheck propCongruentEqualNumbers
|
||||
|
||||
quickCheck propFilterByPredicateSatisfiesPredicate
|
||||
quickCheck propFilterByPredicateLength
|
||||
quickCheck propFilterByPredicateAlwaysTrue
|
||||