[+] A4 Add starter files
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
\documentclass[fontsize=11pt]{article}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsthm}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[margin=0.75in]{geometry}
|
||||
|
||||
\title{CSC110 Assignment 4: Number Theory, Cryptography, and Algorithm Running Time}
|
||||
\author{TODO: FILL IN YOUR NAME HERE}
|
||||
\date{\today}
|
||||
|
||||
% Some useful LaTeX commands. You are free to use these or not, and also add your own.
|
||||
\newcommand{\N}{\mathbb{N}}
|
||||
\newcommand{\Z}{\mathbb{Z}}
|
||||
\newcommand{\R}{\mathbb{R}}
|
||||
\newcommand{\cO}{\mathcal{O}}
|
||||
\newcommand{\floor}[1]{\left\lfloor #1 \right\rfloor}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
\section*{Part 1: Practice with Proofs}
|
||||
|
||||
\begin{enumerate}
|
||||
|
||||
\item[1.] Statement to prove:
|
||||
|
||||
$$\forall a, k, n \in \Z,~ \gcd(a, n) = 1 \Rightarrow \gcd(a + kn, n) = 1$$
|
||||
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
|
||||
\item[2.] Statement to prove (we've expanded the definition of Omega for you!):
|
||||
|
||||
$$\exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \Rightarrow \log_{3} n - \log_{11} n \geq c \cdot \log_{14} n$$
|
||||
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
|
||||
\item[3.] Statement to prove (we haven't expanded the definition of Big-O for you, but we encourage you to do so yourself):
|
||||
|
||||
$$\forall f, g: \N \to \R^{\geq 0},~ g \in \cO(f) \land \big(\forall m \in \N,~ f(m) \geq 1 \big) \Rightarrow g \in \cO(\floor{f})$$
|
||||
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
\newpage
|
||||
|
||||
\section*{Part 2: Generating Coprime Numbers}
|
||||
|
||||
\begin{enumerate}
|
||||
|
||||
\item[1.]
|
||||
Not to be handed in.
|
||||
|
||||
\item[2.]
|
||||
Complete this part in the provided \texttt{a4\_part2.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\item[3.]
|
||||
Prove that each loop invariant holds.
|
||||
|
||||
\begin{enumerate}
|
||||
\item[a.] Loop Invariant 1
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
|
||||
\item[b.] Loop Invariant 2
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
|
||||
\item[c.] Loop Invariant 3
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
|
||||
\item[d.] Loop Invariant 4
|
||||
\begin{proof}
|
||||
TODO: Your proof goes here.
|
||||
\end{proof}
|
||||
\end{enumerate}
|
||||
|
||||
\item[4.]
|
||||
Complete this part in the provided \texttt{a4\_part2.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\item[5.]
|
||||
Complete this part in the provided \texttt{a4\_part2.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
\end{enumerate}
|
||||
|
||||
\newpage
|
||||
|
||||
\section*{Part 3: Running-Time Analysis}
|
||||
|
||||
\begin{enumerate}
|
||||
\item[1.]
|
||||
TODO: Running-time analysis of \texttt{coprime\_to\_2\_and\_3}.
|
||||
|
||||
\item[2.]
|
||||
TODO: Running-time analysis of \texttt{starting\_coprime\_numbers}.
|
||||
|
||||
\item[3.]
|
||||
TODO: Running-time analysis of \texttt{coprime\_to\_all}.
|
||||
\end{enumerate}
|
||||
|
||||
\section*{Part 4: Two New Cryptosystems}
|
||||
|
||||
Complete this part in the provided \texttt{a4\_part4.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,118 @@
|
||||
"""CSC110 Fall 2021 Assignment 4, Part 2: Generating coprime numbers
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
Implement each of the functions in this file. As usual, do not change any function headers
|
||||
or preconditions. You do NOT need to add doctests.
|
||||
|
||||
You may create additional helper functions to help break up your code into smaller parts.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
import math
|
||||
|
||||
|
||||
def coprime_to_2_and_3(n: int) -> list[int]:
|
||||
"""Return the natural numbers less than n that are coprime to both 2 and 3.
|
||||
|
||||
The returned list is sorted.
|
||||
|
||||
Preconditions:
|
||||
- n >= 6
|
||||
|
||||
>>> coprime_to_2_and_3(20)
|
||||
[1, 5, 7, 11, 13, 17, 19]
|
||||
|
||||
Implementation note: recall negative list indexing from Assignment 3.
|
||||
For all lists lst and integers i between 0 and len(lst) - 1 inclusive,
|
||||
lst[-i] == lst[len(lst) - i].
|
||||
"""
|
||||
nums_so_far = [1, 5]
|
||||
while nums_so_far[-2] + 6 < n:
|
||||
# Note: Write four assert statements here expressing the four loop invariants from the
|
||||
# assignment handout. These statements should be at the top of the loop body.
|
||||
|
||||
next_number = nums_so_far[-2] + 6
|
||||
list.append(nums_so_far, next_number)
|
||||
|
||||
return nums_so_far
|
||||
|
||||
|
||||
def coprime_to_all(primes: set[int], n: int) -> list[int]:
|
||||
"""Return the positive integers less than n that are coprime to every number in primes.
|
||||
|
||||
The returned list is sorted.
|
||||
|
||||
Pay attention to the preconditions, as they are designed to help simplify your work for this
|
||||
question.
|
||||
|
||||
Preconditions:
|
||||
- primes != set()
|
||||
- every element of primes is prime
|
||||
- n >= math.prod(primes)
|
||||
|
||||
>>> coprime_to_all({2, 3}, 20)
|
||||
[1, 5, 7, 11, 13, 17, 19]
|
||||
>>> coprime_to_all({2, 3, 7}, 50)
|
||||
[1, 5, 11, 13, 17, 19, 23, 25, 29, 31, 37, 41, 43, 47]
|
||||
|
||||
Implementation notes:
|
||||
- You MUST use the provided helper function starting_coprime_numbers in your implementation,
|
||||
and may NOT modify it (even though it is not as efficient as it could be!!).
|
||||
- You will find the math.prod function useful.
|
||||
"""
|
||||
|
||||
|
||||
def starting_coprime_numbers(primes: set[int]) -> list[int]:
|
||||
"""Return the numbers up to the product of the given primes that are coprime to all of them.
|
||||
|
||||
Note: the length of the returned list is is exactly equal to phi(math.prod(primes)), where
|
||||
phi is the Euler totient function.
|
||||
|
||||
Preconditions:
|
||||
- primes != set()
|
||||
- every element of primes is prime
|
||||
|
||||
>>> starting_coprime_numbers({2, 3})
|
||||
[1, 5]
|
||||
>>> starting_coprime_numbers({3, 11})
|
||||
[1, 2, 4, 5, 7, 8, 10, 13, 14, 16, 17, 19, 20, 23, 25, 26, 28, 29, 31, 32]
|
||||
"""
|
||||
nums_so_far = []
|
||||
m = math.prod(primes)
|
||||
|
||||
for k in range(1, m):
|
||||
is_coprime = True
|
||||
for p in primes:
|
||||
if k % p == 0:
|
||||
is_coprime = False
|
||||
if is_coprime:
|
||||
list.append(nums_so_far, k)
|
||||
|
||||
return nums_so_far
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# Leave this code uncommented when you submit your files.
|
||||
# import python_ta
|
||||
#
|
||||
# python_ta.check_all(config={
|
||||
# 'extra-imports': ['python_ta.contracts', 'math'],
|
||||
# 'max-line-length': 100,
|
||||
# 'disable': ['R1705', 'C0200']
|
||||
# })
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
@@ -0,0 +1,182 @@
|
||||
"""CSC110 Fall 2021 Assignment 4, Part 4: Two New Cryptosystems
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
Implement each of the functions in this file. As usual, do not change any function headers
|
||||
or preconditions. You do NOT need to add doctests.
|
||||
|
||||
You may create some additional helper functions to help break up your code into smaller parts.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
|
||||
|
||||
################################################################################
|
||||
# Task 1 - The Grid Transpose Cryptosystem
|
||||
################################################################################
|
||||
def grid_encrypt(k: int, plaintext: str) -> str:
|
||||
"""Encrypt the given plaintext using the grid cryptosystem.
|
||||
|
||||
Preconditions:
|
||||
- k >= 1
|
||||
- len(plaintext) % k == 0
|
||||
- plaintext != ''
|
||||
|
||||
>>> grid_encrypt(8, 'DAVID AND MARIO TEACH COMPUTER SCIENCE!!')
|
||||
'DDTMCA EPIVMAUEIACTNDRHEC I REAOC !N OS!'
|
||||
"""
|
||||
|
||||
|
||||
def grid_decrypt(k: int, ciphertext: str) -> str:
|
||||
"""Decrypt the given ciphertext using the grid cryptosystem.
|
||||
|
||||
Preconditions:
|
||||
- k >= 1
|
||||
- len(ciphertext) % k == 0
|
||||
- ciphertext != ''
|
||||
|
||||
>>> grid_decrypt(8, 'DDTMCA EPIVMAUEIACTNDRHEC I REAOC !N OS!')
|
||||
'DAVID AND MARIO TEACH COMPUTER SCIENCE!!'
|
||||
"""
|
||||
|
||||
|
||||
def plaintext_to_grid(k: int, plaintext: str) -> list[list[str]]:
|
||||
"""Return the grid with k columns from the given plaintext.
|
||||
|
||||
Preconditions:
|
||||
- k >= 1
|
||||
- len(plaintext) % k == 0
|
||||
- plaintext != ''
|
||||
"""
|
||||
|
||||
|
||||
def grid_to_ciphertext(grid: list[list[str]]) -> str:
|
||||
"""Return the ciphertext corresponding to the given grid.
|
||||
|
||||
Preconditions:
|
||||
- grid != []
|
||||
- grid[0] != []
|
||||
- all({len(row1) == len(row2) for row1 in grid for row2 in grid})
|
||||
"""
|
||||
|
||||
|
||||
def ciphertext_to_grid(k: int, ciphertext: str) -> list[list[str]]:
|
||||
"""Return the grid corresponding to the given ciphertext.
|
||||
|
||||
Note that this grid should be the one that is used to generate the ciphertext.
|
||||
|
||||
Preconditions:
|
||||
- k >= 1
|
||||
- len(ciphertext) % k == 0
|
||||
- ciphertext != ''
|
||||
"""
|
||||
|
||||
|
||||
def grid_to_plaintext(grid: list[list[str]]) -> str:
|
||||
"""Return the plaintext message corresponding to the given grid.
|
||||
|
||||
|
||||
Preconditions:
|
||||
- grid != []
|
||||
- grid[0] != []
|
||||
- all({len(row1) == len(row2) for row1 in grid for row2 in grid})
|
||||
"""
|
||||
|
||||
|
||||
################################################################################
|
||||
# Task 2 - Breaking The Grid Transpose Cryptosystem
|
||||
################################################################################
|
||||
def grid_break(ciphertext: str, candidates: set[str]) -> set[int]:
|
||||
"""Return the set of possible secret keys that decrypt the given ciphertext into a message
|
||||
that contains at least one of the candidate words.
|
||||
|
||||
>>> candidate_words = {'DAVID', 'MINE'}
|
||||
>>> grid_break('DDTMCA EPIVMAUEIACTNDRHEC I REAOC !N OS!', candidate_words) == {8, 10}
|
||||
True
|
||||
"""
|
||||
|
||||
|
||||
def run_example_break(ciphertext_file: str, candidates: set[str]) -> list[str]:
|
||||
"""Return a list of possible plaintexts for the ciphertext found in the given file.
|
||||
|
||||
Based on the A4 directory structure, you can call this function like this:
|
||||
>>> possible_plaintexts = run_example_break('ciphertexts/grid_ciphertext1.txt', {'climate'})
|
||||
"""
|
||||
with open(ciphertext_file, encoding='utf-8') as f:
|
||||
ciphertext = f.read()
|
||||
|
||||
# (Not to be handed in) Try completing this function by calling grid_break and returning a
|
||||
# list of the possible plaintext messages.
|
||||
|
||||
return [ciphertext] + list(candidates) # This is a dummy line, please replace it!
|
||||
|
||||
|
||||
################################################################################
|
||||
# Task 3 - The Permuted Grid Transpose Cryptosystem
|
||||
################################################################################
|
||||
def permutation_grid_encrypt(k: int, perm: list[int], plaintext: str) -> str:
|
||||
"""Encrypt the given plaintext using the grid cryptosystem.
|
||||
|
||||
Preconditions:
|
||||
- k >= 1
|
||||
- len(plaintext) % k == 0
|
||||
- sorted(perm) == list(range(0, k))
|
||||
- plaintext != ''
|
||||
|
||||
>>> permutation_grid_encrypt(8, [0, 1, 2, 3, 4, 5, 6, 7],
|
||||
... 'DAVID AND MARIO TEACH COMPUTER SCIENCE!!')
|
||||
'DDTMCA EPIVMAUEIACTNDRHEC I REAOC !N OS!'
|
||||
>>> permutation_grid_encrypt(8, [3, 2, 5, 0, 7, 1, 6, 4],
|
||||
... 'DAVID AND MARIO TEACH COMPUTER SCIENCE!!')
|
||||
'IACTNVMAUE I REDDTMCN OS!A EPIAOC !DRHEC'
|
||||
"""
|
||||
|
||||
|
||||
def permutation_grid_decrypt(k: int, perm: list[int], ciphertext: str) -> str:
|
||||
"""Return the grid corresponding to the given ciphertext.
|
||||
|
||||
Note that this grid should be the one that is used to generate the ciphertext.
|
||||
|
||||
Preconditions:
|
||||
- k >= 1
|
||||
- len(ciphertext) % k == 0
|
||||
- sorted(perm) == list(range(0, k))
|
||||
- ciphertext != ''
|
||||
|
||||
>>> permutation_grid_decrypt(8, [0, 1, 2, 3, 4, 5, 6, 7],
|
||||
... 'DDTMCA EPIVMAUEIACTNDRHEC I REAOC !N OS!')
|
||||
'DAVID AND MARIO TEACH COMPUTER SCIENCE!!'
|
||||
>>> permutation_grid_decrypt(8, [3, 2, 5, 0, 7, 1, 6, 4],
|
||||
... 'IACTNVMAUE I REDDTMCN OS!A EPIAOC !DRHEC')
|
||||
'DAVID AND MARIO TEACH COMPUTER SCIENCE!!'
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# Leave this code uncommented when you submit your files.
|
||||
#
|
||||
# import python_ta
|
||||
# python_ta.check_all(config={
|
||||
# 'extra-imports': ['python_ta.contracts'],
|
||||
# 'allowed-io': ['run_example_break'],
|
||||
# 'max-line-length': 100,
|
||||
# 'disable': ['R1705', 'C0200']
|
||||
# })
|
||||
|
||||
import python_ta.contracts
|
||||
python_ta.contracts.check_all_contracts()
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
@@ -0,0 +1 @@
|
||||
Ea hadc’rvlstai hnmo'carsetb eica tlne idrtm ahar ate-tet rachenhaadast n ,ogc fehw aihtntuhghmee a dtna h mtecoh iuravnobiturl guiohpzfota u tsteio nolhdnai .rso tfMeo onrtseyhtr.e g oyJlf ua osstutthr e iispncel e at cnhaleegit em l araatesbecto e uci6thv5 ae01ns,1g.0,e 07s(00 W 0aey rbeye ae sraaosrtu strt rchaieegb:rou e th methadtar pvktseio: n /bgv/e ecetrlnhyi e ms saebmtveaeegl.niln n acnvsyiaacnr.lgige aosotv fi/o oeftnv hsige dl ieamnnco cidEeaea/lrr) nt
|
||||
@@ -0,0 +1 @@
|
||||
Gavnst tlbeghswns ol i ooewbesuftuwaaa hpthl vler eadole fuedt cescfna rcv.lekraseue ic,lncsrl(mt idiur hasie elirtt crtntniteoe,rt gsp n eif:esc opesr :htnlstola/ah a smon/nerna sdcg itrhgs leev eal li nea dooomhvrnf bfnaaisdlpa gtsr orlsee oaawe er.annnedca,nlmdiril are miciimsenlantmcoaatalgeaer.d.k dt,egy ers e o Gsaoi aivhl nonccn/aaign hctedcseetaeef i srhnlnfoeb .egesebrrhE erecsseafp a te avfaathsrhkeesree/vai cteda)
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user