diff --git a/Makefile b/Makefile index ecbfafa..2aac5d0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ lint: golangci-lint run ./... -.PHONY: lint +problemset: + bash ./query-problem-set.sh > problemset.jsonl + +.PHONY: lint problemset diff --git a/create.sh b/create.sh index cd8458f..03bb6be 100755 --- a/create.sh +++ b/create.sh @@ -1,21 +1,30 @@ #!/bin/bash -num=$1 +id=$1 -echo "$num" | grep -q "^[1-9][0-9]\{,4\}$" || { - echo "Err: no valid number given" >&2 +echo "$id" | grep -q "^[1-9][0-9]\{,4\}$" || { + echo "Err: no valid problem ID provided." >&2 exit 1 } -parent=$((num / 100)) -pdir="solutions/${parent}/q${num}" +parent=$((id / 100)) +pdir="solutions/${parent}/q${id}" + sol_file="${pdir}/solution.go" if [ -f "$sol_file" ]; then exit 0 fi -echo "Creating template for question No. $num" >&2 +title_slug=$(jq -r "select(.id == $id) | .titleSlug" ./problemset.jsonl) +[ -n "$title_slug" ] || { + echo "Err: problem $id not found in the problem set." >&2 + exit 1 +} + +echo -e "Creating template for problem \033[32m${id}: $title_slug\033[0m" >&2 mkdir -pv "$pdir" -echo "package q$num" > "$sol_file" +echo "// Package q$id implements solution for https://leetcode.com/problems/$title_slug/" > "$sol_file" +echo "package q$id" >> "$sol_file" + echo "Created $sol_file" diff --git a/query-problem-set.sh b/query-problem-set.sh new file mode 100644 index 0000000..72fa3a4 --- /dev/null +++ b/query-problem-set.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + +query() { + page=$1 + offset=$((page * 100)) + + # shellcheck disable=SC2016 + curl -sSLf 'https://leetcode.com/graphql/' \ + --compressed \ + -H 'content-type: application/json' \ + --data-raw '{ + "query": "\n query problemsetQuestionListV2($filters: QuestionFilterInput, $limit: Int, $searchKeyword: String, $skip: Int, $sortBy: QuestionSortByInput, $categorySlug: String) {\n problemsetQuestionListV2(\n filters: $filters\n limit: $limit\n searchKeyword: $searchKeyword\n skip: $skip\n sortBy: $sortBy\n categorySlug: $categorySlug\n ) {\n questions {\n id\n titleSlug\n title\n translatedTitle\n questionFrontendId\n paidOnly\n difficulty\n topicTags {\n name\n slug\n nameTranslated\n }\n status\n isInMyFavorites\n frequency\n acRate\n contestPoint\n }\n totalLength\n finishedLength\n hasMore\n }\n}\n ", + "variables": { + "skip": '"$offset"', + "limit": 100, + "categorySlug": "all-code-essentials", + "filters": {"filterCombineType":"ALL","statusFilter":{"questionStatuses":[],"operator":"IS"},"difficultyFilter":{"difficulties":[],"operator":"IS"},"languageFilter":{"languageSlugs":[],"operator":"IS"},"topicFilter":{"topicSlugs":[],"operator":"IS"},"acceptanceFilter":{},"frequencyFilter":{},"frontendIdFilter":{},"lastSubmittedFilter":{},"publishedFilter":{},"companyFilter":{"companySlugs":[],"operator":"IS"},"positionFilter":{"positionSlugs":[],"operator":"IS"},"positionLevelFilter":{"positionLevelSlugs":[],"operator":"IS"},"contestPointFilter":{"contestPoints":[],"operator":"IS"},"premiumFilter":{"premiumStatus":[],"operator":"IS"}}, + "searchKeyword": "", + "sortBy": {"sortField":"CUSTOM","sortOrder":"ASCENDING"}, + "filtersV2": {"filterCombineType":"ALL","statusFilter":{"questionStatuses":[],"operator":"IS"},"difficultyFilter":{"difficulties":[],"operator":"IS"},"languageFilter":{"languageSlugs":[],"operator":"IS"},"topicFilter":{"topicSlugs":[],"operator":"IS"},"acceptanceFilter":{},"frequencyFilter":{},"frontendIdFilter":{},"lastSubmittedFilter":{},"publishedFilter":{},"companyFilter":{"companySlugs":[],"operator":"IS"},"positionFilter":{"positionSlugs":[],"operator":"IS"},"positionLevelFilter":{"positionLevelSlugs":[],"operator":"IS"},"contestPointFilter":{"contestPoints":[],"operator":"IS"},"premiumFilter":{"premiumStatus":[],"operator":"IS"}} + }, + "operationName": "problemsetQuestionListV2" + }' | jq -c '.data.problemsetQuestionListV2.questions[] | { id, title, titleSlug, difficulty, paidOnly, tags: [ .topicTags[] | .slug ] }' +} + +page=0 +while true; do + echo -ne " Querying page $((page + 1)) ...\r" >&2 + content=$(query $page) + lines=$(echo "$content" | wc -l) + echo "$content" + + [ "$lines" -lt 100 ] && break + page=$((page + 1)) +done | jq -s -c 'sort_by(.id) | .[]' +echo >&2 diff --git a/solutions/1/q134/solution_test.go b/solutions/1/q134/solution_test.go deleted file mode 100644 index 34c42a2..0000000 --- a/solutions/1/q134/solution_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package q134 - -import ( - "testing" -) - -func Test_canCompleteCircuit(t *testing.T) { - tests := []struct { - name string // description of this test case - // Named input parameters for target function. - gas []int - cost []int - want int - }{ - { - gas: []int{1, 2, 3, 4, 5}, - cost: []int{3, 4, 5, 1, 2}, - want: 3, - }, - { - gas: []int{2, 3, 4}, - cost: []int{3, 4, 3}, - want: -1, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := canCompleteCircuit(tt.gas, tt.cost) - if got != tt.want { - t.Errorf("canCompleteCircuit() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/solutions/2/q238/solution_test.go b/solutions/2/q238/solution_test.go deleted file mode 100644 index 3fbfa57..0000000 --- a/solutions/2/q238/solution_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package q238 - -import ( - "slices" - "testing" -) - -func Test_productExceptSelf(t *testing.T) { - tests := []struct { - name string // description of this test case - // Named input parameters for target function. - nums []int - want []int - }{ - { - nums: []int{1, 2, 3, 4}, - want: []int{24, 12, 8, 6}, - }, - { - nums: []int{-1, 1, 0, -3, 3}, - want: []int{0, 0, 9, 0, 0}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := productExceptSelf(tt.nums) - if !slices.Equal(got, tt.want) { - t.Errorf("productExceptSelf() = %v, want %v", got, tt.want) - } - }) - } -}