If we have a ternary machine and we want to produce hex strings of numbers up to a million:
base 3 div 16 limit 1,000,000
try 1 shift 3 exp 27
factor 2 over 5 product 5,000,000
try 2 shift 4 exp 81
factor 6 over 15 product 15,000,000
try 3 shift 5 exp 243
factor 16 over 13 product 13,000,000
try 4 shift 6 exp 729
factor 46 over 7 product 7,000,000
try 5 shift 7 exp 2,187
factor 137 over 5 product 5,000,000
try 6 shift 8 exp 6,561
factor 411 over 15 product 15,000,000
try 7 shift 9 exp 19,683
factor 1,231 over 13 product 13,000,000
try 8 shift 10 exp 59,049
factor 3,691 over 7 product 7,000,000
try 9 shift 11 exp 177,147
factor 11,072 over 5 product 5,000,000
try 10 shift 12 exp 531,441
factor 33,216 over 15 product 15,000,000
try 11 shift 13 exp 1,594,323
factor 99,646 over 13 product 13,000,000
try 12 shift 14 exp 4,782,969
factor 298,936 over 7 product 7,000,000
try 13 shift 15 exp 14,348,907
factor 896,807 over 5 product 5,000,000
x div 16 -> (x * 896,807) >>(3) 15
basebits 26 max 896,807,000,000
we can multiply by 896,807 then right shift by 15 ternary positions. The multiplication requires 26 ternary positions. Examples:
>>> (123456 * 896807) // (3 ** 15)
7716
>>> 123456 // 16
7716
>>> (202020 * 896807) // (3 ** 15)
12626
>>> 202020 // 16
12626
>>> (133713 * 896807) // (3 ** 15)
8357
>>> 133713 // 16
8357
If we meet a time traveler from ancient Sumer who has a base-60 machine, and we want to produce hex strings of numbers up to a million:
base 60 div 16 limit 1,000,000
try 1 shift 1 exp 60
factor 4 over 4 product 4,000,000
try 2 shift 2 exp 3,600
factor 225 over 0 product 0
x div 16 -> (x * 225) >>(60) 2
basebits 5 max 225,000,000
The final 'over' being 0 shows that this will work for arbitrarily large numbers, provided that we have the space for the multiplication. Examples:
>>> (123456 * 225) // (60 ** 2)
7716
>>> 123456 // 16
7716
>>> (202020 * 225) // (60 ** 2)
12626
>>> 202020 // 16
12626
>>> (133713 * 225) // (60 ** 2)
8357
>>> 133713 // 16
8357
The advantage of this iterative method is that it allows the problem to be tackled using only basic knowledge of fractions, without having to resort to rings and modular inverses. Here is a small challenge. Try to find a necessary and sufficient condition for the base and the divisor so that the final 'over' value will be 0. Once you have the condition try to write some code that implements it with some reasonable efficiency.