Red-Green-Code

Deliberate practice techniques for software developers

  • Home
  • About
  • Contact
  • Project 462
  • CP FAQ
  • Newsletter

Lessons from Competitive Programming 3, Chapter Two

By Duncan Smith Leave a Comment Nov 11 3

CP3Chapter2

This post is part of a series of commentaries covering each chapter of Competitive Programming 3 by Steven and Felix Halim. You can find the rest of the posts in the series by visiting my CP3 post category.

Competitive Programming 3 (CP3) Chapter 2 covers a selection of data structures that are useful for solving competitive programming problems. These data structures are used in the Chapter 2 uHunt problems, and in subsequent chapters in the book. In some cases, Chapter 2 just provides a brief introduction to topics that are covered extensively elsewhere. For example, Section 2.4.1 covers some basic information about representing a graph, while Chapter 4 contains the book’s full treatment of graph algorithms. And Section 2.2 devotes a paragraph each to common data structures like arrays, stacks and queues, which readers are expected to know about already. In other cases, Chapter 2 goes into more depth. For example, it’s harder to find information about the Segment Tree data structure in other sources, so it is covered in more detail in this chapter.

As in the rest of the book, each section in this chapter ends with a list of recommended UVa Online Judge problems. The same list can be found on uHunt, where you can also track your progress.

In addition to UVa OJ problems, each section also has written problems. For example, a question in the section on stacks and arrays asks the reader how to implement a stack using an array. Answers are supplied for some of these problems at the end of the chapter. I have just been skimming these written problems. The appeal for me of the CP3/uHunt approach is that problems are “graded” automatically by a computer. Solving problems and then looking up answers at the end of the chapter is the traditional textbook self-study approach. While that can be useful, especially you have a peer or instructor to review your written answers, my goal in using this book is learning through coding. I found plenty of opportunities to learn about the Chapter 2 data structures while I was solving the corresponding uHunt problems.

« Continue »

Lessons from uHunt Chapter Two

By Duncan Smith Leave a Comment Nov 4 0

uHunt Chapter 2

This post is part of a series that considers what can be learned from the problems in each chapter of uHunt, a tool for competitive programming practice. You can find the rest of the posts in the series by visiting my uHunt post category.

I recently finished the last of the 37 starred problems in uHunt Chapter 2. I’m solving these problems as part of a learning project that I’m calling Project 462, after the 462 uHunt starred problems.

Chapter 2 highlights problems that require more specific data structures than the ad-hoc problems in Chapter 1. The chapter starts out with arrays, covers familiar data structures like stacks and queues, and ends with problems that use Segment Trees and Fenwick Trees, data structures that you may not have heard about in college.

The uHunt approach is to categorize problems by the algorithm, data structure or technique that the authors recommend using to solve them. In addition to the category, each problem has a level — generally 1 through 4 — indicating its difficulty level. The Chapter 2 problems mostly use the same range of levels as the Chapter 1 problems. But for each Chapter 2 problem, there is an extra step of learning or reviewing the appropriate data structure. Although they start with a data structure recommendation, most Chapter 2 problems still require problem-solving techniques and creative thinking.

In many competitive programming situations, you won’t know which data structure to use in advance. The goal of the uHunt style of practice is to get familiar with the range of problems that you’ll come across, so that you know which data structure, algorithm, or technique to use when you see a similar problem in the future.

« Continue »

Solving UVa 11402 with Segment Trees

By Duncan Smith Leave a Comment Oct 28 5

Pirate

UVa 11402: Ahoy, Pirates! is one of the most challenging of the uHunt starred problems I have come across so far, for a few reasons:

  • The problem is designed to be solved using a segment tree. This is a data structure that comes up in competitive programming, but isn’t covered in the standard algorithms textbooks (e.g., Sedgewick or CLRS). So I studied it for the first time in preparation for solving this problem.
  • A static segment tree like the one described in Wikipedia, is not sufficient. Solving this problem requires a segment tree that implements lazy propagation so that updates can be made efficiently.
  • As an extra challenge, the problem author added the requirement for an “invert” operation. This adds some implementation complexity and means a generic segment tree implementation won’t work.
  • Java solutions seem to run very close to the time limit, which is a generous five seconds for this problem. Even an efficient solution that addresses the previous points may nevertheless need some additional performance tweaking to run fast enough.

Read on for solutions to these issues, and an explanation of how to go about coding a solution.

« Continue »

Software Methodologies for Very Small Teams

By Duncan Smith Leave a Comment Oct 14 0

Bootstrap DNA

When I was working on my undergraduate degree in Computing and Software Systems, I took a class in software engineering. The purpose of this class was to introduce us to the range of real-world processes that professionals use to develop software, processes that didn’t often come up in our academic work. That goal turned out to be a tall order for a three-month class, given the scope it tried to cover. It might have been more effective to pick one process and use it for a group project. Nevertheless, one exercise I remember from the class is matching software development processes to types of projects.

Here’s the type of question I’m talking about, from a University of New Brunswick class assignment:

Giving reasons for your answer based on the type of system being developed, suggest the most appropriate generic software process model that might be used as a basis for managing the development of the following systems:

a) A system to control anti-lock braking in a car

b) A virtual reality system to support software maintenance

c) A university accounting system that replaces an existing system

d) An interactive travel planning system that helps users plan a journey with the lowest environment impact

« Continue »

Using Integers and Longs in Java

By Duncan Smith Leave a Comment Oct 7 0

101010

Programming puzzles frequently involve manipulation of integers. And even problems that are mainly about string manipulation, character sets, or floating point arithmetic need integers for array indexes and counters. So it pays to know how to use them. In this article, I’m going to cover some of the quirks of integers and longs as implemented in Java.

« Continue »

What is competitive programming?

By Duncan Smith Leave a Comment Sep 16 0

Rating Distribution

What is competitive programming? Here are a few definitions.

From Wikipedia:

Competitive programming is a mind sport usually held over the Internet or a local network, involving participants trying to program according to provided specifications. … A programming competition generally involves the host presenting a set of logical or mathematical problems to the contestants … [who] are required to write computer programs capable of solving each problem. Judging is based mostly upon number of problems solved and time spent for writing successful solutions, but may also include other factors.

« Continue »

Stack Overflow vs. Competitive Programming Questions

By Duncan Smith Leave a Comment Sep 9 1

Stack Overflow

I like to keep an eye on what people are saying about competitive programming, so I subscribe to a Google Alert for that phrase. Almost every day, I get a few results. While programmers are opinionated about a lot of things, this topic seems to bring out especially strong opinions. Here are some places where you might see discussions about competitive programming:

Quora

Quora has more posts containing this phrase than any other single site. When it comes to competitive programming, Quora users are surprisingly tolerant of repetitive questions, beginner questions, very specific questions, and just plain weird questions. Despite the deluge of questions, experienced competitive programmers hang out on Quora and provide advice. If you’re interested in the topic, Quora is a good place to find answers.

A famous Quora question about competitive programming: How is competitive programming different from real-life programming?

Contest sites

Forum and blog posts from the contest sites (TopCoder, CodeForces, CodeChef, etc.) sometimes show up in the results, but not as much as you might think. This is probably because people don’t need to specifically use the “competitive programming” phrase in their posts. What else would people be talking about on those sites?

A secret Facebook group, announced on CodeForces: Rebirth of competitive programming group

News sites

When something happens in the world of competitive programming, like a major contest or a well-known competitive programmer switching jobs, it is sometimes picked up by a news site. Then other news sites who can’t afford to write their own stories copy the first news site, resulting in a flurry of alerts for the same story.

This article showed up on a number of sites: How Competitive Coding Platforms Are Changing the Tech Hiring Landscape

Educational sites and blogs

This category covers sites that write about competitive programming for the purpose of learning and education. It includes blogs like this one, as well as the occasional announcement of an in-person event like a class or meetup.

A local competitive programming group (if you live in Boston): Boston Code Dojo – Competitive Programming

Sorry, wrong number

Television programming (i.e., TV shows) is also a type of “competitive programming.” Fortunately these don’t appear too often, so they don’t really clutter the results.

What’s this professional wrestling story doing in my programming feed?: “compete with competitive programming“

Reddit

Reddit has a lot of programming discussion, and sometimes the topic of competitive programming comes up. Because it’s Reddit, there are often strong opinions. But usually both sides speak up.

/r/learnprogramming is happy to answer these kinds of questions: Need some tips for competitive programming

GitHub

It’s common to post competitive programming solutions on GitHub, and sometimes these show up if people use the term in their readme files or code comments.

Don’t click if you think macros are evil: Basic C++ Template for Competitive Programming

Stack Overflow

Once or twice per week, a question from Stack Overflow (or occasionally one of the other Stack Exchange sites) will show up in an alert. You might expect this. After all, Stack Overflow is the leading site for programming Q&A, and competitive programmers have questions like any other programmers. But clicking on the links to these questions leads to very different results from clicking on links to similar Quora questions, for reasons having to do with Stack Overflow’s moderation culture.

« Continue »

Getting Started With UVa Online Judge: The 3n+1 Problem

By Duncan Smith Leave a Comment Sep 2 0

LotharCollatz

If you’re interested in competitive programming, or you just like solving programming puzzles, UVa Online Judge is not a bad place to start. During the many years that it has been active, people have written books, supporting web sites, and sample code to help programmers get more out of it.

As my contribution to the ongoing commentary on UVa OJ problems, I have been working through and writing about the CP3 starred problems, a subset of UVa OJ problems recommended by the authors of a companion textbook called Competitive Programming 3.

But this week I’m picking a problem that is not on that list: the popular problem #100, also known as The 3n+1 Problem. The origin of problem #100 is the Collatz conjecture, a mathematical conjecture posed by the German mathematician Lothar Collatz, pictured above.

Since I want my friends to keep calling me, I won’t be trying to prove this conjecture (which remains an open problem as of this writing). Instead, I’ll just be writing a short program to count the elements in the sequences generated by the $3n+1$ algorithm. Along the way, I’ll explain a process that you can use when you’re solving other UVa OJ problems.

« Continue »

Solving UVa 978 With Unit Tests

By Duncan Smith Leave a Comment Aug 26 0

Lemming

Last week, I wrote about how unit testing can improve your competitive programming practice. As promised, this week I’m going to go through an example of the unit testing process. For an example problem, I’ll be using UVa 978: Lemmings Battle! See above for a picture of a ferocious lemming.

Problem Summary

Lemmings Battle! is rated Level 4 on uHunt, but I found it to be more of a Level 3 problem. It can be solved by simulating the game rules presented in the problem statement, and I didn’t run into any issues related to runtime performance. Other than getting the details of the simulation right, the only potential challenge is what primary data structure to use. uHunt suggests a TreeSet, but I found a TreeMap to be more appropriate.

Here are the key points of this problem:

  • The goal is to simulate the outcome of a series of battles, and report the final result.
  • The warring parties are the green lemming army and the blue lemming army.
  • The starting conditions consist of a fixed number of battlefields and a list of lemmings on each side. Each lemming starts with a power level (an integer value).
  • At the beginning of each round, a pair of lemmings, one from each army, is assigned to each battlefield in descending order of power level.
  • During the round, each lemming pair fights. In each fight, the lemming with the higher power wins, but its power is reduced by an amount equal to the other lemming’s power. If the lemmings in the pair have equal power, both lemmings end the round with 0 power.
  • At the end of the round, lemmings with nonzero power are returned to their armies.
  • Rounds continue as long as both armies have lemmings available to fight.
  • The problem output must identify the winning army (if any) and the power values of surviving lemmings, in descending order.

TreeMap and TreeSet

In Java, the appropriate data structure to use for this problem is TreeMap or TreeSet. These are classes that both provide ways to efficiently store and retrieve objects in sorted order. You can look up the full list of similarities and differences between the two classes, but for the purpose of this problem, the important differences are:

  • TreeMap maps a key to its corresponding value. If you want to update or retrieve a single value, you have to know its key. With TreeSet, you just store the values. There are no keys, and therefore no way to look up a value directly, though you can retrieve the values in other ways, such as iterating through all of them or retrieving the first or last value.
  • TreeSet does not allow duplicate values. If you want to add an object to a TreeSet that matches one that it already contains, you need to remove the existing one first. Similarly, TreeMap doesn’t allow duplicate keys, since the key uniquely identifies the object to store or retrieve. However, objects that are equal to each other can be associated with multiple keys in a TreeMap.

We’ll use this information later on to pick the appropriate data structure to use to solve this problem.

JUnit

JUnit is a popular Java unit testing tool, and I’ll be using it for this example. To “install” JUnit, you just add its JAR file to your classpath. Links to the required JARs are available on the JUnit GitHub site.

Having JUnit in your classpath allows you to compile and run your test class, which we’ll get to shortly.

A Testable Solution Template

Having a template that you use to start each puzzle solution helps avoid repetitive typing. But a template that isn’t written with unit testing in mind isn’t likely to lead to a testable solution. To that end, I adjusted my standard template so that it works well with tests while also supporting the stdin/stdout model required by UVa Online Judge. That allows me to run tests locally and then submit the same Main.java code to UVa OJ without making any changes.

My updated Main.java template contains the testable code, and a new MainTest.java template contains a sample test.

The following aspects of the updated Main.java make it testable:

  • Input and output implementations are passed to a setupIO method rather than being hard-coded in the main method. This allows the Main class to use stdin for input by default, while giving the test class the option to override this implementation with a FileReader that reads from a test file.
  • Since the public static void main method is bypassed by the test class, it isn’t covered by tests. Therefore, it contains only the minimum code required to kick off the rest of the program. That code comes directly from the template, so there’s less chance of adding bugs to it in the course of solving a problem.
  • Most methods and instance variables are public so they can be called and inspected by the test class.

The other half of the testable template is MainTest.java, which contains the test code. Here are the key parts of that class:

  • The setUp method runs before each test method. It creates an instance of Main and sets up I/O to read the test input file.
  • Methods marked @Test are run by the test runner. They are run in arbitrary order, so they must be independent of each other.
  • Calling assertEquals is a simple way to verify that the result of a method call or the contents of an instance variable is what you expect it to be at a point in the test.

To run the tests in MainTest against the code in Main, use the following commands.

javac Main.java MainTest.java
java org.junit.runner.JUnitCore MainTest

If all goes well and your classpath is set correctly, you should get a result like this:

JUnit version 4.10
.
Time: 0.006

OK (1 test)

If any tests fail, you’ll get a stack trace indicating where the failure occurred.

Testing and Implementing

If we’re going to use unit testing for programming puzzles, we might as well consider using test-driven development (TDD).

Here’s how you could use TDD during the implementation step of a puzzle-solving process:

  • Based on your pseudocode, select a small part of the solution to implement.
  • Write test data and test code that together will verify this part of your implementation.
  • Run all of your tests, and ensure that they all pass except for the new one.
  • Write solution code that will make the new test pass.
  • Run all of your tests and ensure that they all pass.

If you repeat these steps as you work towards a complete solution, you should find yourself spending less time debugging at the end, since you’ll be verifying each part of your solution as you go.

Solving UVa 978

As an example of how TDD can work for programming puzzles, here’s a sequence of tests and implementation that results in a solution to UVa 978.

Process parameters

The template contains pre-tested functionality that we can use for free, including code that retrieves the number of test cases. So the first code we need to test is a method that retrieves the problem’s three parameters:

  • The number of battlegrounds
  • The number of green lemmings
  • The number of blue lemmings

For a puzzle solution, there are some advantages to declaring variables for these values at the class instance level. This also allows our test to do the following:

  • Call a processParams function.
  • Verify that all of the instance variables have the correct values, based on the numbers in the test data file.

For this first test, the actual values used in the test data aren’t too important, so we can use any reasonable numbers, or just use the sample input. Future tests will depend more on carefully-selected input.

With TDD, the idea is to start with a failing test, and write the minimal amount of code required to make it pass. How granular your tests should be, and therefore how little code you write between test runs, is up to you. For example, a compile error is considered a test failure. So if your test code calls processParams but you haven’t written a processParams function, you’ll get a cannot find symbol error from the compiler. This will prompt you to write that function. Whether you actually do the compile step, or just think about doing it, is your choice.

Even if you don’t run your test before you implement processParams, you should definitely run it after you create the method and the instance variables, but before you initialize them. That way you can verify that your test informs you when these variables are not set correctly. (They’ll be set to their default value of 0). It’s important to verify that your test can fail, since otherwise you might inadvertently create a test that can never fail, and therefore isn’t useful for verifying correctness.

Once you verify that your test fails, you can implement processParams and run your test again to verify that it passes.

Build armies

After the three initial parameters, the remainder of the input for each test case consists of a list of power levels for each lemming in the green and blue armies.

To store a list of integer values, we’ll need some kind of collection. It’s clear from the sample input that there can be multiple lemmings with the same power level. And it’s clear from the problem statement that the power value is the one we need to sort on, since the rules require us to use the lemming with the highest power as we’re assigning lemmings to battlefields.

For both TreeSet and TreeMap, duplicate values require special handling of some kind. My approach to handling duplicate power values is to use a second field to store the number of lemmings with a given power. If the collection contains a lemming with a particular power, and another lemming with the same power needs to be stored, I can increment the counter field. If there are multiple lemmings with the same power value and I remove one, I decrement the counter. I could do that with a TreeSet<Pair>, where Pair is a custom object containing two integer values (power and count). But updating the count would take an extra remove step, because Set.add() does nothing if the entry being added matches (according to compareTo) an existing entry. Therefore, I decided that TreeMap<Integer, Integer> is the more appropriate data structure. The first integer is the power level and the second integer is the count. Since two integers are exactly what we need to store, this also avoids having to implement a custom class with a custom compareTo method.

To encapsulate the counting logic required to use the TreeMap for storing multiple identical power values, I decided to implement a function putPower whose responsibility is to add a lemming to an army. To test that function, we can do the following:

  • Pass in a power value and verify that the count is 1.
  • Pass in the same power value again, and verify that the count is 2.
  • Run the test and verify that it fails.

You could also write other tests to verify other cases.

Then to implement the function:

  • Retrieve an entry from the army TreeMap using the power as a key.
  • If get returns null, then put the power with a count of 1.
  • Otherwise, increment the previous count by one.

Now that we have a way to add a lemming to an army, it’s easy to test and implement a buildArmies function to initialize the armies. To test it, just call it and verify that the largest power in each army is as expected based on the test data. To implement it, read the correct number of lines (based on the test case parameters) for each army and call putPower on each one.

Assign battlefields

At the beginning of each round, we need to assign lemmings to battlefields. To do that, we need a way to get the next lemming from an army, while following the lemming ordering rules. I created a getNextLemming function for that purpose. The rule from the problem statement is that the lemming with the highest power is always the next one to fight. So our test must verify that this is in fact the lemming that is retrieved. To implement getNextLemming, we can use the fact that TreeMap keys come out of the tree in sorted order. This is of course why we chose this data structure in the first place. TreeMap.pollLastEntry() removes and returns the lemming with the highest power value. The remaining step is to keep the count field up to date in cases where there are multiple lemmings with the highest power value.

Now that we have a way to get the correct lemming from an army, we can assign a lemming to each battlefield. A test of assignBattlefields is to verify that the highest-powered lemmings is assigned to the lowest-numbered battlefield. Implementing the function is just a matter of looping through each battlefield, and assigning to it the lemming returned by getNextLemming.

Fight!

Once battlefields are assigned, the lemmings can fight. To verify the result of a fight, we just need to verify that the power levels on a battlefield follow the problem rules: the power value of the higher-powered lemming drops by an amount equal to the power value of the lower-powered lemming, or both drop to 0 if the lemmings have equal power. To implement a fight round, we just loop through all of the battlefields and carry out those subtractions.

Send back

After the fights, surviving lemmings are sent back to their armies. To verify that this works correctly, we can check the power values and counts. To implement sendBackToArmies, we can re-use our putPower function: for each battlefield with a lemming of power greater than 0, call putPower for the appropriate army.

Loop

We now have almost everything written and tested, and we just need to string it together: For each test case, we call processParams and buildArmies, then repeatedly call assignBattlefields, fight, and sendBackToArmies until one or both armies are empty.

Print

The only remaining task is to print the results. The strings to be printed are listed in the problem statement, and are entirely based on the size of each army. The winning team has a nonzero army size, and the losing team has an empty army. For the winning team, we have to print the remaining lemming powers in descending order. This is just a matter of calling getNextLemming until it returns null.

We could test the printResults and printArmy functions using string comparisons, but it’s probably better just to diff the results with the sample output and with the expected results from tests cases found on uDebug.

I put the complete solution and tests as described on GitHub.

Thoughts on Implementing and Testing UVa 978

UVa 978 is a reasonable contest problem to use when trying out test-driven development:

  • It’s not trivial to solve. Both the on-paper solution and the implementation contain issues to think about.
  • It naturally breaks down into multiple short functions, each of which can be tested independently.
  • The natural solution breakdown doesn’t require any tweaks to fix runtime performance, as long as you use an appropriate tree for the main data structure. In other words, you don’t have to sacrifice design for performance.

The unit testing approach certainly presents unique challenges compared to a traditional puzzle-solving process. It may result in more code and more time spent, though it’s also possible that the tests lead to a concise solution and the careful approach results in less time spent debugging. But ultimately time and code size aren’t the main concern for beginning and intermediate students. Using unit tests for puzzle solutions is worthwhile if it results in a better understanding of the solution, and the problem-solving process. If you eventually get to the point where you’re optimizing your performance in live contests, you’ll probably drop the unit testing approach. But the experience you get writing solutions in this way will give you a valuable perspective on how to write the best solution you can.

(Image credit: Sander van der Wel)

Unit Testing Your Competitive Programming Solutions

By Duncan Smith Leave a Comment Aug 19 0

Test Well

A couple of months ago, I wrote an article about a type of unit test called a learning test. The goal of learning tests is improving your understanding of how code works, rather than verifying functionality or influencing design, the traditional goals of unit testing. This week, I’m going to discuss those traditional goals of unit testing, but in a less familiar context: testing solutions to programming puzzles.

As I wrote in the previous unit testing article, unit testing is a way to improve the design of your code, while giving you the freedom to refactor with less risk of regression. Some programmers question that these benefits are worth the cost of writing test code. But even programmers who are on board with unit testing in general might be skeptical about using the practice for puzzle solutions. Here are some reasons why it might seem difficult to justify:

« Continue »

  • « Previous Page
  • 1
  • …
  • 3
  • 4
  • 5
  • 6
  • 7
  • Next Page »

Stay in the Know

I'm trying out the latest learning techniques on software development concepts, and writing about what works best. Sound interesting? Subscribe to my free newsletter to keep up to date. Learn More
Unsubscribing is easy, and I'll keep your email address private.

Getting Started

Are you new here? Check out my review posts for a tour of the archives:

  • 2023 in Review: 50 LeetCode Tips
  • 2022 in Review: Content Bots
  • 2021 in Review: Thoughts on Solving Programming Puzzles
  • Lessons from the 2020 LeetCode Monthly Challenges
  • 2019 in Review
  • Competitive Programming Frequently Asked Questions: 2018 In Review
  • What I Learned Working On Time Tortoise in 2017
  • 2016 in Review
  • 2015 in Review
  • 2015 Summer Review

Archives

Recent Posts

  • Do Coding Bots Mean the End of Coding Interviews? December 31, 2024
  • Another Project for 2024 May 8, 2024
  • Dynamic Programming Wrap-Up May 1, 2024
  • LeetCode 91: Decode Ways April 24, 2024
  • LeetCode 70: Climbing Stairs April 17, 2024
  • LeetCode 221: Maximal Square April 10, 2024
  • Using Dynamic Programming for Maximum Product Subarray April 3, 2024
  • LeetCode 62: Unique Paths March 27, 2024
  • LeetCode 416: Partition Equal Subset Sum March 20, 2024
  • LeetCode 1143: Longest Common Subsequence March 13, 2024
Red-Green-Code
  • Home
  • About
  • Contact
  • Project 462
  • CP FAQ
  • Newsletter
Copyright © 2025 Duncan Smith