Make LeetCode (MLC)
Table of Contents
Overview #
I have found that practicing LeetCode problems helps me stay sharp and use them as a way to get better at both general problem solving and Test Driven Development. One painpoint I have had is starting a new problem, since I want to store all my work in my own git repo in a specific format, and I want to be able to run my tests easily. It requires:
- figuring out which folder to add the file to (easy, medium, hard)
- creating the file with the correct naming convention, using the problem number and slug
- copy/pasting the problem description and starter code snippet
- importing that new file into my test file and scaffolding the unit test class, base test case, and first test to be filled out
All of this takes around five minutes, but the repetitive nature easily lends itself to automation – so I did it.
You can find the mlc.sh and sample .mlc config files here – feel free to use it and tweak it to your needs.
To set it up:
-
copy the
.mlc
file to your$HOME
folder and edit the naming per your folder structure -
add the
mlc.sh
file anywhere and add it to your either an already executable bin folder (like/usr/local/bin
or add the folder to yourPATH
):cp mlc.sh /usr/local/bin/mlc chmod +x /usr/local/bin/mlc
or
mkdir ~/scripts cp mlc.sh ~/scripts/mlc chmod +x ~/scripts/mlc PATH=$PATH:~/scripts
To run it: mlc -u "URL_OF_PROBLEM"
, e.g.: mlc.sh -u "https://leetcode.com/problems/valid-palindrome"
Notes #
-
Decided to create it in bash because it is simple file creation from parsing a url. It could easily be turned into a Python or Golang CLI tool – maybe I’ll create those in the future.
-
It is tightly coupled with my current folder structure and practice language of choice / tooling:
-
Language =
python3
-
Tooling = in-built
unittest
module for testing -
Folder Structure:
. ├── README.md ├── lc/ # configurable by editing the lc_folder variable │ ├── 150/ # configurable by editing the study_plan variable │ │ ├── 1_easy │ │ ├── 2_medium │ │ └── 3_hard ├── scripts/ │ └── mlc.sh ├── tests/ # configurable by editing the lc_test_folder variable │ ├── data/ │ ├── test_lc.py
-
-
It is very customized to the way I format solution files and test cases:
-
Solution Files:
- stored in study plan folder, by difficulty
- naming convention: p####_slug_of_problem.py
- file header:
- file name
- problem title
- problem url
- problem description
- snippet of provided starter python3 solution code
# 0125_valid_palindrome.py # # Valid Palindrome # # https://leetcode.com/problems/valid-palindrome # A phrase is a palindrome if, # after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, # it reads the same forward and backward # Alphanumeric characters include letters and numbers # # Given a string s, # return true if it is a palindrome, # or false otherwise # class Solution: def isPalindrome(self, s: str) -> bool:
-
Test File:
-
singular test file with tests for all problems
-
requires importing each file separately because of the folder structure, so need to have a
sys.path.append
for the location of each of the solution folders -
uses
unittest
-
uses a
base_test
which does a call to the function being created and compares the expected value and actual results -
creates a scaffolded
test_1
which contains placeholders for each argument, as well as the expected value, and uses thebase_test
-
top of
test_lc.py
file:
import sys import unittest sys.path.insert(0, "./lc") sys.path.append("./lc/150/1_easy") sys.path.append("./lc/150/2_medium") sys.path.append("./lc/150/3_hard") sys.path.append("./tests/data") if __name__ == "__main__": unittest.main()
- bottom of
test_lc.py
file:
import p0125_valid_palindrome class ValidPalindromeTest(unittest.TestCase): def base_test(self, s, expected): unit_test = p0125_valid_palindrome.Solution() got = unit_test.isPalindrome(s) self.assertEqual(got, expected) def test_1(self): s, expected = 0, 0 self.base_test(s, expected) pass
-
-
-
The most interesting part of this tool is that I got a chance to play with LeetCode’s GraphQL setup, and was able to tweak the input query to get the exact output that I wanted. I didn’t search for any documentation on using their system – just looked at the network requests that showed up while loading a problem. I was expected typical REST requests and was surprised to see them using GraphQL.
-
I have tested this extensively for
python3
usingunittest
on MacOs, not Windows or Linux. I expect you should be able to easily run this using WSL or on Linux – it is plain bash, nothing fancy.
TODOs (maybe) #
- Externalize the configuration - DONE in v0.0.2
- Create a cross-platform port of this in Golang which would be easier to download and run.
- Extend to support pytest
- Extend to support other languages (starting with Java, Go, Javascript, and Rust)
If you have found this useful, ran into bugs or issues using it, or if you are interested in having some other features or enhancements, drop a comment either here or in the mlc.sh Gist.