2

I'm trying to calculate

If we calculated every possible combination of numbers from 0 to (c-1)
with a length of x
what set would occur at point i

For example:

c = 4
x = 4
i = 3

Would yield:

[0000]
[0001]
[0002]
[0003] <- i
[0010]
....
[3333]

This is very nearly the same problem as in the related question Logic to select a specific set from Cartesian set. However, because x and i are large enough to require the use of BigInteger objects, the code has to be changed to return a List, and take an int, instead of a string array:

    int PossibleNumbers;

    public List<int> Get(BigInteger Address)
    {
        List<int> values = new List<int>();
        BigInteger sizes = new BigInteger(1);

        for (int j = 0; j < PixelArrayLength; j++)
        {
            BigInteger index = BigInteger.Divide(Address, sizes);
            index = (index % PossibleNumbers);

            values.Add((int)index);

            sizes *= PossibleNumbers;
        }

        return values;
    }

This seems to behave as I'd expect, however, when I start using values like this:

c = 66000
x = 950000
i = (66000^950000)/2

So here, I'm looking for the ith value in the cartesian set of 0 to (c-1) of length 950000, or put another way, the halfway point.

At this point, I just get a list of zeroes returned. How can I solve this problem?

Notes: It's quite a specific problem, and I apologise for the wall-of-text, I do hope it's not too much, I was just hoping to properly explain what I meant. Thanks to you all!

Edit: Here are some more examples: http://pastebin.com/zmSDQEGC

Transmission
  • 1,219
  • 1
  • 10
  • 11
  • Please clarify, what is the combination of numbers if c > 10 and how 1 such number affects the total length of a combination? – Dmitry Mar 19 '14 at 22:25
  • The way I think about c, is that it's a bit like an array of characters of length c. So, using c as in the example, if you had c=20, x=4: [0,0,0,0] [0,0,0,1] [0,0,0,2] ... [0,0,0,19] [0,0,0,20] [0,0,1,0] [0,0,1,1] Does that make more sense? – Transmission Mar 19 '14 at 22:30
  • If it helps, Dmitry, I've added a link to some examples I created. @HighPerformanceMark: I think you're right, yes. That's the one. – Transmission Mar 19 '14 at 22:54

2 Answers2

2

The first expression of the problem boils down to "write 3 as a 4-digit base-4 number". So, if the problem is "write i as an x-digit base-c number", or, in this case, "write (66000^950000)/2 as a 950000-digit base 66000 number", then does that make it easier?

If you're specifically looking for the halfway point of the cartesian product, it's not so hard. If you assume that c is even, then the most significant digit is c / 2, and the rest of the digits are zero. If your return value is all zeros, then you may have an off-by-one error, or the like, since actually only one digit is incorrect.

phoog
  • 42,068
  • 6
  • 79
  • 117
  • I think that might make it easier, yes, but I won't always be searching for an even number, I'll just be after an arbitrary ID. – Transmission Mar 19 '14 at 22:55
  • @Transmission you need the full set right not just the i-th value. – Kevin Mar 19 '14 at 23:03
  • The requirement is that the base (c) be even, not the number (i). In any event, you'll probably find it easiest to think of this as a base-conversion problem. – phoog Mar 19 '14 at 23:04
  • @Kevin, it's very unlikely that you'd find a disk large enough to store the full set of 66000^950000 values. – phoog Mar 19 '14 at 23:05
  • @phoog agreed... that's just not what the question sounded like. – Kevin Mar 19 '14 at 23:09
  • @Kevin I'm calculating 66000^950000 right now using System.Numerics and so far it has taken about 5 minutes without returning an answer. I've got a meeting now, but I'll add a base-conversion routine to this answer afterwards, if nobody else has done so by then. – phoog Mar 19 '14 at 23:13
  • @phoog I went ahead and wrote it... this was a fun question. – Kevin Mar 20 '14 at 00:05
2

Here is a generic base converter... it takes a decimal for the base10 value to convert into your newBase and returns an array of int's. If you need a BigInteger this method works perfectly well with just changing the base10Value to BigInteger.

EDIT: Converted method to BigInteger since that's what you need.

EDIT 2: Thanks phoog for pointing out BigInteger is base2 so changing the method signature.

public static int[] ConvertToBase(BigInteger value, int newBase, int length)
{
    var result = new Stack<int>();

    while (value > 0)
    {
        result.Push((int)(value % newBase));
        if (value < newBase)
            value = 0;
        else
            value = value / newBase;
    }

    for (var i = result.Count; i < length; i++)
        result.Push(0);

    return result.ToArray();
}

usage...

int[] a = ConvertToBase(13, 4, 4) = [0,0,3,1]
int[] b = ConvertToBase(0, 4, 4) = [0,0,3,1]
int[] c = ConvertToBase(1234, 12, 4) = [0,8,6,10]

However the probelm you specifically state is a bit large to test it on. :)

Just calculating 66000 ^ 950000 / 2 is a good bit of work as Phoog mentioned. Unless of course you meant ^ to be the XOR operator. In which case it's quite fast.

EDIT: From the comments... The largest base10 number that can be represented given a particular newBase and length is...

var largestBase10 = BigInteger.Pow(newBase, length)-1;
Kevin
  • 4,586
  • 23
  • 35
  • Hi there, the logic here seems to work fine, except when I change base10Value to be a BigInteger, I start getting arrays returned that are huge, for example: http://pastebin.com/kpt60qkY – Transmission Mar 20 '14 at 20:19
  • 1
    100 to the 66000th power is indeed a large number. – Kevin Mar 20 '14 at 20:22
  • Actually, I might have this wrong. I'll investiate more and come back with a better question. – Transmission Mar 20 '14 at 20:40
  • 1
    Definitely test it with smaller values to make sure you get the expected outputs for your inputs. Also note that it will not limit the size to be only numbers representable in say 200 digits... if you give it a number that can't be represented in 200 digits but tell it you want it in 200 digits.. it ignores what you told it and will use however many digits it needs to represent the number. – Kevin Mar 20 '14 at 20:50
  • I tested it with your sample values above, and it came out the same. Could I ask you, given base10Value, newBase and length, what would you say the formula for the ID of the very last value would be? I.e., a complete set of the max value of newBase? – Transmission Mar 20 '14 at 21:06
  • 1
    The formula meaning given a newBase and length how do you calculate a base10Value that is the largest possible number you can represent? For instance newBase = 4, length = 4 what is base10Value to get [3,3,3,3]? – Kevin Mar 20 '14 at 21:09
  • 1
    Edited question... if this works can you mark as correct / upvote? :) – Kevin Mar 20 '14 at 21:18
  • It works! Thanks very much, I did a big medium test and it took 36m35s - time to learn to parallelise I think! Thanks again :) – Transmission Mar 20 '14 at 22:46
  • +1, nice answer. Just one quibble: BigInteger is a base-2 type, not base 10, so I would just call the first parameter `value`. – phoog Mar 21 '14 at 03:20
  • I've tried to do this myself at home, but I'm coming to the point where I might need to ask another question: how can I change this method to work out part of that set, so that I can parallelise it. Is it better to post a new question if I can't work it out, or ask here since it's based on this code? (If you know) – Transmission Mar 23 '14 at 00:36
  • Better to ask a new question... when you mentioned it I tried to think of a way to make it parrallel but that's somewhat challenging since each iteration depends on the previous output. I don't see an immediate way to break it up. – Kevin Mar 24 '14 at 14:19