Alex Rivera | Logout

Expressing an integer as a series of multipliers

Asked 2009-04-25T15:04:44.013
11

Scroll down to see latest edit, I left all this text here just so that I don't invalidate the replies this question has received so far!


I have the following brain teaser I'd like to get a solution for, I have tried to solve this but since I'm not mathematically that much above average (that is, I think I'm very close to average) I can't seem wrap my head around this.

The problem: Given number x should be split to a serie of multipliers, where each multiplier <= y, y being a constant like 10 or 16 or whatever. In the serie (technically an array of integers) the last number should be added instead of multiplied to be able to convert the multipliers back to original number.

As an example, lets assume x=29 and y=10. In this case the expected array would be {10,2,9} meaning 10*2+9. However if y=5, it'd be {5,5,4} meaning 5*5+4 or if y=3, it'd be {3,3,3,2} which would then be 3*3*3+2.

I tried to solve this by doing something like this:

  1. while x >= y, store y to multipliers, then x = x - y
  2. when x < y, store x to multipliers

Obviously this didn't work, I also tried to store the "leftover" part separately and add that after everything else but that didn't work either. I believe my main problem is that I try to think this in a way too complex manner while the solution is blatantly obvious and simple.

To reiterate, these are the limits this algorithm should have:

  • has to work with 64bit longs
  • has to return an array of 32bit integers (...well, shorts are OK too)
  • while support for signed numbers (both + and -) would be nice, if it helps th
Edit
Report

1 Answer

1

The original method you chose (a * b + c * d + e) would be very difficult to find optimal solutions for simply due to the large search space of possibilities. You could factorize the number but it's that "+ e" that complicates things since you need to factorize not just that number but quite a few immediately below it.

Two methods for compression spring immediately to mind, both of which give you a much-better-than-10% saving on space from the numeric representation.

A 64-bit number ranges from (unsigned):

                         0 to
18,446,744,073,709,551,616

or (signed):

-9,223,372,036,854,775,808 to
 9,223,372,036,854,775,807

In both cases, you need to reduce the 20-characters taken (without commas) to something a little smaller.

The first is to simply BCD-ify the number the base64 encode it (actually a slightly modified base64 since "/" would not be kosher in a URL - you should use one of the acceptable characters such as "_").

Converting it to BCD will store two digits (or a sign and a digit) into one byte, giving you an immediate 50% reduction in space (10 bytes). Encoding it base 64 (which turns every 3 bytes into 4 base64 characters) will turn the first 9 bytes into 12 characters and that tenth byte into 2 characters, for a total of 14 characters - that's a 30% saving.

The only better method is to just base64 encode the binary representation. This is better because BCD has a small amount of wastage (each digit only needs about 3.32 bits to store [log210], but BCD uses 4).

Working on the binary representation, we only need to base64 encode the 64-bit number (8 bytes). That needs 8 characters for the first 6 bytes and 3 characters for the final 2 bytes. That's 11 characters of base64 for a saving of 45%.

If you wanted maximum compression, there are 73 ch

answered 2009-04-29T08:41:21.140

Your Answer