June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
|
|
@ -1,6 +1,7 @@
|
|||
If you add the square of the digits of a Natural number (an integer bigger than zero), you always end with either 1 or 89:
|
||||
<pre>15 -> 26 -> 40 -> 16 -> 37 -> 58 -> 89
|
||||
7 -> 49 -> 97 -> 130 -> 10 -> 1</pre>
|
||||
|
||||
An example in Python:
|
||||
|
||||
<lang python>>>> step = lambda x: sum(int(d) ** 2 for d in str(x))
|
||||
|
|
@ -8,6 +9,7 @@ An example in Python:
|
|||
>>> [iterate(x) for x in xrange(1, 20)]
|
||||
[1, 89, 89, 89, 89, 89, 1, 89, 89, 1, 89, 89, 1, 89, 89, 89, 89, 89, 1]</lang>
|
||||
|
||||
|
||||
;Task:
|
||||
: Count how many number chains for integers 1 <= n < 100_000_000 end with a value 89.
|
||||
Or, for much less credit - (showing that your algorithm and/or language is slow):
|
||||
|
|
@ -17,8 +19,9 @@ This problem derives from the [https://projecteuler.net/problem=92 Project Euler
|
|||
|
||||
For a quick algorithm for this task see [[Talk:Iterated_digits_squaring|the talk page]]
|
||||
|
||||
;Cf:
|
||||
*[[Combinations with repetitions]]
|
||||
*[[Digital root]]
|
||||
*[[Digital root/Multiplicative digital root]]
|
||||
|
||||
;Related tasks:
|
||||
* [[Combinations with repetitions]]
|
||||
* [[Digital root]]
|
||||
* [[Digital root/Multiplicative digital root]]
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
public static class IteratedDigitsSquaring
|
||||
{
|
||||
public static void Main() {
|
||||
Console.WriteLine(Count89s(1_000_000));
|
||||
Console.WriteLine(Count89s(100_000_000));
|
||||
}
|
||||
|
||||
public static int Count89s(int limit) {
|
||||
if (limit < 1) return 0;
|
||||
int[] end = new int[Math.Min(limit, 9 * 9 * 9 + 2)];
|
||||
int result = 0;
|
||||
|
||||
for (int i = 1; i < end.Length; i++) {
|
||||
for (end[i] = i; end[i] != 1 && end[i] != 89; end[i] = SquareDigitSum(end[i])) { }
|
||||
if (end[i] == 89) result++;
|
||||
}
|
||||
for (int i = end.Length; i < limit; i++) {
|
||||
if (end[SquareDigitSum(i)] == 89) result++;
|
||||
}
|
||||
return result;
|
||||
|
||||
int SquareDigitSum(int n) {
|
||||
int sum = 0;
|
||||
while (n > 0) {
|
||||
int digit = n % 10;
|
||||
sum += digit * digit;
|
||||
n /= 10;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
USING: kernel math math.ranges math.text.utils memoize
|
||||
prettyprint sequences tools.time ;
|
||||
IN: rosetta-code.iterated-digits-squaring
|
||||
|
||||
: sum-digit-sq ( n -- m ) 1 digit-groups [ sq ] map-sum ;
|
||||
|
||||
MEMO: 1or89 ( n -- m )
|
||||
[ dup [ 1 = ] [ 89 = ] bi or ] [ sum-digit-sq ] until ;
|
||||
|
||||
[
|
||||
0 1
|
||||
[
|
||||
dup sum-digit-sq 1or89 89 = [ [ 1 + ] dip ] when
|
||||
1 + dup 100,000,000 <
|
||||
] loop
|
||||
drop .
|
||||
] time
|
||||
|
|
@ -1,18 +1,12 @@
|
|||
function iterate(m)
|
||||
function iterate(m::Integer)
|
||||
while m != 1 && m != 89
|
||||
s = 0
|
||||
while m > 0 # compute sum of squares of digits
|
||||
m, d = divrem(m, 10)
|
||||
s += d*d
|
||||
s += d ^ 2
|
||||
end
|
||||
m = s
|
||||
end
|
||||
return m
|
||||
end
|
||||
function itercount(N)
|
||||
count = 0
|
||||
for n in 1:N
|
||||
count += iterate(n) == 89
|
||||
end
|
||||
return count
|
||||
end
|
||||
itercount(k::Integer) = count(x -> iterate(x) == 89, 1:k)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,28 @@
|
|||
function itercount_combinations(ndigits)
|
||||
count = 0
|
||||
using Combinatorics
|
||||
function itercountcombos(ndigits::Integer)
|
||||
cnt = 0
|
||||
f = factorial(ndigits)
|
||||
# loop over all combinations of ndigits decimal digits:
|
||||
for c in combinations([1:(10+ndigits-1)],ndigits)
|
||||
for comb in combinations(1:(10+ndigits-1), ndigits)
|
||||
s = 0
|
||||
perms = 1
|
||||
prevdigit = -1
|
||||
repeat = 1
|
||||
for k = 1:length(c) # sum digits^2 and count permutations
|
||||
digit = c[k]-k
|
||||
s += digit*digit
|
||||
prevd = -1
|
||||
rep = 1
|
||||
for k = eachindex(comb) # sum digits ^ 2 and count permutations
|
||||
d = comb[k] - k
|
||||
s += d ^ 2
|
||||
# accumulate number of permutations of repeated digits
|
||||
if digit == prevdigit
|
||||
repeat += 1
|
||||
perms *= repeat
|
||||
if d == prevd
|
||||
rep += 1
|
||||
perms *= rep
|
||||
else
|
||||
prevdigit = digit
|
||||
repeat = 1
|
||||
prevd = d
|
||||
rep = 1
|
||||
end
|
||||
end
|
||||
if s > 0 && iterate(s) == 89
|
||||
count += div(f, perms) # numbers we can get from digits
|
||||
cnt += f ÷ perms # numbers we can get from digits
|
||||
end
|
||||
end
|
||||
return count
|
||||
return cnt
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
@time itercount(100_000_000)
|
||||
@time itercountcombos(8)
|
||||
@time itercountcombos(17)
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
use nqp;
|
||||
my $cache := nqp::list_i();
|
||||
nqp::bindpos_i($cache, 650, 0);
|
||||
nqp::bindpos_i($cache, 1, 1);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
/*REXX program performs the squaring of iterated digits (until the sum equals 1 or 89).*/
|
||||
parse arg n . /*obtain optional arguments from the CL*/
|
||||
if n=='' | n=="," then n=10 * 1000000 /*Not specified? Then use the default.*/
|
||||
!.=0; do m=1 for 9; !.m=m**2; end /*m*/ /*build a short─cut for the squares. */
|
||||
a.=. /*intermediate counts of some numbers. */
|
||||
#.=0 /*count of 1 and 89 results so far.*/
|
||||
!.=0; do m=1 for 9; !.m=m**2; end /*m*/ /*build a short─cut for the squares. */
|
||||
a.=.; #.=!. /*intermediate counts of some numbers. */
|
||||
do j=1 for n; x=j /* [↓] process the numbers in the range*/
|
||||
do q=1 until s==89 | s==1; s=0 /*add sum of the squared decimal digits*/
|
||||
do until x=='' /*process each of the dec. digits in X.*/
|
||||
parse var x _ +1 x; s=s+!._ /*get a digit; sum the fast square, */
|
||||
end /*until x== ... */ /* [↑] S≡is sum of the squared digits.*/
|
||||
parse var x _ +1 x; s=s + !._ /*get a digit; sum the fast square, */
|
||||
end /*until x ··· */ /* [↑] S≡is sum of the squared digits.*/
|
||||
z.q=s /*assign sum to a temporary auxiliary. */
|
||||
if a.s\==. then do; s=a.s; leave; end /*Found a previous sum? Then use that.*/
|
||||
x=s /*substitute the sum for the "new" X. */
|
||||
end /*until s== ... */ /* [↑] keep looping 'til S= 1 or 89.*/
|
||||
|
||||
do f=1 for q /* [↓] use the auxiliary array. */
|
||||
_=z.f; a._=s /*assign auxiliaries for future look-up*/
|
||||
end /*f*/
|
||||
#.s=#.s+1 /*bump the counter for the 1's or 89's.*/
|
||||
end /*q*/ /* [↑] keep looping 'til S= 1 or 89.*/
|
||||
do f=1 for q; _=a.f; a._=s /*use the auxiliary arrays (for lookup)*/
|
||||
end /*f*/
|
||||
#.s=#.s + 1 /*bump the counter for the 1's or 89's.*/
|
||||
end /*j*/
|
||||
|
||||
do k=1 by 88 for 2; @=right('"'k'"', 5) /*display two results; define a literal*/
|
||||
say 'count of' @ " chains for all natural numbers up to " n ' is:' #.k
|
||||
do k=1 by 88 for 2; @k=right('"'k'"', 5) /*display two results; define a literal*/
|
||||
say 'count of' @k " chains for all natural numbers up to " n ' is:' #.k
|
||||
end /*k*/ /*stick a fork in it, we're all done. */
|
||||
|
|
|
|||
|
|
@ -1,39 +1,40 @@
|
|||
/*REXX program performs the squaring of iterated digits (until the sum equals 1 or 89).*/
|
||||
parse arg n . /*obtain optional arguments from the CL*/
|
||||
if n=='' | n=="," then n=10 * 1000000 /*Not specified? Then use the default.*/
|
||||
!.=0; do m=1 for 9; !.m=m**2; end /*m*/ /*build a short─cut for the squares. */
|
||||
$.=.; $.0=0; $.00=0; $.000=0; $.0000=0; @.=. /*short-cuts for sub-group summations. */
|
||||
!.=0; do m=1 for 9; !.m=m**2; end /*m*/ /*build a short─cut for the squares. */
|
||||
$.=.; $.0=0; $.00=0; $.000=0; $.0000=0; @.=$. /*short-cuts for sub-group summations. */
|
||||
#.=0 /*count of 1 and 89 results so far.*/
|
||||
do j=1 for n; s=sumDs(j) /* [↓] process each number in a range.*/
|
||||
#.s=#.s+1 /*bump the counter for 1's or 89's. */
|
||||
do j=1 for n; s=sumDs(j) /* [↓] process each number in a range.*/
|
||||
#.s=#.s + 1 /*bump the counter for 1's or 89's. */
|
||||
end /*j*/
|
||||
|
||||
do k=1 by 88 for 2; @=right('"'k'"', 5) /*display two results; define a literal*/
|
||||
say 'count of' @ " chains for all natural numbers up to " n ' is:' #.k
|
||||
end /*k*/
|
||||
end /*k*/ /*stick a fork in it, we're all done. */
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
sumDs: parse arg z; chunk=3 /*obtain the number (for adding digits)*/
|
||||
p=0 /*set partial sum of the decimal digits*/
|
||||
do m=1 by chunk to length(z) /*process the number, in chunks of four*/
|
||||
y=substr(z, m, chunk) /*extract a 4─byte chunk of the number.*/
|
||||
if @.y==. then do; oy=y; a=0 /*Not done before? Then sum the number*/
|
||||
do until y=='' /*process each of the dec. digits in Y.*/
|
||||
parse var y _ +1 y; a=a+!._ /*obtain a decimal digit; add it to A.*/
|
||||
end /*until y ···*/ /* [↑] A ≡ is the sum of squared digs*/
|
||||
@.oy=a /*mark original Y as being summed. */
|
||||
end
|
||||
else a=@.y /*use the pre─summed digits of Y. */
|
||||
p=p+a /*add all the parts of number together.*/
|
||||
end /*m*/
|
||||
p=0 /*set partial sum of the decimal digits*/
|
||||
do m=1 by chunk to length(z) /*process the number, in chunks of four*/
|
||||
y=substr(z, m, chunk) /*extract a 4─byte chunk of the number.*/
|
||||
if @.y==. then do; oy=y; a=0 /*Not done before? Then sum the number*/
|
||||
do until y=='' /*process each of the dec. digits in Y.*/
|
||||
parse var y _ +1 y /*obtain a decimal digit; add it to A.*/
|
||||
a=a + !._ /*obtain a decimal digit; add it to A.*/
|
||||
end /*until y ···*/ /* [↑] A ≡ is the sum of squared digs*/
|
||||
@.oy=a /*mark original Y as being summed. */
|
||||
end
|
||||
else a=@.y /*use the pre─summed digits of Y. */
|
||||
p=p + a /*add all the parts of number together.*/
|
||||
end /*m*/
|
||||
|
||||
if $.p\==. then return $.p /*Computed before? Then use the value.*/
|
||||
y=p /*use a new copy of P. */
|
||||
do until s==1 | s==89; s=0 /*add the squared decimal digits of P.*/
|
||||
do until y=='' /*process each decimal digits in X.*/
|
||||
parse var y _ +1 y; s=s+!._ /*get a dec. digit; sum the fast square*/
|
||||
end /*until y=='' ···*/ /* [↑] S ≡ is sum of the squared digs.*/
|
||||
y=s /*substitute the sum for a "new" X. */
|
||||
end /*until s==1 ···*/ /* [↑] keep looping 'til S=1 or 89.*/
|
||||
$.p=s /*use this for memoization for the sum.*/
|
||||
return s
|
||||
if $.p\==. then return $.p /*Computed before? Then use the value.*/
|
||||
y=p /*use a new copy of P. */
|
||||
do until s==1 | s==89; s=0 /*add the squared decimal digits of P.*/
|
||||
do until y=='' /*process each decimal digits in X.*/
|
||||
parse var y _ +1 y; s=s + !._ /*get a dec. digit; sum the fast square*/
|
||||
end /*until y ···*/ /* [↑] S ≡ is sum of the squared digs.*/
|
||||
y=s /*substitute the sum for a "new" X. */
|
||||
end /*until s ···*/ /* [↑] keep looping 'til S=1 or 89.*/
|
||||
$.p=s /*use this for memoization for the sum.*/
|
||||
return s
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue