10
$\begingroup$

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,

$\endgroup$
  • $\begingroup$ What happens when you increment {9,4,2}? What base is the fourth digit in? $\endgroup$ – Rahul Nov 11 '12 at 9:11
  • 4
    $\begingroup$ P.S. I like this question. It's like incrementing a time in ss:mm:hh-DD/MM/YYYY format. $\endgroup$ – Rahul Nov 11 '12 at 9:14
  • 2
    $\begingroup$ 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. $\endgroup$ – wxffles Nov 11 '12 at 20:41
  • 1
    $\begingroup$ @wxffles, thank you very much! I was just looking for that term (one of those you know it once you know things...) $\endgroup$ – Dan McGrath May 2 '13 at 2:32
  • $\begingroup$ Am I missing something here? Why not just use some combination of IntegerDigits, FromDigits and MixedRadix - all built-ins... $\endgroup$ – ciao Jan 21 '17 at 18:57
7
$\begingroup$

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}}
$\endgroup$
5
$\begingroup$

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}} *)
$\endgroup$
4
$\begingroup$

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

$\endgroup$
  • $\begingroup$ Nice touches +1 $\endgroup$ – Rojo Nov 11 '12 at 20:20
3
$\begingroup$

@cartonn's clock:

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

:)

$\endgroup$
  • $\begingroup$ 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.) $\endgroup$ – Sjoerd C. de Vries Nov 11 '12 at 15:12
  • $\begingroup$ @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. $\endgroup$ – kglr Nov 11 '12 at 15:44
  • $\begingroup$ Interesting. Didn't think DatePlus could be (ab)used for that. Can you give it units other than "Day" etc. to work with? $\endgroup$ – Sjoerd C. de Vries Nov 11 '12 at 15:51
  • $\begingroup$ I think you can only use combinations of built-in date/time units, but day,hour,minute values can be non-integers. $\endgroup$ – kglr Nov 11 '12 at 16:19
2
$\begingroup$

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.

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

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.