Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 46423f6

Browse filesBrowse files
committed
interactive mode, random from list, detailed info
1 parent 01d38f2 commit 46423f6
Copy full SHA for 46423f6

File tree

3 files changed

+105
-36
lines changed
Filter options

3 files changed

+105
-36
lines changed

‎README.md

Copy file name to clipboardExpand all lines: README.md
+7-7Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
# leetcode-problem-picker
22

33
## Purpose:
4-
This project was a response to the reoccurring question "Which leetcode problem should I do next?"
4+
This project was a response to my reoccurring question *"Which leetcode problem should I do next?"*
55

66
Over time I found that the answer varies, depending on progress, needs, and goals:
7-
1. Topic Focus: Narrow down to one or a few subjects e.g. "only problems related to graphs, tries, and DP".
8-
2. Filtered Lists: Which problems were frequently asked by companies I’m interested in? Also lists like Blind 75
9-
3. Level Up (WIP): Deduces user's "skill range" for each topic in order to challenge (but not discourage).
10-
4. Weighted random (TODO): Weighted towards high like count, high like-dislike ratio, etc.
7+
1. **Topic Focus**: Narrow down to 1+ subjects e.g. "only do problems related to graphs or DP".
8+
2. **Filtered Lists**: Honing in on questions asked by desired companies. Applies to lists like Blind's Curated 75.
9+
3. **Level Up** (WIP): Deduces user's "skill range" for each topic in order to challenge (but not discourage).
10+
4. **Weighted random** (TODO): Weighted towards questions with high like count, greater like/dislike ratio, etc.
1111

1212
# State of leetcode-problem-picker
1313
![WIP](https://i.ibb.co/BcSX334/WIP.png)
1414

15-
I wish to share and help others, but what I currently have and use is a product of months of ideas. It is neither presentable nor ready for public consumption. What you see now is just a bunch of stubs.
15+
I wish to share and help others, but what I currently have and use is a product of months of ideas. It is neither presentable nor ready for public consumption. In fact, what you see now is just a bunch of stubs.
1616

17-
**If you are interested in this idea, please star this repo** and give me a week or so to clean it up.
17+
**If you are interested in this idea, please star this repo** and allow me a week or so to clean up the code and get the first two parts ready.
1818

1919
## Setup:
2020
```git clone https://github.com/evliang/leetcode-problem-picker.git```

‎completed.csv

Copy file name to clipboardExpand all lines: completed.csv
Whitespace-only changes.

‎lcpp.py

Copy file name to clipboardExpand all lines: lcpp.py
+98-29Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,40 @@
33
import os
44
from enum import Enum
55
import random
6-
from constants import topics
6+
from constants import topics, blind75
7+
import csv
8+
from collections import defaultdict
9+
from timeit import default_timer as timer
10+
import datetime
711

812
ProblemType = Enum('ProblemType', 'Top Freq Easiest Hardest Common Random')
913

10-
def load_completed():
11-
# completed.csv
14+
def load_completed_list():
15+
completed1 = set()
1216
with open('completed.csv', 'r') as f:
13-
completed1 = f.read().splitlines()
14-
# completed.txt
15-
with open('completed.txt', 'r') as f:
16-
completed2 = f.read().splitlines()
17-
# merge
17+
for line in f.read().splitlines():
18+
try:
19+
completed1.add(int(line.split(',')[0].strip()))
20+
except ValueError:
21+
continue
22+
completed2 = load_problem_nums('completed.txt')
23+
# TODO handle skipped, revisit, refresh lists
24+
return completed1.union(completed2)
1825

19-
# handle skipped, revisit, refresh lists
20-
return set()
26+
def load_problem_nums(file_name):
27+
ret = set()
28+
with open(file_name, 'r') as f:
29+
for num_string in f.read().split(','):
30+
try:
31+
ret.add(int(num_string.strip()))
32+
except ValueError:
33+
continue
34+
return ret
2135

2236
def pick_problems(problem_type=ProblemType.Random, categories=[], companies=[], k=5):
37+
completed = load_completed_list()
38+
skipped_hard = load_problem_nums('skipped.txt')
39+
revisit = load_problem_nums('revisit_later.txt')
2340
problem_set = set(companies) - completed - skipped_hard - revisit
2441
if problem_type==ProblemType.Random:
2542
return random.sample(list(problem_set), k)
@@ -31,27 +48,79 @@ def record_problems():
3148
None
3249

3350
if __name__ == "__main__":
51+
faang_companies = ['amazon', 'apple', 'google', 'netflix', 'facebook']
52+
my_companies = ['adobe', 'microsoft', 'airbnb', 'linkedin', 'tesla', 'twitter', 'hulu', 'redfin', 'snapchat',
53+
'paypal', 'pinterest', 'audible', 'atlassian', 'lyft', 'uber', 'twitch', 'twilio', 'robinhood',
54+
'cruise', 'reddit', 'valve', 'walmart', 'dropbox']
55+
56+
all_problems = {}
57+
easy_set, medium_set, hard_set = set(), set(), set()
58+
# also store in sorted list for binsearch range lookup: https://stackoverflow.com/a/2899190
59+
60+
companies = defaultdict(dict)
61+
problem_to_company = defaultdict(set)
62+
63+
for fi in glob.glob('companies//*.csv'):
64+
(company,duration) = fi[10:-4].rsplit('_')
65+
companies[company][duration] = dict()
66+
with open(fi, 'r') as f:
67+
for line in csv.DictReader(f, fieldnames=('ID', 'Name', 'Acceptance', 'Difficulty', 'Frequency', 'Link')):
68+
problem_num = int(line.pop('ID'))
69+
all_problems[problem_num] = line
70+
companies[company][duration][problem_num] = line.pop('Frequency')
71+
problem_to_company[problem_num].add(company)
72+
73+
#populate company file w/ maximum of 4 lines (sorted). each line is a comma separated list of problem numbers.
74+
# question: does 1yr,2yr and alltime contain 6mo? does 2yr contain 1yr? I think not?
75+
# 6mo
76+
# 1yr
77+
# 2yr
78+
# alltime
3479
if len(sys.argv) == 1:
35-
print(pick_problems(companies=blind_list, k=5))
80+
None
81+
#print(pick_problems(companies=blind_list, k=5))
3682
elif sys.argv[1] == 'interactive':
37-
probs = pick_problems(companies=blind_list, k=5)
38-
print(probs)
83+
problems = pick_problems(companies=blind75, k=5)
3984

4085
companies = faang_companies + my_companies # all companies?
4186
d = {}
42-
for company in companies:
43-
d[company] = get_the_question_set(get_frequencies([company]))
44-
45-
while True:
46-
inp = input('leetcode ID? ')
47-
if inp == '' or inp.startswith('q'):
48-
break
49-
if inp.isdigit():
50-
ret = []
51-
# problem # =>
52-
# details: name, difficulty, accept rate. need to set up dict. can just grab one from company.
53-
# [company (%)] dict from problem# => companyname => %
54-
for company in d:
55-
if int(inp) in d[company]:
56-
ret.append(company)
57-
print(f'\t {len(ret)}: ' + ', '.join(ret))
87+
#for company in companies:
88+
# d[company] = get_the_question_set(get_frequencies([company]))
89+
90+
print("Other valid inputs: info, hint, easy, hard, quit, help")
91+
92+
for (idx,leetcode_id) in enumerate(problems):
93+
problem = all_problems[leetcode_id]
94+
msg = "First problem" if idx == 0 else "Last problem" if idx == len(problems)-1 else "Next up"
95+
print(f"\n\n{msg}:\n{leetcode_id}: {problem['Name']} {problem['Link']}")
96+
start_time = timer()
97+
while True:
98+
inp = input('When completed, enter: y/n,[num_errs],[time]\n')
99+
if inp == '' or inp.startswith('q'):
100+
break # TODO
101+
if inp == 'hint':
102+
ret = []
103+
# problem # =>
104+
# details: name, difficulty, accept rate. need to set up dict. can just grab one from company.
105+
# [company (%)] dict from problem# => companyname => %
106+
for company in d:
107+
if int(inp) in d[company]:
108+
ret.append(company)
109+
print(f'\t {len(ret)}: ' + ', '.join(ret))
110+
elif inp == 'info':
111+
company_list = problem_to_company[leetcode_id]
112+
difficulty_string = "medium difficulty" if problem['Difficulty'] == "Medium" else "considered easy" if problem['Difficulty'] == 'Easy' else problem['Difficulty']
113+
print(f"{leetcode_id} {problem['Name']} is {difficulty_string}: {problem['Acceptance']} of submissions pass")
114+
print(f"{len(company_list)} have asked this question: {', '.join(company_list)}")
115+
elif inp.startswith('y') or inp.startswith('n'):
116+
end_time = timer()
117+
entry = inp.split(',')
118+
was_solved = 'yes' if entry[0].startswith('y') else 'no'
119+
num_errs = entry[1] if len(entry) > 1 else '0'
120+
time = entry[2] if len(entry) > 2 else (start_time - end_time)//60
121+
with open('completed.csv', 'a') as f:
122+
f.write(f'{leetcode_id},{was_solved},{num_errs},{time},{datetime.datetime.now():%Y-%m-%d}')
123+
# log entry into csv
124+
break
125+
else:
126+
print("Invalid input. Type help for options")

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.