# Incrementing a number where each digit has a different base

Let's say I have a list, for instance {10,5,3}, indicating the bases for each digit of my 3-digit number. Using this basis, if I wanted to increment {8,4,1} a couple of times, here's what I would get:

{8,3,1} -> {9,3,1} -> {0,4,1} -> ... -> {9,4,1} -> {0,0,2} -> and so on


Now I can go ahead and do this using loops like one would normally do. But I'm sure there's a more elegant way of implementing this using some of Mathematica's already existing functions. Can anybody think of a sleek way to do this?

-
What happens when you increment {9,4,2}? What base is the fourth digit in? – Rahul Nov 11 '12 at 9:11
P.S. I like this question. It's like incrementing a time in ss:mm:hh-DD/MM/YYYY format. – Rahul Nov 11 '12 at 9:14
To aid in searches, I'd like to note that a number with different bases for each digit is commonly known as a mixed radix number. – wxffles Nov 11 '12 at 20:41
@wxffles, thank you very much! I was just looking for that term (one of those you know it once you know things...) – Dan McGrath May 2 '13 at 2:32

You have several options, either directly implementing incr

incr[digs_, base_] := Module[{carry = 1, ndigs = digs, k = 1, nd},
While[k <= Length[digs],
{carry, nd} =
QuotientRemainder[Part[ndigs, k] + carry, Part[base, k]];
Part[ndigs, k] = nd;
If[carry == 0, Break[]]; k++;
];
ndigs
]


Or implementing FromMultpleBase and ToMultipleBase functions to make your tuple to a natural number, and back:

FromMultipleBase[digs_, base_] := digs.FoldList[Times, 1, Most[base]]

ToMultipleBase[num_, base_] :=
Part[Rest[
FoldList[QuotientRemainder[Last[#1], #2] &, {0, num},
Reverse[FoldList[Times, 1, Most[base]]]]],
Range[Length[base], 1, -1], 1]


Here is the usage:

In[152]:= NestList[inc[#, {10, 5, 3}] &, {8, 3, 1}, 12]

Out[152]= {{8, 3, 1}, {9, 3, 1}, {0, 4, 1}, {1, 4, 1}, {2, 4, 1}, {3,
4, 1}, {4, 4, 1}, {5, 4, 1}, {6, 4, 1}, {7, 4, 1}, {8, 4, 1}, {9, 4,
1}, {0, 0, 2}}

In[153]:= FromMultipleBase[#, {10, 5, 3}] & /@ %

Out[153]= {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100}

In[154]:= NestList[
ToMultipleBase[
FromMultipleBase[#, {10, 5, 3}] + 1, {10, 5, 3}] &, {8, 3, 1}, 12]

Out[154]= {{8, 3, 1}, {9, 3, 1}, {0, 4, 1}, {1, 4, 1}, {2, 4, 1}, {3,
4, 1}, {4, 4, 1}, {5, 4, 1}, {6, 4, 1}, {7, 4, 1}, {8, 4, 1}, {9, 4,
1}, {0, 0, 2}}

-

Let's see some beautiful answers pop up. For now, a not too sleek one to break the ice

fix[l_, base_] :=
Module[{take = 0},
Rest@FoldList[
QuotientRemainder[#2[[1]] + take, #2[[2]]] /. {q_,
r_} :> (take = q; r) &, 0, Transpose@{l, base}]]

inc[{f_, rest___}, base_] := fix[{f + 1, rest}, base]


So

NestList[inc[#, {10, 5, 3}] &, {8, 3, 1}, 5]

(* {{8, 3, 1}, {9, 3, 1}, {0, 4, 1}, {1, 4, 1}, {2, 4, 1}, {3, 4, 1}} *)

-

add[base_][l_, x_] :=
FoldList[QuotientRemainder @@ ({1, 0} # + #2) &, x, {l, base}\[Transpose]][[2 ;;, 2]]

NestList[add[{10, 5, 3}][#, 1] &, {8, 3, 1}, 15]


{{8, 3, 1}, {9, 3, 1}, {0, 4, 1}, {1, 4, 1}, {2, 4, 1}, {3, 4, 1}, {4, 4, 1}, {5, 4, 1}, {6, 4, 1}}

Alternate formulation:

base /: base[l_, blst_] + x_Integer :=
FoldList[QuotientRemainder @@ ({1, 0} # + #2) &, x, {l, blst}\[Transpose]][[2 ;;, 2]]

base[{8, 3, 1}, {10, 5, 3}] + Range[8]


{{9, 3, 1}, {0, 4, 1}, {1, 4, 1}, {2, 4, 1}, {3, 4, 1}, {4, 4, 1}, {5, 4, 1}, {6, 4, 1}}

-
Nice touches +1 – Rojo Nov 11 '12 at 20:20

@cartonn's clock:

 Dynamic[Thread[Mod[{Clock[{8, 17, 1}, 5], Clock[{3, 7, 1}, 25],
Clock[{1, 3, 1}, 75]}, {10, 5, 3}]]]


:)

-
At first I thought synchronization might be a problem for three independent instances of Clock but looking at 'More Information' it seems this should be all right (The base for all times used by Clock is the creation time of the cell in which Clock appears.) – Sjoerd C. de Vries Nov 11 '12 at 15:12
@Sjoerd, I thought I could concoct something with DatePlus but this, although it does not quite work yet (it needs finer tuning to avoid some skips), was hard to resist. Still DatePlus seems more promising. – kglr Nov 11 '12 at 15:44
Interesting. Didn't think DatePlus could be (ab)used for that. Can you give it units other than "Day" etc. to work with? – Sjoerd C. de Vries Nov 11 '12 at 15:51
I think you can only use combinations of built-in date/time units, but day,hour,minute values can be non-integers. – kglr Nov 11 '12 at 16:19

I may be missing the point here, but I think in this case functional programming may drag efficiency down...

incr[list_, {a_, b_, c_}, n_ : 1] :=
With[ {check = {Mod[#[[1]], a] , Mod[#[[2]], b] + Quotient[ #[[1]],a], Mod[#[[3]], c]
+ Quotient[#[[2]],b]} &},
NestList[check[{#[[1]] + 1, #[[2]], #[[3]]}] &, list, n]]


Quotient added on J.M.'s suggestion.

-
The Floor[p/q] bits in your code can of course be done as Quotient[p, q]. – J. M. Nov 11 '12 at 10:07
@J.M. I should have seen that, thanks. – VF1 Nov 11 '12 at 18:10