From a26d602c98c0ae36f992e2993a0c170410cd1ba9 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 09:52:22 +0200 Subject: [PATCH 01/13] Hello world --- 01_hello/hello.py | 32 ++++++++++++++++++++++++++++++++ NOTES.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100755 01_hello/hello.py create mode 100644 NOTES.md diff --git a/01_hello/hello.py b/01_hello/hello.py new file mode 100755 index 000000000..e52da0a24 --- /dev/null +++ b/01_hello/hello.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +""" +Author: Johan Runesson +Purpose: Say hello +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get the command-line arguments""" + parser = argparse.ArgumentParser(description='Say hello') + parser.add_argument('-n', + '--name', + metavar='name', + default='World', + help='Name to greet') + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + args = get_args() + + print('Hello, ' + args.name + '!') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() diff --git a/NOTES.md b/NOTES.md new file mode 100644 index 000000000..5a6cb908d --- /dev/null +++ b/NOTES.md @@ -0,0 +1,31 @@ +# Notes + +## Tools + +Run tests: + +``` +pytest -xv test.py +``` + +Run lint: + +``` +pylint hello.py +``` + +## Tricks + +Make executable: + +``` +chmod +x hello.py +``` + +Add to PATH: + +``` +mkdir ~/bin +cp 01_hello/hello.py ~/bin +PATH=~/bin:$PATH +``` From b3f5ede1d4a70960fd89e187def5f8df44cddc05 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 09:57:37 +0200 Subject: [PATCH 02/13] 01_hello: updating makefile --- 01_hello/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/01_hello/Makefile b/01_hello/Makefile index 1cbd24b42..37577a3d0 100644 --- a/01_hello/Makefile +++ b/01_hello/Makefile @@ -2,3 +2,6 @@ test: pytest -xv test.py + +lint: + pylint hello.py From 3cce0fe093effe03c9f1c8ff76eccd084a2b64a0 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 11:18:45 +0200 Subject: [PATCH 03/13] 02_crowsnest --- NOTES.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/NOTES.md b/NOTES.md index 5a6cb908d..91faf9008 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1,5 +1,9 @@ # Notes +## Links + +- https://docs.python.org/3/ + ## Tools Run tests: @@ -29,3 +33,32 @@ mkdir ~/bin cp 01_hello/hello.py ~/bin PATH=~/bin:$PATH ``` + +Get type of variable: + +``` +type(word) +``` + +Get character of string: + +``` +word = "hej" +word[0] # h +word[2] # j +word[-1] # j +word[:2] # he +``` + +Get length of string: + +``` +len('hej') # 3 +``` + +Get help in repl: + +```bash +python3 +help(str) +``` From 5efbc6cd79a5155f9cee250c7c9e23ea1645a0eb Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 13:10:40 +0200 Subject: [PATCH 04/13] 03_picnic --- 03_picnic/picnic.py.old | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 03_picnic/picnic.py.old diff --git a/03_picnic/picnic.py.old b/03_picnic/picnic.py.old new file mode 100755 index 000000000..9f8ac5ef9 --- /dev/null +++ b/03_picnic/picnic.py.old @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-03 +Purpose: Picnic game +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Picnic game', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('item', + metavar='item', + nargs='+', + help='Item(s) to bring') + + parser.add_argument('-s', + '--sorted', + action='store_true', + help='Sort the items') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + items = args.item + sorted = args.sorted + num = len(items) + + if sorted: + items.sort() + + if num > 1: + items.insert(-1, 'and') + + if num > 3: + last = items.pop(); + items = ', '.join(items) + ' ' + last + else: + items = ' '.join(items) + + print(f'You are bringing {items}.') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() From c0b92a0423ff0218e75985245efd07cbd751fd2b Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 13:11:04 +0200 Subject: [PATCH 05/13] 03_picnic --- 03_picnic/picnic.py.old | 58 ----------------------------------------- 1 file changed, 58 deletions(-) delete mode 100755 03_picnic/picnic.py.old diff --git a/03_picnic/picnic.py.old b/03_picnic/picnic.py.old deleted file mode 100755 index 9f8ac5ef9..000000000 --- a/03_picnic/picnic.py.old +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -""" -Author : Johan Runesson -Date : 2020-08-03 -Purpose: Picnic game -""" - -import argparse - - -# -------------------------------------------------- -def get_args(): - """Get command-line arguments""" - - parser = argparse.ArgumentParser( - description='Picnic game', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - - parser.add_argument('item', - metavar='item', - nargs='+', - help='Item(s) to bring') - - parser.add_argument('-s', - '--sorted', - action='store_true', - help='Sort the items') - - return parser.parse_args() - - -# -------------------------------------------------- -def main(): - """Start things up""" - - args = get_args() - items = args.item - sorted = args.sorted - num = len(items) - - if sorted: - items.sort() - - if num > 1: - items.insert(-1, 'and') - - if num > 3: - last = items.pop(); - items = ', '.join(items) + ' ' + last - else: - items = ' '.join(items) - - print(f'You are bringing {items}.') - - -# -------------------------------------------------- -if __name__ == '__main__': - main() From 197834f77a6e2891e876c868f36e3200479d509d Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 13:11:27 +0200 Subject: [PATCH 06/13] 03_picnic --- 03_picnic/picnic.py | 58 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 03_picnic/picnic.py diff --git a/03_picnic/picnic.py b/03_picnic/picnic.py new file mode 100755 index 000000000..9f8ac5ef9 --- /dev/null +++ b/03_picnic/picnic.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-03 +Purpose: Picnic game +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Picnic game', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('item', + metavar='item', + nargs='+', + help='Item(s) to bring') + + parser.add_argument('-s', + '--sorted', + action='store_true', + help='Sort the items') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + items = args.item + sorted = args.sorted + num = len(items) + + if sorted: + items.sort() + + if num > 1: + items.insert(-1, 'and') + + if num > 3: + last = items.pop(); + items = ', '.join(items) + ' ' + last + else: + items = ' '.join(items) + + print(f'You are bringing {items}.') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() From b412ce7ab50dea3daca163c7106536959f06789d Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Mon, 3 Aug 2020 13:39:37 +0200 Subject: [PATCH 07/13] 04_jump_the_five --- .gitignore | 20 --------------- 02_crowsnest/crowsnest.py | 37 +++++++++++++++++++++++++++ 04_jump_the_five/jump.py | 53 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 20 deletions(-) create mode 100755 02_crowsnest/crowsnest.py create mode 100755 04_jump_the_five/jump.py diff --git a/.gitignore b/.gitignore index 68ca39690..35db47f33 100644 --- a/.gitignore +++ b/.gitignore @@ -11,23 +11,3 @@ tex2pdf* .coverage .idea .vscode -02_crowsnest/crowsnest.py -03_picnic/picnic.py -04_jump_the_five/jump.py -05_howler/howler.py -06_wc/wc.py -07_gashlycrumb/gashlycrumb.py -08_apples_and_bananas/apples.py -09_abuse/abuse.py -10_telephone/telephone.py -11_bottles_of_beer/bottles.py -12_ransom/ransom.py -13_twelve_days/twelve_days.py -14_rhymer/rhymer.py -15_kentucky_friar/friar.py -16_scrambler/scrambler.py -17_mad_libs/mad.py -18_gematria/gematria.py -19_wod/wod.py -20_password/password.py -21_tictactoe/tictactoe.py diff --git a/02_crowsnest/crowsnest.py b/02_crowsnest/crowsnest.py new file mode 100755 index 000000000..58e0dabd3 --- /dev/null +++ b/02_crowsnest/crowsnest.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-03 +Purpose: Crow\'s Nest -- choose the correct article +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Crow\'s Nest -- choose the correct article', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('word', metavar='word', help='A word') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + word = args.word + article = 'an' if word[0].lower() in 'aeiou' else 'a' + + print(f'Ahoy, Captain, {article} {word} off the larboard bow!') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() diff --git a/04_jump_the_five/jump.py b/04_jump_the_five/jump.py new file mode 100755 index 000000000..9f41d9db6 --- /dev/null +++ b/04_jump_the_five/jump.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-03 +Purpose: Jump the Five +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Jump the Five', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('number', metavar='str', help='A number') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + number = args.number + + jumper = { + '1': '9', + '2': '8', + '3': '7', + '4': '6', + '5': '0', + '6': '4', + '7': '3', + '8': '2', + '9': '1', + '0': '5' + } + + for char in number: + print(jumper.get(char, char), end='') + print() # To get rid of the %-character at the end (not sure why it gets printed) + + # print(number.translate(number.maketrans(jumper))) + + +# -------------------------------------------------- +if __name__ == '__main__': + main() From 263e041eb862ab37f3a5b7b737afe15d4ab91e8f Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Tue, 4 Aug 2020 09:49:02 +0200 Subject: [PATCH 08/13] 05_howler --- 05_howler/README.md | 73 -------------------------------------------- 05_howler/hagrid.txt | 0 05_howler/howler.py | 60 ++++++++++++++++++++++++++++++++++++ 05_howler/test.txt | 1 + 05_howler/test2.txt | 1 + NOTES.md | 32 +++++++++++++++++++ out.txt | 2 ++ 7 files changed, 96 insertions(+), 73 deletions(-) create mode 100644 05_howler/hagrid.txt create mode 100755 05_howler/howler.py create mode 100644 05_howler/test.txt create mode 100644 05_howler/test2.txt create mode 100644 out.txt diff --git a/05_howler/README.md b/05_howler/README.md index 36bb0a24d..e69de29bb 100644 --- a/05_howler/README.md +++ b/05_howler/README.md @@ -1,73 +0,0 @@ -# Howler - -https://www.youtube.com/playlist?list=PLhOuww6rJJNNzo5zqtx0388myQkUKyrQz - -Write a program that uppercases the given text: - -``` -$ ./howler.py 'The quick brown fox jumps over the lazy dog.' -THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG. -``` - -If the text names a file, uppercase the contents of the file: - -``` -$ ./howler.py ../inputs/fox.txt -THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG. -``` - -If given no arguments, print a brief usage: - -``` -$ ./howler.py -usage: howler.py [-h] [-o str] str -howler.py: error: the following arguments are required: str -``` - -If the `-o` or `--outfile` option is present, write the output to the given file and print nothing: - -``` -$ ./howler.py ../inputs/fox.txt -o out.txt -``` - -There should now be an `out.txt` file with the contents: - -``` -$ cat out.txt -THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG. -``` - -Respond to `-h` or `--help` with a longer usage: - -``` -$ ./howler.py -h -usage: howler.py [-h] [-o str] str - -Howler (upper-cases input) - -positional arguments: - str Input string or file - -optional arguments: - -h, --help show this help message and exit - -o str, --outfile str - Output filename (default: ) -``` - -Run the test suite to ensure your program is working correctly: - -``` -$ make test -pytest -xv test.py -============================= test session starts ============================== -... -collected 5 items - -test.py::test_exists PASSED [ 20%] -test.py::test_usage PASSED [ 40%] -test.py::test_text_stdout PASSED [ 60%] -test.py::test_text_outfile PASSED [ 80%] -test.py::test_file PASSED [100%] - -============================== 5 passed in 0.40s =============================== -``` diff --git a/05_howler/hagrid.txt b/05_howler/hagrid.txt new file mode 100644 index 000000000..e69de29bb diff --git a/05_howler/howler.py b/05_howler/howler.py new file mode 100755 index 000000000..b2924ecb7 --- /dev/null +++ b/05_howler/howler.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-04 +Purpose: Howler (upper-cases input) +""" + +import argparse +import os + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Howler (upper-cases input)', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('text', + metavar='text', + type=str, + help='Input string or file') + + parser.add_argument('-o', + '--outfile', + help='Output filename', + metavar='str', + type=str, + default='') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + text = args.text + outfile = args.outfile + output = text.upper() + + # validate arguments inside get_args (see solution1.py) + if os.path.isfile(text): + fh_in = open(text) + output = fh_in.read().upper() + fh_in.close() + + if outfile: + fh_out = open(outfile, 'wt') + fh_out.write(output) + fh_out.close() + else: + print(output) + + +# -------------------------------------------------- +if __name__ == '__main__': + main() diff --git a/05_howler/test.txt b/05_howler/test.txt new file mode 100644 index 000000000..05b387ba1 --- /dev/null +++ b/05_howler/test.txt @@ -0,0 +1 @@ +hej hej he diff --git a/05_howler/test2.txt b/05_howler/test2.txt new file mode 100644 index 000000000..71f115934 --- /dev/null +++ b/05_howler/test2.txt @@ -0,0 +1 @@ +HEJ HEJ HE diff --git a/NOTES.md b/NOTES.md index 91faf9008..ebe90781d 100644 --- a/NOTES.md +++ b/NOTES.md @@ -62,3 +62,35 @@ Get help in repl: python3 help(str) ``` + +Read a file (reads the entire file into memory): + +``` +fh = open(text) +text = fh.read() +fh.close() +``` + +Read a file (without reading the entire file into memory): + +``` +fh = open(text) +for line in fh: + print(line.upper()) +fh.close() +``` + +Handle text that might be a file of a string: + +``` +if os.path.isfile(args.text): + args.text = open(args.text) +else: + args.text = io.StringIO(args.text + '\n') +``` + +Handle output to file if specified else to print: + +``` +out_fh = open(args.outfile, 'wt') if args.outfile else sys.stdout +``` diff --git a/out.txt b/out.txt new file mode 100644 index 000000000..1746bd0e2 --- /dev/null +++ b/out.txt @@ -0,0 +1,2 @@ +this is some text +this is some more text From 7ba3e749d9f1a5c28280518f429a98b1ef068087 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Tue, 4 Aug 2020 11:58:44 +0200 Subject: [PATCH 09/13] 06_wc --- 06_wc/wc.py | 1 + NOTES.md | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100755 06_wc/wc.py diff --git a/06_wc/wc.py b/06_wc/wc.py new file mode 100755 index 000000000..2fe6575e7 --- /dev/null +++ b/06_wc/wc.py @@ -0,0 +1 @@ +The quick brown fox jumps over the lazy dog. diff --git a/NOTES.md b/NOTES.md index ebe90781d..ec4ff9cab 100644 --- a/NOTES.md +++ b/NOTES.md @@ -4,6 +4,12 @@ - https://docs.python.org/3/ +## Tips + +- The nargs (number of arguments) option to argparse allows you to validate the number of arguments from the user. The asterisk ('*') means zero or more, whereas '+' means one or more. +- If you define an argument using type=argparse.FileType('rt'), argparse will validate that the user has provided a readable text file and will make the value available in your code as an open file handle. +- You can read and write from the standard in/out file handles by using sys.stdin and sys.stdout. + ## Tools Run tests: From 5ec7566a4770c0f6219069d1d90df5247ff588d6 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Tue, 4 Aug 2020 12:51:09 +0200 Subject: [PATCH 10/13] 07 --- 06_wc/wc.py | 53 ++++++++++++++++++++++++++++++++++- 07_gashlycrumb/gashlycrumb.py | 51 +++++++++++++++++++++++++++++++++ NOTES.md | 6 ++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100755 07_gashlycrumb/gashlycrumb.py diff --git a/06_wc/wc.py b/06_wc/wc.py index 2fe6575e7..c3b0f6a70 100755 --- a/06_wc/wc.py +++ b/06_wc/wc.py @@ -1 +1,52 @@ -The quick brown fox jumps over the lazy dog. +#!/usr/bin/env python3 +"""Emulate wc (word count)""" + +import argparse +import sys + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Emulate wc (word count)', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('file', + metavar='FILE', + nargs='*', + default=[sys.stdin], + type=argparse.FileType('rt'), + help='Input file(s)') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + + total_lines, total_bytes, total_words = 0, 0, 0 + for fh in args.file: + num_lines, num_words, num_bytes = 0, 0, 0 + for line in fh: + num_lines += 1 + num_bytes += len(line) + num_words += len(line.split()) + + total_lines += num_lines + total_bytes += num_bytes + total_words += num_words + + print(f'{num_lines:8}{num_words:8}{num_bytes:8} {fh.name}') + + if len(args.file) > 1: + print(f'{total_lines:8}{total_words:8}{total_bytes:8} total') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() diff --git a/07_gashlycrumb/gashlycrumb.py b/07_gashlycrumb/gashlycrumb.py new file mode 100755 index 000000000..4646aaa51 --- /dev/null +++ b/07_gashlycrumb/gashlycrumb.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-04 +Purpose: Gashlycrumb +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Gashlycrumb', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('letter', + metavar='letter', + nargs='+', + help='Letter(s)') + + parser.add_argument('-f', + '--file', + help='Input file', + metavar='FILE', + type=argparse.FileType('rt'), + default='gashlycrumb.txt') + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + dictionary = { line[0].lower(): line.rstrip() for line in args.file } + # dictionary = {} + + # for line in args.file: + # dictionary[line[0].lower()] = line.rstrip() + + for letter in args.letter: + print(dictionary.get(letter.lower(), f'I do not know "{letter}".')) + + +# -------------------------------------------------- +if __name__ == '__main__': + main() diff --git a/NOTES.md b/NOTES.md index ec4ff9cab..a747e1302 100644 --- a/NOTES.md +++ b/NOTES.md @@ -100,3 +100,9 @@ Handle output to file if specified else to print: ``` out_fh = open(args.outfile, 'wt') if args.outfile else sys.stdout ``` + +Create a dictionary with a loop: + +``` +lookup = { line[0].upper(): line.rstrip() for line in fh } +``` From e19386d2c986530d5bc05534b42aed7bd59c99a0 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Tue, 4 Aug 2020 13:45:17 +0200 Subject: [PATCH 11/13] 08_apples_and_bananas --- 08_apples_and_bananas/apples.py | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 08_apples_and_bananas/apples.py diff --git a/08_apples_and_bananas/apples.py b/08_apples_and_bananas/apples.py new file mode 100755 index 000000000..06cf9ac52 --- /dev/null +++ b/08_apples_and_bananas/apples.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-04 +Purpose: Apples and bananas +""" + +import argparse +import os + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Apples and bananas', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('text', metavar='text', help='Input text or file') + + parser.add_argument('-v', + '--vowel', + help='The vowel to substitute', + metavar='vowel', + type=str, + choices=list('aeiou'), + default='a') + + args = parser.parse_args() + + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + text = args.text + vowel = args.vowel + + new_text = text.translate(str.maketrans('aeiouAEIOU', vowel * 5 + vowel.upper() * 5)); + + print(new_text) + + +# -------------------------------------------------- +if __name__ == '__main__': + main() From 43dd30acc07fee90b9b8ddcbddb2dcd46b0cf824 Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Wed, 5 Aug 2020 11:30:50 +0200 Subject: [PATCH 12/13] 09_abuse --- 09_abuse/abuse.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100755 09_abuse/abuse.py diff --git a/09_abuse/abuse.py b/09_abuse/abuse.py new file mode 100755 index 000000000..0796d3184 --- /dev/null +++ b/09_abuse/abuse.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-04 +Purpose: Heap abuse +""" + +import argparse +import random + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Heap abuse', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('-a', + '--adjectives', + help='Number of adjectives', + metavar='adjectives', + type=int, + default=2) + + parser.add_argument('-n', + '--number', + help='Number of insults', + metavar='insults', + type=int, + default=3) + + parser.add_argument('-s', + '--seed', + help='Random seed', + metavar='seed', + type=int, + default=None) + + args = parser.parse_args() + + if args.adjectives < 1: + parser.error(f'--adjectives "{args.adjectives}" must be > 0') + + if args.number < 1: + parser.error(f'--number "{args.number}" must be > 0') + + return args + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + random.seed(args.seed) + + adjectives = ''' + bankrupt base caterwauling corrupt cullionly + detestable dishonest false filthsome filthy + foolish foul gross heedless indistinguishable + infected insatiate irksome lascivious lecherous + loathsome lubbery old peevish rascaly rotten + ruinous scurilous scurvy slanderous sodden-witted + thin-faced toad-spotted unmannered vile wall-eyed + '''.split() + + nouns = ''' + Judas Satan ape ass barbermonger beggar block boy + braggart butt carbuncle coward coxcomb cur dandy + degenerate fiend fishmonger fool gull harpy jack + jolthead knave liar lunatic maw milksop minion + ratcatcher recreant rogue scold slave swine traitor + varlet villain worm + '''.split() + + for _ in range(args.number): + adjective = ', '.join(random.sample(adjectives, k=args.adjectives)) + print(f'You {adjective} {random.choice(nouns)}!') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() From b0a30a2c5b7e1e68e83597e055fa8d6ee2d9edca Mon Sep 17 00:00:00 2001 From: Johan Runesson Date: Fri, 7 Aug 2020 12:59:45 +0200 Subject: [PATCH 13/13] 10_telephone --- 10_telephone/telephone.py | 73 +++++++++++++++++++++++++++++++++++++++ NOTES.md | 8 +++++ 2 files changed, 81 insertions(+) create mode 100755 10_telephone/telephone.py diff --git a/10_telephone/telephone.py b/10_telephone/telephone.py new file mode 100755 index 000000000..5f769df3f --- /dev/null +++ b/10_telephone/telephone.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +Author : Johan Runesson +Date : 2020-08-07 +Purpose: Telephone +""" + +import argparse +import os +import random +import string + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Telephone', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('text', metavar='text', help='Input text or file') + + parser.add_argument('-s', + '--seed', + help='Random seed', + metavar='int', + type=int, + default=None) + + parser.add_argument('-m', + '--mutations', + help='Percent mutations', + metavar='int', + type=float, + default=0.1) + + args = parser.parse_args() + + if args.mutations < 0 or args.mutations > 1: + parser.error(f'--mutations "{args.mutations}" must be between 0 and 1') + + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def main(): + """Start things up""" + + args = get_args() + text = args.text + random.seed(args.seed) + alpha = ''.join(sorted(string.ascii_letters + string.punctuation)) + num_mutations = round(len(text) * args.mutations) + indexes = random.sample(range(len(text)), num_mutations) + + for i in indexes: + new_char = random.choice(alpha.replace(text[i], '')) + text = text[:i] + new_char + text[i+1:] + # alpha2 = alpha.replace(text[i], '') + # text = text[:i] + random.choice(alpha2) + text[i+1:] + + + print(f'You said: "{args.text}"') + print(f'I heard : "{text}"') + + +# -------------------------------------------------- +if __name__ == '__main__': + main() diff --git a/NOTES.md b/NOTES.md index a747e1302..807a2b99f 100644 --- a/NOTES.md +++ b/NOTES.md @@ -106,3 +106,11 @@ Create a dictionary with a loop: ``` lookup = { line[0].upper(): line.rstrip() for line in fh } ``` + +Change characters in a string (non-deterministic) (good for speed and when working with large files: +``` +new_text = '' +for char in args.text: + new_text += random.choice(alpha) if random.random() <= args.mutations else char +print(new_text) +```