Iterated digits squaring: Difference between revisions

m
syntax highlighting fixup automation
(lang -> syntaxhighlight)
m (syntax highlighting fixup automation)
Line 7:
An example in Python:
 
<syntaxhighlight lang="python">>>> step = lambda x: sum(int(d) ** 2 for d in str(x))
>>> iterate = lambda x: x if x in [1, 89] else iterate(step(x))
>>> [iterate(x) for x in xrange(1, 20)]
Line 32:
{{trans|Python}}
 
<syntaxhighlight lang="11l">F next_step(=x)
V result = 0
L x > 0
Line 90:
 
=={{header|Ada}}==
<syntaxhighlight lang=Ada"ada">with Ada.Text_IO;
 
procedure Digits_Squaring is
Line 137:
=={{header|ALGOL 68}}==
Brute-force with some caching.
<syntaxhighlight lang="algol68"># count the how many numbers up to 100 000 000 have squared digit sums of 89 #
 
# compute a table of the sum of the squared digits of the numbers 00 to 99 #
Line 193:
=={{header|Arturo}}==
{{trans|Nim}}
<syntaxhighlight lang="rebol">gen: function [n][
result: n
while [not? in? result [1 89]][
Line 241:
=={{header|AWK}}==
We use a brute-force approach with buffering for better performance. Numbers are assumed to be double precision floats, which is true for most implementations. It runs in about 320 s on an Intel i5.
<syntaxhighlight lang=AWK"awk"># Usage: GAWK -f ITERATED_DIGITS_SQUARING.AWK
BEGIN {
# Setup buffer for results up to 9*9*8
Line 285:
{{works with|BBC BASIC for Windows}}
Three versions timed on a 2.50GHz Intel Desktop.
<syntaxhighlight lang="bbcbasic"> REM Version 1: Brute force
REM ---------------------------------------------------------
T%=TIME
Line 353:
This is just a brute force solution, so it's not very fast. A decent interpreter will probably take a minute or two for a 1,000,000 iterations. If you want to test with 100,000,000 iterations, change the <tt>::**</tt> (100³) near the end of the first line to <tt>:*:*</tt> (100²<sup>²</sup>). With that many iterations, though, you'll almost certainly want to be using a compiler, otherwise you'll be waiting a long time for the result.
 
<syntaxhighlight lang="befunge">1-1\10v!:/+55\<>::**>>-!|
v0:\+<_:55+%:*^^"d":+1$<:
>\`!#^ _$:"Y"-#v_$\1+\:^0
Line 369:
A simple solution is to compute all square-digit sums in the desired range as an addition table, then repeatedly select from this list using itself as an index so that all values that end at 1 converge (those that reach 89 will find some point in the cycle, but not always the same one).
 
<syntaxhighlight lang="bqn"> +´1?1? ?˜?(?2???) ?+?´6?<ט?10
856929</syntaxhighlight>
 
It will take a lot of memory and many seconds to compute the count under 1e8 this way. The following program computes the count for numbers below <code>10???</code> by using dynamic programming to determine how many numbers have each possible digit sum. Then it finds the fate of each number in this greatly reduced set. This gives an exact result for inputs up to 16, taking a fraction of a millisecond for each.
 
<syntaxhighlight lang="bqn">DigSq ? {
d ? ט ?10 # Digit values
m ? 1+81×2??? # One plus maximum digit sum
Line 383:
}</syntaxhighlight>
 
<syntaxhighlight lang="bqn"> >??DigSq¨ 1+?16
+-
? 1 7
Line 405:
=={{header|C}}==
C99, tested with "gcc -std=c99". Record how many digit square sum combinations there are. This reduces <math>10^n</math> numbers to <math>81n</math>, and the complexity is about <math>O(n^2)</math>. The 64 bit integer counter is good for up to <math>10^{19}</math>, which takes practically no time to run.
<syntaxhighlight lang="c">#include <stdio.h>
 
typedef unsigned long long ull;
Line 476:
</pre>
Fast C implementation (<1 second my machine), which performs iterated digits squaring only once for each unique 8 digit combination. The cases 0 and 100,000,000 are ignored since they don't sum to 89:
<syntaxhighlight lang="c">
#include <stdio.h>
 
Line 566:
The largest sum possible for any number is 9*9*9, so the first 730 numbers are calculated and stored in an array.<br/>
The rest is then looked up. A limit of 100 million takes about 6 seconds. int.MaxValue takes about 2 and a half minutes.
<syntaxhighlight lang="csharp">using System;
public static class IteratedDigitsSquaring
{
Line 610:
{{Libheader|System.Numerics}}
Translation of the first C version, with BigIntegers. This can get pretty far in six seconds, even on Tio.run.
<syntaxhighlight lang="csharp">using System;
using System.Numerics;
 
Line 883:
=={{header|C++}}==
Slow (~10 seconds on my machine) brute force C++ implementation:
<syntaxhighlight lang="cpp">
#include <iostream>
 
Line 926:
 
=={{header|Ceylon}}==
<syntaxhighlight lang="ceylon">shared void run() {
function digitsSquaredSum(variable Integer n) {
Line 957:
=={{header|Clojure}}==
===Direct Method===
<syntaxhighlight lang="lisp">(ns async-example.core
(:require [clojure.math.numeric-tower :as math])
(:use [criterium.core])
Line 1,058:
 
=={{header|Common Lisp}}==
<syntaxhighlight lang="lisp">
(defun square (number)
(expt number 2))
Line 1,108:
=={{header|D}}==
A simple memoizing partially-imperative brute-force solution:
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.functional;
 
uint step(uint x) pure nothrow @safe @nogc {
Line 1,131:
 
A fast imperative brute-force solution:
<syntaxhighlight lang="d">void main() nothrow @nogc {
import core.stdc.stdio: printf;
 
Line 1,176:
 
A more efficient solution:
<syntaxhighlight lang="d">import core.stdc.stdio, std.algorithm, std.range;
 
enum factorial = (in uint n) pure nothrow @safe @nogc
Line 1,257:
A purely functional version, from the Haskell code. It includes two functions currently missing in Phobos used in the Haskell code.
{{trans|Haskell}}
<syntaxhighlight lang="d">import std.stdio, std.typecons, std.traits, std.typetuple, std.range, std.algorithm;
 
auto divMod(T)(T x, T y) pure nothrow @safe @nogc {
Line 1,320:
 
=={{header|ERRE}}==
<syntaxhighlight lang=ERRE"erre">
PROGRAM ITERATION
 
Line 1,367:
</pre>
=={{header|Forth}}==
<syntaxhighlight lang="forth">
Tested for VFX Forth and GForth in Linux
\ To explain the algorithm: Each iteration is performed in set-count-sumsq below.
Line 1,517:
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
' similar to C Language (first approach)
Line 1,572:
 
=={{header|Frink}}==
<syntaxhighlight lang="frink">
total = 0
d = new dict
Line 1,621:
It's basic. Runs in about 30 seconds on an old laptop.
 
<syntaxhighlight lang="go">package main
 
import (
Line 1,658:
=={{header|Haskell}}==
Basic solution that contains just a little more than the essence of this computation. This runs in less than eight minutes:
<syntaxhighlight lang="haskell">import Data.List (unfoldr)
import Data.Tuple (swap)
 
Line 1,678:
Here's an expression to turn a number into digits:
 
<syntaxhighlight lang=J"j">digits=: 10&#.inv</syntaxhighlight>
 
And here's an expression to square them and find their sum:
<syntaxhighlight lang=J"j">sumdigsq=: +/"1@:*:@digits</syntaxhighlight>
 
But note that while the task description claims "you always end with either 1 or 89", that claim is somewhat arbitrary.
:But only somewhat the loop is 89 ? 145 ? 42 ? 20 ? 4 ? 16 ? 37 ? 58 ? 89, so it only ends with 1 or one of the numbers in this loop. 42 is of course far more significant and the one I would choose!!--[[User:Nigel Galloway|Nigel Galloway]] ([[User talk:Nigel Galloway|talk]]) 10:12, 16 September 2014 (UTC)
 
<syntaxhighlight lang=J"j"> sumdigsq^:(i.16) 15
15 26 40 16 37 58 89 145 42 20 4 16 37 58 89 145</syntaxhighlight>
 
You could just as easily claim that you always end with either 1 or 4. So here's a routine which repeats the sum-square process until the sequence converges, or until it reaches the value 4:
 
<syntaxhighlight lang=J"j">itdigsq4=:4 = sumdigsq^:(0=e.&4)^:_"0</syntaxhighlight>
 
But we do not actually need to iterate. The largest value after the first iteration would be:
 
<syntaxhighlight lang=J"j"> sumdigsq 99999999
648</syntaxhighlight>
 
So we could write a routine which works for the intended range, and stops after the first iteration:
<syntaxhighlight lang=J"j">itdigsq1=:1 = sumdigsq^:(0=e.&4)^:_"0
digsq1e8=:(I.itdigsq1 i.649) e.~ sumdigsq</syntaxhighlight>
 
Line 1,706:
And this is sufficient to find our result. We don't want to compute the entire batch of values in one pass, however, so let's break this up into 100 batches of one million each:
 
<syntaxhighlight lang=J"j"> +/+/@:-.@digsq1e8"1(1+i.100 1e6)
85744333</syntaxhighlight>
 
Of course, there are faster ways of obtaining that result. The fastest is probably this:
<syntaxhighlight lang=J"j"> 85744333
85744333</syntaxhighlight>
 
Line 1,717:
=={{header|Java}}==
{{works with|Java|8}}
<syntaxhighlight lang="java">import java.util.stream.IntStream;
 
public class IteratedDigitsSquaring {
Line 1,752:
 
'''Part 1: Foundations'''
<syntaxhighlight lang="jq">def factorial: reduce range(2;.+1) as $i (1; . * $i);
 
# Pick n items (with replacement) from the input array,
Line 1,778:
 
Count how many number chains beginning with n (where 0 < n < 10^D) end with a value 89.
<syntaxhighlight lang="jq">def terminus:
# sum of the squared digits
def ssdigits: tostring | explode | map(. - 48 | .*.) | add;
Line 1,807:
end) ;</syntaxhighlight>
'''Part 3: D=8'''
<syntaxhighlight lang="jq">task(8)</syntaxhighlight>
{{out}}
<syntaxhighlight lang="sh">$ jq -M -n -f Iterated_digits_squaring_using_pick.jq
85744333
 
Line 1,823:
{{works with|Julia|0.6}}
'''Brute force solution''':
<syntaxhighlight lang="julia">function iterate(m::Integer)
while m != 1 && m != 89
s = 0
Line 1,837:
 
'''More clever solution''':
<syntaxhighlight lang="julia">using Combinatorics
function itercountcombos(ndigits::Integer)
cnt = 0
Line 1,867:
 
'''Benchmarks'''
<syntaxhighlight lang="julia">@time itercount(100_000_000)
@time itercountcombos(8)
@time itercountcombos(17)</syntaxhighlight>
Line 1,877:
=={{header|Kotlin}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="scala">// version 1.0.6
 
fun endsWith89(n: Int): Boolean {
Line 1,920:
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">squares = {}
 
for i = 0, 9 do
Line 1,971:
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang=Mathematica"mathematica">sumDigitsSquared[n_Integer] := Total[IntegerDigits[n]^2]
stopValues = Join[{1}, NestList[sumDigitsSquared, 89, 7]];
iterate[n_Integer] :=
Line 2,016:
We provide the result for 8 digits and also for 50 digits. The result is obtained in 7 ms.
 
<syntaxhighlight lang=Nim"nim">import tables
 
iterator digits(n: int): int =
Line 2,068:
=={{header|Oberon-2}}==
{{works with|oo2c Version 2}}
<syntaxhighlight lang="oberon2">
MODULE DigitsSquaring;
IMPORT
Line 2,114:
 
=={{header|Objeck}}==
<syntaxhighlight lang="objeck">class Abbreviations {
function : Main(args : String[]) ~ Nil {
Count89s(1000000)->PrintLine();
Line 2,169:
Brute force implementation
 
<syntaxhighlight lang=Oforth"oforth">: sq_digits(n)
while (n 1 <> n 89 <> and ) [
0 while(n) [ n 10 /mod ->n dup * + ]
Line 2,183:
 
=={{header|PARI/GP}}==
<syntaxhighlight lang="parigp">ssd(n)=n=digits(n); sum(i=1, #n, n[i]^2);
happy(n)=while(n>6, n=ssd(n)); n==1;
ct(n)=my(f=n!,s=10^n-1,d); forvec(v=vector(9,i,[0,n]), d=vector(9,i, if(i>8,n,v[i+1])-v[i]); if(happy(sum(i=1,9,d[i]*i^2)), s-=f/prod(i=1,9,d[i]!)/v[1]!), 1); s;
Line 2,203:
 
Tested with freepascal.
<syntaxhighlight lang="pascal">program Euler92;
const
maxdigCnt = 14;
Line 2,359:
{{trans|Raku}}
 
<syntaxhighlight lang="perl">use warnings;
use strict;
 
Line 2,388:
=={{header|Phix}}==
{{trans|C}}
<!--<syntaxhighlight lang=Phix"phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAXINT</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">machine_bits</span><span style="color: #0000FF;">()=</span><span style="color: #000000;">32</span><span style="color: #0000FF;">?</span><span style="color: #000000;">53</span><span style="color: #0000FF;">:</span><span style="color: #000000;">64</span><span style="color: #0000FF;">))</span>
Line 2,466:
I realised I needed to do this in two stages.<br>
Phase 1. Make sure we can count.
<!--<syntaxhighlight lang=Phix"phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">chosen</span><span style="color: #0000FF;">={})</span>
Line 2,510:
Phase 2. Add in the rest of the logic, as suggested count 1's in preference to 89's and subtract from 10^n to get the answer.<br>
[PS There is an eerie similarity between this and the 2nd C version, but I swear it is not a copy, and I noticed that later.]
<!--<syntaxhighlight lang=Phix"phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">is1</span>
Line 2,597:
=={{header|PicoLisp}}==
Brute force with caching
<syntaxhighlight lang=PicoLisp"picolisp">(de *Idx1or89 (89 . 89) ((1 . 1)))
 
(de 1or89 (N)
Line 2,607:
(idx '*Idx1or89 (cons N @) T) ) ) ) )</syntaxhighlight>
Test:
<syntaxhighlight lang=PicoLisp"picolisp">(let Ones 0
(for I 100000000
(and (=1 (1or89 I)) (inc 'Ones)) )
Line 2,615:
 
=={{header|PL/I}}==
<syntaxhighlight lang=PL"pl/Ii">
test: procedure options (main, reorder); /* 6 August 2015 */
 
Line 2,654:
=={{header|PureBasic}}==
{{Trans|C}}
<syntaxhighlight lang="purebasic">OpenConsole()
Procedure is89(x)
Repeat
Line 2,715:
elapsed milliseconds= 9</pre>
{{Trans|C++}}
<syntaxhighlight lang="purebasic">OpenConsole()
Procedure sum_square_digits(n)
num=n : sum=0
Line 2,754:
====Translation of D====
{{trans|D}}
<syntaxhighlight lang="python">from math import ceil, log10, factorial
 
def next_step(x):
Line 2,815:
====Translation of Ruby====
{{trans|Ruby}}
<syntaxhighlight lang="python">
from itertools import combinations_with_replacement
from array import array
Line 2,879:
 
===Python: Simple caching===
<syntaxhighlight lang="python">>>> from functools import lru_cache
>>> @lru_cache(maxsize=1024)
def ids(n):
Line 2,898:
===Python: Enhanced caching===
Notes that the order of digits in a number does not affect the final result so caches the digits of the number in sorted order for more hits.
<syntaxhighlight lang="python">>>> from functools import lru_cache
>>> @lru_cache(maxsize=1024)
def _ids(nt):
Line 2,922:
===Count digit sums===
If we always count up to powers of 10, it's faster to just record how many different numbers have the same digit square sum. The <code>check89()</code> function is pretty simple-minded, because it doesn't need to be fancy here.
<syntaxhighlight lang="python">from __future__ import print_function
from itertools import count
 
Line 2,947:
{{works with|QuickBasic}}
{{trans|BBC BASIC}}
<syntaxhighlight lang=QBasic"qbasic">REM Version 1: Brute force
 
T = TIMER
Line 2,969:
=={{header|Quackery}}==
 
<syntaxhighlight lang=Quackery"quackery">[ abs 0 swap
[ base share /mod
dup *
Line 2,994:
This contains two versions (in one go). The naive version which can (and should, probably) be used for investigating a single number. The second version can count the IDSes leading to 89 for powers of 10.
 
<syntaxhighlight lang="racket">#lang racket
;; Tim-brown 2014-09-11
 
Line 3,115:
This fairly abstract version does caching and filtering to reduce the number of values it needs to check and moves calculations out of the hot loop, but is still interminably slow... even for just up to 1,000,000.
 
<syntaxhighlight lang=perl6"raku" line>constant @sq = ^10 X** 2;
my $cnt = 0;
 
Line 3,132:
<pre>856929</pre>
All is not lost, however. Through the use of gradual typing, Raku scales down as well as up, so this jit-friendly version is performant enough to brute force the larger calculation:
<syntaxhighlight lang=perl6"raku" line>my @cache;
@cache[1] = 1;
@cache[89] = 89;
Line 3,171:
The biggest gains are often from choosing the right algorithm.
 
<syntaxhighlight lang=perl6"raku" line>sub endsWithOne($n --> Bool) {
my $digit;
my $sum = 0;
Line 3,211:
{Both REXX versions don't depend on a specific end-number.}
===with memoization===
<syntaxhighlight lang="rexx">/*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.*/
Line 3,242:
===process in chunks===
This version is about &nbsp; <big> 2½ </big> &nbsp; times faster than the previous REXX version.
<syntaxhighlight lang="rexx">/*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.*/
Line 3,290:
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
nr = 1000
num = 0
Line 3,347:
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby"># Count how many number chains for Natural Numbers < 10**d end with a value of 1.
def iterated_square_digit(d)
f = Array.new(d+1){|n| (1..n).inject(1, :*)} #Some small factorials
Line 3,398:
 
'''Naive Recursion'''
<syntaxhighlight lang="rust">fn digit_square_sum(mut num: usize) -> usize {
let mut sum = 0;
while num != 0 {
Line 3,423:
 
'''With precomputation'''
<syntaxhighlight lang="rust">fn dig_sq_sum(mut num : usize ) -> usize {
let mut sum = 0;
while num != 0 {
Line 3,452:
===Naïve Version, conventional iteration and (tail) recursive in one===
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/3XRtgEE/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/6HeszTpxTXOqvrytzShUzg Scastie (remote JVM)] to compare the run times.
<syntaxhighlight lang=Scala"scala">import scala.annotation.tailrec
 
object Euler92 extends App {
Line 3,497:
 
=={{header|Sidef}}==
<syntaxhighlight lang="ruby">func digit_square_sum_iter(n) is cached {
 
if ((n == 1) || (n == 89)) {
Line 3,518:
With nth power support.
 
<syntaxhighlight lang="swift">import BigInt
 
func is89(_ n: Int) -> Bool {
Line 3,585:
All three versions below produce identical output (<tt>85744333</tt>), but the third is fastest and the first is the slowest, both by substantial margins.
===''Very'' Naïve Version===
<syntaxhighlight lang="tcl">proc ids n {
while {$n != 1 && $n != 89} {
set n [tcl::mathop::+ {*}[lmap x [split $n ""] {expr {$x**2}}]]
Line 3,597:
===Intelligent Version===
Conversion back and forth between numbers and strings is slow. Using math operations directly is much faster (around 4 times in informal testing).
<syntaxhighlight lang="tcl">proc ids n {
while {$n != 1 && $n != 89} {
for {set m 0} {$n} {set n [expr {$n / 10}]} {
Line 3,614:
<!-- It takes about 200 seconds on my machine, but I can't compare with anyone else's system… -->
:Donald, you have 1 too many 9's the value after step 1 is 81*8 = 648. Not that that is the problem here, you can not afford to go around this loop 100 million times. Notice that IDS[21] == IDS[12], IDS[123] == IDS[132] == IDS[213} ... etc, etc. The Ruby version takes about a tenth of a second.--[[User:Nigel Galloway|Nigel Galloway]] ([[User talk:Nigel Galloway|talk]]) 12:47, 31 August 2014 (UTC)
<syntaxhighlight lang="tcl"># Basic implementation
proc ids n {
while {$n != 1 && $n != 89} {
Line 3,648:
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
start_time = Now
cnt = 0
Line 3,680:
=={{header|Wren}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="ecmascript">var endsWith89 = Fn.new { |n|
var digit = 0
var sum = 0
Line 3,728:
=={{header|X86 Assembly}}==
{{works with|nasm}}
<syntaxhighlight lang="asm">
section .data
count dd 0
Line 3,788:
{{trans|D}}
{{trans|http://www.mathblog.dk/project-euler-92-square-digits-number-chain/}}
<syntaxhighlight lang="zkl">fcn check(number){ // a list of digits: 13 is L(0,0,0,0,0,0,1,3)
candidate:=number.reduce(fcn(sum,n){ sum*10 + n },0); // digits to int
 
Line 3,826:
{{trans|BBC_BASIC}}
Very, very slow. Use a ZX Spectrum emulator and run with maximum speed option enabled.
<syntaxhighlight lang="zxbasic">10 LET n=0
20 FOR i=1 TO 1000
30 LET j=i
10,333

edits