From f7ee06ba4dae8ecbd1e2b1d4567177b256b83a51 Mon Sep 17 00:00:00 2001 From: seven Date: Mon, 19 Jun 2023 23:23:43 +0800 Subject: [PATCH 01/33] feat: add new notes --- 01_hello/hello.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 01_hello/hello.py diff --git a/01_hello/hello.py b/01_hello/hello.py new file mode 100755 index 000000000..b0946d300 --- /dev/null +++ b/01_hello/hello.py @@ -0,0 +1,3 @@ +#! /usr/bin/python3 +# Purpose: Say hello +print("Hello, World!") From 835dd1fd9dfc2157c2594e2800afc24447710a77 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 30 Jun 2023 18:40:44 +0800 Subject: [PATCH 02/33] feat: add the program to PATH 1. as the execute program --- 01_hello/hello.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01_hello/hello.py b/01_hello/hello.py index b0946d300..6eaafbc01 100755 --- a/01_hello/hello.py +++ b/01_hello/hello.py @@ -1,3 +1,3 @@ -#! /usr/bin/python3 +#! /usr/bin/env python3 # Purpose: Say hello print("Hello, World!") From 6f233b62dd9c4c6e7f394cf94c8c05c4ef00719f Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 30 Jun 2023 18:49:43 +0800 Subject: [PATCH 03/33] feat(parameter): 1.7 add the parameter and help 1. use the Module argparse to read the argument and do sth. Including show the help message --- 01_hello/hello.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/01_hello/hello.py b/01_hello/hello.py index 6eaafbc01..a5064cd0a 100755 --- a/01_hello/hello.py +++ b/01_hello/hello.py @@ -1,3 +1,9 @@ #! /usr/bin/env python3 # Purpose: Say hello -print("Hello, World!") + +import argparse + +parser = argparse.ArgumentParser(description="Say hello") +parser.add_argument("name", help="Name to greet") +args = parser.parse_args() +print(f"Hello {args.name}!") From 14f8ac2f82407d6d673e85a782e434b0d787533a Mon Sep 17 00:00:00 2001 From: LJ117 <35555585+LJ117@users.noreply.github.com> Date: Sat, 1 Jul 2023 11:51:12 +0800 Subject: [PATCH 04/33] feat: add the optional parameters --- 01_hello/hello.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/01_hello/hello.py b/01_hello/hello.py index a5064cd0a..2415dcf51 100755 --- a/01_hello/hello.py +++ b/01_hello/hello.py @@ -4,6 +4,8 @@ import argparse parser = argparse.ArgumentParser(description="Say hello") -parser.add_argument("name", help="Name to greet") +parser.add_argument( + "-n", "--name", metavar="name", default="World", help="Name to greet" +) args = parser.parse_args() print(f"Hello {args.name}!") From 357b1d3801885faf23bca01611b94fa9e8fb1b37 Mon Sep 17 00:00:00 2001 From: LJ117 <35555585+LJ117@users.noreply.github.com> Date: Sat, 1 Jul 2023 12:22:20 +0800 Subject: [PATCH 05/33] feat: 1.9 pass the test --- 01_hello/hello.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01_hello/hello.py b/01_hello/hello.py index 2415dcf51..b1efbef8d 100755 --- a/01_hello/hello.py +++ b/01_hello/hello.py @@ -8,4 +8,4 @@ "-n", "--name", metavar="name", default="World", help="Name to greet" ) args = parser.parse_args() -print(f"Hello {args.name}!") +print(f"Hello, {args.name}!") From faeabf75affd921bf208d6d3b2b594c425942096 Mon Sep 17 00:00:00 2001 From: LJ117 <35555585+LJ117@users.noreply.github.com> Date: Sat, 1 Jul 2023 13:09:33 +0800 Subject: [PATCH 06/33] feat: 1.11 def the func and add comments --- 01_hello/hello.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/01_hello/hello.py b/01_hello/hello.py index b1efbef8d..acaec31a2 100755 --- a/01_hello/hello.py +++ b/01_hello/hello.py @@ -1,11 +1,27 @@ #! /usr/bin/env python3 -# Purpose: Say hello +""" +Author: Seven +Purpose: Say hello +""" import argparse -parser = argparse.ArgumentParser(description="Say hello") -parser.add_argument( - "-n", "--name", metavar="name", default="World", help="Name to greet" -) -args = parser.parse_args() -print(f"Hello, {args.name}!") + +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(): + """Make a jazz noise here""" + args = get_args() + print("Hello, " + args.name + "!") + + +if __name__ == "__main__": + main() From 94b489f5b7301d758d88ce39c09c16bb9cfcd430 Mon Sep 17 00:00:00 2001 From: LJ117 <35555585+LJ117@users.noreply.github.com> Date: Sat, 1 Jul 2023 13:46:48 +0800 Subject: [PATCH 07/33] feat: 1.13 use the bin/new.py to generate the code --- 01_hello/hello.py | 2 +- 01_hello/hello2.py | 74 +++++++++++++++++++++++++++++++++++++++++ bin/new.py | 82 ++++++++++++++++++++++++---------------------- 3 files changed, 118 insertions(+), 40 deletions(-) create mode 100644 01_hello/hello2.py diff --git a/01_hello/hello.py b/01_hello/hello.py index acaec31a2..cd1faf8f6 100755 --- a/01_hello/hello.py +++ b/01_hello/hello.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python3 +#!/usr/bin/env python3 """ Author: Seven Purpose: Say hello diff --git a/01_hello/hello2.py b/01_hello/hello2.py new file mode 100644 index 000000000..578c859b4 --- /dev/null +++ b/01_hello/hello2.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-01 +Purpose: Rock the Casbah +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Rock the Casbah", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("positional", metavar="str", help="A positional argument") + + parser.add_argument( + "-a", + "--arg", + help="A named string argument", + metavar="str", + type=str, + default="", + ) + + parser.add_argument( + "-i", + "--int", + help="A named integer argument", + metavar="int", + type=int, + default=0, + ) + + parser.add_argument( + "-f", + "--file", + help="A readable file", + metavar="FILE", + type=argparse.FileType("rt"), + default=None, + ) + + parser.add_argument("-o", "--on", help="A boolean flag", action="store_true") + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + str_arg = args.arg + int_arg = args.int + file_arg = args.file + flag_arg = args.on + pos_arg = args.positional + + print(f'str_arg = "{str_arg}"') + print(f'int_arg = "{int_arg}"') + print('file_arg = "{}"'.format(file_arg.name if file_arg else "")) + print(f'flag_arg = "{flag_arg}"') + print(f'positional = "{pos_arg}"') + + +# -------------------------------------------------- +if __name__ == "__main__": + main() diff --git a/bin/new.py b/bin/new.py index d8a3dcbf2..935c18601 100755 --- a/bin/new.py +++ b/bin/new.py @@ -29,41 +29,45 @@ def get_args() -> Args: """Get arguments""" parser = argparse.ArgumentParser( - description='Create Python argparse program', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) + description="Create Python argparse program", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) defaults = get_defaults() - username = os.getenv('USER') or 'Anonymous' - hostname = os.getenv('HOSTNAME') or 'localhost' - - parser.add_argument('program', help='Program name', type=str) - - parser.add_argument('-n', - '--name', - type=str, - default=defaults.get('name', username), - help='Name for docstring') - - parser.add_argument('-e', - '--email', - type=str, - default=defaults.get('email', f'{username}@{hostname}'), - help='Email for docstring') - - parser.add_argument('-p', - '--purpose', - type=str, - default=defaults.get('purpose', 'Rock the Casbah'), - help='Purpose for docstring') - - parser.add_argument('-f', - '--force', - help='Overwrite existing', - action='store_true') + username = os.getenv("USER") or "Anonymous" + hostname = os.getenv("HOSTNAME") or "localhost" + + parser.add_argument("program", help="Program name", type=str) + + parser.add_argument( + "-n", + "--name", + type=str, + default=defaults.get("name", username), + help="Name for docstring", + ) + + parser.add_argument( + "-e", + "--email", + type=str, + default=defaults.get("email", f"{username}@{hostname}"), + help="Email for docstring", + ) + + parser.add_argument( + "-p", + "--purpose", + type=str, + default=defaults.get("purpose", "Rock the Casbah"), + help="Purpose for docstring", + ) + + parser.add_argument("-f", "--force", help="Overwrite existing", action="store_true") args = parser.parse_args() - args.program = args.program.strip().replace('-', '_') + args.program = args.program.strip().replace("-", "_") if not args.program: parser.error(f'Not a usable filename "{args.program}"') @@ -80,20 +84,20 @@ def main() -> None: if os.path.isfile(program) and not args.overwrite: answer = input(f'"{program}" exists. Overwrite? [yN] ') - if not answer.lower().startswith('y'): - sys.exit('Will not overwrite. Bye!') + if not answer.lower().startswith("y"): + sys.exit("Will not overwrite. Bye!") - print(body(args), file=open(program, 'wt'), end='') + print(body(args), file=open(program, "wt"), end="") - if platform.system() != 'Windows': - subprocess.run(['chmod', '+x', program], check=True) + if platform.system() != "Windows": + subprocess.run(["chmod", "+x", program], check=True) print(f'Done, see new script "{program}."') # -------------------------------------------------- def body(args: Args) -> str: - """ The program template """ + """The program template""" today = str(date.today()) @@ -176,11 +180,11 @@ def main(): def get_defaults(): """Get defaults from ~/.new.py""" - rc = os.path.join(str(Path.home()), '.new.py') + rc = os.path.join(str(Path.home()), ".new.py") defaults = {} if os.path.isfile(rc): for line in open(rc): - match = re.match('([^=]+)=([^=]+)', line) + match = re.match("([^=]+)=([^=]+)", line) if match: key, val = map(str.strip, match.groups()) if key and val: @@ -190,5 +194,5 @@ def get_defaults(): # -------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": main() From 084a39ba84cd8217c614e64e2489f692ba4725ef Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Tue, 4 Jul 2023 18:10:54 +0800 Subject: [PATCH 08/33] feat: finished the ch 02 --- 02_crowsnest/crowsnest_finished.py | 38 +++++++++++++++++++++ 02_crowsnest/test.py | 53 ++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 02_crowsnest/crowsnest_finished.py diff --git a/02_crowsnest/crowsnest_finished.py b/02_crowsnest/crowsnest_finished.py new file mode 100644 index 000000000..79170e6a5 --- /dev/null +++ b/02_crowsnest/crowsnest_finished.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-04 +Purpose: Crow's Nest +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Crow's Nest -- choose the corrcet article", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("word", metavar="word", help="A word") + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + word = args.word + vowel = "aeiou" + article = "an" if word[0].lower() in vowel else "a" + print(f"Ahoy, Captain, {article} {word} off the larboard bow!") + + +# -------------------------------------------------- +if __name__ == "__main__": + main() diff --git a/02_crowsnest/test.py b/02_crowsnest/test.py index d4e25c6c7..13d18364c 100755 --- a/02_crowsnest/test.py +++ b/02_crowsnest/test.py @@ -4,15 +4,32 @@ import os from subprocess import getstatusoutput, getoutput -prg = './crowsnest.py' +prg = "./crowsnest.py" consonant_words = [ - 'brigantine', 'clipper', 'dreadnought', 'frigate', 'galleon', 'haddock', - 'junk', 'ketch', 'longboat', 'mullet', 'narwhal', 'porpoise', 'quay', - 'regatta', 'submarine', 'tanker', 'vessel', 'whale', 'xebec', 'yatch', - 'zebrafish' + "brigantine", + "clipper", + "dreadnought", + "frigate", + "galleon", + "haddock", + "junk", + "ketch", + "longboat", + "mullet", + "narwhal", + "porpoise", + "quay", + "regatta", + "submarine", + "tanker", + "vessel", + "whale", + "xebec", + "yatch", + "zebrafish", ] -vowel_words = ['aviso', 'eel', 'iceberg', 'octopus', 'upbound'] -template = 'Ahoy, Captain, {} {} off the larboard bow!' +vowel_words = ["aviso", "eel", "iceberg", "octopus", "upbound"] +template = "Ahoy, Captain, {} {} off the larboard bow!" # -------------------------------------------------- @@ -26,10 +43,10 @@ def test_exists(): def test_usage(): """usage""" - for flag in ['-h', '--help']: - rv, out = getstatusoutput(f'{prg} {flag}') + for flag in ["-h", "--help"]: + rv, out = getstatusoutput(f"{prg} {flag}") assert rv == 0 - assert out.lower().startswith('usage') + assert out.lower().startswith("usage") # -------------------------------------------------- @@ -37,8 +54,8 @@ def test_consonant(): """brigantine -> a brigantine""" for word in consonant_words: - out = getoutput(f'{prg} {word}') - assert out.strip() == template.format('a', word) + out = getoutput(f"{prg} {word}") + assert out.strip() == template.format("a", word) # -------------------------------------------------- @@ -46,8 +63,8 @@ def test_consonant_upper(): """brigantine -> a Brigatine""" for word in consonant_words: - out = getoutput(f'{prg} {word.title()}') - assert out.strip() == template.format('a', word.title()) + out = getoutput(f"{prg} {word.title()}") + assert out.strip() == template.format("a", word.title()) # -------------------------------------------------- @@ -55,8 +72,8 @@ def test_vowel(): """octopus -> an octopus""" for word in vowel_words: - out = getoutput(f'{prg} {word}') - assert out.strip() == template.format('an', word) + out = getoutput(f"{prg} {word}") + assert out.strip() == template.format("an", word) # -------------------------------------------------- @@ -64,5 +81,5 @@ def test_vowel_upper(): """octopus -> an Octopus""" for word in vowel_words: - out = getoutput(f'{prg} {word.upper()}') - assert out.strip() == template.format('an', word.upper()) + out = getoutput(f"{prg} {word.upper()}") + assert out.strip() == template.format("an", word.upper()) From 532afea9186578a2cf8d9b012f852fe6e3674776 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Wed, 5 Jul 2023 10:55:04 +0800 Subject: [PATCH 09/33] style(lf): format code with lf style --- 03_picnic/all_test.sh | 2 +- 03_picnic/solution.py | 27 +++++++++++---------------- 03_picnic/test.py | 31 ++++++++++++++++--------------- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/03_picnic/all_test.sh b/03_picnic/all_test.sh index 0ad9120c3..abb0dd043 100755 --- a/03_picnic/all_test.sh +++ b/03_picnic/all_test.sh @@ -4,7 +4,7 @@ set -eu -o pipefail PRG="picnic.py" for FILE in solution*.py; do - echo "==> ${FILE} <==" + echo "==> ${FILE} <==" cp "$FILE" "$PRG" make test done diff --git a/03_picnic/solution.py b/03_picnic/solution.py index 4ccc500fb..d92b914ec 100755 --- a/03_picnic/solution.py +++ b/03_picnic/solution.py @@ -9,18 +9,13 @@ def get_args(): """Get command-line arguments""" parser = argparse.ArgumentParser( - description='Picnic game', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) + description="Picnic game", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) - parser.add_argument('item', - metavar='str', - nargs='+', - help='Item(s) to bring') + parser.add_argument("item", metavar="str", nargs="+", help="Item(s) to bring") - parser.add_argument('-s', - '--sorted', - action='store_true', - help='Sort the items') + parser.add_argument("-s", "--sorted", action="store_true", help="Sort the items") return parser.parse_args() @@ -36,18 +31,18 @@ def main(): if args.sorted: items.sort() - bringing = '' + bringing = "" if num == 1: bringing = items[0] elif num == 2: - bringing = ' and '.join(items) + bringing = " and ".join(items) else: - items[-1] = 'and ' + items[-1] - bringing = ', '.join(items) + items[-1] = "and " + items[-1] + bringing = ", ".join(items) - print('You are bringing {}.'.format(bringing)) + print("You are bringing {}.".format(bringing)) # -------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/03_picnic/test.py b/03_picnic/test.py index 281fab552..1dbba3484 100755 --- a/03_picnic/test.py +++ b/03_picnic/test.py @@ -4,7 +4,7 @@ import os from subprocess import getoutput -prg = './picnic.py' +prg = "./picnic.py" # -------------------------------------------------- @@ -18,17 +18,17 @@ def test_exists(): def test_usage(): """usage""" - for flag in ['', '-h', '--help']: - out = getoutput(f'{prg} {flag}') - assert out.lower().startswith('usage') + for flag in ["", "-h", "--help"]: + out = getoutput(f"{prg} {flag}") + assert out.lower().startswith("usage") # -------------------------------------------------- def test_one(): """one item""" - out = getoutput(f'{prg} chips') - assert out.strip() == 'You are bringing chips.' + out = getoutput(f"{prg} chips") + assert out.strip() == "You are bringing chips." # -------------------------------------------------- @@ -36,7 +36,7 @@ def test_two(): """two items""" out = getoutput(f'{prg} soda "french fries"') - assert out.strip() == 'You are bringing soda and french fries.' + assert out.strip() == "You are bringing soda and french fries." # -------------------------------------------------- @@ -44,9 +44,10 @@ def test_more_than_two(): """more than two items""" arg = '"potato chips" coleslaw cupcakes "French silk pie"' - out = getoutput(f'{prg} {arg}') - expected = ('You are bringing potato chips, coleslaw, ' - 'cupcakes, and French silk pie.') + out = getoutput(f"{prg} {arg}") + expected = ( + "You are bringing potato chips, coleslaw, " "cupcakes, and French silk pie." + ) assert out.strip() == expected @@ -54,15 +55,15 @@ def test_more_than_two(): def test_two_sorted(): """two items sorted output""" - out = getoutput(f'{prg} -s soda candy') - assert out.strip() == 'You are bringing candy and soda.' + out = getoutput(f"{prg} -s soda candy") + assert out.strip() == "You are bringing candy and soda." # -------------------------------------------------- def test_more_than_two_sorted(): """more than two items sorted output""" - arg = 'bananas apples dates cherries' - out = getoutput(f'{prg} {arg} --sorted') - expected = ('You are bringing apples, bananas, cherries, and dates.') + arg = "bananas apples dates cherries" + out = getoutput(f"{prg} {arg} --sorted") + expected = "You are bringing apples, bananas, cherries, and dates." assert out.strip() == expected From f89c1aac68c350eb57f22b8967e9ffff1280d840 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Wed, 5 Jul 2023 11:01:43 +0800 Subject: [PATCH 10/33] feat(ignore): comment the default ignore files to make sure the code I wrote can be committed --- .gitignore | 40 +++++++++++++++++++-------------------- 02_crowsnest/crowsnest.py | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 02_crowsnest/crowsnest.py diff --git a/.gitignore b/.gitignore index 68ca39690..ef23d45b5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,23 +11,23 @@ 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 +# 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 100644 index 000000000..79170e6a5 --- /dev/null +++ b/02_crowsnest/crowsnest.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-04 +Purpose: Crow's Nest +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Crow's Nest -- choose the corrcet article", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("word", metavar="word", help="A word") + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + word = args.word + vowel = "aeiou" + article = "an" if word[0].lower() in vowel else "a" + print(f"Ahoy, Captain, {article} {word} off the larboard bow!") + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From bf3d1da86d8c030bcc86a76b7a96cc05a70be697 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Wed, 5 Jul 2023 15:27:11 +0800 Subject: [PATCH 11/33] feat(code): finished the ch03 list --- 03_picnic/picnic.py | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 03_picnic/picnic.py diff --git a/03_picnic/picnic.py b/03_picnic/picnic.py new file mode 100644 index 000000000..84d7f6e30 --- /dev/null +++ b/03_picnic/picnic.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +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="str", nargs="+", help="Item(s) to bring") + + parser.add_argument("-s", "--sorted", action="store_true", help="Sort the items") + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + items = args.item + num = len(items) + + if args.sorted: + items.sort() + + bringing = "" + if num == 1: + bringing = items[0] + elif num == 2: + bringing = " and ".join(items) + else: + items[-1] = "and " + items[-1] + bringing = ", ".join(items) + + print(f"You are bringing {bringing}.") + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 9eb3a3c7cc4af2533837bc5873ce35faffdd9136 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 7 Jul 2023 18:04:35 +0800 Subject: [PATCH 12/33] feat: finished the ch04 the use case about the dict attention: use the dict.get() ,its a safe way to get dict value --- 04_jump_the_five/jump.py | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 04_jump_the_five/jump.py diff --git a/04_jump_the_five/jump.py b/04_jump_the_five/jump.py new file mode 100644 index 000000000..640b3ac2d --- /dev/null +++ b/04_jump_the_five/jump.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-07 +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("text", metavar="str", help="Input text") + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + jumper = { + "1": "9", + "9": "1", + "2": "8", + "8": "2", + "3": "7", + "7": "3", + "4": "6", + "6": "4", + "5": "0", + "0": "5", + } + + for char in args.text: + print(jumper.get(char, char), end="") + + print() + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 1fd9e53f1bc3da38c67f4c61181e498d62c910a2 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Mon, 10 Jul 2023 15:02:16 +0800 Subject: [PATCH 13/33] feat: finished the chapter 05 1. work with files and STDOUT --- 05_howler/howler.py | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 05_howler/howler.py diff --git a/05_howler/howler.py b/05_howler/howler.py new file mode 100644 index 000000000..f869dda8d --- /dev/null +++ b/05_howler/howler.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-10 +Purpose: Howler (upper-cases input) +""" + +import argparse +import os +import io +import sys + + +# -------------------------------------------------- +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="", + ) + parser.add_argument( + "-e", + "--ee", + help="lowercase text", + metavar="bool", + type=bool, + default=False, + ) + + args = parser.parse_args() + + if os.path.isfile(args.text): + args.text = open(args.text) + else: + args.text = io.StringIO(args.text + "\n") + + return args + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + out_fh = open(args.outfile, "wt") if args.outfile else sys.stdout + + for line in args.text: + if args.ee: + out_fh.write(line.lower()) + else: + out_fh.write(line.upper()) + + out_fh.close() + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From ef370892cc6efdec7428ae774ecf6b9930ae20b8 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Tue, 11 Jul 2023 10:55:34 +0800 Subject: [PATCH 14/33] feat(code): feat: ch06 Words count 1. Reading files and STDIN 2. learn the default type of argparse 3. for loop nesting 4. nargs use --- 06_wc/wc.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 06_wc/wc.py diff --git a/06_wc/wc.py b/06_wc/wc.py new file mode 100644 index 000000000..d75d9e547 --- /dev/null +++ b/06_wc/wc.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-11 +Purpose: 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="*", # zero or more + default=[sys.stdin], + type=argparse.FileType("rt"), + help="Input file(s)", + ) + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + files = args.file + + # init the total count + total_lines, total_words, total_bytes = 0, 0, 0 + + for fh in files: + # init the fh count + 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_words += num_words + total_bytes += num_bytes + print(f"{num_lines:8}{num_words:8}{num_bytes:8} {fh.name}") + + if len(files) > 1: + print(f"{total_lines:8}{total_words:8}{total_bytes:8} total") + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 365a874a4141d7e9657017b23f6016ac0c1d92bd Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 14 Jul 2023 16:13:31 +0800 Subject: [PATCH 15/33] feat(code): finished the complete ch7 --- 07_gashlycrumb/gashlycrumb.py | 61 +++++++++++++++++++++++ 07_gashlycrumb/gashlycrumb_interactive.py | 29 ++++++----- 07_gashlycrumb/solution2_dict_comp.py | 33 ++++++------ 07_gashlycrumb/solution3_dict_get.py | 33 ++++++------ 4 files changed, 111 insertions(+), 45 deletions(-) create mode 100644 07_gashlycrumb/gashlycrumb.py diff --git a/07_gashlycrumb/gashlycrumb.py b/07_gashlycrumb/gashlycrumb.py new file mode 100644 index 000000000..278b3ac3e --- /dev/null +++ b/07_gashlycrumb/gashlycrumb.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-14 +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="+", type=str, 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(): + """Make a jazz noise here""" + + args = get_args() + + letterDict = dict() + file = args.file + for line in file: + # print(line, end="") + l_list = line.split() + letterDict[str(l_list[0]).upper()] = str(line).rstrip() + file.close() + + letters = args.letter + for letter in letters: + letter_key = str(letter).upper() + if letter_key in letterDict: + print(letterDict[letter_key]) + else: + print(f'I do not know "{letter}".') + + +# -------------------------------------------------- +if __name__ == "__main__": + main() diff --git a/07_gashlycrumb/gashlycrumb_interactive.py b/07_gashlycrumb/gashlycrumb_interactive.py index 6ed82c5ef..d1e269331 100755 --- a/07_gashlycrumb/gashlycrumb_interactive.py +++ b/07_gashlycrumb/gashlycrumb_interactive.py @@ -9,15 +9,18 @@ def get_args(): """get command-line arguments""" parser = argparse.ArgumentParser( - description='Interactive Gashlycrumb', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - - parser.add_argument('-f', - '--file', - help='Input file', - metavar='str', - type=argparse.FileType('r'), - default='gashlycrumb.txt') + description="Interactive Gashlycrumb", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument( + "-f", + "--file", + help="Input file", + metavar="str", + type=argparse.FileType("r"), + default="gashlycrumb.txt", + ) return parser.parse_args() @@ -30,15 +33,15 @@ def main(): lookup = {line[0]: line.rstrip() for line in args.file} while True: - letter = input('Please provide a letter [! to quit]: ') + letter = input("Please provide a letter [! to quit]: ") - if letter == '!': - print('Bye') + if letter == "!": + print("Bye") break print(lookup.get(letter.upper(), f'I do not know "{letter}".')) # -------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/07_gashlycrumb/solution2_dict_comp.py b/07_gashlycrumb/solution2_dict_comp.py index 39ea519a7..d4776f00b 100755 --- a/07_gashlycrumb/solution2_dict_comp.py +++ b/07_gashlycrumb/solution2_dict_comp.py @@ -9,21 +9,22 @@ def get_args(): """get command-line arguments""" parser = argparse.ArgumentParser( - description='Gashlycrumb', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - - parser.add_argument('letter', - help='Letter(s)', - metavar='letter', - nargs='+', - type=str) - - parser.add_argument('-f', - '--file', - help='Input file', - metavar='FILE', - type=argparse.FileType('r'), - default='gashlycrumb.txt') + description="Gashlycrumb", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument( + "letter", help="Letter(s)", metavar="letter", nargs="+", type=str + ) + + parser.add_argument( + "-f", + "--file", + help="Input file", + metavar="FILE", + type=argparse.FileType("r"), + default="gashlycrumb.txt", + ) return parser.parse_args() @@ -43,5 +44,5 @@ def main(): # -------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/07_gashlycrumb/solution3_dict_get.py b/07_gashlycrumb/solution3_dict_get.py index 6bea7d2c0..1c06db448 100755 --- a/07_gashlycrumb/solution3_dict_get.py +++ b/07_gashlycrumb/solution3_dict_get.py @@ -9,21 +9,22 @@ def get_args(): """get command-line arguments""" parser = argparse.ArgumentParser( - description='Gashlycrumb', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - - parser.add_argument('letter', - help='Letter(s)', - metavar='letter', - nargs='+', - type=str) - - parser.add_argument('-f', - '--file', - help='Input file', - metavar='FILE', - type=argparse.FileType('r'), - default='gashlycrumb.txt') + description="Gashlycrumb", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument( + "letter", help="Letter(s)", metavar="letter", nargs="+", type=str + ) + + parser.add_argument( + "-f", + "--file", + help="Input file", + metavar="FILE", + type=argparse.FileType("r"), + default="gashlycrumb.txt", + ) return parser.parse_args() @@ -40,5 +41,5 @@ def main(): # -------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": main() From bfbc31d6be0158acfc991dbba34de603ff3fb45f Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Mon, 17 Jul 2023 18:56:30 +0800 Subject: [PATCH 16/33] feat: finished the ch08 --- 08_apples_and_bananas/apples.py | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 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 100644 index 000000000..978c8a48e --- /dev/null +++ b/08_apples_and_bananas/apples.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-17 +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(s) allowed", + metavar="vowel", + type=str, + default="a", + choices=list("aeiou"), + ) + + args = parser.parse_args() + + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + text = args.text + vowel = args.vowel + new_text = list() + + for char in text: + if char in "aeiou": + new_text.append(vowel) + elif char in "AEIOU": + new_text.append(str(vowel).upper()) + else: + new_text.append(char) + + print("".join(new_text)) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From ce5543ec3ca411d16dbdd68a051c69d01ce63e47 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Tue, 18 Jul 2023 18:15:09 +0800 Subject: [PATCH 17/33] feat: init the abuse.py --- 09_abuse/abuse.py | 79 ++++++++++++++++++++++++++++++++++++++++++++ 09_abuse/solution.py | 53 ++++++++++++++--------------- 09_abuse/test.py | 28 ++++++++-------- 3 files changed, 120 insertions(+), 40 deletions(-) create mode 100644 09_abuse/abuse.py diff --git a/09_abuse/abuse.py b/09_abuse/abuse.py new file mode 100644 index 000000000..7b236f0b9 --- /dev/null +++ b/09_abuse/abuse.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-18 +Purpose: Heap abuse +""" + +import argparse + + +# -------------------------------------------------- +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=str, + ) + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + adjectives = args.adjectives + + insults = args.insults + + 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 + """.strip().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 + """.strip().split() + print(f"You {adjectives[0]}, {adjectives[1]} {nouns[3]}") + + +# -------------------------------------------------- +if __name__ == "__main__": + main() diff --git a/09_abuse/solution.py b/09_abuse/solution.py index c1801c4d5..e687805df 100755 --- a/09_abuse/solution.py +++ b/09_abuse/solution.py @@ -10,29 +10,30 @@ 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) + 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() @@ -68,10 +69,10 @@ def main(): """.strip().split() for _ in range(args.number): - adjs = ', '.join(random.sample(adjectives, k=args.adjectives)) - print(f'You {adjs} {random.choice(nouns)}!') + adjs = ", ".join(random.sample(adjectives, k=args.adjectives)) + print(f"You {adjs} {random.choice(nouns)}!") # -------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/09_abuse/test.py b/09_abuse/test.py index ff31fc90a..5ab496901 100755 --- a/09_abuse/test.py +++ b/09_abuse/test.py @@ -7,7 +7,7 @@ import string from subprocess import getstatusoutput, getoutput -prg = './abuse.py' +prg = "./abuse.py" # -------------------------------------------------- @@ -21,8 +21,8 @@ def test_exists(): def test_usage(): """usage""" - for flag in ['-h', '--help']: - rv, out = getstatusoutput(f'{prg} {flag}') + for flag in ["-h", "--help"]: + rv, out = getstatusoutput(f"{prg} {flag}") assert rv == 0 assert re.match("usage", out, re.IGNORECASE) @@ -32,7 +32,7 @@ def test_bad_adjective_str(): """bad_adjectives""" bad = random_string() - rv, out = getstatusoutput(f'{prg} -a {bad}') + rv, out = getstatusoutput(f"{prg} -a {bad}") assert rv != 0 assert re.search(f"invalid int value: '{bad}'", out) @@ -42,7 +42,7 @@ def test_bad_adjective_num(): """bad_adjectives""" n = random.choice(range(-10, 0)) - rv, out = getstatusoutput(f'{prg} -a {n}') + rv, out = getstatusoutput(f"{prg} -a {n}") print(out) assert rv != 0 assert re.search(f'--adjectives "{n}" must be > 0', out) @@ -53,7 +53,7 @@ def test_bad_number_str(): """bad_number""" bad = random_string() - rv, out = getstatusoutput(f'{prg} -n {bad}') + rv, out = getstatusoutput(f"{prg} -n {bad}") assert rv != 0 assert re.search(f"invalid int value: '{bad}'", out) @@ -63,7 +63,7 @@ def test_bad_number_int(): """bad_number""" n = random.choice(range(-10, 0)) - rv, out = getstatusoutput(f'{prg} -n {n}') + rv, out = getstatusoutput(f"{prg} -n {n}") assert rv != 0 assert re.search(f'--number "{n}" must be > 0', out) @@ -73,7 +73,7 @@ def test_bad_seed(): """bad seed""" bad = random_string() - rv, out = getstatusoutput(f'{prg} -s {bad}') + rv, out = getstatusoutput(f"{prg} -s {bad}") assert rv != 0 assert re.search(f"invalid int value: '{bad}'", out) @@ -82,15 +82,15 @@ def test_bad_seed(): def test_01(): """test""" - out = getoutput(f'{prg} -s 1 -n 1') - assert out.strip() == 'You filthsome, cullionly fiend!' + out = getoutput(f"{prg} -s 1 -n 1") + assert out.strip() == "You filthsome, cullionly fiend!" # -------------------------------------------------- def test_02(): """test""" - out = getoutput(f'{prg} --seed 2') + out = getoutput(f"{prg} --seed 2") expected = """ You corrupt, detestable beggar! You peevish, foolish gull! @@ -103,7 +103,7 @@ def test_02(): def test_03(): """test""" - out = getoutput(f'{prg} -s 3 -n 5 -a 1') + out = getoutput(f"{prg} -s 3 -n 5 -a 1") expected = """ You infected villain! You vile braggart! @@ -118,7 +118,7 @@ def test_03(): def test_04(): """test""" - out = getoutput(f'{prg} --seed 4 --number 2 --adjectives 4') + out = getoutput(f"{prg} --seed 4 --number 2 --adjectives 4") expected = """ You infected, lecherous, dishonest, rotten recreant! You filthy, detestable, cullionly, base lunatic! @@ -130,4 +130,4 @@ def test_04(): def random_string(): """generate a random filename""" - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=5)) + return "".join(random.choices(string.ascii_lowercase + string.digits, k=5)) From cb8cb3a047db1db683ec10428f6de554a2c0c50d Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Wed, 19 Jul 2023 11:29:44 +0800 Subject: [PATCH 18/33] feat: finished the ch09 1. the parser.error() use 2. Triple-quoted strings use demo 3. the random.sample() use and random.choice() --- 09_abuse/abuse.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/09_abuse/abuse.py b/09_abuse/abuse.py index 7b236f0b9..964ffefcf 100644 --- a/09_abuse/abuse.py +++ b/09_abuse/abuse.py @@ -6,6 +6,7 @@ """ import argparse +import random # -------------------------------------------------- @@ -40,9 +41,17 @@ def get_args(): "--seed", help="Random seed", metavar="seed", - type=str, + type=int, ) - return parser.parse_args() + args = parser.parse_args() + + # check the negative number + 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 # -------------------------------------------------- @@ -50,12 +59,9 @@ def main(): """Make a jazz noise here""" args = get_args() - - adjectives = args.adjectives - - insults = args.insults - - seed = args.seed + random.seed(args.seed) + adjective_num = args.adjectives + lines = args.number adjectives = """ bankrupt base caterwauling corrupt cullionly detestable dishonest false @@ -71,7 +77,14 @@ def main(): gull harpy jack jolthead knave liar lunatic maw milksop minion ratcatcher recreant rogue scold slave swine traitor varlet villain worm """.strip().split() - print(f"You {adjectives[0]}, {adjectives[1]} {nouns[3]}") + + # only range the number, so use '_' to disregard + for _ in range(lines): + insult = "You " + adj_list = random.sample(population=adjectives, k=adjective_num) + noun = random.choice(nouns) + insult = insult + ", ".join(adj_list) + print(f"{insult} {noun}!") # -------------------------------------------------- From 58cb3a8afd88d0b066fdb1d9c8a1b56a4228e071 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Thu, 20 Jul 2023 17:04:40 +0800 Subject: [PATCH 19/33] feat: finished ch10 1. the model string usage --- 10_telephone/telephone.py | 70 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 10_telephone/telephone.py diff --git a/10_telephone/telephone.py b/10_telephone/telephone.py new file mode 100644 index 000000000..4ec26038e --- /dev/null +++ b/10_telephone/telephone.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-20 +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", metavar="seed", help="Random seed", type=int, default=None + ) + + parser.add_argument( + "-m", + "--mutations", + help="Percent mutations", + metavar="mutations", + type=float, + default=0.1, + ) + + args = parser.parse_args() + + mutations = args.mutations + if not 0 <= mutations <= 1: + parser.error(f'--mutations "{mutations}" must be between 0 and 1') + + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + random.seed(args.seed) + text = args.text + alpha = "".join(sorted(string.ascii_letters + string.punctuation)) + len_text = len(text) + num_mutations = round(len_text * args.mutations) + new_text = list(text) + + for i in random.sample(range(len_text), num_mutations): + new_text[i] = random.choice(alpha.replace(new_text[i], "")) + + print(f'You said: "{text}"\nI heard : "{new_text}"') + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From c6371900d896bcb90cac87bc7f655791f3729d83 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 21 Jul 2023 14:59:53 +0800 Subject: [PATCH 20/33] feat: finished the ch11 1. learn how to do Test-driven development 2. --- 11_bottles_of_beer/bottles.py | 90 +++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 11_bottles_of_beer/bottles.py diff --git a/11_bottles_of_beer/bottles.py b/11_bottles_of_beer/bottles.py new file mode 100644 index 000000000..e2a0b7e90 --- /dev/null +++ b/11_bottles_of_beer/bottles.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-21 +Purpose: Bottle of beer song +""" + +import argparse + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Bottle of beer song", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument( + "-n", + "--num", + help="How many bottles", + metavar="number", + type=int, + default=10, + ) + + args = parser.parse_args() + + if args.num < 1: + parser.error(f'--num "{args.num}" must be greater than 0') + + return args + + +def verse(bottle): + """Sing a verse""" + next_bottle = bottle - 1 + s1 = "" if bottle == 1 else "s" + s2 = "" if next_bottle == 1 else "s" + num_text = "No more" if next_bottle == 0 else next_bottle + + return "\n".join( + [ + f"{bottle} bottle{s1} of beer on the wall,", + f"{bottle} bottle{s1} of beer,", + "Take one down, pass it around,", + f"{num_text} bottle{s2} of beer on the wall!", + ] + ) + + +def test_verse(): + """Test verse""" + + last_verse = verse(1) + assert last_verse == "\n".join( + [ + "1 bottle of beer on the wall,", + "1 bottle of beer,", + "Take one down, pass it around,", + "No more bottles of beer on the wall!", + ] + ) + + two_verse = verse(2) + assert two_verse == "\n".join( + [ + "2 bottles of beer on the wall,", + "2 bottles of beer,", + "Take one down, pass it around,", + "1 bottle of beer on the wall!", + ] + ) + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + int_arg = args.num + print("\n\n".join(map(verse, range(int_arg, 0, -1)))) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From e95996ff0f84ea4d655031409cf43ec75b4b5246 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Tue, 25 Jul 2023 11:16:01 +0800 Subject: [PATCH 21/33] feat: finished the ch12 the usage of random --- 12_ransom/ransom.py | 79 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 12_ransom/ransom.py diff --git a/12_ransom/ransom.py b/12_ransom/ransom.py new file mode 100644 index 000000000..3e80c2798 --- /dev/null +++ b/12_ransom/ransom.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-25 +Purpose: Ransom Note +""" + +import argparse +import os +import random + + +# -------------------------------------------------- + + +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Ransom Note", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("text", metavar="text", help="Input text or file") + + parser.add_argument( + "-s", "--seed", metavar="int", help="Random seed", type=int, default=None + ) + + args = parser.parse_args() + + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def choose(letter): + """Randomly choose an upper or lowercase letter to return""" + + # return str(letter).lower() if random.choice([True, False]) else str(letter).upper() + return letter.upper() if random.choice([0, 1]) else letter.lower() + + +# -------------------------------------------------- +def test_choose(): + state = random.getstate() + random.seed(1) + assert choose("a") == "a" + assert choose("b") == "b" + assert choose("c") == "C" + assert choose("d") == "d" + random.setstate(state) + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + random.seed(args.seed) + text = args.text + # way0 normal for loop + # ret = "" + # for t in text: + # ret += choose(t) + # print(ret) + + # way1 list comprehension + # print("".join([choose(t) for t in text])) + + # way2 map func + print("".join(map(choose, text))) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 43fa0240dc881618d30e160db99b5a82d6f4c6ab Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Wed, 26 Jul 2023 14:40:49 +0800 Subject: [PATCH 22/33] feat: finished the ch13 1. the argparse.FileType('wt) to indicate a writeable file 2. use pylint to check code if effect by the shadow --- 13_twelve_days/twelve_days.py | 125 ++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 13_twelve_days/twelve_days.py diff --git a/13_twelve_days/twelve_days.py b/13_twelve_days/twelve_days.py new file mode 100644 index 000000000..0da6b62c4 --- /dev/null +++ b/13_twelve_days/twelve_days.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-26 +Purpose: Twelve Days of Christmas +""" + +import argparse +import sys + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Twelve Days of Christmas", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument( + "-n", + "--num", + help="Number of days to sing", + metavar="days", + type=int, + default=12, + ) + + parser.add_argument( + "-o", + "--outfile", + help="Outfile", + metavar="FILE", + type=argparse.FileType(mode="wt", encoding="utf-8"), + default=sys.stdout, + ) + args = parser.parse_args() + if not 0 < args.num < 13: + parser.error(f'--num "{args.num}" must be between 1 and 12') + return args + + +# -------------------------------------------------- +def test_verse(): + """Test verse""" + day_one = "\n".join( + [ + "On the first day of Christmas,", + "My true love gave to me,", + "A partridge in a pear tree.", + ] + ) + + day_two = "\n".join( + [ + "On the second day of Christmas,", + "My true love gave to me,", + "Two turtle doves,", + "And a partridge in a pear tree.", + ] + ) + assert verse(1) == day_one + assert verse(2) == day_two + + +# -------------------------------------------------- +def verse(day): + """Generate the verse of Twelve Days""" + ordinal = { + 1: "first", + 2: "second", + 3: "third", + 4: "fourth", + 5: "fifth", + 6: "sixth", + 7: "seventh", + 8: "eighth", + 9: "ninth", + 10: "tenth", + 11: "eleventh", + 12: "twelfth", + } + gifts = [ + "A partridge in a pear tree.", + "Two turtle doves,", + "Three French hens,", + "Four calling birds,", + "Five gold rings,", + "Six geese a laying,", + "Seven swans a swimming,", + "Eight maids a milking,", + "Nine ladies dancing,", + "Ten lords a leaping,", + "Eleven pipers piping,", + "Twelve drummers drumming,", + ] + + ret = [f"On the {ordinal[day]} day of Christmas,", "My true love gave to me,"] + + send_gifts = list(reversed(gifts[:day])) + + if day > 1: + send_gifts[-1] = "And " + send_gifts[-1].lower() + + ret.extend(send_gifts) + return "\n".join(ret) + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + days = args.num + outfile = args.outfile + verses = [verse(day) for day in range(1, days + 1)] + + print("\n\n".join(verses), file=outfile) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 72e27a1f1c9099496f380649b96babb5cf1f2e3b Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Thu, 27 Jul 2023 18:17:44 +0800 Subject: [PATCH 23/33] feat: finished the ch14 1. the regular expression init 2. the filter func usage --- 14_rhymer/rhymer.py | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 14_rhymer/rhymer.py diff --git a/14_rhymer/rhymer.py b/14_rhymer/rhymer.py new file mode 100644 index 000000000..f321a9b1e --- /dev/null +++ b/14_rhymer/rhymer.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-27 +Purpose: Make rhyming "words" +""" + +import argparse +import re + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description='Make rhyming "words"', + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("word", metavar="word", type=str, help="A word to rhyme") + + return parser.parse_args() + + +# -------------------------------------------------- +def test_stemmer(): + """Test stemmer""" + assert stemmer("") == ("", "") + assert stemmer("cake") == ("c", "ake") + assert stemmer("chair") == ("ch", "air") + assert stemmer("APPLE") == ("", "apple") + assert stemmer("RDNZL") == ("rdnzl", "") + assert stemmer("123") == ("123", "") + + +import string + + +# -------------------------------------------------- +def stemmer(text): + """Return leading consonants (if any), and 'stem' of word""" + + text = text.lower() + + vowels = "aeiou" + consonants = "".join([c for c in string.ascii_lowercase if c not in vowels]) + + # pattern = f"([{consonants_pattern}]+)?([aeiou])(.*)" + pattern = "([" + consonants + "]+)?" "([" + vowels + "])" "(.*)" + match_res = re.match(pattern, text) + if match_res: + p1 = match_res.group(1) or "" + p2 = match_res.group(2) or "" + p3 = match_res.group(3) or "" + return (p1, p2 + p3) + else: + return (text, "") + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + prefixes = ( + list("bcdfghjklmnpqrstvwxyz") + + ( + "bl br ch cl cr dr fl fr gl gr pl pr sc " + "sh sk sl sm sn sp st sw th tr tw thw wh wr " + "sch scr shr sph spl spr squ str thr" + ).split() + ) + + word = args.word + start, reset = stemmer(word) + if reset: + print("\n".join(sorted(([p + reset for p in prefixes if p != start])))) + else: + print(f'Cannot rhyme "{word}"') + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From b1d56b3b1e08e1d6a422b23b8df1d647401861f7 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 28 Jul 2023 12:17:52 +0800 Subject: [PATCH 24/33] feat: init ch15 --- 15_kentucky_friar/friar.py | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 15_kentucky_friar/friar.py diff --git a/15_kentucky_friar/friar.py b/15_kentucky_friar/friar.py new file mode 100644 index 000000000..40ae880cc --- /dev/null +++ b/15_kentucky_friar/friar.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-07-28 +Purpose: Southern fry text +""" + +import argparse +import os +import re + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Southern fry text", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("text", metavar="text", help="Input text or file") + + args = parser.parse_args() + + if os.path.isfile(args.text): + with open(args.text, encoding="utf-8") as text_file: + args.text = text_file.read() + + return args + + +# -------------------------------------------------- +def stemmer(word): + """split words""" + pattern = "([aeiou]*)?(ing)(.*)" + match = re.match(pattern, word) + if match: + res1 = match.group(1) or "" + res2 = match.group(2) or "" + return (res1, res2) + else: + return (word, "") + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + pos_arg = args.text + + print(stemmer(pos_arg)) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 98777b18e608ac8ea43cf83b4ef4e8533259f8af Mon Sep 17 00:00:00 2001 From: LJ117 <35555585+LJ117@users.noreply.github.com> Date: Sun, 30 Jul 2023 22:43:50 +0800 Subject: [PATCH 25/33] feat: add some change of ch15 1. splitlines() to get the str list as result 2. the re.split() can be same as the str.split --- 15_kentucky_friar/friar.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/15_kentucky_friar/friar.py b/15_kentucky_friar/friar.py index 40ae880cc..10d3bf67b 100644 --- a/15_kentucky_friar/friar.py +++ b/15_kentucky_friar/friar.py @@ -25,7 +25,7 @@ def get_args(): if os.path.isfile(args.text): with open(args.text, encoding="utf-8") as text_file: - args.text = text_file.read() + args.text = text_file.read().rstrip() return args @@ -48,10 +48,8 @@ def main(): """Make a jazz noise here""" args = get_args() - - pos_arg = args.text - - print(stemmer(pos_arg)) + for line in str(args.text).splitlines(): + print(line.split()) # -------------------------------------------------- From 613e0ada5aff5c9cab0b8e9bd5ddc20768197dc7 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Mon, 31 Jul 2023 13:52:19 +0800 Subject: [PATCH 26/33] feat: finished the ch15 --- 15_kentucky_friar/friar.py | 43 +++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/15_kentucky_friar/friar.py b/15_kentucky_friar/friar.py index 10d3bf67b..23bfefbff 100644 --- a/15_kentucky_friar/friar.py +++ b/15_kentucky_friar/friar.py @@ -25,22 +25,37 @@ def get_args(): if os.path.isfile(args.text): with open(args.text, encoding="utf-8") as text_file: - args.text = text_file.read().rstrip() + args.text = text_file.read() return args # -------------------------------------------------- -def stemmer(word): - """split words""" - pattern = "([aeiou]*)?(ing)(.*)" - match = re.match(pattern, word) - if match: - res1 = match.group(1) or "" - res2 = match.group(2) or "" - return (res1, res2) - else: - return (word, "") +def test_fry(): + """Test the func fry()""" + assert fry("you") == "y'all" + assert fry("You") == "Y'all" + assert fry("fishing") == "fishin'" + assert fry("Aching") == "Achin'" + assert fry("swing") == "swing" + + +# -------------------------------------------------- +def fry(word): + """ + Drop the `g` fron `-ing` words, change `you` to `y'all` + """ + match_you = re.match("([Yy])ou$", word) + match_ing = re.search("(.+)ing$", word) + + if match_you: + return match_you.group(1) + "'all" + elif match_ing: + prefix = match_ing.group(1) + if re.search("[aeiouy]", prefix, re.IGNORECASE): + return prefix + "in'" + + return word # -------------------------------------------------- @@ -48,8 +63,12 @@ def main(): """Make a jazz noise here""" args = get_args() + + splitter = re.compile(r"(\W+)") + for line in str(args.text).splitlines(): - print(line.split()) + words = [fry(word) for word in splitter.split(line.rstrip())] + print("".join(words)) # -------------------------------------------------- From 41f519c73dd41b2779f72c0d644be5d00f92ca84 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Thu, 3 Aug 2023 11:35:53 +0800 Subject: [PATCH 27/33] feat: finished the ch16 --- 16_scrambler/scrambler.py | 106 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 16_scrambler/scrambler.py diff --git a/16_scrambler/scrambler.py b/16_scrambler/scrambler.py new file mode 100644 index 000000000..5dbf95fa4 --- /dev/null +++ b/16_scrambler/scrambler.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-08-02 +Purpose: Scramble the letters of words +""" + +import argparse +import os +import random +import re + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Scramble the letters of words", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("text", metavar="text", help="Input text or file") + + parser.add_argument( + "-s", + "--seed", + help="Random seed", + metavar="seed", + type=int, + default=None, + ) + + args = parser.parse_args() + + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def test_scramble(): + """ + Test the scrambler func + """ + state = random.getstate() + + random.seed(1) + + # assert scramble("a") == "a" + # assert scramble("ab") == "ab" + # assert scramble("abc") == "abc" + # assert scramble("abcd") == "acbd" + # assert scramble("abcde") == "acbde" + # assert scramble("abcdef") == "aecbdf" + # assert scramble("abcde'f") == "abcd'ef" + assert scramble("foobar") == "faobor" + + random.setstate(state) + + +# -------------------------------------------------- +def scramble(word): + """ + Scrambler a word: + 1. If the word is three characters or shorter, return the word unchanged + 2. Use a string slice to copy the characters, not including the first and last. + 3. Use the random.shuffle() method to mix up the letters in the middle. + 4. Return the new "word" by combining the first, middle, and last parts + """ + # re.match(r"\w+", word) 确保里面有character, 有字符可以用于交换; + # 换言之,空格或者换行符 直接原样返回 + if len(word) > 3 and re.match(r"\w+", word): + middle = list(word[1:-1]) + random.shuffle(middle) + word = word[0] + "".join(middle) + word[-1] + + return word + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + args = get_args() + + random.seed(args.seed) + + ret = [] + + splitter = re.compile("([a-zA-Z](?:[a-zA-Z']*[a-zA-Z])?)") + + # for line in args.text.splitlines(): + # ret_line = [] + # for word in splitter.split(line): + # ret_line.append(scramble(word)) + # ret.append("".join(ret_line)) + # print("\n".join(ret)) + + for line in str(args.text).splitlines(): + print("".join([scramble(word) for word in splitter.split(line)])) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 998e189daa5d032a3679f1dd265df73bb23fbc19 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Thu, 3 Aug 2023 11:40:22 +0800 Subject: [PATCH 28/33] feat: add a new solution 1. use the map() to solve this problem --- 16_scrambler/scrambler.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/16_scrambler/scrambler.py b/16_scrambler/scrambler.py index 5dbf95fa4..ec4c2124d 100644 --- a/16_scrambler/scrambler.py +++ b/16_scrambler/scrambler.py @@ -97,8 +97,11 @@ def main(): # ret.append("".join(ret_line)) # print("\n".join(ret)) + # for line in str(args.text).splitlines(): + # print("".join([scramble(word) for word in splitter.split(line)])) + for line in str(args.text).splitlines(): - print("".join([scramble(word) for word in splitter.split(line)])) + print("".join(map(scramble, splitter.split(line)))) # -------------------------------------------------- From ee1fe223afefa191fb5e6749c7728f2a79bcde40 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Mon, 7 Aug 2023 12:15:56 +0800 Subject: [PATCH 29/33] feat: finished the ch17 --- 17_mad_libs/mad.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 17_mad_libs/mad.py diff --git a/17_mad_libs/mad.py b/17_mad_libs/mad.py new file mode 100644 index 000000000..84428991f --- /dev/null +++ b/17_mad_libs/mad.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-08-07 +Purpose: Mad Libs +""" + +import argparse +import re +import sys +from pprint import pprint + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Mad Libs", formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "file", metavar="FILE", type=argparse.FileType("rt"), help="Input file" + ) + + parser.add_argument( + "-i", + "--inputs", + help="Inputs (for testing)", + metavar="input", + type=str, + nargs="*", + default=None, + ) + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + + inputs = args.inputs + text = args.file.read().rstrip() + filename = args.file.name + blanks = re.findall("(<(.*?)>)", text) + if not blanks: + sys.exit(f'"{filename}" has no placeholders.') + + tmpl = "Give me {} {}:" + for placeholder, pos in blanks: + article = "an" if pos.lower()[0] in "aeiou" else "a" + answer = inputs.pop(0) if inputs else input(tmpl.format(article, pos)) + text = re.sub(placeholder, answer, text, count=1) + + print(text) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From f0df3b679b2fb014bf77707dab0ef216a4949edb Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Fri, 11 Aug 2023 21:17:16 +0800 Subject: [PATCH 30/33] feat: init ch18 --- 18_gematria/gematria.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 18_gematria/gematria.py diff --git a/18_gematria/gematria.py b/18_gematria/gematria.py new file mode 100644 index 000000000..0c00a3d5e --- /dev/null +++ b/18_gematria/gematria.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +""" +Author : Me +Date : today +Purpose: Gematria +""" + +import argparse +import os + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Gematria", formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument("text", metavar="text", help="Inout text of file") + + args = parser.parse_args() + if os.path.isfile(args.text): + args.text = open(args.text).read().rstrip() + + return args + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + print(args.text) + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From 97ea64c67416223140a64cb2414cff7ad71ca579 Mon Sep 17 00:00:00 2001 From: seven Date: Fri, 11 Aug 2023 23:35:50 +0800 Subject: [PATCH 31/33] feat: finished ch18 --- 18_gematria/gematria.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) mode change 100644 => 100755 18_gematria/gematria.py diff --git a/18_gematria/gematria.py b/18_gematria/gematria.py old mode 100644 new mode 100755 index 0c00a3d5e..645019837 --- a/18_gematria/gematria.py +++ b/18_gematria/gematria.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 """ -Author : Me -Date : today +Author : seven +Date : 2023-08-11 Purpose: Gematria """ import argparse import os +import re +from functools import reduce # -------------------------------------------------- @@ -17,21 +19,48 @@ def get_args(): description="Gematria", formatter_class=argparse.ArgumentDefaultsHelpFormatter ) - parser.add_argument("text", metavar="text", help="Inout text of file") - + parser.add_argument("text", metavar="text", help="Input text of file") args = parser.parse_args() + if os.path.isfile(args.text): args.text = open(args.text).read().rstrip() return args +# -------------------------------------------------- +def word2num(word): + vals = map(ord, re.sub("[^a-zA-Z0-9]", "", word)) + + word_sum = sum(vals) + + return str(word_sum) + + +# -------------------------------------------------- +def test_word2num(): + """ + Test word2num + """ + assert word2num("a") == "97" + assert word2num("abc") == "294" + assert word2num("ab'c") == "294" + assert word2num("4a-b'c,") == "346" + + # -------------------------------------------------- def main(): """Make a jazz noise here""" args = get_args() - print(args.text) + # for line in str(args.text).splitlines(): + # print(" ".join(map(word2num, line.split()))) + + for line in str(args.text).splitlines(): + new_line = list() + for word in line.split(): + new_line.append(word2num(word)) + print(" ".join(new_line)) # -------------------------------------------------- From a0c61f4095706575b79ed3d31f4ca52fc7013bc1 Mon Sep 17 00:00:00 2001 From: seven-yoga14 Date: Wed, 16 Aug 2023 15:01:13 +0800 Subject: [PATCH 32/33] feat: init ch19 read at 19.1.2 --- 19_wod/wod.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 19_wod/wod.py diff --git a/19_wod/wod.py b/19_wod/wod.py new file mode 100644 index 000000000..a6f54a07c --- /dev/null +++ b/19_wod/wod.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +Author : seven +Date : 2023-08-16 +Purpose: Create Workout of (the) Day (WOD) +""" + +import argparse +import random + + +# -------------------------------------------------- +def get_args(): + """Get command-line arguments""" + + parser = argparse.ArgumentParser( + description="Create Workout of (the) Day (WOD)", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument( + "-f", + "--file", + help="CSV input file of exercises", + metavar="FILE", + type=argparse.FileType("rt"), + default="inputs/exercises.csv", + ) + + parser.add_argument( + "-s", + "--seed", + help="Random seed", + metavar="seed", + type=int, + default=None, + ) + + parser.add_argument( + "-n", + "--num", + help="Number of exercises", + metavar="exercises", + type=int, + default=4, + ) + + parser.add_argument("-e", "--easy", help="Halve the reps", default=False) + + return parser.parse_args() + + +# -------------------------------------------------- +def main(): + """Make a jazz noise here""" + + args = get_args() + str_arg = args.arg + int_arg = args.int + file_arg = args.file + flag_arg = args.on + pos_arg = args.positional + + print(f'str_arg = "{str_arg}"') + print(f'int_arg = "{int_arg}"') + print('file_arg = "{}"'.format(file_arg.name if file_arg else "")) + print(f'flag_arg = "{flag_arg}"') + print(f'positional = "{pos_arg}"') + + +# -------------------------------------------------- +if __name__ == "__main__": + main() From dcaa7457b70bed3226b41fe8954b1941b088278a Mon Sep 17 00:00:00 2001 From: LJ117 <35555585+LJ117@users.noreply.github.com> Date: Sat, 26 Aug 2023 16:32:20 +0800 Subject: [PATCH 33/33] feat: finished ch19 --- 19_wod/wod.py | 70 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/19_wod/wod.py b/19_wod/wod.py index a6f54a07c..a07d9c128 100644 --- a/19_wod/wod.py +++ b/19_wod/wod.py @@ -7,6 +7,11 @@ import argparse import random +import io +import csv +import re +from pprint import pprint +from tabulate import tabulate # -------------------------------------------------- @@ -45,27 +50,62 @@ def get_args(): default=4, ) - parser.add_argument("-e", "--easy", help="Halve the reps", default=False) + parser.add_argument("-e", "--easy", help="Halve the reps", action="store_true") + args = parser.parse_args() - return parser.parse_args() + if args.num < 1: + parser.error(f'--num "{args.num}" must be greater than 0') + + return args # -------------------------------------------------- -def main(): - """Make a jazz noise here""" +def test_read_csv(): + """ + Test the function read_csv() + """ + text = io.StringIO("exercise,reps\nBurpees,20-50\nSitups,40-100\n") + assert read_csv(text) == [("Burpees", 20, 50), ("Situps", 40, 100)] + +# -------------------------------------------------- +def read_digits(text): + pattern = r"(\d+)-(\d+)" + match = re.match(pattern, text) + if match: + low, hight = match.groups() + return int(low), int(hight) + return (0, 0) + + +# -------------------------------------------------- +def read_csv(fh): + """ + Read the CSV input + """ + reader = csv.DictReader(fh, delimiter=",") + exercise = list() + for row in reader: + name, reps = row["exercise"], row["reps"] + low, high = read_digits(reps) + exercise.append((name, low, high)) + return exercise + + +# -------------------------------------------------- +def main(): args = get_args() - str_arg = args.arg - int_arg = args.int - file_arg = args.file - flag_arg = args.on - pos_arg = args.positional - - print(f'str_arg = "{str_arg}"') - print(f'int_arg = "{int_arg}"') - print('file_arg = "{}"'.format(file_arg.name if file_arg else "")) - print(f'flag_arg = "{flag_arg}"') - print(f'positional = "{pos_arg}"') + random.seed(args.seed) + wod = [] + exercises = read_csv(args.file) + + for name, low, high in random.sample(exercises, k=args.num): + reps = random.randint(low, high) + if args.easy: + reps = int(reps / 2) + wod.append((name, reps)) + + print(tabulate(wod, headers=["Exercise", "Reps"])) # --------------------------------------------------