POV-Ray : Newsgroups : povray.off-topic : Small math/programming problem Server Time
13 Oct 2026 02:05:19 EDT (-0400)
  Small math/programming problem (Message 1 to 25 of 25)  
From: Kevin Wampler
Subject: Small math/programming problem
Date: 30 Jun 2010 20:38:10
Message: <4c2be372$1@news.povray.org>
I was going through some old stuff on my hard drive, and I came across a 
small code snippet which led to a cute little problem:

I have a number which is defined with the following bit of pseudocode, 
with all variables representing ideal mathematical integers:

n = 2
for(a = n; a > 0; a--)
   for(b = n; b > 0; b--)
     for(c = n; c > 0; c--)
       for(d = n; n > 0; d--)
         n++;
print n

What are the last 10 digits of the result printed by this program?


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 30 Jun 2010 20:40:00
Message: <4c2be3e0$1@news.povray.org>
I just spotted a typo:  The code should obviously read:

n = 2
for(a = n; a > 0; a--)
   for(b = n; b > 0; b--)
     for(c = n; c > 0; c--)
       for(d = n; d > 0; d--)
         n++;
print n

Since the version I gave didn't terminate!


Kevin Wampler wrote:
> I was going through some old stuff on my hard drive, and I came across a 
> small code snippet which led to a cute little problem:
> 
> I have a number which is defined with the following bit of pseudocode, 
> with all variables representing ideal mathematical integers:
> 
> n = 2
> for(a = n; a > 0; a--)
>   for(b = n; b > 0; b--)
>     for(c = n; c > 0; c--)
>       for(d = n; n > 0; d--)
>         n++;
> print n
> 
> What are the last 10 digits of the result printed by this program?


Post a reply to this message

From: Invisible
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 05:45:14
Message: <4c2c63aa$1@news.povray.org>
Kevin Wampler wrote:

> n = 2
> for(a = n; a > 0; a--)
>   for(b = n; b > 0; b--)
>     for(c = n; c > 0; c--)
>       for(d = n; d > 0; d--)
>         n++;
> print n

Damned mutable state! >_<

OK, well

   for(d=n; d>0; d--) n++;

is equivilent to

   n = 2*n;

so we have

   for(c=n;c>0;c--) n = 2*n;

which is

   n = n * 2^n;

so now we have

   for(b=n;b>0;b--) n = n * 2^n;

Now there's trouble. You see, initially we have

   n[0] = n

On the next iteration we have

   n[1] = n[0] 2^n[0] = n 2^n

But then we have

   n[2] = n[1] 2^n[1] = (n 2^n) 2^(n 2^n)

You can simplify this to

   n[2] = n 2^(n + n 2^n)

but that's still quite complex. More to the point, on the next iteration 
it'll get even more complex, and I don't see a closed-form solution to this.

More to the point, by the time a=1, n=2048. That means that the b-loop 
runs 2048 times. And when you consider that 2048 * 2^2048 is

6618522843404494295186406745839606161498952226757731129780294743557
0493724401440549267868490798926773634494383968047143923956857140205
4064027405360874460838310520368482324399959044049927980075147183260
4341057037983087046378008526061944441720519919712375121070497035272
7833755425876102776028267313405809429548880554782040765277562828362
8842383254654485203483075749433459903099416426669267233797295981858
3473505473250041540988386836142315991377081221877271190177224955315
3402287759789517121744336755350465901655205184917370974202405586941
2110653955407655676631932971733672542303136122441829419995004023881
95450053080383488

(i.e., 6.618 * 10^619), you realise that the very next iteration is 
going to produce some absurdly *huge* number. This explains why the 
program I wrote eats several GB of RAM without ever coming up with an 
answer.

The difficulty, then, is coming up with an algorithm to compute the 
least-significant digits of λ n → n 2^n without computing the entire 
number. I'll have to go check my number theory; I don't recall the exact 
details of the algorithm.


Post a reply to this message

From: Invisible
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 06:12:19
Message: <4c2c6a03$1@news.povray.org>
Invisible wrote:

> The difficulty, then, is coming up with an algorithm to compute the 
> least-significant digits of λ n → n 2^n without computing the entire 
> number. I'll have to go check my number theory; I don't recall the exact 
> details of the algorithm.

You're asking for the last 10 digits of the answer. In other words, the 
answer modulo 10^10. (Assuming you meant the last 10 *decimal* digits...)

In modular arithmetic,

   (X mod M) * (Y mod M) = (X * Y) mod M

In other words, we can reduce our running total to the least positive 
reside class mod 10^10 and still get the same answer. Handling 
billion-digit numbers is quite expensive, but piffling 10-digit numbers 
are no match for the GMP.

Unfortimately,

   (X mod M)^(Y mod M) ≠ (X^Y) mod M

But fortunately,

   (X mod M)^Y = (X^Y) mod M

due to the first theorum. Better still,

   A+B = Y ⇒ (X mod M)^A * (X mod M)^B = (X^Y) mod M

by the usual first law of logarithms. This gives us the binary 
exponentiation algorithm:

   x = 1;
   b = base;
   e = exponent;
   while (e>0)
     if odd(e) then x = x*b mod m;
     e = shift_right(e);
     b = b*b mod m;

At any time, you need to deal with numbers containing at most 20 digits.

So what's the answer? I make it

.....1,549,498,368

It took about 0.2 seconds to compute. I have very little confidence that 
this is correct though.


Post a reply to this message

From: scott
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 06:36:46
Message: <4c2c6fbe$1@news.povray.org>
> .....1,549,498,368

I recognise those last 6 digits!  I think I got them from my program, but 
then my method was too slow to do any more digits in reasonable time.


Post a reply to this message

From: Invisible
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 06:43:28
Message: <4c2c7150@news.povray.org>
scott wrote:
>> .....1,549,498,368
> 
> I recognise those last 6 digits!  I think I got them from my program, 
> but then my method was too slow to do any more digits in reasonable time.

Heh. Could be just fluke.

I'm still not 100% certain that my program works. For example, the 
exponent is reduced as per the modulus too, which could affect the 
answer. As a quick check, I tried rerunning with 20 digits:

.......1,225,862,901,549,498,368

So the digits don't change by making the calculation wider. Which 
presumably means it's wide enough not to screw up the answer. (Or it's a 
very big fluke. You never know - mathematics is like that!)


Post a reply to this message

From: scott
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 07:52:00
Message: <4c2c8160$1@news.povray.org>
> I'm still not 100% certain that my program works. For example, the 
> exponent is reduced as per the modulus too, which could affect the 
> answer. As a quick check, I tried rerunning with 20 digits:
> 
> .......1,225,862,901,549,498,368

Next task, give us some indication of how big n is :-)


Post a reply to this message

From: Invisible
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 08:22:19
Message: <4c2c887b$1@news.povray.org>
scott wrote:

> Next task, give us some indication of how big n is :-)

I can see I won't get much work done today...



OK, well we have

   d = λ n → n 2
   c = λ n → n 2^n
   b = λ n → c@n n
   a = λ n → b@n n

where "b@n" means "b applied n times".

If n = 100, then 2^n ≈ 10^30, while is a mere 10^2 times larger. As n 
becomes larger, the difference becomes more and more insignificant. So, 
we can approximate with

   c = λ n → 2^n

On that bases, the final result is guaranteed to be an exact power of 2. 
We just need to figure out which one.

Using Knuth's "up-arrow notation", we have

   c = λ n → 2↑n
   b = λ n → 2↑↑n
   a = λ n → 2↑↑↑n

So the answer we seek is (approximately) 2↑↑↑2. In other words, the 
pentation of 2 with 2. Unfortunately, I don't know of any efficient way 
to compute the size of this ludicrously massive quantity.


Post a reply to this message

From: scott
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 10:29:54
Message: <4c2ca662$1@news.povray.org>
> So the answer we seek is (approximately) 2↑↑↑2.

Isn't that 4?


Post a reply to this message

From: Darren New
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 11:25:28
Message: <4c2cb368$1@news.povray.org>
Invisible wrote:
> scott wrote:
>>> .....1,549,498,368
>>
>> I recognise those last 6 digits!  I think I got them from my program, 
>> but then my method was too slow to do any more digits in reasonable time.
> 
> Heh. Could be just fluke.

Nah. That would be a one in a million chance.

Wait, no, one in a million chances work out all the time!

-- 
Darren New, San Diego CA, USA (PST)
    C# - a language whose greatest drawback
    is that its best implementation comes
    from a company that doesn't hate Microsoft.


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 11:26:43
Message: <4c2cb3b3@news.povray.org>
Invisible wrote:
> So what's the answer? I make it
> 
> .....1,549,498,368

I believe that answer is correct, although I'm not sure your reasoning 
behind the algorithm was watertight.  In particular, since you're 
applying modular exponentiation in each iteration, you're implicitly 
assuming that a^b mod m == a^(b mod m) in the next iteration. 
Fortunately this ends up bring very close to true in this case, so 
everything still works out, but to be totally safe you should really 
compute everything mod lcm(10^10,phi(10^10)) = 10^11.  Unless I was 
overly conservative in my analysis somewhere.

Now for a tricker question, say I add another loop:

n = 2
for(a = n; a > 0; a--)
   for(b = n; b > 0; b--)
     for(c = n; c > 0; c--)
       for(d = n; d > 0; d--)
         for(e = n; e > 0; e--)
           n++
print n

What are the last five digits printed?

Note that I haven't actually worked through this yet to be sure that my 
idea or solving it will actually work, so be forewarned that I'm not 
positive it's possible.


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 1 Jul 2010 11:38:33
Message: <4c2cb679@news.povray.org>
scott wrote:
>> So the answer we seek is (approximately) 2↑↑↑2.
> 
> Isn't that 4?

No, since 2^^^2 = 2^^2^^2 = 2^^(2^2^2) = 2^^16 = 
2^2^2^2^2^2^2^2^2^2^2^2^2^2^2^2.

However, in this case you can very easily give a somewhat tighter lower 
bound of 2^^2048, that is 2^2^2^2^ ... 2048 times ... ^2^2^2


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 00:11:41
Message: <4c2d66fd@news.povray.org>
Kevin Wampler wrote:
> 
> Now for a tricker question, say I add another loop:
> 
> n = 2
> for(a = n; a > 0; a--)
>   for(b = n; b > 0; b--)
>     for(c = n; c > 0; c--)
>       for(d = n; d > 0; d--)
>         for(e = n; e > 0; e--)
>           n++
> print n
> 
> What are the last five digits printed?
> 

Ok, I haven't been able to post today since I've been on airplanes on or 
airports without wireless the whole time, but I implemented the solution 
and it seems to work, so this problem is totally solvable, and only 
takes a fraction of a second on my computer.

It turns out that the solution is actually quite simple too!  Possibly 
even more so than that to the last puzzle -- although certainly not as 
mathematically concise.

Actually pretty fun, so feel free to give it a shot knowing that it does 
indeed have a relatively simple solution!


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 00:16:19
Message: <4c2d6813$1@news.povray.org>
Invisible wrote:
> 
>  (Assuming you meant the last 10 *decimal* digits...)
> 

Man, meaning the last ten binary digits would have made this the lamest 
trick question ever (so yeah, you're correct in solving for decimal 
obviously).


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 00:50:33
Message: <4c2d7019$1@news.povray.org>
scott wrote:
>> .....1,549,498,368
> 
> I recognise those last 6 digits!  I think I got them from my program, 
> but then my method was too slow to do any more digits in reasonable time.
> 

It's interesting that you had an algorithm that could compute six digits 
but not ten.  You might try running it on the second version of the 
puzzle that I gave, since I only ask for the last five digits in that 
case.  Maybe it'll work!


Post a reply to this message

From: scott
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 02:10:10
Message: <4c2d82c2$1@news.povray.org>
>>> So the answer we seek is (approximately) 2↑↑↑2.
>>
>> Isn't that 4?
>
> No, since 2^^^2 = 2^^2^^2

I understood from wikipedia that 2^^^3 = 2^^2^^2 and 2^^^2 = 2^^2.  Is that 
wrong?


Post a reply to this message

From: scott
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 02:13:24
Message: <4c2d8384$1@news.povray.org>
>>> .....1,549,498,368
>>
>> I recognise those last 6 digits!  I think I got them from my program, but 
>> then my method was too slow to do any more digits in reasonable time.
>>
>
> It's interesting that you had an algorithm that could compute six digits 
> but not ten.

Well I simplified as far as Invisible did, and then didn't go through the 
modular math to simplifiy it, just applied the mod operator at various 
points in the code.  Using mod 1e5 took a fraction of a second, mod 1e6 took 
about 10 seconds, and mod 1e7 never finished!

> You might try running it on the second version of the puzzle that I gave, 
> since I only ask for the last five digits in that case.  Maybe it'll work!

Hmmm.


Post a reply to this message

From: Invisible
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 03:56:09
Message: <4c2d9b99$1@news.povray.org>
Kevin Wampler wrote:

> Ok, I haven't been able to post today since I've been on airplanes on or 
> airports without wireless the whole time, but I implemented the solution 
> and it seems to work, so this problem is totally solvable, and only 
> takes a fraction of a second on my computer.
> 
> It turns out that the solution is actually quite simple too!  Possibly 
> even more so than that to the last puzzle -- although certainly not as 
> mathematically concise.
> 
> Actually pretty fun, so feel free to give it a shot knowing that it does 
> indeed have a relatively simple solution!

I have a truly marvelous proof of this, which this forum is too small to 
contain...


Post a reply to this message

From: Stephen
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 05:31:02
Message: <4c2db1d6@news.povray.org>
On 02/07/2010 8:56 AM, Invisible wrote:
> Kevin Wampler wrote:
>
>> Ok, I haven't been able to post today since I've been on airplanes on
>> or airports without wireless the whole time, but I implemented the
>> solution and it seems to work, so this problem is totally solvable,
>> and only takes a fraction of a second on my computer.
>>
>> It turns out that the solution is actually quite simple too! Possibly
>> even more so than that to the last puzzle -- although certainly not as
>> mathematically concise.
>>
>> Actually pretty fun, so feel free to give it a shot knowing that it
>> does indeed have a relatively simple solution!
>
> I have a truly marvelous proof of this, which this forum is too small to
> contain...

LOL ;-)

-- 

Best Regards,
	Stephen


Post a reply to this message

From: Invisible
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 05:33:23
Message: <4c2db263$1@news.povray.org>
>> I have a truly marvelous proof of this, which this forum is too small to
>> contain...
> 
> LOL ;-)

You may laugh, but for 300 years mathematicians have been unable to 
rediscover this "marvellous proof" - so excuse me if mathematicians are 
a teeny bit skeptical about sweeping claims. ;-)


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 11:08:59
Message: <4c2e010b$1@news.povray.org>
scott wrote:
> 
> I understood from wikipedia that 2^^^3 = 2^^2^^2 and 2^^^2 = 2^^2.  Is 
> that wrong?
> 

Nope, it appears that the error was all mine.  Sorry about that!


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 11:13:14
Message: <4c2e020a@news.povray.org>
Invisible wrote:
> 
> I have a truly marvelous proof of this, which this forum is too small to 
> contain...

LOL.  Fortunately the code is small enough to post, I just didn't want 
to spoil the puzzle.

If you want to check your algorithm, the last five digits of the case 
with ten nested for-loops I get as being 68608.


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 11:21:08
Message: <4c2e03e4@news.povray.org>
I sent the problem to someone on IRC, who spent a while trying to solve it, 
then he posted it to ycombinator:

http://news.ycombinator.com/item?id=1480303

Interesting comments there.


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 2 Jul 2010 11:31:52
Message: <4c2e0668$1@news.povray.org>
Nicolas Alvarez wrote:
> I sent the problem to someone on IRC, who spent a while trying to solve it, 
> then he posted it to ycombinator:
> 
> http://news.ycombinator.com/item?id=1480303
> 
> Interesting comments there.
> 

Cool!  I'm glad to see that people like it!


Post a reply to this message

From: Kevin Wampler
Subject: Re: Small math/programming problem
Date: 5 Jul 2010 20:49:51
Message: <4c327daf$1@news.povray.org>
Kevin Wampler wrote:
> 
> Now for a tricker question, say I add another loop:
> 
> n = 2
> for(a = n; a > 0; a--)
>   for(b = n; b > 0; b--)
>     for(c = n; c > 0; c--)
>       for(d = n; d > 0; d--)
>         for(e = n; e > 0; e--)
>           n++
> print n
> 
> What are the last five digits printed?
> 

Don't read if you don't want the puzzle spoiled for you.

Ok, since nobody's posted in a while I'll assume that either everyone's 
lost interest or they're ready to hear the solution.  Invisible had the 
right answer (minus some minor analysis issues) for the case with four 
loops, but the technique he used doesn't extend well beyond that.

To figure out how to make things work for more nested for-loops, let's 
consider the function representing the body of the innermost loop:

f_0(n) = n+1

On successive iterations of the innermost loop, we end up computing:

f_0(n)
f_0(f_0(n))
f_0(f_0(f_0(n)))
etc...

Of course, we're only interested in the last k digits of the answer, so 
the values of these successive iterations end up repeating.  Obviously 
it's easy to represent this in closed from, but let's say we don't want 
to do that.  Then we can explicitly represent this with:

orbit_0 = []|[2,3,4,...,10^k,0,1]

The notation A|B here indicates that the initial value of n (2 in this 
case) goes through the values in A once, and then loops through the 
values in B forever.  We'll call this the orbit of n mod 10^k under f_0, 
meaning that these are the values we get if we start at n and then keep 
applying f_0.  For convienence I'll call A and B the prefix and loop of 
the orbit respectively.

The method of solving the puzzle for many nested loops will involve 
computing orbit_i, which is the orbit of n mod 10^k under f_i, where f_i 
is the function defined by i nested for-loops.  The a'th element in this 
orbit will be given by f_i^a(n), which stands for a compositions of f_i, 
so f_i^3(n) = f_i(f_i(f_i(n))).

In this approach to solving the problem, we'll store each orbit_i 
explicitly.  Thus we can get the value of f_i^a(n) by simply indexing 
into orbit_i.  In the case that the orbit's prefix is empty, then we can 
do this by f_0^a(n) = orbit_i.loop[ (indexOf(n,orbit_i) + a) mod 
period(orbit_i) ], which we'll write as orbit_i[n,a] for shorthand.  If 
the or orbit's prefix is non-empty, then the formula is a bit more 
complicated, but still not too bad, and we'll denote it with 
orbit_i[n,a] in any case.

So far this may not seem very interesting, but the power of this way of 
looking at things will become apparent if we consider the function 
defined by having a single for-loop:

for(a = n; a > 0; a--)
	n = f_{i-1}(n)
	
As noted before, this loop defines the function:

f_i(n) = f_{i-1}^n(n)

Now, the trick to getting this whole approach to work is to directly 
calculate orbit_i entirely in terms of the initial value of n (2 in this 
case) and orbit_{i-1}.  Since we show that the first element in orbit_i 
(it's 2), it's sufficient to be able to calculate element a in orbit_i 
given element a-1.  It's pretty direct to see how to do this:

Since: orbit_{i-1}[n,a] = f_{i-1}^a(n)
and: f_i(n) = f_{i-1}^n(n)
then: f_i(n) = orbit_{i-1}[n,n]

So to generate the orbit defined by f_i, we can use the procedure:

f_i^0(n) = 2
f_i^a(n) = orbit_{i-1}[f_i^{a-1}(n), f_i^{a-1}(n)]
          = orbit_i[n,a]

This allows us to generate values of f_i^a(n) until we hit a repeated 
value, at which point we have the full definition of orbit_i.  Thus if 
we want the last m digits of the result if we start at n and use i 
nested loops, we just look up the value of orbit_i[n,n].  Thus the 
algorithm requires linear time in the numeber of nested loops, although 
exponential time in the number of digits you want to return (which is 
why I changed the problem to only ask for five digits).

The Python code I udes to solve this problem (posted below) uses this 
procedure to get the answer for the case with five nested for-loops: 86528

Even better, the Python code allows you to create an orbit of orbits, 
and thus find that the last five digits for the case with 10^100 nested 
for-loops are 45728!  Not bad considering how completely intractable the 
problem appears at first.  I also think it's sort of nifty that the 
entire algorithm is basically just fancy array indexing, so in some 
sense it's quite simple.  Also, I haven't quite proved rigorusly that 
this algorithm works, and I double I'll bother to, so let me know if you 
find an error.  I also suspect it might even be possible to make an 
algorithm which is sub-exponential in the number of digits, but I 
haven't look into this much.

At any rate, here's the code which I used to compute all these answers:

-------------------------------------------------------------------------------

class InvertibleList(object):
	"""Like a list, but also allows you to efficiently find the index
	at which a given element appears.  All elements in the list are assumed
	to be unique.  Python probably has something like this built in, but it
	was easy enough to code that I just implemented it myself."""

	def __init__(self, items=[]):
		self.values = []
		self.invValues = {}
		self.extend(items)

	def __len__(self):
		return len(self.values)

	def __getitem__(self, key):
		return self.values[key]
		
	def indexOf(self, value):
		return self.invValues[value]

	def append(self, item):
		self.values.append(item)
		self.invValues[item] = len(self.values)-1
		
	def extend(self, items):
		for item in items:
			self.append(item)
		
	def __contains__(self, value):
		return value in self.invValues
		
	def __eq__(self, other):
		if len(self) != len(other): return False
		for v1, v2, in zip(self.values, other.values):
			if v1 != v2: return False
		return True
		
	def __hash__(self):
		h = hash(len(self))
		for i, v in enumerate(self.values):
			h ^= hash(i) + hash(v)
		return h

	def __str__(self):
		return str(self.values)


class Orbit(object):
	"""Represents the orbit which a value takes under the composition of a
	function in a finite field.  For convienence you can give the value and
	the function to be composed as parameters to the constructor."""

	def __init__(self, n=None, f=None):
		self.prefix = InvertibleList()
		self.loop = InvertibleList()

		if n is not None:
			assert f is not None
			
			# generate values until we hit a repeat
			o = InvertibleList()
			o.append(n)
			
			n = f(n)
			while n not in o:
				o.append(n)
				n = f(n)

			# partition o into perfix and loop components
			ind = o.indexOf(n)
			for i in xrange(ind):
				self.prefix.append(o[i])
			for i in xrange(ind,len(o)):
				self.loop.append(o[i])
				
	def itemFrom(self, n, a):
		"""Get the a'th item after the appearance on n in this orbit."""

		if n in self.loop:
			nInd = self.loop.indexOf(n)
			return self.loop[(a+nInd) % len(self.loop)]
		else:
			assert n in self.prefix
			nInd = self.prefix.indexOf(n)
			nInd2 = a + nInd
			if nInd2 < len(self.prefix):
				return self.prefix[nInd2]
			else:
				return self.loop[(nInd2-len(self.prefix)) % len(self.loop)]

	def __str__(self):
		return str(self.prefix) + "|" + str(self.loop)

	def __len__(self):
		return len(self.loop)
		
	def __eq__(self, other):
		return (self.prefix == other.prefix) and (self.loop == other.loop)
		
	def __hash__(self):
		return hash(self.prefix) ^ hash(self.loop)


def reduceOrbit(n, o1):
	"""Given an orbit for f, returns an orbit of n under the function
	f^n(n).  This assumes n is in the orbit o1, and that the sizes of
	these orbits behave nicely."""

	o2 = Orbit(n, lambda i: o1.itemFrom(i,i))
	assert len(o1.loop) % len(o2.loop) == 0
	return o2


def getLastDigits(n, numLevels, numDigits):
	mod = 10**numDigits

	o = Orbit(2, lambda i: (i+1) % mod)
	for i in xrange(1, numLevels):
		o = reduceOrbit(n, o)

	return o.itemFrom(n, n)


def getLastDigitsOrbit(n, numDigits):
	mod = 10**numDigits
	metaOrbit = Orbit(
		Orbit(2, lambda i: (i+1) % mod),
		lambda orb: reduceOrbit(n, orb))
	return metaOrbit

#-----------------------------[ main ]----------------------------#

if __name__ == "__main__":
	numDigits = 5
	print "These are the last five digits for the case with five nested 
for-loops:"
	print getLastDigits(2, 5, numDigits)

	print
	print "The last five digits for the case with 10^100 nested for-loops:"
	metaOrbit = getLastDigitsOrbit(2, numDigits)
	print metaOrbit.itemFrom(metaOrbit.prefix[0], 10**100).itemFrom(2,2)


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.