From c9b46d1387bbfc4649dcd1266319d753dfa2524b Mon Sep 17 00:00:00 2001 From: Bob Belderbos Date: Mon, 8 Feb 2021 12:39:49 +0100 Subject: [PATCH 1/3] Update .gitignore --- .gitignore | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index ed6cb0195..cea7431dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,10 @@ -**pyc -**swp -**log +**.pyc +**.swp **__pycache__ +**.venv **venv -**drafts **.cache -**sqlite +**sqlite3 **.idea **.vscode **.DS_Store From 612d9df6b39bfad36f5ccc5e47d2636ea6d75563 Mon Sep 17 00:00:00 2001 From: Bob Belderbos Date: Mon, 29 Nov 2021 08:39:57 +0100 Subject: [PATCH 2/3] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f61e4afd..8f35dde66 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ Head over to [our platform](https://codechalleng.es/challenges/), click on one a Browse (or checkout) [our community branch](https://github.com/pybites/challenges/tree/community) - all PRs get merged into that branch. ### How do I join your Slack Community? -Use [this link](https://join.slack.com/t/pybites/shared_invite/enQtNDAxODc0MjEyODM2LTNiZjljNTI2NGJiNWI0MTRkNjY4YzQ1ZWU4MmQzNWQyN2Q4ZTQzMTk0NzkyZTRmMThlNmQzYTk5Y2Y5ZDM4NDU) - and use our #codechallenges channel for coding questions. +Use [this link](https://pybit.es/community/) - and use our #codechallenges channel for coding questions. ### Can I help you out with code reviewing? -We are still getting a pretty manageable number of PRs to be able to merge them all in ourselves, but we do want to give each PR a bit more of a code review. As we're pretty busy we want to turn this into a *community effort*. So if you want to help out merging PRs into our challenges branch, become a moderator (and mentor!), you can volunteer [on Slack](https://join.slack.com/t/pybites/shared_invite/enQtNDAxODc0MjEyODM2LTNiZjljNTI2NGJiNWI0MTRkNjY4YzQ1ZWU4MmQzNWQyN2Q4ZTQzMTk0NzkyZTRmMThlNmQzYTk5Y2Y5ZDM4NDU). +We are still getting a pretty manageable number of PRs to be able to merge them all in ourselves, but we do want to give each PR a bit more of a code review. As we're pretty busy we want to turn this into a *community effort*. So if you want to help out merging PRs into our challenges branch, become a moderator (and mentor!), you can volunteer [on Slack](https://pybit.es/community/). ### Is this a place where we gonna be cool... just like Fonzie? Ah you mean something like a _Code of conduct_? We wrote this when we started 2 years ago and it still holds true: "Remember, we don't strive for the 'best' solution, it's not a competition! Learning more + better Python is the main objective. Respect the newbie. There is no right or wrong answer. Do as much or as little as you want. Just have fun!" From ad83ea24038bec65192a1c97d0e595931016e670 Mon Sep 17 00:00:00 2001 From: rhys Date: Mon, 24 Oct 2022 18:00:40 +0100 Subject: [PATCH 3/3] pcc03 --- 03/rhys/rss.xml | 2 + 03/rhys/tags.html | 216 +++++++++++++++++++++++++++++++++++++++++++ 03/rhys/tags.py | 61 ++++++++++++ 03/rhys/test_tags.py | 48 ++++++++++ 4 files changed, 327 insertions(+) create mode 100644 03/rhys/rss.xml create mode 100644 03/rhys/tags.html create mode 100644 03/rhys/tags.py create mode 100644 03/rhys/test_tags.py diff --git a/03/rhys/rss.xml b/03/rhys/rss.xml new file mode 100644 index 000000000..f7ed55b11 --- /dev/null +++ b/03/rhys/rss.xml @@ -0,0 +1,2 @@ + +PyBiteshttp://pybit.es/Python code challenges, tutorials and news, one bite a dayTue, 17 Jan 2017 00:01:00 +0100List of Awesome Python Resourceshttp://pybit.es/awesome_python_resources.html<p>A great list of Python Resources that should keep you busy for a while!</p>JulianTue, 17 Jan 2017 00:01:00 +0100tag:pybit.es,2017-01-17:/awesome_python_resources.htmlpythontipstricksresourcesflaskcrontoolsCode Challenge 02 - Word Values Part II - a simple gamehttp://pybit.es/codechallenge02.html<p>Using what we've learned the last challenge this week we build a simple Scrabble-like game: given a random set of 7 letters build the most valuable word. Good luck!</p>PyBitesMon, 16 Jan 2017 00:01:00 +0100tag:pybit.es,2017-01-16:/codechallenge02.htmlscrabblecode challengesgithubforklearninggameitertoolsrandomsetsTwitter digest 2017 week 02http://pybit.es/twitter_digest_201702.html<p>On Saturdays we will share a curated list of 15 cool things (mostly Python) we found / tweeted during the week.</p>PyBitesSat, 14 Jan 2017 00:05:00 +0100tag:pybit.es,2017-01-14:/twitter_digest_201702.htmltwitternewspythonpodcastsdata sciencechallengesAPIsconda3.6Code Challenge 01 - Word Values Part I - Reviewhttp://pybit.es/codechallenge01_review.html<p>Wow! We have been amazed by the great response on <a href="https://github.com/pybites/challenges">github</a> and <a href="https://news.ycombinator.com/item?id=13352447">HN</a>. It's Friday so we review the code challenge of this week. We describe our learning and a possible solution. We will also digest comments left on the <a href="http://pybit.es/codechallenge01.html">Monday post</a>.</p>PyBitesFri, 13 Jan 2017 12:40:00 +0100tag:pybit.es,2017-01-13:/codechallenge01_review.htmlcode challengescode reviewHNgithublearningmaxgeneratorsscrabblerefactoring5 cool things you can do with itertoolshttp://pybit.es/itertools-examples.html<p>Itertools is a very useful module. In this short post I show some 5 examples how you can use it. Some of this stuff might be useful in next week's challenge ...</p>BobThu, 12 Jan 2017 23:55:00 +0100tag:pybit.es,2017-01-12:/itertools-examples.htmliteratorsitertoolstricksgeneratorgamesnotebookspermutationsCreate a Simple Web Scraper with BeautifulSoup4http://pybit.es/simplewebscraper.html<p>Learn to create a simple web scraper in Python using BeautifulSoup4</p>JulianWed, 11 Jan 2017 13:00:00 +0100tag:pybit.es,2017-01-11:/simplewebscraper.htmlpythontipstrickscodepybitesbeautifulsoupbs4webscrapingnamedtupleBeautiful, idiomatic Pythonhttp://pybit.es/beautiful-python.html<p><a href="https://www.youtube.com/watch?v=OSGv2VnC0go">Transforming Code into Beautiful, Idiomatic Python</a> is a must-watch to write more Pythonic code. In this post some highlights.</p>BobTue, 10 Jan 2017 09:00:00 +0100tag:pybit.es,2017-01-10:/beautiful-python.htmlpythoniccleancodecollections2vs3namedtupledecoratorscontextmanagersCode Challenge 01 - Word Values Part Ihttp://pybit.es/codechallenge01.html<p>Our first weekly code challenge is to calculate the (language) dictionary word that would have the most value in Scrabble. Enjoy and let us know if you like this format.</p>PyBitesMon, 09 Jan 2017 09:00:00 +0100tag:pybit.es,2017-01-09:/codechallenge01.htmlscrabbletddcode challengesgithublearningTwitter digest 2017 week 01http://pybit.es/twitter_digest_201701.html<p>On Saturdays we will share a curated list of 15 cool things (mostly Python) we found / tweeted during the week.</p>PyBitesSat, 07 Jan 2017 09:00:00 +0100tag:pybit.es,2017-01-07:/twitter_digest_201701.htmltwitternewspythonpodcastsdataiteratorspythontipsCopy and Paste with Pypercliphttp://pybit.es/pyperclip.html<p>Use the Pyperclip module to copy and paste with the clipboard!</p>JulianFri, 06 Jan 2017 12:00:00 +0100tag:pybit.es,2017-01-06:/pyperclip.htmlpythontipstrickscodepybitesCode Challenge Pilot - code reviewhttp://pybit.es/challenge_pilot_codereview.html<p>In this post I review the code of challenge # 1 and refactor it to make it more Pythonic.</p>BobThu, 05 Jan 2017 09:00:00 +0100tag:pybit.es,2017-01-05:/challenge_pilot_codereview.htmlchallengerefactoringcode reviewbest practicespythonicgitGithubgit flowvimassertCode Challenge Pilot - calculate total time JS coursehttp://pybit.es/js_time_scraper_ch.html<p>Coding Challenge to create a web scraper that calculates the total time of a Javascript Course.</p>JulianWed, 04 Jan 2017 20:01:00 +0100tag:pybit.es,2017-01-04:/js_time_scraper_ch.htmlchallengeslearningpythonbeginnerscodeA great book that makes algorithms accessiblehttp://pybit.es/grokking_algorithms.html<p>I finished reading Grokking Algorithms, it's a very accessible resource for learning algorithms / data structures, highly recommended.</p>BobTue, 03 Jan 2017 09:00:00 +0100tag:pybit.es,2017-01-03:/grokking_algorithms.htmlalgorithmsdata structuresperformancecollections5 min guide to PEP8http://pybit.es/pep8.html<p>Today a post on PEP8, the Style Guide for Python Code</p>BobMon, 02 Jan 2017 09:00:00 +0100tag:pybit.es,2017-01-02:/pep8.htmlpep8cleancodeguidelinescoding stylebest practicespythonicvimPython Naming Conventionshttp://pybit.es/naming_conventions.html<p>Naming conventions can be tricky in Py. It's good to make sure we're all on the same page.</p>JulianSun, 01 Jan 2017 11:14:00 +0100tag:pybit.es,2017-01-01:/naming_conventions.htmllearningpythonbeginnerstipscleancodebest-practices3.6 new featureshttp://pybit.es/3.6_new.html<p>Finally got a chance to look into Python 3.6's new features. In this post some highlights and pointers.</p>BobSat, 31 Dec 2016 11:39:00 +0100tag:pybit.es,2016-12-31:/3.6_new.html3.6featuresreleaseasyncioformattingtypingdictssecretsgeneratorsreadabilityDon't Let Indentation Catch You Outhttp://pybit.es/indentation_tips.html<p>Python indentation can be a cruel mistress. Let's get it right!</p>JulianFri, 30 Dec 2016 19:51:00 +0100tag:pybit.es,2016-12-30:/indentation_tips.htmlpythonlearningbeginnerstipscleancodebest-practicesAutomate Tweeting: how to build a Twitterbothttp://pybit.es/automate-twitter.html<p>In this post I will show you how we automate part of our Twitter posting using feedparser and tweepy.</p>BobThu, 29 Dec 2016 01:28:00 +0100tag:pybit.es,2016-12-29:/automate-twitter.htmltwitterapitweepyfeedparserrssloggingpodcastsvirtualenvpyvenvvenvnews3.6Learning from Python mistakeshttp://pybit.es/py-mistakes.html<p>In this post I summarize some great lessons Mike Pirnat shared in his free ebook 'How to make mistakes in Python'</p>BobWed, 28 Dec 2016 09:00:00 +0100tag:pybit.es,2016-12-28:/py-mistakes.htmlbest practicespep8virtualenvcleancodeloggingpytestebookrefactoringgotchasHow to create a nice-looking HTML page of your Kindle book highlights (notes)http://pybit.es/kindle-json-to-html.html<p>In this post I share a simple script to convert Bookcision JSON into a HTML page for your blog.</p>BobTue, 27 Dec 2016 00:10:00 +0100tag:pybit.es,2016-12-27:/kindle-json-to-html.htmlkindleTemplate stringsjsonhtmlbooksbookcisiongeneratorsA Quick Automate the Boring Stuff Reviewhttp://pybit.es/automate_the_boring_stuff_review.html<p>A quick review of the legendary free book, Automate the Boring Stuff.</p>JulianMon, 26 Dec 2016 23:00:00 +0100tag:pybit.es,2016-12-26:/automate_the_boring_stuff_review.htmlpythonreviewbookslearningbeginnersautomationZip and ship, make an executable zipfile of your py projecthttp://pybit.es/zip-and-ship.html<p>In this post I show an example how you can distribute your code as an executable zipfile, a neat trick I discovered in Chapter 6 of The Hitchhiker's Guide to Python</p>BobSun, 25 Dec 2016 09:06:00 +0100tag:pybit.es,2016-12-25:/zip-and-ship.htmlzippackagingdistributepipGet a weekly digest from a Pelican bloghttp://pybit.es/blog-digest.html<p>In this post a script we use to get a weekly digest of our posts.</p>BobSat, 24 Dec 2016 15:40:00 +0100tag:pybit.es,2016-12-24:/blog-digest.htmlpelicanfeedparserrss2016 py articles and useful bookshttp://pybit.es/py-articles-books2016.html<p>Some of my Python articles I posted on my blog this year and useful books</p>BobFri, 23 Dec 2016 00:31:00 +0100tag:pybit.es,2016-12-23:/py-articles-books2016.htmlpythonicbookscollectionstrickstipsdata sciencematplotlibpandasThe Beauty of Python Virtualenvshttp://pybit.es/the-beauty-of-virtualenv.html<p>Python Virtualenvs are incredible yet sadly under utilised!</p>JulianThu, 22 Dec 2016 22:11:00 +0100tag:pybit.es,2016-12-22:/the-beauty-of-virtualenv.htmlpythonpipvirtualenvvenvRead the stdlib: dequehttp://pybit.es/collections-deque.html<p>Use collections.deque to rotate letters in string (or elements in list). It has a native method which performs faster too.</p>BobWed, 21 Dec 2016 00:05:00 +0100tag:pybit.es,2016-12-21:/collections-deque.htmlcollectionsdata structuresperformancestdlibdequeHow to get PyBites up and running on your machinehttp://pybit.es/install-me.html<p>This is a short post for Julian to get this Pelican blog up and running on his system.</p>PybitesTue, 20 Dec 2016 10:40:00 +0100tag:pybit.es,2016-12-20:/install-me.htmlpelicanpublishinggithubpipvirtualenvgit__init__http://pybit.es/hello-world.html<p>Welcome to our new PyBites blog where our goal is to further develop our Python skills and share what we learn.</p>PybitesMon, 19 Dec 2016 10:26:00 +0100tag:pybit.es,2016-12-19:/hello-world.htmlpelicanpublishingblogpybites \ No newline at end of file diff --git a/03/rhys/tags.html b/03/rhys/tags.html new file mode 100644 index 000000000..0039bf689 --- /dev/null +++ b/03/rhys/tags.html @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PyBites – Tags + + + + + + + + +
+ + +
+
+

Tags +

+
+
+ +
+
+ + +
+ + + + + + + + + + + diff --git a/03/rhys/tags.py b/03/rhys/tags.py new file mode 100644 index 000000000..12fe75ba1 --- /dev/null +++ b/03/rhys/tags.py @@ -0,0 +1,61 @@ +from collections import Counter +from difflib import SequenceMatcher +from itertools import product +import re + +IDENTICAL = 1.0 +TOP_NUMBER = 10 +RSS_FEED = "rss.xml" +SIMILAR = 0.87 +TAG_HTML = re.compile(r"([^<]+)") + + +def get_tags(): + """Find all tags (TAG_HTML) in RSS_FEED. + Replace dash with whitespace. + Hint: use TAG_HTML.findall""" + with open("rss.xml", "r") as f: + for line in f: + line = line.replace("-", " ").lower() + tags = TAG_HTML.findall(line) + return tags + + +def get_top_tags(tags): + """Get the TOP_NUMBER of most common tags + Hint: use most_common method of Counter (already imported)""" + return Counter(tags).most_common(TOP_NUMBER) + + +def get_similarities(tags): + """Find set of tags pairs with similarity ratio of > SIMILAR + Hint 1: compare each tag, use for in for, or product from itertools (already imported) + Hint 2: use SequenceMatcher (imported) to calculate the similarity ratio + Bonus: for performance gain compare the first char of each tag in pair and continue if not the same""" + result = {} + result = {} + for x, y in product(tags, tags): + plural = y + singular = x + if x[0] == y[0] and x != y: + ratio = SequenceMatcher(None, x, y).ratio() + if x.endswith("s"): + plural = x + singular = y + if SIMILAR <= ratio and singular not in result: + result[singular] = plural + return result + + +if __name__ == "__main__": + + tags = get_tags() + top_tags = get_top_tags(tags) + print("* Top {} tags:".format(TOP_NUMBER)) + for tag, count in top_tags: + print("{:<20} {}".format(tag, count)) + similar_tags = dict(get_similarities(tags)) + print() + print("* Similar tags:") + for singular, plural in similar_tags.items(): + print("{:<20} {}".format(singular, plural)) diff --git a/03/rhys/test_tags.py b/03/rhys/test_tags.py new file mode 100644 index 000000000..b4838f23e --- /dev/null +++ b/03/rhys/test_tags.py @@ -0,0 +1,48 @@ +import re +import unittest + +from tags import get_tags, get_top_tags +from tags import get_similarities, TOP_NUMBER + +TAG_COUNT = re.compile(r'">([^<]+)\s\((\d+)\)<') +TAGS = 'tags.html' + + +def parse_tags_html(): + with open(TAGS) as f: + for line in f: + if '/tag/' not in line: + continue + m = TAG_COUNT.search(line.rstrip()) + if m: + yield m.groups()[0], int(m.groups()[1]) + + +class test_tags(unittest.TestCase): + + def setUp(self): + self.tags = get_tags() + + def test_get_tags(self): + self.assertEqual(len(self.tags), 189) + self.assertEqual(len(set(self.tags)), 100) + self.assertEqual(self.tags.count('collections'), 4) + self.assertEqual(self.tags.count('python'), 10) + + def test_get_top_tags(self): + top_tags = dict(get_top_tags(self.tags)).items() + self.assertEqual(len(top_tags), TOP_NUMBER) + pybites_tags = dict(parse_tags_html()) + for tag in top_tags: + self.assertIn(tag, pybites_tags.items()) + + def test_get_similarities(self): + similar_tags = dict(get_similarities(self.tags)).items() + self.assertEqual(len(similar_tags), 3) + self.assertIn(('game', 'games'), similar_tags) + self.assertIn(('challenge', 'challenges'), similar_tags) + self.assertIn(('generator', 'generators'), similar_tags) + + +if __name__ == "__main__": + unittest.main()