June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

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

View file

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

View file

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

View file

@ -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)

View file

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

View file

@ -0,0 +1,3 @@
@time itercount(100_000_000)
@time itercountcombos(8)
@time itercountcombos(17)

View file

@ -1,3 +1,4 @@
use nqp;
my $cache := nqp::list_i();
nqp::bindpos_i($cache, 650, 0);
nqp::bindpos_i($cache, 1, 1);

View file

@ -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. */

View file

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