Interesting problems I encountered while coding for my job.
These are simplified of course, so you get only the essential “challenge”.
I had two sequences of values, similar to enumerations, for which I needed to know the differences. In my specific case, just the amount of unique items in each was enough. The items in both sequences were provided in ascending order. The amount of items can differ between both and even be 0.
(long OnlyA, long OnlyB, long Both) CountDifferences<T>(IEnumerator<T> a, IEnumerator<T> b) where T : IComparable<T>
As an example:a = [1, 2, 3, 5]
b = [1, 4, 5]
=> OnlyA=2, OnlyB=1, Both=2
The tricky part here was: The sequences were long. Very long. Just storing them in some data structure would take too many resources. I had to compare the two without storing the values and without a second look at any item.
I got a randomly ordered list of pairs of integers. What was required was a list of all those integers, ordered in such a way that the order of each pair still holds up. Which can of course only work if there are no cycles, so I had to catch that scenario if the data was corrupted and throw an Exception. The specific order didn’t matter, if there were multiple solutions.
int[] FlattenPairedOrder((int before, int after)[] individualOrders)
Example:
[(1, 2), (2, 3), (9, 4), (5, 7)] => [1, 2, 3, 5, 7, 9, 4]
In case you’re wondering: These pairs did in fact describe directed edges between nodes.
The input was a sequence of integers in ascending order without duplicates. I needed to split this sequence into chunks of continuous integers, meaning split at every point where two neighbors are more than one apart. Additionally, each block may not exceed a predefined maximum of numbers.
IEnumerable<(int From, int To)> SplitInBlocks(IEnumerator<int> individual, int maxBlockSize)
Example:
individual = [-1, 1, 2, 4, 5, 6, 7, 8, 10]
maxBlockSize = 3
=> [(-1, -1), (1, 2), (4, 6), (7, 8), (10, 10)]
If this doesn’t seem like much of a challenge, it’s because it isn’t. The part that made this stick in my mind was not the overall “how do I solve this problem”, but the specific “how do I translate that in code”.
We had a situation where a large set of data contained some corruption. We didn’t know what kind, or where, or how much. All we had was the info that a certain operation, which takes all the data at once, failed. Splitting the data apart was easy, but testing for the problem could only be done by passing it into a method and see if it fails. And that method unfortunately takes quite a bit of time, regardless of how much data is passed into it. The goal now was to find all defective parts of the data while keeping the number of checks to a minimum.
List<int> FindCorruptValues(List<int> values, Func<List<int>, bool> hasCorruptData)
Example:
values = [1, 4, 5, 10, 20, 22, 999, 1000]
hasCorruptData = v => v.Any(i => i > 10 && i < 100)
=> [20, 22]
The obvious solution would be a form of binary search, just keep in mind that there can be several corrupt values, not just one!
This last one isn’t exactly an abstract issue, but it is an interesting problem that I had to solve at one time. We have a system that has to trigger certain actions from time to time. To control when exactly this happens, we use cron syntax. Which is essentially a filter for giving you a yes or no to a specific time. What I needed know however, was how long the system is going to sleep before triggering again.
This one won’t get any examples, I think it’s pretty clear what to expect.
I recommend you create your own cron implementation before solving the problem. The syntax isn’t hard to parse, and it will help you greatly in understanding exactly what values and combinations are possible. Also, try to find a solution other than simply checking every minute until one matches.
