# 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?

Thanks in advance,

• What happens when you increment {9,4,2}? What base is the fourth digit in?
– user484
Nov 11, 2012 at 9:11
• P.S. I like this question. It's like incrementing a time in ss:mm:hh-DD/MM/YYYY format.
– user484
Nov 11, 2012 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. Nov 11, 2012 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...) May 2, 2013 at 2:32
• Am I missing something here? Why not just use some combination of IntegerDigits, FromDigits and MixedRadix - all built-ins...
– ciao
Jan 21, 2017 at 18:57

## 6 Answers

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}} *)


Based on Rojo's answer:

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, 2012 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.) Nov 11, 2012 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, 2012 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? Nov 11, 2012 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, 2012 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]. Nov 11, 2012 at 10:07
• @J.M. I should have seen that, thanks.
– VF1
Nov 11, 2012 at 18:10

Since version 10.2, MixedRadix[] has been built-in. Its convention (most significant digits first) is the reverse of the OP's, however.

Thus, borrowing Sasha's example:

d = {1, 3, 8}; mr = MixedRadix[{3, 5, 10}];
Table[IntegerDigits[FromDigits[d, mr] + k, mr], {k, 0, 12}]
{{1, 3, 8}, {1, 3, 9}, {1, 4, 0}, {1, 4, 1}, {1, 4, 2}, {1, 4, 3}, {1, 4, 4},
{1, 4, 5}, {1, 4, 6}, {1, 4, 7}, {1, 4, 8}, {1, 4, 9}, {2, 0, 0}}


Apply Reverse[] if needed.

• +1, I was puzzled (per my comment) why all the machinations when it's built-in...
– ciao
Jan 21, 2017 at 22:51