-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
42 changed files
with
1,545 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from cs50 import get_string | ||
from sys import argv | ||
|
||
|
||
def main(): | ||
if len(argv) != 2: | ||
print("Usage: python bleep.py dictionary") | ||
exit(1) | ||
|
||
file = open(argv[1]) | ||
banned_words = set() | ||
|
||
for line in file: | ||
banned_words.add(line.strip().lower()) | ||
|
||
input_str = get_string("What message would you like to censor?\n") | ||
output_str = "" | ||
|
||
words = input_str.split() | ||
|
||
for word in words: | ||
if word.lower() in banned_words: | ||
output_str += "*" * len(word) + " " | ||
else: | ||
output_str += word + " " | ||
|
||
print(output_str + "\n") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from cs50 import get_string | ||
from sys import argv | ||
|
||
|
||
def main(): | ||
# Check to see that only one argument is given after ./caesar | ||
if len(argv) != 2: | ||
print("Usage ./caesar k") | ||
exit(1) | ||
|
||
# Prompt user for a plaintext | ||
plaintext = get_string("plaintext: ") | ||
|
||
# Ciphertext string to append to after converting the plaintext | ||
ciphertext = '' | ||
|
||
# Convert string to integer of key e.g. "5" to 5 | ||
key = int(argv[1]) | ||
|
||
# For each character in plaintext string, check if it is an alphabet while preserving case and shift by key | ||
for i in plaintext: | ||
if i.isalpha(): | ||
if i.isupper(): | ||
alphabet = ord(i) + key % 26 | ||
if alphabet > ord('Z'): | ||
alphabet -= 26 | ||
ciphertext += chr(alphabet) | ||
else: | ||
alphabet = ord(i) + key % 26 | ||
if alphabet > ord('z'): | ||
alphabet -= 26 | ||
ciphertext += chr(alphabet) | ||
else: | ||
ciphertext += i | ||
|
||
print("ciphertext: " + ciphertext) | ||
return 0 | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from cs50 import get_float | ||
|
||
|
||
def main(): | ||
|
||
# Prompt user for an amount of change | ||
while True: | ||
change = get_float("Change owed: ") | ||
if change > 0: | ||
break | ||
|
||
coin = 0 | ||
|
||
# Convert dollar to cents | ||
amount = round(change * 100) | ||
|
||
if amount % 25 != amount: | ||
coin += amount // 25 | ||
amount = amount % 25 | ||
|
||
# Check how many dimes fit in change | ||
if amount % 10 != amount: | ||
coin += amount // 10 | ||
amount = amount % 10 | ||
|
||
# Check how many nickels fit in change | ||
if amount % 5 != amount: | ||
coin += amount // 5 | ||
amount = amount % 5 | ||
|
||
# Check how many pennies fit in change | ||
if amount % 1 != amount: | ||
coin += amount // 1 | ||
amount = amount % 1 | ||
|
||
print(coin) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Prints "hello, world" | ||
|
||
name = input("Enter your name: ") | ||
|
||
print(name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from cs50 import get_int | ||
|
||
|
||
def main(): | ||
|
||
# Prompt user to enter a number between 0 and 23 | ||
while True: | ||
height = get_int("Height: ") | ||
if height > 0 and height < 9: | ||
break | ||
|
||
spaces = height - 1 | ||
blocks = 1 | ||
|
||
# Print the rows | ||
for i in range(height): | ||
|
||
# Print the spaces | ||
for j in range(spaces): | ||
print(" ", end='') | ||
|
||
# Print the blocks | ||
for k in range(blocks): | ||
print("#", end='') | ||
|
||
spaces -= 1 | ||
blocks += 1 | ||
print(" ", end='') | ||
|
||
# Print the blocks | ||
for k in range(blocks - 1): | ||
print("#", end='') | ||
|
||
print() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import cs50 | ||
import re | ||
from flask import Flask, abort, redirect, render_template, request | ||
from html import escape | ||
from werkzeug.exceptions import default_exceptions, HTTPException | ||
|
||
from helpers import lines, sentences, substrings | ||
|
||
# Web app | ||
app = Flask(__name__) | ||
|
||
|
||
@app.after_request | ||
def after_request(response): | ||
"""Disable caching""" | ||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" | ||
response.headers["Expires"] = 0 | ||
response.headers["Pragma"] = "no-cache" | ||
return response | ||
|
||
|
||
@app.route("/") | ||
def index(): | ||
"""Handle requests for / via GET (and POST)""" | ||
return render_template("index.html") | ||
|
||
|
||
@app.route("/compare", methods=["POST"]) | ||
def compare(): | ||
"""Handle requests for /compare via POST""" | ||
|
||
# Read files | ||
if not request.files["file1"] or not request.files["file2"]: | ||
abort(400, "missing file") | ||
try: | ||
file1 = request.files["file1"].read().decode("utf-8") | ||
file2 = request.files["file2"].read().decode("utf-8") | ||
except Exception: | ||
abort(400, "invalid file") | ||
|
||
# Compare files | ||
if not request.form.get("algorithm"): | ||
abort(400, "missing algorithm") | ||
elif request.form.get("algorithm") == "lines": | ||
regexes = [f"^{re.escape(match)}$" for match in lines(file1, file2)] | ||
elif request.form.get("algorithm") == "sentences": | ||
regexes = [re.escape(match) for match in sentences(file1, file2)] | ||
elif request.form.get("algorithm") == "substrings": | ||
if not request.form.get("length"): | ||
abort(400, "missing length") | ||
elif not int(request.form.get("length")) > 0: | ||
abort(400, "invalid length") | ||
regexes = [re.escape(match) for match in substrings( | ||
file1, file2, int(request.form.get("length")))] | ||
else: | ||
abort(400, "invalid algorithm") | ||
|
||
# Highlight files | ||
highlights1 = highlight(file1, regexes) | ||
highlights2 = highlight(file2, regexes) | ||
|
||
# Output comparison | ||
return render_template("compare.html", file1=highlights1, file2=highlights2) | ||
|
||
|
||
def highlight(s, regexes): | ||
"""Highlight all instances of regexes in s.""" | ||
|
||
# Get intervals for which strings match | ||
intervals = [] | ||
for regex in regexes: | ||
if not regex: | ||
continue | ||
matches = re.finditer(regex, s, re.MULTILINE) | ||
for match in matches: | ||
intervals.append((match.start(), match.end())) | ||
intervals.sort(key=lambda x: x[0]) | ||
|
||
# Combine intervals to get highlighted areas | ||
highlights = [] | ||
for interval in intervals: | ||
if not highlights: | ||
highlights.append(interval) | ||
continue | ||
last = highlights[-1] | ||
|
||
# If intervals overlap, then merge them | ||
if interval[0] <= last[1]: | ||
new_interval = (last[0], interval[1]) | ||
highlights[-1] = new_interval | ||
|
||
# Else, start a new highlight | ||
else: | ||
highlights.append(interval) | ||
|
||
# Maintain list of regions: each is a start index, end index, highlight | ||
regions = [] | ||
|
||
# If no highlights at all, then keep nothing highlighted | ||
if not highlights: | ||
regions = [(0, len(s), False)] | ||
|
||
# If first region is not highlighted, designate it as such | ||
elif highlights[0][0] != 0: | ||
regions = [(0, highlights[0][0], False)] | ||
|
||
# Loop through all highlights and add regions | ||
for start, end in highlights: | ||
if start != 0: | ||
prev_end = regions[-1][1] | ||
if start != prev_end: | ||
regions.append((prev_end, start, False)) | ||
regions.append((start, end, True)) | ||
|
||
# Add final unhighlighted region if necessary | ||
if regions[-1][1] != len(s): | ||
regions.append((regions[-1][1], len(s), False)) | ||
|
||
# Combine regions into final result | ||
result = "" | ||
for start, end, highlighted in regions: | ||
escaped = escape(s[start:end]) | ||
if highlighted: | ||
result += f"<span>{escaped}</span>" | ||
else: | ||
result += escaped | ||
return result | ||
|
||
|
||
@app.errorhandler(HTTPException) | ||
def errorhandler(error): | ||
"""Handle errors""" | ||
return render_template("error.html", error=error), error.code | ||
|
||
|
||
# https://github.com/pallets/flask/pull/2314 | ||
for code in default_exceptions: | ||
app.errorhandler(code)(errorhandler) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import re | ||
import sys | ||
|
||
from helpers import lines, sentences, substrings | ||
|
||
|
||
def main(): | ||
|
||
# Parse command-line arguments | ||
parser = argparse.ArgumentParser() | ||
group = parser.add_mutually_exclusive_group(required=True) | ||
group.add_argument("--lines", action="store_true", help="compare lines") | ||
group.add_argument("--sentences", action="store_true", help="compare sentences") | ||
group.add_argument("--substrings", metavar="N", type=positive, | ||
help="compare substrings of length N") | ||
parser.add_argument("FILE1", help="file to compare") | ||
parser.add_argument("FILE2", help="file to compare") | ||
args = vars(parser.parse_args()) | ||
|
||
# Read files | ||
try: | ||
with open(args["FILE1"], "r") as file: | ||
file1 = file.read() | ||
except IOError: | ||
sys.exit(f"Could not read {args['FILE1']}") | ||
try: | ||
with open(args["FILE2"], "r") as file: | ||
file2 = file.read() | ||
except IOError: | ||
sys.exit(f"Could not read {args['FILE2']}") | ||
|
||
# Compare files | ||
if args["lines"]: | ||
matches = lines(file1, file2) | ||
elif args["sentences"]: | ||
matches = sentences(file1, file2) | ||
elif args["substrings"]: | ||
matches = substrings(file1, file2, args["substrings"]) | ||
|
||
# Output matches, sorted from longest to shortest, with line endings escaped | ||
for match in sorted(matches, key=len, reverse=True): | ||
print(match.replace("\n", "\\n").replace("\r", "\\r")) | ||
|
||
|
||
def positive(string): | ||
"""Convert string to a positive integer.""" | ||
value = int(string) | ||
if value <= 0: | ||
raise argparse.ArgumentTypeError("invalid length") | ||
return value | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
from nltk.tokenize import sent_tokenize | ||
|
||
|
||
def lines(a, b): | ||
"""Return lines in both a and b""" | ||
|
||
a_lines = a.split('\n') | ||
b_lines = b.split('\n') | ||
both = set(a_lines).intersection(b_lines) | ||
return both | ||
|
||
|
||
def sentences(a, b): | ||
"""Return sentences in both a and b""" | ||
|
||
a_sentences = sent_tokenize(a) | ||
b_sentences = sent_tokenize(b) | ||
both = set(a_sentences).intersection(b_sentences) | ||
return both | ||
|
||
|
||
def substrings(a, b, n): | ||
"""Return substrings of length n in both a and b""" | ||
|
||
a_substrings = substringTokenize(a, n) | ||
b_substrings = substringTokenize(b, n) | ||
both = set(a_substrings).intersection(b_substrings) | ||
return both | ||
|
||
|
||
def substringTokenize(x, n): | ||
"""Return the substrings of a given string based on length provided""" | ||
|
||
len_str = len(x) | ||
result = set() | ||
count = 0 | ||
for i in range(len(x) - n + 1): | ||
result.add(x[i:i + n]) | ||
return result |
Oops, something went wrong.