Home/Blog/Programming/Visualize Code in ASCII: N-Queens and More
Home/Blog/Programming/Visualize Code in ASCII: N-Queens and More

Visualize Code in ASCII: N-Queens and More

5 min read
Jan 22, 2024
content
Slide decks
ASCII printing
Use case 1: LRU cache
Use case 2: N-Queens problem

Become a Software Engineer in Months, Not Years

From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.

If you’re like me, you need to see a tool work in order to figure out how it works before being able to trust that it will indeed be good enough for the job at hand. In other words, like me, you’re more of a hands-on, visual learner. For people like us, seeing is essential for understanding—magic just doesn’t cut it. And in coding interview situations, the confidence that comes from knowing exactly what works how is the key to success.

Slide decks#

For this reason, we at Educative have made a concerted effort to use all the tools at our disposal to demystify even the most complex and subtle algorithms used in our coding interview prep material. For example, while revamping the course Coderust: Hacking the Coding Interview, a major improvement came in the form of slide decks that illustrated the working of an algorithm for a manageable input size. This was welcomed by our learners, as it made it easier to make the connections between the written description of the algorithm, the code itself, and the changing states of the data structures during code execution.

For example, the solution to the Sliding Window Median problem requires tracking two halves of a window as it slides across an array of numbers. To better support the written explanation of the solution, we added a slide deck to illustrate how we use two heaps, labeled "small list" and "large list," to accomplish this task.

canvasAnimation-image
1 / 19

However, such slides are limited in their utility in that they are a static illustration of an algorithm for a fixed set of inputs.

ASCII printing#

An important question that static slide decks cannot really answer is: "What do the data structures look like if I change the input like so?" Additionally, we may want to see the contents of the data structures used after making a small but critical change in the code in order to visually debug the code. To quickly address these concerns, we turned to ASCII printing to give our users a way to visually trace the execution of a solution.

Let's look at how a relatively simple bit of printing code can help us understand some subtle interactions as well as help us verify the output for specific test cases.

Use case 1: LRU cache#

The code below tests an implementation of a cache (the hidden class LRU Cache) with a Least Recently Used (LRU) eviction policy. It supports two methods: Set() and Get(). The Set() command adds the supplied key-value pair to our cache. If that key already exists, its value is updated. The Get() command fetches from the cache the value associated with the supplied key. If the key is not present in the cache, it returns 1−1.

In the test case setup section, we set up a sequence of Get() and Set() commands to test our cache. Looking at the code below, but before running it, can you guess the result of the function call Get(52)?

int main()
{
// Creating a cache of size 4
int cacheCapacity = 4;
LRUCache cache(cacheCapacity);
std::cout << "Initial state of cache" << std::endl;
std::cout << "Cache capacity: " << cacheCapacity << std::endl;
cache.Print();
// Test case setup
std::vector<int> keys = {51, 52, 53, 54, 51, 55, 52};
std::vector<std::string> values = {"51", "52", "53", "54", "151", "55", "Get"};
for (int i = 0; i < keys.size(); i++)
{
if (values[i] == "Get")
{
std::cout << "Getting by Key: " << keys[i] << std::endl;
std::cout << "Cached value returned: " << (cache.Get(keys[i])) << std::endl;
}
else
{
std::cout << "Setting cache: Key: " << keys[i] << ", Value: " << values[i] << std::endl;
cache.Set(keys[i], stoi(values[i]));
}
// cache.Print();
}
}
Implement LRU Cache

Now that you've run the code, if you were surprised that Get(52) returns 1-1, it could be because you hadn't realized that the recency criterion applies to both the Get() and the Set() operations. The mystery is easily solved by uncommenting(Windows/Linux: Ctrl + /, Mac: Command + /) the call to print the state of the cache (see the highlighted line inside the for-loop). Printing the contents of the cache after every operation allows us to simply see that the pair with key 5252 becomes the least recently used element when we issue the call Set(51, "151"). As a result, the next Set() operation causes the pair with key 5252 to be evicted from the cache.

Use case 2: N-Queens problem#

Here’s another example where printing helps to quickly check, just by looking at the output, whether the result for a specific test case is correct: the famous N-Queens problem.

N-Queens problem statement: Given a chessboard of size n×nn \times n, determine how many ways nn queens can be placed on the board, such that no two queens attack each other. A queen can move horizontally, vertically, and diagonally on a chessboard. One queen can be attacked by another queen if both share the same row, column, or diagonal.

In the code sample below, the implementation of the solution, Solve N Queens(), has not been shown:

int main() {
// printBoard = true;
std::vector<int> n = {4, 5, 6};
for (int i : n) {
std::cout << i-3 << ".\tQueens: " <<
i << ", Chessboard: (" << i << "x" << i << ")\n";
std::vector<std::vector<int>> results;
int res = SolveNQueens(i);
std::cout <<"\n\tTotal valid placements for " << i << " queens on a "
<< i << "x" << i << " chessboard: " << res << std::endl;
std::cout << std::string(100, '-') << std::endl;
}
}
N-Queens

After running this code, though we can check online whether the results are correct (since this is such a well-studied problem), we're left with the feeling that we don't really know what is going on. For example, why are there 1010 valid placements for the 5-Queens problem and only 44 for the 6-Queens problem? If only we could see the placements...

Tip: Un-comment the command (highlighted) that turns on the printing switch for this code sample, and then run it again.

Now that we can see the valid placements for each test case, we start to understand the problem better—which is the first step in understanding the solution.

In the next post in this two-part series, we'll delve into the code to print a binary tree, and use it to help us solve a thorny problem.

If this short blog post has whetted your appetite for problem-solving, you can dive right in to the challenging set of problems we have curated to help you prepare for your coding interview:

Get your hands dirty dissecting subtle algorithms!

Cover
Grokking the Coding Interview Patterns

With thousands of potential questions to account for, preparing for the coding interview can feel like an impossible challenge. Yet with a strategic approach, coding interview prep doesn’t have to take more than a few weeks. Stop drilling endless sets of practice problems, and prepare more efficiently by learning coding interview patterns. This course teaches you the underlying patterns behind common coding interview questions. By learning these essential patterns, you will be able to unpack and answer any problem the right way — just by assessing the problem statement. This approach was created by FAANG hiring managers to help you prepare for the typical rounds of interviews at major tech companies like Apple, Google, Meta, Microsoft, and Amazon. Before long, you will have the skills you need to unlock even the most challenging questions, grok the coding interview, and level up your career with confidence. This course is also available in JavaScript, Python, Go, and C++ — with more coming soon!

85hrs
Intermediate
371 Challenges
372 Quizzes

Frequently Asked Questions

Is there a way to visualize code?

One of the ways to visualize code is through a Code Map. A Code Map helps developers see their codebase structure in a graphical format. This is useful for grasping how different code parts connect, and it makes navigating the code simpler.

What is the N queens problem?

In the game of chess, the queen can move and attack in horizontal, vertical, and diagonal directions. The N-queens puzzle poses the question: What method can we use to position N queens on an NxN chessboard so that none of them are in a position to attack each other?


Written By:
Amanullah Kariapper

Free Resources