Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Skills and conventions for an educational algorithms and data structures repository. Use this skill whenever working on algorithm implementations, data structure code, LeetCode-style problems, graph theory, dynamic programming, or any Java-based educational coding project. Trigger on mentions of: algorithms, data structures, graph theory, sorting, searching, trees, DP, BFS, DFS, linked lists, heaps, segment trees, union-find, or any request to write, refactor, document, or test educational code.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 93% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 93% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 98% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 279% | 0% |
This skill defines the conventions and standards for an educational algorithms repository. The goal is to make every algorithm implementation clear, well-tested, and accessible to learners who may not have deep CS backgrounds.
Goal: Every file should teach, not just implement.
Every public method gets a doc comment that explains:
java/** * Finds the shortest path from a source node to all other nodes * using Bellman-Ford's algorithm. Unlike Dijkstra's, this handles * negative edge weights and detects negative cycles. * * @param graph - adjacency list where graph[i] lists edges from node i * @param start - the source node index * @param n - total number of nodes in the graph * @return dist array where dist[i] = shortest distance from start to i, * or Double.NEGATIVE_INFINITY if node i is in a negative cycle * * Time: O(V * E) — relaxes all edges V-1 times * Space: O(V) — stores distance array */
Comment the why, not the what. Focus on lines where the logic isn't obvious:
java// Relax all edges V-1 times. After V-1 passes, shortest paths // are guaranteed if no negative cycles exist. for (int i = 0; i < n - 1; i++) { for (Edge e : edges) { if (dist[e.from] + e.cost < dist[e.to]) { dist[e.to] = dist[e.from] + e.cost; } } } // If we can still relax an edge after V-1 passes, that node // is reachable from a negative cycle — mark it as -infinity. for (int i = 0; i < n - 1; i++) { for (Edge e : edges) { if (dist[e.from] + e.cost < dist[e.to]) { dist[e.to] = Double.NEGATIVE_INFINITY; } } }
Every file starts with a comment block explaining the algorithm in the file
java/** * Bellman-Ford Shortest Path Algorithm * * Computes single-source shortest paths in a weighted graph. * Handles negative edge weights and detects negative cycles. * * Use cases: * - Graphs with negative weights (where Dijkstra fails) * - Detecting negative cycles (e.g., currency arbitrage) * * Run with: * bazel run //src/main/java/com/williamfiset/algorithms/graphtheory:BellmanFordAdjacencyList * * @see <a href="https://en.wikipedia.org/wiki/Bellman-Ford_algorithm">Wikipedia</a> */
Goal: Every algorithm has tests that prove it works and teach edge cases.
Place tests alongside source files or in a tests/ directory. Name test files to mirror the source: BellmanFord.java → BellmanFordTest.java.
For every algorithm, cover these categories:
Use descriptive names that read like a sentence:
java@Test public void testShortestPathSimpleGraph() { ... } @Test public void testDetectsNegativeCycle() { ... } @Test public void testSingleNodeGraph() { ... } @Test public void testDisconnectedNodes() { ... }
Each test method gets a brief comment explaining what scenario it covers and why that scenario matters:
java/** * Graph with a negative cycle reachable from the source. * Bellman-Ford should mark affected nodes as NEGATIVE_INFINITY. * * 0 --5--> 1 --(-10)--> 2 --3--> 1 * (creates cycle 1→2→1 with net cost -7) */ @Test public void testDetectsNegativeCycle() { // ... test body }
Every code change must be accompanied by:
Goal: Keep the codebase clean without losing educational value.
Remove code that is:
Keep alternative implementations when they teach different approaches:
java// ✓ KEEP — BFS and DFS solutions to the same problem teach different techniques public int[] bfsSolve(int[][] grid) { ... } public int[] dfsSolve(int[][] grid) { ... } // ✓ KEEP — iterative vs recursive shows tradeoffs public int fibRecursive(int n) { ... } public int fibIterative(int n) { ... } // ✗ REMOVE — identical logic, just different variable names public int search_v1(int[] arr, int target) { ... } public int search_v2(int[] arr, int target) { ... }
When keeping alternatives, clearly label them with a comment explaining the educational purpose:
java/** * Recursive implementation of binary search. * Compare with binarySearchIterative() to see the iterative approach. * The iterative version avoids stack overhead for large arrays. */
When refactoring, scan for:
Goal: Uniform style across the entire repository.
Use short, clear variable names. Prefer readability through simplicity:
java// ✓ GOOD — short and clear int n = graph.length; int[] dist = new int[n]; boolean[] vis = new boolean[n]; List<int[]> adj = new ArrayList<>(); Queue<Integer> q = new LinkedList<>(); int src = 0; int dst = n - 1; // ✗ BAD — verbose names that clutter algorithm logic int numberOfNodesInGraph = graph.length; int[] shortestDistanceFromSource = new int[numberOfNodesInGraph]; boolean[] hasNodeBeenVisited = new boolean[numberOfNodesInGraph]; List<int[]> adjacencyListRepresentation = new ArrayList<>(); Queue<Integer> breadthFirstSearchQueue = new LinkedList<>(); int sourceNodeIndex = 0; int destinationNodeIndex = numberOfNodesInGraph - 1;
Common short names (use consistently across the repo):
| Name | Meaning | |--------|-------------------------------| | n | number of elements/nodes | | m | number of edges | | i, j | loop indices | | from, to | graph node endpoints | | cost | edge weight | | dist | distance array | | vis | visited array | | adj | adjacency list | | q | queue | | pq | priority queue | | st | stack | | dp | dynamic programming table | | ans | result/answer | | lo | low pointer/bound | | hi | high pointer/bound | | mid | midpoint | | src | source node | | dst | destination node | | cnt | counter | | sz | size | | cur | current element | | prev | previous element | | next | next element (use nxt if shadowing keyword) |
if (...) {)Always use explicit multiplication and parentheses in Big-O expressions for clarity:
java// ✓ GOOD — explicit and unambiguous // Time: O(n*log(n)) // Time: O(n*log^2(n)) // Time: O(n^2*log(n)) // ✗ BAD — missing multiplication and parentheses // Time: O(n log n) // Time: O(n log^2 n) // Time: O(n^2 log n) // Simple expressions without multiplication are fine as-is // Time: O(n) // Time: O(n^2) // Time: O(log(n)) // Space: O(n)
Always place the body of a for loop on its own line, even for single statements. This improves readability, especially in nested loops:
java// ✗ BAD — body on same line as for for (int j = 0; j < n; j++) augmented[i][j] = matrix[i][j]; // ✓ GOOD — body on its own line for (int j = 0; j < n; j++) augmented[i][j] = matrix[i][j]; // ✓ GOOD — nested for loops, each level on its own line for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) for (int k = 0; k < n; k++) result[i][j] += m1[i][k] * m2[k][j];
Streams hurt readability for learners. Use plain loops instead:
java// ✗ AVOID — streams obscure the logic for beginners int sum = Arrays.stream(arr).filter(x -> x > 0).reduce(0, Integer::sum); // ✓ PREFER — a loop is immediately readable int sum = 0; for (int x : arr) { if (x > 0) sum += x; }
Goal: The simplest correct code teaches the best.
java// ✗ AVOID — deep nesting if (node != null) { if (node.left != null) { if (node.left.val == target) { return true; } } } return false; // ✓ PREFER — early returns keep code flat if (node == null) return false; if (node.left == null) return false; return node.left.val == target;
Arrays.sort(), Collections.swap(),Math.min(), etc. are fine because learners need to know these exist
int[] is clearer than ArrayList<Integer> when the size is known
Goal: Catch bugs proactively whenever touching code.
When modifying any lines of code, actively check for and report:
== vs <=, < vs <= in loop conditionsi+1, i-1 without range checksWhen a bug is found, report it clearly:
🐛 BUG FOUND in BellmanFord.java line 42:
Loop runs `i < n` but should be `i < n - 1`.
The extra iteration incorrectly marks reachable nodes as
being in a negative cycle.
FIX: Change `i < n` to `i < n - 1`Goal: Help learners understand the why behind each algorithm.
Goal: The main java method should be near the bottom of the Java file for consistency throughout the project
Other measured skills in the registry, with their headline benchmark lift.