[+] 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