Skip to content

Commit c6b0e9c

Browse files
committed
Add presets
1 parent e45218c commit c6b0e9c

File tree

10 files changed

+415
-16
lines changed

10 files changed

+415
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Changelog
2+
3+
## 1.1.0
4+
- Added support for using presets of questions, including the Grind 75, Grind 169, and the original Blind 75. This argument is an optional argument instead of inputting urls or a file of questions.

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,19 @@ $ pip install leetcode-study-tool
2222

2323
## Usage
2424
```shell
25-
usage: leetcode-study-tool [-h] (--url URL | --file FILE) [--format {cards}] [--output OUTPUT] [--language LANGUAGE]
25+
usage: leetcode-study-tool [-h] (--url URL | --file FILE | --preset {blind_75,grind_75,grind_169}) [--format {anki}] [--csrf CSRF] [--output OUTPUT] [--language LANGUAGE]
2626

2727
Generates problems from LeetCode questions in a desired format.
2828

2929
options:
3030
-h, --help show this help message and exit
3131
--url URL, -u URL The URL(s) or slug(s) of the LeetCode question(s) to generate problem(s) for. (default: None)
3232
--file FILE, -f FILE The file containing the URL(s) or slug(s) of the LeetCode question(s) to generate problem(s) for. (default: None)
33-
--format {cards}, -F {cards}
34-
The format to save the Anki problem(s) in. (default: cards)
33+
--preset {blind_75,grind_75,grind_169}, -p {blind_75,grind_75,grind_169}
34+
The preset to use to generate problem(s) for. (default: None)
35+
--format {anki}, -F {anki}
36+
The format to save the Leetcode problem(s) in. (default: anki)
37+
--csrf CSRF, -c CSRF The CSRF token to use for LeetCode authentication. (default: None)
3538
--output OUTPUT, -o OUTPUT
3639
The output file to write the problem(s) to. (default: output.txt)
3740
--language LANGUAGE, -l LANGUAGE

leetcode_study_tool/cli.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import argparse
22

3-
from leetcode_study_tool.creator import ProblemsCreator
3+
from .constants.presets import PRESET_MAP
4+
from .creator import ProblemsCreator
45

56

67
def parse_args() -> argparse.Namespace:
@@ -41,6 +42,14 @@ def parse_args() -> argparse.Namespace:
4142
),
4243
)
4344

45+
input.add_argument(
46+
"--preset",
47+
"-p",
48+
type=str,
49+
choices=PRESET_MAP.keys(),
50+
help=("The preset to use to generate problem(s) for."),
51+
)
52+
4453
parser.add_argument(
4554
"--format",
4655
"-F",

leetcode_study_tool/constants/presets.py

Lines changed: 335 additions & 0 deletions
Large diffs are not rendered by default.

leetcode_study_tool/creator.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
import html
33
import os
44
import re
5-
from functools import partial
65
from multiprocessing import Pool
76
from typing import List, Union
87

8+
from .constants.presets import PRESET_MAP
99
from .formatters import FORMAT_MAP
1010
from .outputs import SAVE_MAP
1111
from .queries import generate_session, get_data, get_slug
@@ -42,17 +42,16 @@ def __init__(self, args: Union[argparse.Namespace, dict]) -> None:
4242
with open(args["file"], "r") as f:
4343
self.urls = f.read().splitlines()
4444

45+
elif args.get("preset"):
46+
self.urls = PRESET_MAP[args["preset"]]
47+
4548
def create_problems(self) -> None:
4649
"""
4750
Create the problems for Anki.
4851
"""
4952
with Pool() as pool:
5053
problems = pool.map(
51-
partial(
52-
self._generate_problem,
53-
language=self.language,
54-
format=self.format,
55-
),
54+
self._generate_problem,
5655
self.urls,
5756
)
5857

leetcode_study_tool/formatters.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,10 @@ def format_anki(url: str, slug: str, data: dict):
110110
for solution in data["solutions"]
111111
],
112112
)
113-
problem += "<strong>LeetCode User Solutions:</strong><br>"
114113

115114
problem += ";"
116115

117-
problem += " ".join([tag["slug"] for tag in data["tags"]])
116+
problem += " ".join([tag["slug"].lower() for tag in data["tags"]])
118117

119118
# Makes code easier to read to remove at the end
120119
problem = dedent(problem).replace("\n", "")

leetcode_study_tool/outputs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ def save_string(problems: List[Union[str, None]], file: str) -> None:
1212
file : str
1313
The file to save the problems to.
1414
"""
15-
print("foo")
1615
with open(file + ".txt", "w") as f:
1716
for problem in problems:
1817
if problem:

pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "leetcode-study-tool"
7-
version = "1.0.2"
7+
version = "1.1.0"
88
description = "A tool for studying Leetcode with Python"
99
authors = [{name="John Sutor", email="johnsutor3@gmail.com" }]
1010
license = {file = "LICENSE.txt"}
@@ -47,10 +47,13 @@ leetcode-study-tool = "leetcode_study_tool.cli:main"
4747

4848
[project.urls]
4949
homepage = "https://github.com/johnsutor/leetcode-study-tool"
50+
repository = "https://github.com/johnsutor/leetcode-study-tool"
51+
changelog = "https://github.com/johnsutor/leetcode-study-tool/blob/main/CHANGELOG.md"
5052

5153
[tool.mypy]
5254
exclude = [
53-
"build"
55+
"build",
56+
"scripts"
5457
]
5558
ignore_missing_imports = true
5659

scripts/presets.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python
2+
# encoding: utf-8
3+
# Utility script to generate lists of presets for the leetcode_study_tool. This includes
4+
# the Blind 75, the Grind 75, and the Grind 169.
5+
6+
import json
7+
import sys
8+
import urllib
9+
10+
import requests
11+
from bs4 import BeautifulSoup
12+
13+
14+
def main(url: str, output_file: str = "presets.txt"):
15+
response = requests.get(url)
16+
problems = []
17+
18+
soup = BeautifulSoup(response.content, "html.parser")
19+
20+
for link in soup.find_all("a"):
21+
# save only the links that are leetcode problems
22+
url = urllib.parse.urlparse(link.get("href"))
23+
24+
try:
25+
if (
26+
url.path.startswith("/problems/")
27+
and url.netloc == "leetcode.com"
28+
):
29+
problems.append(url.geturl())
30+
except Exception as e:
31+
print(e)
32+
if (
33+
url.path.decode().startswith("/problems/")
34+
and url.netloc.decode() == "leetcode.com"
35+
):
36+
problems.append(url.geturl().decode())
37+
38+
with open(output_file, "w") as f:
39+
json.dump(problems, f)
40+
41+
42+
if __name__ == "__main__":
43+
url = sys.argv[1]
44+
if sys.argv[2]:
45+
output_file = sys.argv[2]
46+
else:
47+
output_file = "presets.txt"
48+
main(url, output_file)

tests/test_formatters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
class TestFormatters(unittest.TestCase):
99
def setUp(self) -> None:
1010
super().setUp()
11-
self.correct_anki_formatted_two_sum_problem = ' <h1> <a href="https://leetcode.com/problems/two-sum/">1. Two Sum</a> </h1> <p> <p>Given an array of integers <code>nums</code>&nbsp;and an integer <code>target</code>, return <em>indices of the two numbers such that they add up to <code>target</code></em>.</p><p>You may assume that each input would have <strong><em>exactly</em> one solution</strong>, and you may not use the <em>same</em> element twice.</p><p>You can return the answer in any order.</p><p>&nbsp;</p><p><strong class="example">Example 1:</strong></p><pre><strong>Input:</strong> nums = [2,7,11,15], target = 9<strong>Output:</strong> [0,1]<strong>Explanation:</strong> Because nums[0] + nums[1] == 9, we return [0, 1].</pre><p><strong class="example">Example 2:</strong></p><pre><strong>Input:</strong> nums = [3,2,4], target = 6<strong>Output:</strong> [1,2]</pre><p><strong class="example">Example 3:</strong></p><pre><strong>Input:</strong> nums = [3,3], target = 6<strong>Output:</strong> [0,1]</pre><p>&nbsp;</p><p><strong>Constraints:</strong></p><ul>\t<li><code>2 &lt;= nums.length &lt;= 10<sup>4</sup></code></li>\t<li><code>-10<sup>9</sup> &lt;= nums[i] &lt;= 10<sup>9</sup></code></li>\t<li><code>-10<sup>9</sup> &lt;= target &lt;= 10<sup>9</sup></code></li>\t<li><strong>Only one valid answer exists.</strong></li></ul><p>&nbsp;</p><strong>Follow-up:&nbsp;</strong>Can you come up with an algorithm that is less than <code>O(n<sup>2</sup>)</code><font face="monospace">&nbsp;</font>time complexity? <p> <strong>Tags:</strong><br> <ul> <li>Array</li><li>Hash Table</li> </ul> ;<strong>NeetCode Solution:</strong><br><a href="https://youtube.com/watch?v=KLlXCFG5TnA">Two Sum - Leetcode 1 - HashMap - Python</a></li><br><br> <strong>LeetCode User Solutions:</strong><br> <ul> <li>https://leetcode.com/problems/two-sum/solutions/2/1/</li><li>https://leetcode.com/problems/two-sum/solutions/3/1/</li><li>https://leetcode.com/problems/two-sum/solutions/4/1/</li><li>https://leetcode.com/problems/two-sum/solutions/6/1/</li><li>https://leetcode.com/problems/two-sum/solutions/7/1/</li><li>https://leetcode.com/problems/two-sum/solutions/8/1/</li><li>https://leetcode.com/problems/two-sum/solutions/9/1/</li><li>https://leetcode.com/problems/two-sum/solutions/10/1/</li><li>https://leetcode.com/problems/two-sum/solutions/11/1/</li><li>https://leetcode.com/problems/two-sum/solutions/12/1/</li> </ul> <strong>LeetCode User Solutions:</strong><br>;array hash-table'
11+
self.correct_anki_formatted_two_sum_problem = ' <h1> <a href="https://leetcode.com/problems/two-sum/">1. Two Sum</a> </h1> <p> <p>Given an array of integers <code>nums</code>&nbsp;and an integer <code>target</code>, return <em>indices of the two numbers such that they add up to <code>target</code></em>.</p><p>You may assume that each input would have <strong><em>exactly</em> one solution</strong>, and you may not use the <em>same</em> element twice.</p><p>You can return the answer in any order.</p><p>&nbsp;</p><p><strong class="example">Example 1:</strong></p><pre><strong>Input:</strong> nums = [2,7,11,15], target = 9<strong>Output:</strong> [0,1]<strong>Explanation:</strong> Because nums[0] + nums[1] == 9, we return [0, 1].</pre><p><strong class="example">Example 2:</strong></p><pre><strong>Input:</strong> nums = [3,2,4], target = 6<strong>Output:</strong> [1,2]</pre><p><strong class="example">Example 3:</strong></p><pre><strong>Input:</strong> nums = [3,3], target = 6<strong>Output:</strong> [0,1]</pre><p>&nbsp;</p><p><strong>Constraints:</strong></p><ul>\t<li><code>2 &lt;= nums.length &lt;= 10<sup>4</sup></code></li>\t<li><code>-10<sup>9</sup> &lt;= nums[i] &lt;= 10<sup>9</sup></code></li>\t<li><code>-10<sup>9</sup> &lt;= target &lt;= 10<sup>9</sup></code></li>\t<li><strong>Only one valid answer exists.</strong></li></ul><p>&nbsp;</p><strong>Follow-up:&nbsp;</strong>Can you come up with an algorithm that is less than <code>O(n<sup>2</sup>)</code><font face="monospace">&nbsp;</font>time complexity? <p> <strong>Tags:</strong><br> <ul> <li>Array</li><li>Hash Table</li> </ul> ;<strong>NeetCode Solution:</strong><br><a href="https://youtube.com/watch?v=KLlXCFG5TnA">Two Sum - Leetcode 1 - HashMap - Python</a></li><br><br> <strong>LeetCode User Solutions:</strong><br> <ul> <li>https://leetcode.com/problems/two-sum/solutions/2/1/</li><li>https://leetcode.com/problems/two-sum/solutions/3/1/</li><li>https://leetcode.com/problems/two-sum/solutions/4/1/</li><li>https://leetcode.com/problems/two-sum/solutions/6/1/</li><li>https://leetcode.com/problems/two-sum/solutions/7/1/</li><li>https://leetcode.com/problems/two-sum/solutions/8/1/</li><li>https://leetcode.com/problems/two-sum/solutions/9/1/</li><li>https://leetcode.com/problems/two-sum/solutions/10/1/</li><li>https://leetcode.com/problems/two-sum/solutions/11/1/</li><li>https://leetcode.com/problems/two-sum/solutions/12/1/</li> </ul> ;array hash-table'
1212

1313
def test_format_list_element(self):
1414
self.assertEqual(

0 commit comments

Comments
 (0)