UVa 10706. Number Sequence with F#

This post describes an algorithm to solve UVa 10706: Number Sequence problem from UVa OJ. Before outlining the algorithm, we first give an overview of this problem in the next section.

Interpretation

This is a straight-forward problem, which however, requires careful introspection. Our objective is to write a program that compute the

value of a sequence

, which is comprised of the number groups

. Each

consists of positive integers

written one after another and thus, the first

digits of

are --11212312341234512345612345671234567812345678912345678910123456789101112345678910

It is imperative to note that, the value of

has the following range

. Realize that, the maximum value of

is indeed Int32.MaxValue. In the provided test cases, the values of

are stated. We simply have to compute

; therefore, we are required to write a function

that has following signature:

.  That is --f: 10 --> S.[10] = 4 f: 8  --> S.[8]  = 2 f: 3  --> S.[3]  = 2

Note also that the maximum number of test cases is 25. Question for the reader: What is the maximum possible value of

for the specified sequence

, which is constituted of

?

We hope that by this time, it is clear where we are headed towards. In next section, we outline an algorithm to solve this problem. But, before moving further, we would like to recommend you to try to solve it yourselves first and then, read the rest of the post. By the way, we believe that the solution that we have presented next can be further optimized (or, even a better solution can be derived). We highly welcome your feedback regarding this.

Algorithm

Recall that,

is constituted of number groups

. In order to identify the digit located at the

position of

, we first determine the number group

that

digit is associated with and then, we figure out the

digit from

.

To do so, we first compute the length of each number group

. Consider the number group till

--112123123412345123456…12345678910

As mentioned, this sequence is basically constituted of

as shown below (with their respective lengths).1                    --> 1 1 2                  --> 2 1 2 3                --> 3 1 2 3 4              --> 4 1 2 3 4 5            --> 5 1 2 3 4 5 6          --> 6 1 2 3 4 5 6 7        --> 7 1 2 3 4 5 6 7 8      --> 8 1 2 3 4 5 6 7 8 9    --> 9 1 2 3 4 5 6 7 8 9 10 --> 11

It implies that the length of

can be computed from the length of

as shown below.

eqn-1

Using Eq.1, we calculate the cumulative sum of each number group as follows.

eqn-2

Why do we calculate cumulative sum? The purpose in this is to be able to simply run a binary search to determine which number group the

digit belongs to in

time. For example, consider i=40.1                    --> 1 1 2                  --> 2 1 2 3                --> 6 1 2 3 4              --> 10 1 2 3 4 5            --> 15 1 2 3 4 5 6          --> 21 1 2 3 4 5 6 7        --> 28 1 2 3 4 5 6 7 8      --> 36 1 2 3 4 5 6 7 8 9    --> 451 2 3 4 5 6 7 8 9 10 --> 56

Using binary search, we can find out that

contains the

digit. Then, using a linear search, we can simply derive the first four digits of

to eventually find out the corresponding digit, 4.

eqn-3

Similarly, for i=55, we can figure out that the digit is indeed 1.

Implementation

Next, we outline a F# implementation of the stated algorithm. We start with computing the cumulative sums of the lengths as follows. [gist]5259549[/gist]

Then, for each i, we perform a binary search to locate

. [gist]5259589[/gist]

Lastly, we perform a linear search to figure out the ith digit from

. [gist]5259609[/gist]

Complexity.

where  the value of

is bounded above by

.

For complete implementation of this algorithm, please visit this gist. More so, to play further with this implementation, we have created a IDEONE page with sample input and corresponding output. Please leave a comment if there is any question or suggestion. Thanks!