Ulam numbers: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
(11 intermediate revisions by 7 users not shown)
Line 20:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F ulam(n)
I n <= 2
R n
Line 45:
L(p) 5
V n = 10 ^ p
print(‘The #.#. Ulam number is #.’.format(n, I n != 1 {‘th’} E ‘st’, ulam(n)))</langsyntaxhighlight>
 
{{out}}
Line 54:
The 1000th Ulam number is 12294
The 10000th Ulam number is 132788
</pre>
 
=={{header|360 Assembly}}==
<syntaxhighlight lang="360asm">* Ulam numbers 25/01/2021
ULAMNUM CSECT
USING ULAMNUM,R13 base register
B 72(R15) skip savearea
DC 17F'0' savearea
SAVE (14,12) save previous context
ST R13,4(R15) link backward
ST R15,8(R13) link forward
LR R13,R15 set addressability
LA R1,1 1
ST R1,ULAM ulam(1)=1
LA R1,2 2
ST R1,ULAM+4 ulam(2)=2
LA R9,2 k=2
LA R8,2 n=2
DO WHILE=(C,R9,LT,NN) do while k<nn
LA R8,1(R8) n=n+1
XR R10,R10 count=0
LR R0,R9 k
BCTR R0,0 -1
LA R6,1 i=1
DO WHILE=(CR,R6,LE,R0) do i=1 to k-1
LR R7,R6 i
LA R7,1(R7) j=i+1
DO WHILE=(CR,R7,LE,R9) do j=i+1 to k
LR R1,R6 i
SLA R1,2 ~
L R2,ULAM-4(R1) ulam(i)
LR R1,R7 j
SLA R1,2 ~
L R3,ULAM-4(R1) ulam(j)
AR R2,R3 ulam(i)+ulam(j)
IF CR,R2,EQ,R8 THEN if ulam(i)+ulam(j)=n then
LA R10,1(R10) count=count+1
ENDIF , endif
LA R7,1(R7) j++
ENDDO , enddo j
LA R6,1(R6) i++
ENDDO , enddo i
IF C,R10,EQ,=F'1' THEN if count=1 then
LA R9,1(R9) k=k+1
LR R1,R9 k
SLA R1,2 ~
ST R8,ULAM-4(R1) ulam(k)=n
LR R4,R9 k
SRDA R4,32 ~
D R4,=F'50' k/50
IF LTR,R4,Z,R4 THEN if mod(k,50)=0 then
XDECO R9,PG k
XDECO R8,PG+12 n
XPRNT PG,L'PG print buffer
ENDIF , endif
ENDIF , endif
ENDDO , enddo n
L R13,4(0,R13) restore previous savearea pointer
RETURN (14,12),RC=0 restore registers from calling save
U EQU 500 u : max value
NN DC A(U) nn
ULAM DS (U)F ulam(u)
PG DC CL80' ' buffer
REGEQU
END ULAMNUM</syntaxhighlight>
{{out}}
<pre>
50 253
100 690
150 1257
200 1792
250 2484
300 3068
350 3632
400 4326
450 4996
500 5685
</pre>
 
=={{header|Action!}}==
Calculations on a real Atari 8-bit computer take quite long time. It is recommended to use an emulator capable with increasing speed of Atari CPU.
<langsyntaxhighlight Actionlang="action!">PROC Main()
DEFINE MAX="1000"
INT ARRAY ulam(MAX)
Line 85 ⟶ 162:
n==+1
OD
RETURN</langsyntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Ulam_numbers.png Screenshot from Atari 8-bit computer]
<pre>
1 2 3 4 6 8 11 13 16 18 26 28 36 38 47 48 53 57 62 69 72 77 82 87 97 99 102 106 114 126 131 138 145 148 155 175 ...
</pre>
 
=={{header|ALGOL 68}}==
Basically, the same algotithm as XPL0.
<syntaxhighlight lang="algol68">
BEGIN # find some Ulam numbers, U(n) = the smallest number > U(n-1) that is #
# the uniue sum of U(i) and U(j), i, j < n, i =/= j, U(1)=1, U(2) = 2 #
INT max ulam = 10 000; # maximum ulam number to find #
[ 1 : max ulam ]INT u; # ulam numbers found #
FOR i TO UPB u DO u[ i ] := 0 OD;
INT ulam size = 20 000; # initial size of the ulam number buffer #
CHAR unused = "0", one = "1", multiple = "2"; # states of ulam numbers #
FLEX[ 1 : ulam size ]CHAR ulam;FOR i TO UPB ulam DO ulam[ i ] := unused OD;
ulam[ 3 ] := ulam[ 2 ] := ulam[ 1 ] := one; u[ 1 ] := 1; u[ 2 ] := 2;
print( ( " 1 2" ) );
INT u count := 2; # numer of ulam numbers found #
INT power of ten := 100; # next "power of ten" ulam number to show #
FOR i FROM 3 WHILE u count < max ulam DO
IF ulam[ i ] = one THEN
# can use this number #
u[ u count +:= 1 ] := i;
IF u count < 21 THEN
print( ( " ", whole( i, 0 ) ) );
IF u count = 20 THEN print( ( "..." ) ) FI
ELIF u count = power of ten THEN
print( ( newline, "The ", whole( power of ten, -6 ), "th Ulam number is: ", whole( i, 0 ) ) );
power of ten *:= 10
FI;
FOR p TO u count - 1 DO
INT pi = u[ p ] + i;
IF pi > UPB ulam THEN
# need a bigger ulam buffer #
[ 1 : UPB ulam + ulam size ]CHAR new ulam;
new ulam[ 1 : UPB ulam ] := ulam;
FOR u FROM UPB ulam + 1 TO UPB new ulam DO new ulam[ u ] := unused OD;
ulam := new ulam
FI;
CHAR upi = ulam[ pi ];
IF upi = unused
THEN ulam[ pi ] := one # u[ p ] + i is unique so far #
ELIF upi = one
THEN ulam[ pi ] := multiple # u[ p ] + i isn't unique #
FI
OD
FI
OD
END
</syntaxhighlight>
{{out}}
<pre>
1 2 3 4 6 8 11 13 16 18 26 28 36 38 47 48 53 57 62 69...
The 100th Ulam number is: 690
The 1000th Ulam number is: 12294
The 10000th Ulam number is: 132788
</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f ULAM_NUMBERS.AWK
BEGIN {
Line 116 ⟶ 247:
exit(0)
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 128 ⟶ 259:
=={{header|C}}==
{{trans|Phix}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 198 ⟶ 329:
printf("Elapsed time: %.3f seconds\n", (finish - start + 0.0)/CLOCKS_PER_SEC);
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 213 ⟶ 344:
=={{header|C++}}==
{{trans|Phix}}
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <chrono>
#include <iostream>
Line 241 ⟶ 372:
std::chrono::duration<double> duration(end - start);
std::cout << "Elapsed time: " << duration.count() << " seconds\n";
}</langsyntaxhighlight>
 
{{out}}
Line 253 ⟶ 384:
Elapsed time: 9.09242 seconds
</pre>
 
=={{header|Delphi}}==
{{trans|Phix}}
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
 
 
<syntaxhighlight lang="Delphi">
 
 
 
function GetUlamNumber(N: integer): integer;
var Ulams: array of integer;
var U,ULen,I: integer;
var Sieve: array of integer;
begin
SetLength(Ulams,Max(N,2));
Ulams[0]:= 1;
Ulams[1]:= 2;
SetLength(Sieve, 2);
Sieve[0]:=1;
Sieve[1]:= 1;
U:=2; ULen:=2;
while Ulen < N do
begin
SetLength(Sieve,U + Ulams[Ulen - 2]);
for I:= 0 to ulen - 2 do
Sieve[u + Ulams[I] - 1]:=Sieve[u + Ulams[i] - 1]+1;
for I:=U to High(Sieve) do
if Sieve[I] = 1 then
begin
U:=I + 1;
Ulams[Ulen]:=U;
Inc(ULen);
break;
end;
end;
Result:=ULams[N - 1];
end;
 
 
 
procedure ShowUlamNumbers(Memo: TMemo);
var N: integer;
var S: string;
begin
N:=1;
while N<=100000 do
begin
S:=Format('Ulam(%d)',[N]);
Memo.Lines.Add(Format('%-12S = %8d', [S, GetUlamNumber(N)]));
N:=N * 10
end;
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
Ulam(1) = 1
Ulam(10) = 18
Ulam(100) = 690
Ulam(1000) = 12294
Ulam(10000) = 132788
Ulam(100000) = 1351223
 
Elapsed Time: 17.685 Sec.
 
</pre>
 
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">redim as uinteger ulam(1 to 2)
ulam(1) = 1 : ulam(2) = 2
 
Line 289 ⟶ 490:
print 10^i, get_ulam(10^i, ulam())
next i
</syntaxhighlight>
</lang>
 
{{out}}
Line 300 ⟶ 501:
===Version 1===
{{trans|Wren}}
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 335 ⟶ 536:
fmt.Println("The", n, "\bth Ulam number is", ulam(n))
}
}</langsyntaxhighlight>
 
{{out}}
Line 350 ⟶ 551:
 
Although not shown here, the 100,000th Ulam number (1,351,223) is computed in about 13.5 seconds.
<langsyntaxhighlight lang="go">package main
 
import (
Line 409 ⟶ 610:
}
fmt.Println("\nTook", time.Since(start))
}</langsyntaxhighlight>
 
{{out}}
Line 427 ⟶ 628:
 
As mentioned in the Wren version 3 example, you need to know how much memory to allocate in advance.
<langsyntaxhighlight lang="go">package main
 
import (
Line 490 ⟶ 691:
}
fmt.Println("\nTook", time.Since(start))
}</langsyntaxhighlight>
 
{{out}}
Line 506 ⟶ 707:
 
===Lazy List===
<langsyntaxhighlight lang="haskell">
import Data.List
 
Line 535 ⟶ 736:
isSingleton as
| length as == 1 = True
| otherwise = False</langsyntaxhighlight>
 
=={{header|J}}==
 
Implementation:
 
<syntaxhighlight lang=J>require'stats'
nextulam=: , {{<./(#~ ({:y)<])(~. #~ 1 = #/.~) +/"1 y{~2 comb #y}}
ulam=: <: { (nextulam^:(<:@(>./)`(1 2"_)))</syntaxhighlight>
 
This could be optimized, for example: caching could help.
 
Examples:
 
<syntaxhighlight lang=J> ulam 1
1
ulam 10
18
ulam 100
690
ulam 1000
12294
ulam 10000
132788
ulam 20 30 40 50 60
69 126 189 253 341</syntaxhighlight>
 
=={{header|Java}}==
{{trans|Phix}}
<langsyntaxhighlight lang="java">public class UlamNumbers {
public static void main(String[] args) {
long start = System.currentTimeMillis();
Line 582 ⟶ 808:
return newArray;
}
}</langsyntaxhighlight>
 
{{out}}
Line 597 ⟶ 823:
=={{header|jq}}==
'''Adaptation of [[#awk|awk]] solution'''
<langsyntaxhighlight lang="jq"># Input: the target number of Ulam numbers to generate
# Output: an array of Ulam numbers
def ulams:
Line 617 ⟶ 843:
select(.nulams >= $target) | .ulam, break $done);
 
def nth_ulam: ulams[.-1];</langsyntaxhighlight>
 
'''Illustration'''
<langsyntaxhighlight lang="jq">(5 | nth_ulam) | "5 => \(.)",
"",
([5, 10, 100] as $in
Line 626 ⟶ 852:
| $in[]
| "\(.) => \($u[. - 1])" )
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 638 ⟶ 864:
=={{header|Julia}}==
{{trans|Wren}}
<langsyntaxhighlight lang="julia">function nthUlam(n)
ulams = [1, 2]
memoized = Set([1, 2])
Line 664 ⟶ 890:
@time println("The ", n, "th Ulam number is: ", nthUlam(n))
end
</langsyntaxhighlight>{{out}}
<pre>
The 10th Ulam number is: 18
Line 678 ⟶ 904:
=={{header|Lua}}==
Implemented from scratch, but algorithmically equivalent to other solutions where a running count of number-of-ways-to-reach-sum is maintained in order to sieve candidate values.
<langsyntaxhighlight lang="lua">function ulam(n)
local ulams, nways, i = { 1,2 }, { 0,0,1 }, 3
repeat
Line 696 ⟶ 922:
local s, u, e = os.clock(), ulam(n), os.clock()
print(string.format("%dth is %d (%f seconds elapsed)", n, u, e-s))
end</langsyntaxhighlight>
{{out}}
Times are Lua 5.4 on i7-2600@3.4GHz
Line 711 ⟶ 937:
 
It has been compiled with option <code>-d:release</code> which means that all runtime checks are done but debugging data is limited.
<langsyntaxhighlight Nimlang="nim">import strformat, times
 
func ulam(n: Positive): int =
Line 737 ⟶ 963:
echo &"The {n}{suffix} Ulam number is {ulam(n)}."
n *= 10
echo &"\nTook {cpuTime() - t0:.3f} s."</langsyntaxhighlight>
 
{{out}}
Line 755 ⟶ 981:
It has been compiled with the same option as the other version.
 
<langsyntaxhighlight Nimlang="nim"> import strformat, times
 
func ulam(n: Positive): int =
Line 786 ⟶ 1,012:
echo &"The {n}th Ulam number is {ulam(n)}."
n *= 10
echo &"\nTook {cpuTime() - t0:.3f} s."</langsyntaxhighlight>
 
{{out}}
Line 801 ⟶ 1,027:
=={{header|Pascal}}==
{{works with|Free Pascal}} like GO,PHIX who was first
<langsyntaxhighlight lang="pascal">program UlamNumbers;
{$IFDEF FPC}
{$MODE DELPHI}
Line 897 ⟶ 1,123:
setlength(Ulams,0);
end.
</langsyntaxhighlight>{{out}}
<pre> Ulam(1) 1
Ulam(10) 18
Line 918 ⟶ 1,144:
=={{header|Perl}}==
{{trans|Julia}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature <say state>;
Line 952 ⟶ 1,178:
}
 
printf "The %dth Ulam number is: %d\n", 10**$_, ulam(10**$_) for 1..4;</langsyntaxhighlight>
{{out}}
<pre>The 10th Ulam number is: 18
Line 961 ⟶ 1,187:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="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;">ulam</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
Line 989 ⟶ 1,215:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 1,012 ⟶ 1,238:
=={{header|Python}}==
{{trans|XPL0}}
<langsyntaxhighlight lang="python">import time
 
def ulam(n):
Line 1,042 ⟶ 1,268:
 
print("\nElapsed time:", time.time() - t0)
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,063 ⟶ 1,289:
=={{header|Raku}}==
 
<syntaxhighlight lang="raku" perl6line>my @ulams = 1, 2, &next-ulam … *;
 
sub next-ulam {
Line 1,076 ⟶ 1,302:
for 1 .. 4 {
say "The {10**$_}th Ulam number is: ", @ulams[10**$_ - 1]
}</langsyntaxhighlight>
{{out}}
<pre>The 10th Ulam number is: 18
Line 1,087 ⟶ 1,313:
 
This REXX version has several speed improvements.
<langsyntaxhighlight lang="rexx">/*REXX program finds & displays the Nth Ulam number (or any number of specified values).*/
parse arg $ /*obtain optional argument from the CL.*/
if $='' | $="," then $= 10 100 1000 10000 /*Not specified? Then use the defaults.*/
Line 1,117 ⟶ 1,343:
z= z + 1 /*bump next possible term. */
end /*until*/
return @.#</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input of: &nbsp; &nbsp; <tt> 10 &nbsp; 100 &nbsp; 1000 &nbsp; 10000 </tt>}}
<pre>
Line 1,131 ⟶ 1,357:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
 
Line 1,168 ⟶ 1,394:
ok
next
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,179 ⟶ 1,405:
=={{header|Rust}}==
{{trans|Phix}}
<langsyntaxhighlight lang="rust">fn ulam(n: usize) -> usize {
let mut ulams = vec![1, 2];
let mut sieve = vec![1, 1];
Line 1,208 ⟶ 1,434:
}
println!("Elapsed time: {:.2?}", start.elapsed());
}</langsyntaxhighlight>
 
{{out}}
Line 1,223 ⟶ 1,449:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">func ulam(n) {
 
static u = Set(1,2)
Line 1,253 ⟶ 1,479:
for k in (1..3) {
say "The 10^#{k}-th Ulam number is: #{ulam(10**k)}"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,261 ⟶ 1,487:
</pre>
 
=={{header|V (Vlang)}}==
===Version 1===
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">import time
fn ulam(n int) int {
mut ulams := [1, 2]
Line 1,298 ⟶ 1,524:
}
println("\nTook ${time.since(start)}")
}</langsyntaxhighlight>
 
{{out}}
Line 1,308 ⟶ 1,534:
 
Took 9.611s
</pre>
 
===Version 2===
{{trans|Go}}
The following version, which builds up a sieve as it goes along, is (astonishingly) about 40 times faster!
<syntaxhighlight lang="go">import time
fn ulam(n int) int {
mut ulams := [1, 2]
mut sieve := [1, 1]
mut u := 2
for ulams.len < n {
s := u + ulams[ulams.len-2]
t := s - sieve.len
for i := 0; i < t; i++ {
sieve << 0
}
for i := 1; i <= ulams.len-1; i++ {
v := u + ulams[i-1] - 1
sieve[v]++
}
mut index := -1
for i, e in sieve[u..] {
if e == 1 {
index = u + i
break
}
}
u = index + 1
ulams << u
}
return ulams[n-1]
}
fn commatize(n int) string {
mut s := '$n'
if n < 0 {
s = s[1..]
}
le := s.len
for i := le - 3; i >= 1; i -= 3 {
s = '${s[0..i]},${s[i..]}'
}
if n >= 0 {
return s
}
return "-$s"
}
fn main() {
start := time.now()
for n := 1; n <= 10000; n *= 10 {
mut s := "th"
if n == 1 {
s = "st"
}
println("The ${commatize(n)}$s Ulam number is ${commatize(ulam(n))}")
}
println("\nTook ${time.since(start)}")
}</syntaxhighlight>
 
{{out}}
<pre>
The 1st Ulam number is 1
The 10th Ulam number is 18
The 100th Ulam number is 690
The 1,000th Ulam number is 12,294
The 10,000th Ulam number is 132,788
 
Took 415.000ms
</pre>
 
===Version 3===
{{trans|Go}}
This version is even quicker than Version 2 and reduces the time needed to calculate the 10,000th and 100,000th Ulam numbers to about 40 milliseconds and 3.25 seconds respectively.
 
As mentioned in the Wren version 3 example, you need to know how much memory to allocate in advance.
<syntaxhighlight lang="v (vlang)">import time
fn ulam(n int) int {
if n <= 2 {
return n
}
max := 1_352_000
mut list := []int{len:max+1}
list[0], list[1] = 1, 2
mut sums := []byte{len:2*max+1}
sums[3] = 1
mut size := 2
mut query := 0
for {
query = list[size-1] + 1
for {
if sums[query] == 1 {
for i in 0..size {
sum := query + list[i]
t := sums[sum] + 1
if t <= 2 {
sums[sum] = t
}
}
list[size] = query
size++
break
}
query++
}
if size >= n {
break
}
}
return query
}
fn commatize(n int) string {
mut s := '$n'
if n < 0 {
s = s[1..]
}
le := s.len
for i := le - 3; i >= 1; i -= 3 {
s = '${s[0..i]},${s[i..]}'
}
if n >= 0 {
return s
}
return "-$s"
}
fn main() {
start := time.now()
for n := 1; n <= 100000; n *= 10 {
mut s := "th"
if n == 1 {
s = "st"
}
println("The ${commatize(n)}$s Ulam number is ${commatize(ulam(n))}")
}
println("\nTook ${time.since(start)}")
}</syntaxhighlight>
 
{{out}}
<pre>
The 1st Ulam number is 1
The 10th Ulam number is 18
The 100th Ulam number is 690
The 1,000th Ulam number is 12,294
The 10,000th Ulam number is 132,788
The 100,000th Ulam number is 1,351,223
 
Took 42.912s
</pre>
 
Line 1,313 ⟶ 1,688:
===Version 1===
{{libheader|Wren-set}}
<langsyntaxhighlight ecmascriptlang="wren">import "./set" for Set
 
var ulam = Fn.new() { |n|
Line 1,342 ⟶ 1,717:
System.print("The %(n)th Ulam number is %(ulam.call(n))")
if (n == 10000) break
}</langsyntaxhighlight>
 
{{out}}
Line 1,357 ⟶ 1,732:
{{libheader|Wren-fmt}}
The above version is reasonably efficient and runs in about 21.6 seconds on my machine (Intel Core i7-8565U). The following version, which builds up a sieve as it goes along, is more than 3 times faster.
<langsyntaxhighlight ecmascriptlang="wren">import "./seq" for Lst
import "./fmt" for Fmt
 
var ulam = Fn.new { |n|
Line 1,382 ⟶ 1,757:
Fmt.print("The $,r Ulam number is $,d", n, ulam.call(n))
}
System.print("\nTook %(System.clock - start) seconds.")</langsyntaxhighlight>
 
{{out}}
Line 1,400 ⟶ 1,775:
 
The only downside with this version is that you need to know how much memory to allocate in advance.
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
 
var ulam = Fn.new { |n|
Line 1,439 ⟶ 1,814:
if (n > 100000) break
}
System.print("\nTook %(System.clock - start) seconds.")</langsyntaxhighlight>
 
{{out}}
Line 1,457 ⟶ 1,832:
Ulam number in 24.7 seconds on a Pi4.
 
<langsyntaxhighlight XPL0lang="xpl0">func Ulam(N); \Return Nth Ulam number
int N;
def Max = 1_352_000; \enough for 100_000th Ulam number
Line 1,492 ⟶ 1,867:
N:= N*10;
until N > 100_000;
]</langsyntaxhighlight>
 
{{out}}
9,482

edits