From 5f2d5fb86c990b469f8555e26e6b8bd79d32b64e Mon Sep 17 00:00:00 2001 From: zevav Date: Thu, 11 Jun 2020 10:56:27 +0200 Subject: [PATCH] first --- .gitignore | 140 ++++++++++++++++++++++++++++++++++++++ Pipfile | 12 ++++ Pipfile.lock | 100 +++++++++++++++++++++++++++ README.md | 27 ++++++++ app/__init__.py | 0 app/check.py | 3 + app/config.py | 1 + app/generate.py | 15 ++++ app/main.py | 27 ++++++++ app/test/test_generate.py | 29 ++++++++ setup.py | 26 +++++++ 11 files changed, 380 insertions(+) create mode 100644 .gitignore create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 README.md create mode 100644 app/__init__.py create mode 100644 app/check.py create mode 100644 app/config.py create mode 100644 app/generate.py create mode 100755 app/main.py create mode 100644 app/test/test_generate.py create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ac6e56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,140 @@ +.idea/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..982a13e --- /dev/null +++ b/Pipfile @@ -0,0 +1,12 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +pytest = "*" + +[requires] +python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..8649223 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,100 @@ +{ + "_meta": { + "hash": { + "sha256": "828b8ad012f4c8773e6e61e3ac2be0ffcd7540fd7ed175a8355676c8e31c4d3d" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "version": "==19.3.0" + }, + "importlib-metadata": { + "hashes": [ + "sha256:0505dd08068cfec00f53a74a0ad927676d7757da81b7436a6eefe4c7cf75c545", + "sha256:15ec6c0fd909e893e3a08b3a7c76ecb149122fb14b7efe1199ddd4c7c57ea958" + ], + "markers": "python_version < '3.8'", + "version": "==1.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", + "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" + ], + "version": "==8.3.0" + }, + "packaging": { + "hashes": [ + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + ], + "version": "==20.4" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "version": "==0.13.1" + }, + "py": { + "hashes": [ + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" + ], + "version": "==1.8.1" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "version": "==2.4.7" + }, + "pytest": { + "hashes": [ + "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1", + "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8" + ], + "index": "pypi", + "version": "==5.4.3" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "version": "==1.15.0" + }, + "wcwidth": { + "hashes": [ + "sha256:79375666b9954d4a1a10739315816324c3e73110af9d0e102d906fdb0aec009f", + "sha256:8c6b5b6ee1360b842645f336d9e5d68c55817c26d3050f46b235ef2bc650e48f" + ], + "version": "==0.2.4" + }, + "zipp": { + "hashes": [ + "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", + "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" + ], + "version": "==3.1.0" + } + }, + "develop": {} +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..3380cc9 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Binary Math Exercises + +## Description + +A command line application and Python library for generating binary numbers for a human to decode, as well as generating the integers they represent, to check the human's work. + +## Installation on MacOS or Linux +1) `git clone https://github.com/Averbach-Transcription/email_quote` +2) `ln -s /app/get_quote /usr/local/bin/` + +## Usage +```make_binary_problems ``` + +## TODO +- use click to make it a proper CLI, now that there will be multiple options +- make it produce printable sheets, probably as PDFs + - add nice spacing for easy reading + - options + - create_pdf + - number of columns [auto] + - font + - include column labels + +### Other Projects That Could Depend On This +- do the problems online/on computer +- a website to serve these up and let people use them for free + - a web API that serves it, so people can do that programmatically diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/check.py b/app/check.py new file mode 100644 index 0000000..131823b --- /dev/null +++ b/app/check.py @@ -0,0 +1,3 @@ + +def check(binary_string): + return int(binary_string, 2) diff --git a/app/config.py b/app/config.py new file mode 100644 index 0000000..445c913 --- /dev/null +++ b/app/config.py @@ -0,0 +1 @@ +BEGIN_ANSWERS_TOKEN = "*BEGIN ANSWERS*" diff --git a/app/generate.py b/app/generate.py new file mode 100644 index 0000000..d011d4a --- /dev/null +++ b/app/generate.py @@ -0,0 +1,15 @@ +import random + +from app.check import check + + +def generate(bits=8): + return "".join([random.choice("10") for i in range(bits)]) + + +def generate_problems(bits, num_problems): + return [generate(bits) for i in range(num_problems)] + + +def generate_answers(problems): + return [check(problem) for problem in problems] diff --git a/app/main.py b/app/main.py new file mode 100755 index 0000000..269e906 --- /dev/null +++ b/app/main.py @@ -0,0 +1,27 @@ +import sys + +from app.generate import generate_answers, generate_problems +from config import BEGIN_ANSWERS_TOKEN + + +def main(): + if len(sys.argv) < 3: + print( + "please supply the number of bits and the number of exercises you'd like, " + "space-separated, like so:\n\n $ binary 8 100\n" + ) + sys.exit() + + bits = int(sys.argv[1]) + num_problems = int(sys.argv[2]) + + problems = generate_problems(bits, num_problems) + answers = generate_answers(problems) + + problems_string = "\n\n".join(problems) + answers_string = "\n\n".join( + [f"{problem} | {answer} " for problem, answer in zip(problems, answers)] + ) + + sys.stdout.write(BEGIN_ANSWERS_TOKEN.join((problems_string, answers_string))) + return problems_string, answers_string diff --git a/app/test/test_generate.py b/app/test/test_generate.py new file mode 100644 index 0000000..36566d5 --- /dev/null +++ b/app/test/test_generate.py @@ -0,0 +1,29 @@ + +from app.generate import generate, generate_problems +from app.check import check + + +def test_generate(): + first_problem = generate(bits=5) + assert len(first_problem) == 5 + assert all(char in ('1', '0') for char in first_problem) + assert '1' in first_problem + assert '0' in first_problem + + +def test_generate_problems(): + problems = generate_problems(bits=5, num_problems=100) + first_problem = problems[0] + assert len(problems) == 100 + assert len(first_problem) == 5 + assert all(char in ('1', '0') for char in first_problem) + assert '1' in first_problem + assert '0' in first_problem + + +def test_check(): + assert check('110') == 6 + assert check('000') == 0 + assert check('001') == 1 + assert check('011') == 3 + assert check('010') == 2 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..0f8a1b9 --- /dev/null +++ b/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup, find_packages + + +with open("README.md", "r") as fh: + long_description = fh.read() + +setup( + name="binary_math_exercises", + author="Zev Averbach", + author_email="zev@averba.ch", + version="0.1", + description=( + "A command line application and Python library for generating binary numbers for " + "a human to decode, as well as generating the integers they represent, to check " + "the human's work." + ), + long_description=long_description, + packages=find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + python_requires=">=3.5", + entry_points={"console_scripts": ["binary=app.main:main"]}, +)