leezy: leetcode helper for the lazy

# Quick Start

## Install

Requirements:

• Python >= 3.6
• requests >= 2.18.0
• pytest >= 5.1.3

$pip install leezy  ## Examples 1. 拉取题目 在终端进入刷题目录： $ leezy pull 1

$tree . └── 001 - Two Sum ├── 001.html # 题目描述，在浏览器或者其他html预览器中查看 └── 001_two-sum.py # solution模板，在这里编辑解法  # 001_two-sum.py(initial) from leezy import Solution, solution class Q001(Solution): # 继承Solution @solution # 被solution装饰的函数将参与最后的结果输出或测试 def twoSum(self, nums, target): pass def main(): q = Q001() q.add_case(q.case([2, 7, 11, 15], 9)) # 添加自己的测试用例 q.run() if __name__ == "__main__": main()  1. 尝试死磕多种解法 # 001_two-sum.py(modified) from leezy import Solution, solution class Q001(Solution): @solution def twoSum(self, nums, target): for i,x in enumerate(nums): for j, y in enumerate(nums[i+1:], i+1): if x + y == target: return [i, j] @solution def twoSum_sort(self, nums, target): L, i, j = len(nums), 0, len(nums)-1 sorted_i = sorted(range(L), key=nums.__getitem__) while i < j: s = nums[sorted_i[i]] + nums[sorted_i[j]] if s > target: j -= 1 elif s < target: i += 1 else: return [sorted_i[i], sorted_i[j]] @solution def twoSum_hash(self, nums, target): hash_table = {} for i, x in enumerate(nums): another = target - x if x in hash_table: return [hash_table[x], i] else: hash_table[another] = i def main(): q = Q001() q.add_case(q.case([3, 2, 4], 6)) q.add_case(q.case([3,3], 6)) q.add_case(q.case([2, 7, 11, 15], 9)) q.add_case(q.case([2, 7, 11, 15], 17)) q.add_case(q.case([2, 7, 11, 15], 26)) q.run() if __name__ == "__main__": main()  1. 运行/查看结果 $ python "001 - Two Sum\001_two-sum.py"
+----------+----------+---------------+---------------+
|          |  twoSum  |  twoSum_sort  |  twoSum_hash  |
+==========+==========+===============+===============+
|  case 0  |  [1, 2]  |  [1, 2]       |  [1, 2]       |
+----------+----------+---------------+---------------+
|  case 1  |  [0, 1]  |  [0, 1]       |  [0, 1]       |
+----------+----------+---------------+---------------+
|  case 2  |  [0, 1]  |  [0, 1]       |  [0, 1]       |
+----------+----------+---------------+---------------+
|  case 3  |  [0, 3]  |  [0, 3]       |  [0, 3]       |
+----------+----------+---------------+---------------+
|  case 4  |  [2, 3]  |  [2, 3]       |  [2, 3]       |
+----------+----------+---------------+---------------+

1. 执行测试

# 001_two-sum.py(modified, testcase-added)

...

def main():
q = Q001()
q.add_case(q.case([2, 7, 11, 15], 9).assert_equal([0, 1]))
q.add_case(q.case([2, 7, 11, 15], 17).assert_equal([0, 3]))
q.add_case(q.case([2, 7, 11, 15], 26).assert_equal([2, 3]))
q.run()


$python "001 - Two Sum\001_two-sum.py" +----------+----------+-----------+ | | twoSum | two_sum | +==========+==========+===========+ | case 0 | [1, 2] | [1, 2] | +----------+----------+-----------+ | case 1 | [0, 1] | [0, 1] | +----------+----------+-----------+ ......... [100%] 9 passed in 0.09s  此外，测试用例支持assert_true_with(fn)，传入自定义测试函数。比如第1054题，要求结果数组相邻的两个数不相等，因此可以构建如下的测试函数 from itertools import chain from collections import Counter class Q1054(Solution): @solution def rearrangeBarcodes(self, barcodes): # 452ms 92.03% N = len(barcodes) idx = chain(range(0, N, 2), range(1, N, 2)) counter = Counter(barcodes) ans = [0] * N for x, cnt in counter.most_common(): for _ in range(cnt): ans[next(idx)] = x return ans def main(): q = Q1054() def check(A): return all(x != nx for x, nx in zip(A, A[1:]) q.add_case(q.case([1, 1, 1, 2, 2, 2]).assert_true_with(check)) q.add_case(q.case([1, 2, 2, 2, 5]).assert_true_with(check)) q.add_case(q.case([1, 1, 1, 1, 2, 2, 3, 3]).assert_true_with(check)) q.run()  # Why leezy? leezy名字来自于leetcode和lazy的组合。懒惰就是生产力。 如果你有以下标签所描述的倾向，leezy可能会给你一些参考： 【第一遍刷Leetcode】【使用本地编辑器】【愿意尝试一题多解】【少些重复print、测试用例】 还可以通过下面的问题进一步了解为什么要使用leezy • 为什么不在线刷题？ 在线编辑器没有智能提示，run code的速度不稳定，不适合初期的debug。 因为是第一次做题，希望把重点放在解题本身，环境就使用自己习惯的就好。 在本地通过自己构想的测试用例后，再到网上提交。如果是第n遍刷题了，直接上web更方便。 当然本地刷题也有利于随时翻查复习啦 • leezy的核心是什么？ 少写print，少写重复测试用例。和上面提到的标签所暗示的那样，做题大概率不能一次成功，需要在本地用自己的测试用例反复运行，打印结果，修改。当使用多个解法时，又需要重复这些工作。所以一次性写完这些重复的print、测试用例就是leezy最最平常且简单的目的 • 和其他刷题工具有什么区别？ 其他的刷题工具，典型的有基于CLI的leetcode-cli, 基于VSCode的leetcode for vscode(也基于leetcode-cli)，都支持完整的刷题流程：用户登录、题目拉取、编写、测试、提交、查看统计数据。本质是把网页版的功能在用另一套接口进行实现。 leezy仅仅把目标放在拉取、编写、测试上。相比上述工具，leezy对题目拉取后，模板文件不再和网页上提供的模板一致，更方便实现一题多解的本地调试 # More things ## 命令行 使用leezy [command]完成拉取题目及设置相关操作 $ leezy -h
usage: leezy [-h] COMMAND [...]

optional arguments:
-h, --help  show this help message and exit

commands:
use 'leezy command -h' to see more

pull      拉取题目到本地文件
show      打印编号的题目
config    全局配置


usage: leezy config [-h] [--add | --unset | --list]

optional arguments:
-h, --help  show this help message and exit
--unset     name
--list


$leezy config --add table.max_col_width 50$ leezy config --add table.max_content_length -1

$leezy config --unset table  可用配置项： name description default table.max_col_width 表格列的最大宽度 40字符 table.max_content_length 每个单元格支持的最长内容长度，超过部分将被截断(-1表示不截断) 100字符 ## 辅助类 针对使用链表或者树结构的题目，也提供了和网页版类似的基础类型，初始化的参数也和网页版保持一致。 leezy.assists中导入 from leezy.assists import TreeNode, LinkedListNode t = TreeNode.make_tree([1, 2, 3, 4, 5, None, 6]) print(type(t)) # <class 'leezy.assists.TreeNode'> print(t) # Tree(1-2-3-4-5-None-6) print(t.left) # Tree(2-4-5) print(t.right) # Tree(3-None-6) l = LinkedListNode.make_linked_list([1, 2, 3, 4, 5]) print(type(l)) # <class 'leezy.assists.LinkedListNode'> print(l) # 1->2->3->4->5 print(l.next) # 2->3->4->5  现在支持的类型: • TreeNode • LinkedListNode 除了手动使用make_tree, make_linkedlist构造，还提供了TreeContext，LinkedListContext，将add_case传入的集合类型参数自动构造为树或链表。省得每次添加测试用例都要写make_*函数 from leezy import Solution, solution from leezy.assists import TreeContext # 导入TreeContext class Q700(Solution): @solution def searchBST(self, root, val): if root is None: return if root.val > val: return self.searchBST(root.left, val) elif root.val < val: return self.searchBST(root.right, val) else: return root @solution def search(self, root, val): while root: if root.val > val: root = root.left elif root.val < val: root = root.right else: return root return None def main(): q = Q700() q.set_context(TreeContext) # 设置TreeContex q.add_case(q.case([4, 2, 7, 1, 3], 2)) # 这里传入的列表自动会被转化为Tree q.run()  为了进一步简化，pull命令支持--context选项 $ leezy pull --context tree 700 701


## Project details

Uploaded Source
Uploaded Python 3