Annotations Config
Annotations allow you to customize how your code is visualized during execution. By adding special comments at specific points in your code, you can control the visualization behavior to better suit your needs.
Available Annotations
@hist=<var1>,<var2>,...
Purpose:Switch the visualization of a 1D array to a histogram where element values determine bar heights.
Usage:
- Python/JavaScript:Place at the beginning of code files
- C++:Place above main function
- Variables must be non-negative 1D arrays
Examples:
// @hist=arr
const arr = [3, 1, 4, 2];
function visualizeData() {
// During visualization, arr will be displayed as a histogram
}
# @hist=scores,counts
scores = [85, 92, 78, 90]
counts = [10, 15, 8, 12]
def process_data():
# During visualization, scores and counts will be displayed as histograms
std::vector<double> bubbleSort(std::vector<double> arr) {
// During visualization, arr will be displayed as a histogram
}
//@hist=arr
int main() {
std::vector<double> result = bubbleSort(std::vector<double>{5, 2, 9, 1, 9, 9, 1, 2, 5.6, 0, 3});
return 0;
}
Generating interactive preview...
Use Cases:
- When needing to intuitively compare numerical values of array elements
- When analyzing data distribution characteristics
- When array values span a wide range suitable for height-based visualization
@ignore-function-tree
Purpose: Prevents the visualizer from drawing function call nodes in the visualization tree.
Usage: Place this annotation directly above a function definition.
Example:
// @ignore-function-tree
function traverseTree(node) {
if (!node) return;
traverseTree(node.left);
processNode(node);
traverseTree(node.right);
}
# @ignore-function-tree
def traverse_tree(node):
if node is None:
return
traverse_tree(node.left)
process_node(node)
traverse_tree(node.right)
Generating interactive preview...
Use Case: This annotation is particularly useful when:
- Visualizing recursive algorithms, especially tree traversals
- You want to focus on data structure operations rather than function calls
- The function call tree would add unnecessary complexity to the visualization
Instead of showing a new function node for each recursive call, the visualizer will only show the movement between tree nodes, making the visualization clearer and more focused on the algorithm's behavior.
@function-tree-once
Purpose: Prevents the visualizer from drawing function call nodes to multiple sub trees.
Usage: Place this annotation directly above a function definition.
Example:
// @function-tree-once
function expandAroundCenter(s, left, right) {
while (left >= 0 && right < s.length && s[left] === s[right]) {
left--;
right++;
}
return [left + 1, right - 1];
}
function longestPalindrome(s) {
let start = 0, end = 0;
for (let i = 0; i < s.length; i++) {
const [left1, right1] = expandAroundCenter(s, i, i);
const [left2, right2] = expandAroundCenter(s, i, i + 1);
if (right1 - left1 > end - start) {
start = left1;
end = right1;
}
if (right2 - left2 > end - start) {
start = left2;
end = right2;
}
}
return s.substring(start, end + 1);
}
longestPalindrome("babadcda")
# @function-tree-once
def expandAroundCenter(s, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return left + 1, right - 1
def longestPalindrome(s: str) -> str:
start, end = 0, 0
for i in range(len(s)):
left1, right1 = expandAroundCenter(s, i, i)
left2, right2 = expandAroundCenter(s, i, i + 1)
if right1 - left1 > end - start:
start, end = left1, right1
if right2 - left2 > end - start:
start, end = left2, right2
return s[start: end + 1]
longestPalindrome("babadcda")
Generating interactive preview...
Use Case: This annotation is particularly useful when:
-
You want to visualize recursive function calls but avoid redundant representations of the same function in different sub-trees.
-
The function call tree would otherwise become too cluttered with repeated instances of the same function.
-
You want to maintain a cleaner and more concise visualization of the algorithm's flow.
@skip-function
Purpose: Completely skips the visualization of the function's execution and directly returns the function's result.
Usage: Place this annotation directly above a function definition.
Example:
// @skip-function
function calculateSum(a, b) {
return a + b;
}
function main() {
const result = calculateSum(5, 10); // The visualization will skip the execution of calculateSum and directly show the result as 15
}
main();
# @skip-function
def calculate_sum(a, b):
return a + b
def main():
result = calculate_sum(5, 10) # The visualization will skip the execution of calculate_sum and directly show the result as 15
main()
Generating interactive preview...
Use Case: This annotation is particularly useful when:
- The function is a utility or helper function whose internal logic is not relevant to the visualization.
- You want to focus on higher-level operations and avoid cluttering the visualization with details of simple or well-understood functions.
- The function's execution is trivial or does not contribute significantly to the understanding of the algorithm.
Best Practices
- Place annotations on their own line directly above the relevant code
- Use annotations sparingly to maintain clear visualizations
- Consider your audience when deciding which parts of the execution to show or hide
Feedback and Suggestions
If you have ideas for new annotation types or improvements to existing ones, please feel free to contribute to the project or submit feature requests.