A simple Leetcode setup
whyš
Time to time I practice on platforms like Leetcode, Codewars, and others. I needed a simple way of organizing the tasks and solutions, a possibility to edit codes in an IDE, running tests. The problem with default approach is that typically you need to "create a project", - so for Java it would be pom.xml and all that stuff; it works while you have just a few tasks, but it all dies when it is a hundred of them.
whatš
This is a simple approach that allows quick editing, running tests from CLI, ordering and organizing tasks, using IDE without bloating "projects".
files and foldersš
I practice with a few languages, so I have fodler structure per-language.
- create a folder where you will keep your coding art - for example,
katas - create per-language subfolders. For example,
katas/javaandkatas/ts(for TypeScript) - create folders for problems' complexity:
katas/java/easy,katas/java/medium,katas/java/hard. Repeat for each language.
VSCode workspaceš
Create katas/katas.code-workspace file and put the following content into it:
{
"folders": [
{ "path": "ts" },
{ "path": "java" },
{ "path": "ocaml" },
{ "path": "lisp" }
],
"settings": {
// --- Keep the Java extension relaxed (important) ---
"java.import.maven.enabled": false,
"java.import.gradle.enabled": false,
"java.project.importOnFirstTimeStartup": "disabled",
"java.configuration.updateBuildConfiguration": "disabled",
// Avoid aggressive indexing of random folders
"search.exclude": {
"**/.git": true,
"**/.idea": true,
"**/target": true,
"**/.gradle": true,
"**/node_modules": true,
"**/_build": true
},
"files.watcherExclude": {
"**/.git/**": true,
"**/.idea/**": true,
"**/node_modules/**": true
}
}
}
So, now you can open in VSCode the workspace you just created, it will open the folder and show you the files tree.
configuring TypeScriptš
For TypeScript solutions I use Deno - "the open-source JavaScript runtime for the modern web". Go to their website and install it.
configuring Deno for VSCodeš
I use VSCode. If you use something else, you can skip this section.
Install Deno VSCode extension - that will help
To fix VSCode warnings, create katas/ts/.vscode/settings.json with the following content:
{
"deno.enable": true,
"deno.unstable": true
}
To enable Deno only in the TypeScript folder, create katas/.vscode/settings.json with the following content:
{
"deno.enable": false
}
using the TypeScript approachš
Create a new file katas/ts/easy/kata.test.ts:
// code - here you write your solution
export function sum(a: number, b: number) { return a + b; }
// tests - here you put your tests
Deno.test("sum works", () => {
if (sum(2, 3) !== 5) throw new Error("nope");
});
And now you can run it - open a terminal in the katas folder and run the command: deno test ts/easy/kata.test.ts:
~/katas deno test ts/easy/kata.test.ts
Check file:///Users/as/katas/ts/easy/kata.test.ts
running 1 test from ./ts/easy/kata.test.ts
sum works ... ok
ok | 1 passed | 0 failed
What happened is that it run the test, the test run the solution function, 1 test passed and 0 tests failed.
configuring Javaš
For Java solutions I use JBang. Go to their website and install it.
adding common libš
With Java, it is usually convenient to have a set of helpers. So, create katas/java/common/CommonBase.java:
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import java.io.PrintWriter;
/**
* This class contains common test-running logic and helper utilities.
* It will be "included" by individual problems files.
* * JBang will automatically pull in the //DEPS from this file.
*/
public class CommonBase {
/**
* A reusable test runner.
* @param testClasses The specific test class(es) to run.
*/
public static void runTests(Class<?>... testClasses) {
var launcher = LauncherFactory.create();
var listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
var requestBuilder = LauncherDiscoveryRequestBuilder.request();
// Discover all test classes passed as arguments
var selectors = new java.util.ArrayList<DiscoverySelectors>();
for (var testClass : testClasses) {
requestBuilder.selectors(DiscoverySelectors.selectClass(testClass));
}
launcher.execute(requestBuilder.build());
var summary = listener.getSummary();
var writer = new PrintWriter(System.out);
summary.printTo(writer);
writer.flush(); // Make sure all output is printed
// Exit with a non-zero code if tests failed
if (summary.getTestsFailedCount() > 0) {
System.out.println("\nš„ Some tests FAILED!");
System.exit(1);
} else {
System.out.println("\nā
All tests PASSED!");
}
}
/**
* A helper class for common LeetCode utilities.
* Example: public static ListNode buildList(int[] vals) { ... }
* Example: public static TreeNode buildTree(Integer[] vals) { ... }
*/
public static class Helpers {
// Example helper:
public static void printArray(int[] arr) {
System.out.println(java.util.Arrays.toString(arr));
}
// Add your other common helpers here
}
}
So it helps with running tests and various helpers can be placed here as well.
using the Java approachš
Create a test solution katas/java/easy/TwoSum.java
//DEPS org.junit.jupiter:junit-jupiter:5.10.2
//DEPS org.junit.platform:junit-platform-launcher:1.10.2
//SOURCES ../common/CommonBase.java
// We can import the test tools and helpers from the included file
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
/**
* This is the main file for the TwoSum problem.
*/
public class TwoSum {
// --- SOLUTION CLASS ---
class Solution {
public int[] twoSum(int[] nums, int target) {
java.util.Map<Integer, Integer> map = new java.util.HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
return null;
}
}
// --- END OF SOLUTION CLASS
// --- JUNIT TESTS ---
static class TwoSumTests {
@Test
void testExample1() {
Solution sol = new TwoSum().new Solution();
int[] nums = {2, 7, 11, 15};
int target = 9;
// You can use your helpers!
// printArray(sol.twoSum(nums, target));
assertArrayEquals(new int[]{0, 1}, sol.twoSum(nums, target));
}
@Test
void testExample2() {
Solution sol = new TwoSum().new Solution();
int[] nums = {3, 2, 4};
int target = 6;
assertArrayEquals(new int[]{1, 2}, sol.twoSum(nums, target));
}
}
// --- END OF JUNIT TESTS
/**
* The main entry point.
* All it does is tell the CommonBase to run this file's tests.
*/
public static void main(String[] args) {
System.out.println("Running tests for TwoSum...");
CommonBase.runTests(TwoSumTests.class);
}
}
Now run command: jbang java/easy/TwoSum.java
This is what you should see if everything works:
Running tests for TwoSum...
Test run finished after 41 ms
[ 2 containers found ]
[ 0 containers skipped ]
[ 2 containers started ]
[ 0 containers aborted ]
[ 2 containers successful ]
[ 0 containers failed ]
[ 2 tests found ]
[ 0 tests skipped ]
[ 2 tests started ]
[ 0 tests aborted ]
[ 2 tests successful ]
[ 0 tests failed ]
ā
All tests PASSED!
conclusionš
I have a very simple approach of editing and testing code problems for platforms such as Leetcode and others.