Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,3 @@
---
from: http://rosettacode.org/wiki/Fractran
note: Prime Numbers

46
Task/Fractran/00-TASK.txt Normal file
View file

@ -0,0 +1,46 @@
'''[[wp:FRACTRAN|FRACTRAN]]''' is a Turing-complete esoteric programming language invented by the mathematician [[wp:John Horton Conway|John Horton Conway]].
A FRACTRAN program is an ordered list of positive fractions <math>P = (f_1, f_2, \ldots, f_m)</math>, together with an initial positive integer input <math>n</math>.
The program is run by updating the integer <math>n</math> as follows:
* for the first fraction, <math>f_i</math>, in the list for which <math>nf_i</math> is an integer, replace <math>n</math> with <math>nf_i</math> ;
* repeat this rule until no fraction in the list produces an integer when multiplied by <math>n</math>, then halt.
<br>
Conway gave a program for primes in FRACTRAN:
: <math>17/91</math>, <math>78/85</math>, <math>19/51</math>, <math>23/38</math>, <math>29/33</math>, <math>77/29</math>, <math>95/23</math>, <math>77/19</math>, <math>1/17</math>, <math>11/13</math>, <math>13/11</math>, <math>15/14</math>, <math>15/2</math>, <math>55/1</math>
Starting with <math>n=2</math>, this FRACTRAN program will change <math>n</math> to <math>15=2\times (15/2)</math>, then <math>825=15\times (55/1)</math>, generating the following sequence of integers:
: <math>2</math>, <math>15</math>, <math>825</math>, <math>725</math>, <math>1925</math>, <math>2275</math>, <math>425</math>, <math>390</math>, <math>330</math>, <math>290</math>, <math>770</math>, <math>\ldots</math>
After 2, this sequence contains the following powers of 2:
:<math>2^2=4</math>, <math>2^3=8</math>, <math>2^5=32</math>, <math>2^7=128</math>, <math>2^{11}=2048</math>, <math>2^{13}=8192</math>, <math>2^{17}=131072</math>, <math>2^{19}=524288</math>, <math>\ldots</math>
which are the prime powers of 2.
;Task:
Write a program that reads a list of fractions in a ''natural'' format from the keyboard or from a string,
to parse it into a sequence of fractions (''i.e.'' two integers),
and runs the FRACTRAN starting from a provided integer, writing the result at each step.
It is also required that the number of steps is limited (by a parameter easy to find).
;Extra credit:
Use this program to derive the first '''20''' or so prime numbers.
;See also:
For more on how to program FRACTRAN as a universal programming language, see:
* J. H. Conway (1987). Fractran: A Simple Universal Programming Language for Arithmetic. In: Open Problems in Communication and Computation, pages 426. Springer.
* J. H. Conway (2010). "FRACTRAN: A simple universal programming language for arithmetic". In Jeffrey C. Lagarias. The Ultimate Challenge: the 3x+1 problem. American Mathematical Society. pp. 249264. ISBN 978-0-8218-4940-8. Zbl 1216.68068.
* [http://scienceblogs.com/goodmath/2006/10/27/prime-number-pathology-fractra/Prime Number Pathology: Fractran] by Mark C. Chu-Carroll; October 27, 2006.
<br><br>

View file

@ -0,0 +1,12 @@
F fractran(prog, =val, limit)
V fracts = prog.split( ).map(p -> p.split(/).map(i -> Int(i)))
[Float] r
L(n) 0 .< limit
r [+]= val
L(p) fracts
I val % p[1] == 0
val = p[0] * val / p[1]
L.break
R r
print(fractran(17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1, 2, 15))

View file

@ -0,0 +1,48 @@
* FRACTRAN 17/02/2019
FRACTRAN CSECT
USING FRACTRAN,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 R6,1 i=1
DO WHILE=(C,R6,LE,TERMS) do i=1 to terms
LA R7,1 j=1
DO WHILE=(C,R7,LE,=A(NF)) do j=1 to nfracs
LR R1,R7 j
SLA R1,3 ~
L R2,FRACS-4(R1) d(j)
L R4,NN nn
SRDA R4,32 ~
DR R4,R2 nn/d(j)
IF LTR,R4,Z,R4 THEN if mod(nn,d(j))=0 then
XDECO R6,XDEC edit i
MVC PG(3),XDEC+9 output i
L R1,NN nn
XDECO R1,PG+5 edit & output nn
XPRNT PG,L'PG print buffer
LR R1,R7 j
SLA R1,3 ~
L R3,FRACS-8(R1) n(j)
MR R4,R3 *n(j)
ST R5,NN nn=nn/d(j)*n(j)
B LEAVEJ leave j
ENDIF , end if
LA R7,1(R7) j++
ENDDO , end do j
LEAVEJ LA R6,1(R6) i++
ENDDO , end do i
L R13,4(0,R13) restore previous savearea pointer
RETURN (14,12),RC=0 restore registers from calling sav
NF EQU (TERMS-FRACS)/8 number of fracs
NN DC F'2' nn
FRACS DC F'17',F'91',F'78',F'85',F'19',F'51',F'23',F'38',F'29',F'33'
DC F'77',F'29',F'95',F'23',F'77',F'19',F'1',F'17',F'11',F'13'
DC F'13',F'11',F'15',F'14',F'15',F'2',F'55',F'1'
TERMS DC F'100' terms
PG DC CL80'*** :' buffer
XDEC DS CL12 temp
REGEQU
END FRACTRAN

View file

@ -0,0 +1,74 @@
# as the numbers required for finding the first 20 primes are quite large, #
# we use Algol 68G's LONG LONG INT with a precision of 100 digits #
PR precision 100 PR
# mode to hold fractions #
MODE FRACTION = STRUCT( INT numerator, INT denominator );
# define / between two INTs to yield a FRACTION #
OP / = ( INT a, b )FRACTION: ( a, b );
# mode to define a FRACTRAN progam #
MODE FRACTRAN = STRUCT( FLEX[0]FRACTION data
, LONG LONG INT n
, BOOL halted
);
# prepares a FRACTRAN program for use - sets the initial value of n and halted to FALSE #
PRIO STARTAT = 1;
OP STARTAT = ( REF FRACTRAN f, INT start )REF FRACTRAN:
BEGIN
halted OF f := FALSE;
n OF f := start;
f
END;
# sets n OF f to the next number in the sequence or sets halted OF f to TRUE if the sequence has ended #
OP NEXT = ( REF FRACTRAN f )LONG LONG INT:
IF halted OF f
THEN n OF f := 0
ELSE
BOOL found := FALSE;
LONG LONG INT result := 0;
FOR pos FROM LWB data OF f TO UPB data OF f WHILE NOT found DO
LONG LONG INT value = n OF f * numerator OF ( ( data OF f )[ pos ] );
INT denominator = denominator OF ( ( data OF f )[ pos ] );
IF found := ( value MOD denominator = 0 ) THEN result := value OVER denominator FI
OD;
IF NOT found THEN halted OF f := TRUE FI;
n OF f := result
FI ;
# generate and print the sequence of numbers from a FRACTRAN pogram #
PROC print fractran sequence = ( REF FRACTRAN f, INT start, INT limit )VOID:
BEGIN
VOID( f STARTAT start );
print( ( "0: ", whole( start, 0 ) ) );
FOR i TO limit
WHILE VOID( NEXT f );
NOT halted OF f
DO
print( ( " " + whole( i, 0 ) + ": " + whole( n OF f, 0 ) ) )
OD;
print( ( newline ) )
END ;
# print the first 16 elements from the primes FRACTRAN program #
FRACTRAN pf := ( ( 17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1 ), 0, FALSE );
print fractran sequence( pf, 2, 15 );
# find some primes using the pf FRACTRAN progam - n is prime for the members in the sequence that are 2^n #
INT primes found := 0;
VOID( pf STARTAT 2 );
INT pos := 0;
print( ( "seq position prime sequence value", newline ) );
WHILE primes found < 20 AND NOT halted OF pf DO
LONG LONG INT value := NEXT pf;
INT power of 2 := 0;
pos +:= 1;
WHILE value MOD 2 = 0 AND value > 0 DO power of 2 PLUSAB 1; value OVERAB 2 OD;
IF value = 1 THEN
# found a prime #
primes found +:= 1;
print( ( whole( pos, -12 ) + " " + whole( power of 2, -6 ) + " (" + whole( n OF pf, 0 ) + ")", newline ) )
FI
OD

View file

@ -0,0 +1,11 @@
fractran{
parts ' '
frac ¨'/'
simp ÷/
mul simp×
prog simpfrac¨parts
step {(1=2¨next)/next mul¨( 1)}
(start nstep)
rslt (,progstep)nstep¨start
((/)(\0))rslt
}

View file

@ -0,0 +1,2 @@
'17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1' fractran 2 20
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116 308 364 68 4 30

View file

@ -0,0 +1,43 @@
with Ada.Text_IO;
procedure Fractan is
type Fraction is record Nom: Natural; Denom: Positive; end record;
type Frac_Arr is array(Positive range <>) of Fraction;
function "/" (N: Natural; D: Positive) return Fraction is
Frac: Fraction := (Nom => N, Denom => D);
begin
return Frac;
end "/";
procedure F(List: Frac_Arr; Start: Positive; Max_Steps: Natural) is
N: Positive := Start;
J: Positive;
begin
Ada.Text_IO.Put(" 0:" & Integer'Image(N) & " ");
for I in 1 .. Max_Steps loop
J := List'First;
loop
if N mod List(J).Denom = 0 then
N := (N/List(J).Denom) * List(J).Nom;
exit; -- found fraction
elsif J >= List'Last then
return; -- did try out all fractions
else
J := J + 1; -- try the next fraction
end if;
end loop;
Ada.Text_IO.Put(Integer'Image(I) & ":" & Integer'Image(N) & " ");
end loop;
end F;
begin
-- F((2/3, 7/2, 1/5, 1/7, 1/9, 1/4, 1/8), 2, 100);
-- output would be "0: 2 1: 7 2: 1" and then terminate
F((17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23,
77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1),
2, 15);
-- output is "0: 2 1: 15 2: 825 3: 725 ... 14: 132 15: 116"
end Fractan;

View file

@ -0,0 +1,24 @@
n := 2, steplimit := 15, numerator := [], denominator := []
s := "17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
Loop, Parse, s, % A_Space
if (!RegExMatch(A_LoopField, "^(\d+)/(\d+)$", m))
MsgBox, % "Invalid input string (" A_LoopField ")."
else
numerator[A_Index] := m1, denominator[A_Index] := m2
SetFormat, FloatFast, 0.0
Gui, Add, ListView, R10 W100 -Hdr, |
SysGet, VSBW, 2
LV_ModifyCol(1, 95 - VSBW), LV_Add( , 0 ": " n)
Gui, Show
Loop, % steplimit {
i := A_Index
Loop, % numerator.MaxIndex()
if (!Mod(nn := n * numerator[A_Index] / denominator[A_Index], 1)) {
LV_Modify(LV_Add( , i ": " (n := nn)), "Vis")
continue, 2
}
break
}

View file

@ -0,0 +1,34 @@
# Fractran interpreter
# Helpers
_while_ {𝔽𝔾𝔽_𝕣_𝔾𝔽𝔾𝕩}
ToInt 10×+˜´·-'0'
ToFrac {
i /'/'=𝕩
ToInt¨i(1+)𝕩
}
Split ((¬-˜×·+`»>))
Fractran {
𝕊 nnumden:
ind /0=den|num×n
(n×indnum)÷indden num den
}
RunFractran {
steps 𝕊 inpprg:
numden <˘>ToFrac¨' 'Split prg
step 1
list inp
{
step + 1
out Fractran 𝕩
list out
out
} _while_ {𝕊 nnumden: (step<steps) ´0=den|num} inpnumden
list
}
seq 200 RunFractran 2"17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
•Out "Generated numbers: "•Repr seq
•Out "Primes: "•Repr 12(=)(2())/ seq

View file

@ -0,0 +1,3 @@
)ex fractran.bqn
Generated numbers: 21582572519252275425390330290770910170156132116308364684302251237510875288752537567375796251487513650255023401980174046204060107801274023802184408152923802309505752375962511375212519501650145038504550850780660580154018203403122642326167281368604503375185625163125433125380625101062588812523581252786875520625477750892508190015300140401188010440277202436064680568401509201783603332030576571221281288532032201330080503325020125831253368753981257437568250127501170099008700231002030053900637001190010920204018721584139236963248862410192190411212090067505062527843752446875649687557093751515937513321875353718753108437582534375975406251822187516721250312375028665005355004914009180084240712806264016632014616038808034104090552079576021128802497040466480428064799682979218032744804508018620011270046550028175011637507043752909375117906251393437526031252388750446250409500765007020059400522001386001218003234002842007546008918001666001528802856026208489618241104
Primes: 23

View file

@ -0,0 +1,56 @@
@echo off
setlocal enabledelayedexpansion
::Set the inputs
set "code=17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
set "n=2"
::Basic validation of code
for %%. in (!code!) do (
echo.%%.|findstr /r /c:"^[0-9][0-9]*/[1-9][0-9]*$">nul||goto error_code
)
::Validate the input
set /a "tst=1*!n!" 2>nul
if !tst! lss 0 goto error_input
if !tst! equ 0 (if not "!n!"=="0" (goto error_input))
::Set the limit outputs
set limit=20
::Execute the code
echo.Input:
echo. !n!
echo.Output:
for /l %%? in (1,1,!limit!) do (
set shouldwehalt=1
for %%A in (!code!) do (
for /f "tokens=1,2 delims=/" %%B in ("%%A") do (
set /a "tst=!n! %% %%C"
if !tst! equ 0 (
if !shouldwehalt! equ 1 (
set shouldwehalt=0
set /a "n=n*%%B/%%C"
echo. !n!
)
)
)
)
if !shouldwehalt! equ 1 goto halt
)
:halt
echo.
pause
exit /b 0
:error_code
echo.Syntax error in code.
echo.
pause
exit /b 1
:error_input
echo.Invalid input.
echo.
pause
exit /b 1

View file

@ -0,0 +1,5 @@
p0" :snoitcarF">:#,_>&00g5p~$&00g:v
v"Starting value: "_^#-*84~p6p00+1<
>:#,_&0" :snoitaretI">:#,_#@>>$&\:v
:$_\:10g5g*:10g6g%v1:\1$\$<|!:-1\.<
g0^<!:-1\p01+1g01$_10g6g/\^>\010p00

View file

@ -0,0 +1,36 @@
(fractran=
np n fs A Z fi P p N L M
. !arg:(?N,?n,?fs) {Number of iterations, start n, fractions}
& :?P:?L {Initialise accumulators.}
& whl
' ( -1+!N:>0:?N {Stop when counted down to zero.}
& !n !L:?L {Prepend all numbers to result list.}
& (2\L!n:#?p&!P !p:?P|) {If log2(n) is rational, append it to list of primes.}
& !fs:? (/?fi&!n*!fi:~/:?n) ? {This line does the following (See task description):
"for the first fraction, fi, in the list for which
nfi is an integer, replace n by nfi ;"}
)
& :?M
& whl'(!L:%?n ?L&!n !M:?M) {Invert list of numbers. (append to long list is
very expensive. Better to prepend and finally invert.}
& (!M,!P) {Return the two lists}
);
( clk$:?t0
& fractran$(430000, 2, 17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1)
: (?numbers,?primes)
& lst$(numbers,"numbers.lst",NEW)
& put$("
FRACTRAN found these primes:"
!primes
"\nThe list of numbers is saved in numbers.txt
The biggest number in the list is"
( 0:?max
& !numbers:? (>%@!max:?max&~) ?
| !max
)
str$("\ntime: " flt$(clk$+-1*!t0,4) " sec\n")
, "FRACTRAN.OUT",NEW)
);

View file

@ -0,0 +1,65 @@
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <cmath>
using namespace std;
class fractran
{
public:
void run( std::string p, int s, int l )
{
start = s; limit = l;
istringstream iss( p ); vector<string> tmp;
copy( istream_iterator<string>( iss ), istream_iterator<string>(), back_inserter<vector<string> >( tmp ) );
string item; vector< pair<float, float> > v;
pair<float, float> a;
for( vector<string>::iterator i = tmp.begin(); i != tmp.end(); i++ )
{
string::size_type pos = ( *i ).find( '/', 0 );
if( pos != std::string::npos )
{
a = make_pair( atof( ( ( *i ).substr( 0, pos ) ).c_str() ), atof( ( ( *i ).substr( pos + 1 ) ).c_str() ) );
v.push_back( a );
}
}
exec( &v );
}
private:
void exec( vector< pair<float, float> >* v )
{
int cnt = 0;
while( cnt < limit )
{
cout << cnt << " : " << start << "\n";
cnt++;
vector< pair<float, float> >::iterator it = v->begin();
bool found = false; float r;
while( it != v->end() )
{
r = start * ( ( *it ).first / ( *it ).second );
if( r == floor( r ) )
{
found = true;
break;
}
++it;
}
if( found ) start = ( int )r;
else break;
}
}
int start, limit;
};
int main( int argc, char* argv[] )
{
fractran f; f.run( "17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1", 2, 15 );
cin.get();
return 0;
}

View file

@ -0,0 +1,65 @@
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
typedef struct frac_s *frac;
struct frac_s {
int n, d;
frac next;
};
frac parse(char *s)
{
int offset = 0;
struct frac_s h = {0}, *p = &h;
while (2 == sscanf(s, "%d/%d%n", &h.n, &h.d, &offset)) {
s += offset;
p = p->next = malloc(sizeof *p);
*p = h;
p->next = 0;
}
return h.next;
}
int run(int v, char *s)
{
frac n, p = parse(s);
mpz_t val;
mpz_init_set_ui(val, v);
loop: n = p;
if (mpz_popcount(val) == 1)
gmp_printf("\n[2^%d = %Zd]", mpz_scan1(val, 0), val);
else
gmp_printf(" %Zd", val);
for (n = p; n; n = n->next) {
// assuming the fractions are not reducible
if (!mpz_divisible_ui_p(val, n->d)) continue;
mpz_divexact_ui(val, val, n->d);
mpz_mul_ui(val, val, n->n);
goto loop;
}
gmp_printf("\nhalt: %Zd has no divisors\n", val);
mpz_clear(val);
while (p) {
n = p->next;
free(p);
p = n;
}
return 0;
}
int main(void)
{
run(2, "17/91 78/85 19/51 23/38 29/33 77/29 95/23 "
"77/19 1/17 11/13 13/11 15/14 15/2 55/1");
return 0;
}

View file

@ -0,0 +1,124 @@
ratio = cluster is new, parse, unparse, get_num, get_denom, mul
rep = struct[num, denom: int]
new = proc (num, denom: int) returns (cvt)
return(simplify(rep${num: num, denom: denom}))
end new
parse = proc (rat: string) returns (ratio) signals (bad_format)
rat := trim(rat)
sep: int := string$indexc('/', rat)
if sep = 0 then signal bad_format end
num: string := string$substr(rat, 1, sep-1)
denom: string := string$rest(rat, sep+1)
return(new(int$parse(num), int$parse(denom))) resignal bad_format
end parse
trim = proc (s: string) returns (string)
start: int := 1
while start <= string$size(s) cand s[start] = ' ' do start := start + 1 end
end_: int := string$size(s)
while end_ >= 1 cand s[end_] = ' ' do end_ := end_ - 1 end
return(string$substr(s, start, end_-start+1))
end trim
unparse = proc (rat: cvt) returns (string)
return(int$unparse(rat.num) || "/" || int$unparse(rat.denom))
end unparse
get_num = proc (rat: cvt) returns (int)
return(rat.num)
end get_num
get_denom = proc (rat: cvt) returns (int)
return(rat.denom)
end get_denom
mul = proc (a, b: cvt) returns (ratio)
return(new(a.num * b.num, a.denom * b.denom))
end mul
simplify = proc (rat: rep) returns (rep)
num: int := int$abs(rat.num)
denom: int := int$abs(rat.denom)
sign: int
if (rat.num < 0) = (rat.denom < 0)
then sign := 1
else sign := -1
end
factor: int := gcd(num, denom)
return(rep${num: sign*num/factor, denom: denom/factor})
end simplify
gcd = proc (a, b: int) returns (int)
while b ~= 0 do
a, b := b, a // b
end
return(a)
end gcd
end ratio
fractran = cluster is parse, run
rep = sequence[ratio]
parse = proc (program: string) returns (cvt)
parsed: array[ratio] := array[ratio]$[]
for rat: ratio in ratioes(program) do
array[ratio]$addh(parsed, rat)
end
return(rep$a2s(parsed))
end parse
ratioes = iter (program: string) yields (ratio)
while true do
sep: int := string$indexc(',', program)
if sep = 0 then
yield(ratio$parse(program))
break
else
yield(ratio$parse(string$substr(program, 1, sep-1)))
program := string$rest(program, sep+1)
end
end
end ratioes
run = iter (program: cvt, n, maxiter: int) yields (int)
nrat: ratio := ratio$new(n, 1)
while maxiter > 0 do
yield(nrat.num)
begin
for rat: ratio in rep$elements(program) do
mul: ratio := rat * nrat
if mul.denom = 1 then
exit found(mul)
end
end
break
end except when found(new: ratio):
nrat := new
end
maxiter := maxiter - 1
end
end run
end fractran
start_up = proc ()
po: stream := stream$primary_output()
program: string := "17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, "
|| "77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1"
parsed: fractran := fractran$parse(program)
index: int := 0
for result: int in fractran$run(parsed, 2, 20) do
stream$putright(po, int$unparse(index), 3)
stream$putc(po, ':')
stream$putright(po, int$unparse(result), 10)
stream$putl(po, "")
index := index + 1
end
end start_up

View file

@ -0,0 +1,21 @@
(defun fractran (n frac-list)
(lambda ()
(prog1
n
(when n
(let ((f (find-if (lambda (frac)
(integerp (* n frac)))
frac-list)))
(when f (setf n (* f n))))))))
;; test
(defvar *primes-ft* '(17/91 78/85 19/51 23/38 29/33 77/29 95/23
77/19 1/17 11/13 13/11 15/14 15/2 55/1))
(loop with fractran-instance = (fractran 2 *primes-ft*)
repeat 20
for next = (funcall fractran-instance)
until (null next)
do (print next))

View file

@ -0,0 +1,18 @@
import std.stdio, std.algorithm, std.conv, std.array;
void fractran(in string prog, int val, in uint limit) {
const fracts = prog.split.map!(p => p.split("/").to!(int[])).array;
foreach (immutable n; 0 .. limit) {
writeln(n, ": ", val);
const found = fracts.find!(p => val % p[1] == 0);
if (found.empty)
break;
val = found.front[0] * val / found.front[1];
}
}
void main() {
fractran("17/91 78/85 19/51 23/38 29/33 77/29 95/23
77/19 1/17 11/13 13/11 15/14 15/2 55/1", 2, 15);
}

View file

@ -0,0 +1,26 @@
import std.stdio, std.algorithm, std.conv, std.array, std.range;
struct Fractran {
int front;
bool empty = false;
const int[][] fracts;
this(in string prog, in int val) {
this.front = val;
fracts = prog.split.map!(p => p.split("/").to!(int[])).array;
}
void popFront() {
const found = fracts.find!(p => front % p[1] == 0);
if (found.empty)
empty = true;
else
front = found.front[0] * front / found.front[1];
}
}
void main() {
Fractran("17/91 78/85 19/51 23/38 29/33 77/29 95/23
77/19 1/17 11/13 13/11 15/14 15/2 55/1", 2)
.take(15).writeln;
}

View file

@ -0,0 +1,92 @@
program FractranTest;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.RegularExpressions;
type
TFractan = class
private
limit: Integer;
num, den: TArray<Integer>;
procedure compile(prog: string);
procedure exec(val: Integer);
function step(val: Integer): integer;
procedure dump();
public
constructor Create(prog: string; val: Integer);
end;
{ TFractan }
constructor TFractan.Create(prog: string; val: Integer);
begin
limit := 15;
compile(prog);
dump();
exec(2);
end;
procedure TFractan.compile(prog: string);
var
reg: TRegEx;
m: TMatch;
begin
reg := TRegEx.Create('\s*(\d*)\s*\/\s*(\d*)\s*');
m := reg.Match(prog);
while m.Success do
begin
SetLength(num, Length(num) + 1);
num[high(num)] := StrToIntDef(m.Groups[1].Value, 0);
SetLength(den, Length(den) + 1);
den[high(den)] := StrToIntDef(m.Groups[2].Value, 0);
m := m.NextMatch;
end;
end;
procedure TFractan.exec(val: Integer);
var
n: Integer;
begin
n := 0;
while (n < limit) and (val <> -1) do
begin
Writeln(n, ': ', val);
val := step(val);
inc(n);
end;
end;
function TFractan.step(val: Integer): integer;
var
i: integer;
begin
i := 0;
while (i < length(den)) and (val mod den[i] <> 0) do
inc(i);
if i < length(den) then
exit(round(num[i] * val / den[i]));
result := -1;
end;
procedure TFractan.dump();
var
i: Integer;
begin
for i := 0 to high(den) do
Write(num[i], '/', den[i], ' ');
Writeln;
end;
const
DATA =
'17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1';
begin
TFractan.Create(DATA, 2).Free;
Readln;
end.

View file

@ -0,0 +1,66 @@
defmodule Fractran do
use Bitwise
defp binary_to_ratio(b) do
[_, num, den] = Regex.run(~r/(\d+)\/(\d+)/, b)
{String.to_integer(num), String.to_integer(den)}
end
def load(program) do
String.split(program) |> Enum.map(&binary_to_ratio(&1))
end
defp step(_, []), do: :halt
defp step(n, [f|fs]) do
{p, q} = mulrat(f, {n, 1})
case q do
1 -> p
_ -> step(n, fs)
end
end
def exec(k, n, program) do
exec(k-1, n, fn (_) -> true end, program, [n]) |> Enum.reverse
end
def exec(k, n, pred, program) do
exec(k-1, n, pred, program, [n]) |> Enum.reverse
end
defp exec(0, _, _, _, steps), do: steps
defp exec(k, n, pred, program, steps) do
case step(n, program) do
:halt -> steps
m -> if pred.(m), do: exec(k-1, m, pred, program, [m|steps]),
else: exec(k, m, pred, program, steps)
end
end
def is_pow2(n), do: band(n, n-1) == 0
def lowbit(n), do: lowbit(n, 0)
defp lowbit(n, k) do
case band(n, 1) do
0 -> lowbit(bsr(n, 1), k + 1)
1 -> k
end
end
# rational multiplication
defp mulrat({a, b}, {c, d}) do
{p, q} = {a*c, b*d}
g = gcd(p, q)
{div(p, g), div(q, g)}
end
defp gcd(a, 0), do: a
defp gcd(a, b), do: gcd(b, rem(a, b))
end
primegen = Fractran.load("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1")
IO.puts "The first few states of the Fractran prime automaton are:\n#{inspect Fractran.exec(20, 2, primegen)}\n"
prime = Fractran.exec(26, 2, &Fractran.is_pow2/1, primegen)
|> Enum.map(&Fractran.lowbit/1)
|> tl
IO.puts "The first few primes are:\n#{inspect prime}"

View file

@ -0,0 +1,59 @@
#! /usr/bin/escript
-mode(native).
-import(lists, [map/2, reverse/1]).
binary_to_ratio(B) ->
{match, [_, Num, Den]} = re:run(B, "([0-9]+)/([0-9]+)"),
{binary_to_integer(binary:part(B, Num)),
binary_to_integer(binary:part(B, Den))}.
load(Program) ->
map(fun binary_to_ratio/1, re:split(Program, "[ ]+")).
step(_, []) -> halt;
step(N, [F|Fs]) ->
{P, Q} = mulrat(F, {N, 1}),
case Q of
1 -> P;
_ -> step(N, Fs)
end.
exec(K, N, Program) -> reverse(exec(K - 1, N, fun (_) -> true end, Program, [N])).
exec(K, N, Pred, Program) -> reverse(exec(K - 1, N, Pred, Program, [N])).
exec(0, _, _, _, Steps) -> Steps;
exec(K, N, Pred, Program, Steps) ->
case step(N, Program) of
halt -> Steps;
M -> case Pred(M) of
true -> exec(K - 1, M, Pred, Program, [M|Steps]);
false -> exec(K, M, Pred, Program, Steps)
end
end.
is_pow2(N) -> N band (N - 1) =:= 0.
lowbit(N) -> lowbit(N, 0).
lowbit(N, K) ->
case N band 1 of
0 -> lowbit(N bsr 1, K + 1);
1 -> K
end.
main(_) ->
PrimeGen = load("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"),
io:format("The first few states of the Fractran prime automaton are: ~p~n~n", [exec(20, 2, PrimeGen)]),
io:format("The first few primes are: ~p~n", [tl(map(fun lowbit/1, exec(26, 2, fun is_pow2/1, PrimeGen)))]).
% rational multiplication
mulrat({A, B}, {C, D}) ->
{P, Q} = {A*C, B*D},
G = gcd(P, Q),
{P div G, Q div G}.
gcd(A, 0) -> A;
gcd(A, B) -> gcd(B, A rem B).

View file

@ -0,0 +1,35 @@
USING: io kernel math math.functions math.parser multiline
prettyprint sequences splitting ;
IN: rosetta-code.fractran
STRING: fractran-string
17/91 78/85 19/51 23/38 29/33 77/29 95/23
77/19 1/17 11/13 13/11 15/14 15/2 55/1
;
: fractran-parse ( str -- seq )
" \n" split [ string>number ] map ;
: fractran-step ( seq n -- seq n'/f )
2dup [ * integer? ] curry find nip dup [ * ] [ nip ] if ;
: fractran-run-full ( seq n -- )
[ dup ] [ dup . fractran-step ] while 2drop ;
: fractran-run-limited ( seq n steps -- )
[ dup pprint bl fractran-step ] times 2drop nl ;
: fractran-primes ( #primes seq n -- )
[ pick zero? ] [
dup 2 logn dup [ floor 1e-9 ~ ] [ 1. = not ] bi and [
dup 2 logn >integer pprint bl [ 1 - ] 2dip
] when fractran-step
] until 3drop nl ;
: main ( -- )
fractran-string fractran-parse 2
[ "First 20 numbers: " print 20 fractran-run-limited nl ]
[ "First 20 primes: " print [ 20 ] 2dip fractran-primes ]
2bi ;
MAIN: main

View file

@ -0,0 +1,26 @@
Func FT( arr, n, m ) =
;{executes John H. Conway's FRACTRAN language for a program stored in [arr], an}
;{input integer stored in n, for a maximum of m steps}
;{To allow the program to run indefinitely, give it negative or noninteger m}
exec:=1; {boolean to track whether the program needs to halt}
len:=Cols[arr]; {length of the input program}
while exec=1 and m<>0 do
m:-;
!!n; {output the memory}
i:=1; {index variable}
exec:=0;
while i<=len and exec=0 do
nf:=n*arr[i];
if Denom(nf) = 1 then
n:=nf; {did we find an instruction to execute?}
exec:=1
fi;
i:+;
od;
od;
.;
;{Here is the program to run}
[arr]:=[( 17/91,78/85,19/51,23/38,29/33,77/29,95/23,77/19,1/17,11/13,13/11,15/14,15/2,55/1 )];
FT( [arr], 2, 20 );

View file

@ -0,0 +1,2 @@
C:\Nicky\RosettaCode\FRACTRAN\FRACTRAN.for(6) : Warning: This name has not been given an explicit type. [M]
INTEGER P(M),Q(M)!The terms of the fractions.

View file

@ -0,0 +1,49 @@
INTEGER FUNCTION FRACTRAN(N,P,Q,M) !Notion devised by J. H. Conway.
Careful: the rule is N*P/Q being integer. N*6/3 is integer always because this is N*2/1, but 3 may not divide N.
Could check GCD(P,Q), dividing out the common denominator so MOD(N,Q) works.
INTEGER*8 N !The work variable. Modified!
INTEGER M !The number of fractions supplied.
INTEGER P(M),Q(M)!The terms of the fractions.
INTEGER I !A stepper.
DO I = 1,M !Search the supplied fractions, P(i)/Q(i).
IF (MOD(N,Q(I)).EQ.0) THEN !Does the denominator divide N?
N = N/Q(I)*P(I) !Yes, compute N*P/Q but trying to dodge overflow.
FRACTRAN = I !Report the hit.
RETURN !Done!
END IF !Otherwise,
END DO !Try the next fraction in the order supplied.
FRACTRAN = 0 !No hit.
END FUNCTION FRACTRAN !That's it! Even so, "Turing complete"...
PROGRAM POKE
INTEGER FRACTRAN !Not the default type of function.
INTEGER P(66),Q(66) !Holds the fractions as P(i)/Q(i).
INTEGER*8 N !The working number.
INTEGER I,IT,L,M !Assistants.
WRITE (6,1) !Announce.
1 FORMAT ("Interpreter for J.H. Conway's FRACTRAN language.")
Chew into an example programme.
OPEN (10,FILE = "Fractran.txt",STATUS="OLD",ACTION="READ") !Rather than compiled-in stuff.
READ (10,*) L !I need to know this without having to scan the input.
WRITE (6,2) L !Reveal in case of trouble.
2 FORMAT (I0," fractions, as follow:") !Should the input evoke problems.
READ (10,*) (P(I),Q(I),I = 1,L) !Ask for the specified number of P,Q pairs.
WRITE (6,3) (P(I),Q(I),I = 1,L) !Show what turned up.
3 FORMAT (24(I0,"/",I0:", ")) !As P(i)/Q(i) pairs. The colon means that there will be no trailing comma.
READ (10,*) N,M !The start value, and the step limit.
CLOSE (10) !Finished with input.
WRITE (6,4) N,M !Hopefully, all went well.
4 FORMAT ("Start with N = ",I0,", step limit ",I0)
Commence.
WRITE (6,10) 0,N !Splat a heading.
10 FORMAT (/," Step #F: N",/,I6,4X,": ",I0) !Matched FORMAT 11.
DO I = 1,M !Here we go!
IT = FRACTRAN(N,P,Q,L) !Do it!
WRITE (6,11) I,IT,N !Show it!
11 FORMAT (I6,I4,": ",I0) !N last, as it may be big.
IF (IT.LE.0) EXIT !No hit, so quit.
END DO !The next step.
END !Whee!

View file

@ -0,0 +1,11 @@
DO I = 1,M !Here we go!
IT = FRACTRAN(N,P,Q,L) !Do it!
IF (POPCNT(N).EQ.1) WRITE (6,11) I,IT,N !Show it!
11 FORMAT (I6,I4,": ",I0) !N last, as it may be big.
IF (IT.LE.0) EXIT !No hit, so quit.
IF (N.LE.0) THEN !Otherwise, worry about overflow.
WRITE (6,*) "Integer overflow!" !Justified. The test is not certain.
WRITE (6,11) I,IT,N !Alas, the step failed.
EXIT !Give in.
END IF !So much for overflow.
END DO !The next step.

View file

@ -0,0 +1,187 @@
MODULE CONWAYSIDEA !Notion devised by J. H. Conway.
USE PRIMEBAG !This is a common need.
INTEGER LASTP,ENUFF !Some size allowances.
PARAMETER (LASTP = 66, ENUFF = 66) !Should suffice for the example in mind.
INTEGER NPPOW(1:LASTP) !Represent N as a collection of powers of prime numbers.
TYPE FACTORED !But represent P and Q of freaction = P/Q
INTEGER PNUM(0:LASTP) !As a list of prime number indices with PNUM(0) the count.
INTEGER PPOW(LASTP) !And the powers. for the fingered primes.
END TYPE FACTORED !Rather than as a simple number multiplied out.
TYPE(FACTORED) FP(ENUFF),FQ(ENUFF) !Thus represent a factored fraction, P(i)/Q(i).
INTEGER PLIVE(ENUFF),NL !Helps subroutine SHOWN display NPPOW.
CONTAINS !Now for the details.
SUBROUTINE SHOWFACTORS(N) !First, to show an internal data structure.
TYPE(FACTORED) N !It is supplied as a list of prime factors.
INTEGER I !A stepper.
DO I = 1,N.PNUM(0) !Step along the list.
IF (I.GT.1) WRITE (MSG,"('x',$)") !Append a glyph for "multiply".
WRITE (MSG,"(I0,$)") PRIME(N.PNUM(I)) !The prime fingered in the list.
IF (N.PPOW(I).GT.1) WRITE (MSG,"('^',I0,$)") N.PPOW(I) !With an interesting power?
END DO !On to the next element in the list.
WRITE (MSG,1) N.PNUM(0) !End the line
1 FORMAT (": Factor count ",I0) !With a count of prime factors.
END SUBROUTINE SHOWFACTORS !Hopefully, this will not be needed often.
TYPE(FACTORED) FUNCTION FACTOR(IT) !Into a list of primes and their powers.
INTEGER IT,N !The number and a copy to damage.
INTEGER P,POW !A stepper and a power.
INTEGER F,NF !A factor and a counter.
IF (IT.LE.0) STOP "Factor only positive numbers!" !Or else...
N = IT !A copy I can damage.
NF = 0 !No factors found.
P = 0 !Because no primes have been tried.
PP:DO WHILE (N.GT.1) !Step through the possibilities.
P = P + 1 !Another prime impends.
F = PRIME(P) !Grab a possible factor.
POW = 0 !It has no power yet.
FP:DO WHILE(MOD(N,F).EQ.0) !Well?
POW = POW + 1 !Count a factor..
N = N/F !Reduce the number.
END DO FP !The P'th prime's power's produced.
IF (POW.GT.0) THEN !So, was it a factor?
IF (NF.GE.LASTP) THEN !Yes. Have I room in the list?
WRITE (MSG,1) IT,LASTP !Alas.
1 FORMAT ("Factoring ",I0," but with provision for only ",
1 I0," prime factors!")
FACTOR.PNUM(0) = NF !Place the count so far,
CALL SHOWFACTORS(FACTOR)!So this can be invoked.
STOP "Not enough storage!" !Quite.
END IF !But normally,
NF = NF + 1 !Admit another factor.
FACTOR.PNUM(NF) = P !Identify the prime. NOT the prime itself.
FACTOR.PPOW(NF) = POW !Place its power.
END IF !So much for that factor.
END DO PP !Try another prime, if N > 1 still.
FACTOR.PNUM(0) = NF !Place the count.
END FUNCTION FACTOR !Thus, a list of primes and their powers.
INTEGER FUNCTION GCD(I,J) !Greatest common divisor.
INTEGER I,J !Of these two integers.
INTEGER N,M,R !Workers.
N = MAX(I,J) !Since I don't want to damage I or J,
M = MIN(I,J) !These copies might as well be the right way around.
1 R = MOD(N,M) !Divide N by M to get the remainder R.
IF (R.GT.0) THEN !Remainder zero?
N = M !No. Descend a level.
M = R !M-multiplicity has been removed from N.
IF (R .GT. 1) GO TO 1 !No point dividing by one.
END IF !If R = 0, M divides N.
GCD = M !There we are.
END FUNCTION GCD !Euclid lives on!
INTEGER FUNCTION FRACTRAN(L) !Applies Conway's idea to a list of fractions.
Could abandon all parameters since global variables have the details...
INTEGER L !The last fraction to consider.
INTEGER I,NF !Assistants.
DO I = 1,L !Step through the fractions in the order they were given.
NF = FQ(I).PNUM(0) !How many factors are listed in FQ(I)?
IF (ALL(NPPOW(FQ(I).PNUM(1:NF)) !Can N (as NPPOW) be divided by Q (as FQ)?
1 .GE. FQ(I).PPOW(1:NF))) THEN !By comparing the supplies of prime factors.
FRACTRAN = I !Yes!
NPPOW(FQ(I).PNUM(1:NF)) = NPPOW(FQ(I).PNUM(1:NF)) !Remove prime powers from N
1 - FQ(I).PPOW(1:NF) !Corresponding to Q.
NF = FP(I).PNUM(0) !Add powers to N
NPPOW(FP(I).PNUM(1:NF)) = NPPOW(FP(I).PNUM(1:NF)) !Corresponding to P.
1 + FP(I).PPOW(1:NF) !Thus, N = N/Q*P.
RETURN !That's all it takes! No multiplies nor divides!
END IF !So much for that fraction.
END DO !This relies on ALL(zero tests) yielding true, as when Q = 1.
FRACTRAN = 0 !No hit.
END FUNCTION FRACTRAN !No massive multi-precision arithmetic!
SUBROUTINE SHOWN(S,F) !Service routine to show the state after a step is calculated.
Could imaging a function I6FMT(23) that returns " 23" and " " for non-positive numbers.
Can't do it, as if this were invoked via a WRITE statement, re-entrant use of WRITE usually fails.
INTEGER S,F !Step number, Fraction number.
INTEGER I !A stepper.
CHARACTER*(9+4+1 + NL*6) ALINE !A scratchpad matching FORMAT 103.
WRITE (ALINE,103) S,F,NPPOW(PLIVE(1:NL)) !Show it!
103 FORMAT (I9,I4,":",<NL>I6) !As a sequence of powers of primes.
IF (F.LE.0) ALINE(10:13) = "" !Scrub when no fraction is fingered.
DO I = 1,NL !Step along the live primes.
IF (NPPOW(PLIVE(I)).GT.0) CYCLE !Ignoring the empowered ones.
ALINE(15 + (I - 1)*6:14 + I*6) = "" !Blank out zero powers.
END DO !On to the next.
WRITE (MSG,"(A)") ALINE !Reveal at last.
END SUBROUTINE SHOWN !A struggle.
END MODULE CONWAYSIDEA !Simple...
PROGRAM POKE
USE CONWAYSIDEA !But, where does he get his ideas from?
INTEGER P(ENUFF),Q(ENUFF) !Holds the fractions as P(i)/Q(i).
INTEGER N !The working number.
INTEGER LF !Last fraction given.
INTEGER LP !Last prime needed.
INTEGER MS !Maximum number of steps.
INTEGER I,IT !Assistants.
LOGICAL*1 PUSED(ENUFF) !Track the usage of prime numbers,
MSG = 6 !Standard output.
WRITE (6,1) !Announce.
1 FORMAT ("Interpreter for J. H. Conway's FRACTRAN language.")
Chew into an example programme.
10 OPEN (10,FILE = "Fractran.txt",STATUS="OLD",ACTION="READ") !Rather than compiled-in stuff.
READ (10,*) LF !I need to know this without having to scan the input.
WRITE (MSG,11) LF !Reveal in case of trouble.
11 FORMAT (I0," fractions, as follow:") !Should the input evoke problems.
READ (10,*) (P(I),Q(I),I = 1,LF) !Ask for the specified number of P,Q pairs.
WRITE (MSG,12) (P(I),Q(I),I = 1,LF) !Show what turned up.
12 FORMAT (24(I0,"/",I0:", ")) !As P(i)/Q(i) pairs. The colon means that there will be no trailing comma.
READ (10,*) N,MS !The start value, and the step limit.
CLOSE (10) !Finished with input.
WRITE (MSG,13) N,MS !Hopefully, all went well.
13 FORMAT ("Start with N = ",I0,", step limit ",I0)
IF (.NOT.GRASPPRIMEBAG(66)) STOP "Gan't grab my file of primes!" !Attempt in hope.
Convert the starting number to a more convenient form, an array of powers of successive prime numbers.
20 FP(1) = FACTOR(N) !Borrow one of the factor list variables.
NPPOW = 0 !Clear all prime factor counts.
DO I = 1,FP(1).PNUM(0) !Now find what they are.
NPPOW(FP(1).PNUM(I)) = FP(1).PPOW(I) !Convert from a variable-length list
END DO !To a fixed-length random-access array.
PUSED = NPPOW.GT.0 !Note which primes have been used.
LP = FP(1).PNUM(FP(1).PNUM(0)) !Recall the last prime required. More later.
Convert the supplied P(i)/Q(i) fractions to lists of prime number factors and powers in FP(i) and FQ(i).
DO I = 1,LF !Step through the fractions.
IT = GCD(P(I),Q(I)) !Suspicion.
IF (IT.GT.1) THEN !Justified?
WRITE (MSG,21) I,P(I),Q(I),IT !Alas. Complain. The rule is N*(P/Q) being integer.
21 FORMAT ("Fraction ",I3,", ",I0,"/",I0,!N*6/3 is integer always because this is N*2/1, but 3 may not divide N.
1 " has common factor ",I0,"!") !By removing IT,
P(I) = P(I)/IT !The test need merely check if N is divisible by Q.
Q(I) = Q(I)/IT !And, as N is factorised in NPPOW
END IF !And Q in FQ, subtractions of powers only is needed.
FP(I) = FACTOR(P(I)) !Righto, form the factor list for P.
PUSED(FP(I).PNUM(1:FP(I).PNUM(0))) = .TRUE. !Mark which primes it fingers.
LP = MAX(LP,FP(I).PNUM(FP(I).PNUM(0))) !One has no prime factors: PNUM(0) = 0.
FQ(I) = FACTOR(Q(I)) !And likewise for Q.
PUSED(FQ(I).PNUM(1:FQ(I).PNUM(0))) = .TRUE. !Some primes may be omitted.
LP = MAX(LP,FQ(I).PNUM(FQ(I).PNUM(0))) !If no prime factors, PNUM(0) fingers element zero, which is zero.
END DO !All this messing about saves on multiplication and division.
Check which primes are in use, preparing an index of live primes..
NL = 0 !No live primes.
DO I = 1,LP !Check up to the last prime.
IF (PUSED(I)) THEN !This one used?
NL = NL + 1 !Yes. Another.
PLIVE(NL) = I !Fingered.
END IF !So much for that prime.
END DO !On to the next.
WRITE (MSG,22) NL,LP,PRIME(LP) !Remark on usage.
22 FORMAT ("Require ",I0," primes only, up to Prime(",I0,") = ",I0) !Presume always more than one prime.
IF (LP.GT.LASTP) STOP "But, that's too many for array NPPOW!"
Cast forth a heading.
100 WRITE (MSG,101) (PRIME(PLIVE(I)), I = 1,NL) !Splat a heading.
101 FORMAT (/,14X,"N as powers of prime factors",/, !The prime heading,
1 5X,"Step F#:",<LP>I6) !With primes beneath.
CALL SHOWN(0,0) !Initial state of N as NPPOW. Step zero, no fraction.
Commence!
DO I = 1,MS !Here we go!
IT = FRACTRAN(LF) !Do it!
CALL SHOWN(I,IT) !Show it!
IF (IT.LE.0) EXIT !Quit it?
END DO !The next step.
Complete!
END !Whee!

View file

@ -0,0 +1,5 @@
DO I = 1,MS !Here we go!
IT = FRACTRAN(LF) !Do it!
IF (ALL(NPPOW(2:LP).EQ.0)) CALL SHOWN(I,IT) !Show it!
IF (IT.LE.0) EXIT !Quit it?
END DO !The next step.

View file

@ -0,0 +1,90 @@
' version 06-07-2015
' compile with: fbc -s console
' uses gmp
#Include Once "gmp.bi"
' in case the two #define's are missing from 'gmp.bi' define them now
#Ifndef mpq_numref
#Define mpq_numref(Q) (@(Q)->_mp_num)
#Define mpq_denref(Q) (@(Q)->_mp_den)
#EndIf
Dim As String prog(0 To ...) = {"17/91", "78/85", "19/51", "23/38", "29/33",_
"77/29", "95/23", "77/19", "1/17", "11/13", "13/11", "15/14", "15/2", "55/1"}
Dim As UInteger i, j, c, max = UBound(prog)
Dim As Integer scanbit
Dim As ZString Ptr gmp_str : gmp_str = Allocate(10000)
Dim As Mpq_ptr in_, out_
in_ = Allocate(Len(__mpq_struct)) : Mpq_init(in_)
out_ = Allocate(Len(__mpq_struct)) : Mpq_init(out_)
Dim As mpz_ptr num, den
num = Allocate(Len(__mpz_struct)) : Mpz_init(num)
den = Allocate(Len(__mpz_struct)) : Mpz_init(den)
Dim As mpq_ptr instruction(max)
For i = 0 To max
instruction(i) = Allocate(Len(__mpq_struct))
mpq_init(instruction(i))
mpq_set_str(instruction(i), prog(i), 10 )
Next
mpq_set_str(in_ ,"2",10)
i = 0 : j = 0
Print "2";
Do
mpq_mul(out_, instruction(i), in_)
i = i + 1
den = mpq_denref(out_)
If mpz_cmp_ui(den, 1) = 0 Then
Mpq_get_str(gmp_str, 10, out_)
Print ", ";*gmp_str;
mpq_swap(in_, out_)
i = 0
j = j + 1
End If
Loop Until j > 14
' this one only display if the integer is 2^p, p being prime
mpq_set_str(in_ ,"2",10)
i = 0 : j = 0 : c = 0
Print : Print : Print
Print "count iterations prime 2^prime"
Do
mpq_mul(out_, instruction(i), in_)
i = i + 1
j = j + 1
den = mpq_denref(out_)
If mpz_cmp_ui(den, 1) = 0 Then
num = mpq_numref(out_)
scanbit = mpz_scan1(num, 0)
' if scanbit = 0 then number is odd
If scanbit > 0 Then
' return from mpz_scan1(num, scanbit+1) is -1 for power of 2
If mpz_scan1(num, scanbit +1) = -1 Then
If c <= 20 Then Mpq_get_str(gmp_str, 10, out_) Else *gmp_str = ""
c = c + 1
Print Using "##### ################### ######## "; c; j; scanbit;
Print *gmp_str
If InKey <> "" Then Exit Do
End If
End If
mpq_swap(in_, out_)
i = 0
End If
Loop
' Loop Until scanbit > 300
' Loop Until InKey <> ""
' Loop Until scanbit > 300 Or InKey <> ""
' stopping conditions will slow down the hole loop
' loop will check for key if it's printing a result
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,62 @@
package main
import (
"fmt"
"log"
"math/big"
"os"
"strconv"
"strings"
)
func compile(src string) ([]big.Rat, bool) {
s := strings.Fields(src)
r := make([]big.Rat, len(s))
for i, s1 := range s {
if _, ok := r[i].SetString(s1); !ok {
return nil, false
}
}
return r, true
}
func exec(p []big.Rat, n *big.Int, limit int) {
var q, r big.Int
rule:
for i := 0; i < limit; i++ {
fmt.Printf("%d ", n)
for j := range p {
q.QuoRem(n, p[j].Denom(), &r)
if r.BitLen() == 0 {
n.Mul(&q, p[j].Num())
continue rule
}
}
break
}
fmt.Println()
}
func usage() {
log.Fatal("usage: ft <limit> <n> <prog>")
}
func main() {
if len(os.Args) != 4 {
usage()
}
limit, err := strconv.Atoi(os.Args[1])
if err != nil {
usage()
}
var n big.Int
_, ok := n.SetString(os.Args[2], 10)
if !ok {
usage()
}
p, ok := compile(os.Args[3])
if !ok {
usage()
}
exec(p, &n, limit)
}

View file

@ -0,0 +1,35 @@
package main
import (
"fmt"
"log"
"math/big"
"os"
"os/exec"
)
func main() {
c := exec.Command("ft", "1000000", "2", `17/91 78/85 19/51 23/38
29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1`)
c.Stderr = os.Stderr
r, err := c.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err = c.Start(); err != nil {
log.Fatal(err)
}
var n big.Int
for primes := 0; primes < 20; {
if _, err = fmt.Fscan(r, &n); err != nil {
log.Fatal(err)
}
l := n.BitLen() - 1
n.SetBit(&n, l, 0)
if n.BitLen() == 0 && l > 1 {
fmt.Printf("%d ", l)
primes++
}
}
fmt.Println()
}

View file

@ -0,0 +1,8 @@
import Data.List (find)
import Data.Ratio (Ratio, (%), denominator)
fractran :: (Integral a) => [Ratio a] -> a -> [a]
fractran fracts n = n :
case find (\f -> n `mod` denominator f == 0) fracts of
Nothing -> []
Just f -> fractran fracts $ truncate (fromIntegral n * f)

View file

@ -0,0 +1 @@
import Data.List.Split (splitOn)

View file

@ -0,0 +1,3 @@
readProgram :: String -> [Ratio Int]
readProgram = map (toFrac . splitOn "/") . splitOn ","
where toFrac [n,d] = read n % read d

View file

@ -0,0 +1,2 @@
import Data.Maybe (mapMaybe)
import Data.List (elemIndex)

View file

@ -0,0 +1,20 @@
primes :: [Int]
primes = mapMaybe log2 $ fractran prog 2
where
prog =
[ 17 % 91
, 78 % 85
, 19 % 51
, 23 % 38
, 29 % 33
, 77 % 29
, 95 % 23
, 77 % 19
, 1 % 17
, 11 % 13
, 13 % 11
, 15 % 14
, 15 % 2
, 55 % 1
]
log2 = fmap succ . elemIndex 2 . takeWhile even . iterate (`div` 2)

View file

@ -0,0 +1,27 @@
record fract(n,d)
procedure main(A)
fractran("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1", 2)
end
procedure fractran(s, n, limit)
execute(parse(s),n, limit)
end
procedure parse(s)
f := []
s ? while not pos(0) do {
tab(upto(' ')|0) ? put(f,fract(tab(upto('/')), (move(1),tab(0))))
move(1)
}
return f
end
procedure execute(f,d,limit)
/limit := 15
every !limit do {
if d := (d%f[i := !*f].d == 0, (writes(" ",d)/f[i].d)*f[i].n) then {}
else break write()
}
write()
end

View file

@ -0,0 +1,2 @@
toFrac=: '/r' 0&".@charsub ] NB. read fractions from string
fractran15=: ({~ (= <.) i. 1:)@(toFrac@[ * ]) ^:(<15) NB. return first 15 Fractran results

View file

@ -0,0 +1,3 @@
taskstr=: '17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1'
taskstr fractran15 2
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132

View file

@ -0,0 +1 @@
fractran=. (((({~ (1 i.~ (= <.)))@:* ::]^:)(`]))(".@:('1234567890r ' {~ '1234567890/ '&i.)@:[`))(`:6)

View file

@ -0,0 +1,2 @@
'17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1' (<15) fractran 2
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132

View file

@ -0,0 +1,4 @@
primes=. ('fractan'f.) ((1 }. 2 ^. (#~ *./@:e.&2 0"1@:q:))@:)
'17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1' (<555555) primes 2
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71

View file

@ -0,0 +1,2 @@
primes
((((({~ (1 i.~ (= <.)))@:* ::]^:)(`]))(".@:('1234567890r ' {~ '1234567890/ '&i.)@:[`))(`:6))((1 }. 2 ^. (#~ *./@:e.&2 0"1@:q:))@:)

View file

@ -0,0 +1,2 @@
_ fractran
".@:('1234567890r ' {~ '1234567890/ '&i.)@:[ ({~ (1 i.~ (= <.)))@:* ::]^:_ ]

View file

@ -0,0 +1 @@
FRACTRAN=. ({~ (1 i.~ (= <.)))@:* ::]^:_

View file

@ -0,0 +1,2 @@
455r33 11r13 1r11 3r7 11r2 1r3 FRACTRAN 11664
59604644775390625

View file

@ -0,0 +1,54 @@
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Fractran{
public static void main(String []args){
new Fractran("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1", 2);
}
final int limit = 15;
Vector<Integer> num = new Vector<>();
Vector<Integer> den = new Vector<>();
public Fractran(String prog, Integer val){
compile(prog);
dump();
exec(2);
}
void compile(String prog){
Pattern regexp = Pattern.compile("\\s*(\\d*)\\s*\\/\\s*(\\d*)\\s*(.*)");
Matcher matcher = regexp.matcher(prog);
while(matcher.find()){
num.add(Integer.parseInt(matcher.group(1)));
den.add(Integer.parseInt(matcher.group(2)));
matcher = regexp.matcher(matcher.group(3));
}
}
void exec(Integer val){
int n = 0;
while(val != null && n<limit){
System.out.println(n+": "+val);
val = step(val);
n++;
}
}
Integer step(int val){
int i=0;
while(i<den.size() && val%den.get(i) != 0) i++;
if(i<den.size())
return num.get(i)*val/den.get(i);
return null;
}
void dump(){
for(int i=0; i<den.size(); i++)
System.out.print(num.get(i)+"/"+den.get(i)+" ");
System.out.println();
}
}

View file

@ -0,0 +1,45 @@
// Parses the input string for the numerators and denominators
function compile(prog, numArr, denArr) {
let regex = /\s*(\d*)\s*\/\s*(\d*)\s*(.*)/m;
let result;
while (result = regex.exec(prog)) {
numArr.push(result[1]);
denArr.push(result[2]);
prog = result[3];
}
return [numArr, denArr];
}
// Outputs the result of the compile stage
function dump(numArr, denArr) {
let output = "";
for (let i in numArr) {
output += `${numArr[i]}/${denArr[i]} `;
}
return `${output}<br>`;
}
// Step
function step(val, numArr, denArr) {
let i = 0;
while (i < denArr.length && val % denArr[i] != 0) i++;
return numArr[i] * val / denArr[i];
}
// Executes Fractran
function exec(val, i, limit, numArr, denArr) {
let output = "";
while (val && i < limit) {
output += `${i}: ${val}<br>`;
val = step(val, numArr, denArr);
i++;
}
return output;
}
// Main
// Outputs to DOM (clears and writes at the body tag)
let body = document.body;
let [num, den] = compile("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1", [], []);
body.innerHTML = dump(num, den);
body.innerHTML += exec(2, 0, 15, num, den);

View file

@ -0,0 +1,242 @@
(() => {
'use strict';
// fractran :: [Ratio Int] -> Int -> Gen [Int]
const fractran = (xs, n) => {
function* go(n) {
const p = r => 0 === v % r.d;
let
v = n,
mb = find(p, xs);
yield v
while (!mb.Nothing) {
mb = bindMay(
find(p, xs),
r => (
v = truncate({
type: 'Ratio',
n: v * r.n,
d: r.d
}),
Just(v)
)
);
mb.Just && (yield v)
}
};
return go(n);
};
// readRatios :: String -> [Ratio]
const readRatios = s =>
map(x => ratio(...map(read, splitOn('/', x))),
splitOn(',', s)
);
// main :: IO()
const main = () => {
// strRatios :: String
const strRatios = `17/91, 78/85, 19/51, 23/38, 29/33, 77/29,
95/23 , 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1`;
showLog(
'First fifteen steps:',
take(15,
fractran(readRatios(strRatios), 2)
)
);
showLog(
'First five primes:',
take(5,
mapMaybeGen(
x => fmapMay(
succ,
elemIndex(
2,
takeWhileGen(
even,
iterate(n => div(n, 2), x)
)
)
),
fractran(readRatios(strRatios), 2)
)
)
);
};
// GENERIC ABSTRACTIONS ----------------------------
// Just :: a -> Maybe a
const Just = x => ({
type: 'Maybe',
Nothing: false,
Just: x
});
// Nothing :: Maybe a
const Nothing = () => ({
type: 'Maybe',
Nothing: true,
});
// Tuple (,) :: a -> b -> (a, b)
const Tuple = (a, b) => ({
type: 'Tuple',
'0': a,
'1': b,
length: 2
});
// abs :: Num -> Num
const abs = Math.abs;
// bindMay (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
const bindMay = (mb, mf) =>
mb.Nothing ? mb : mf(mb.Just);
// div :: Int -> Int -> Int
const div = (x, y) => Math.floor(x / y);
// elemIndex :: Eq a => a -> [a] -> Maybe Int
const elemIndex = (x, xs) => {
const i = xs.indexOf(x);
return -1 === i ? (
Nothing()
) : Just(i);
};
// even :: Int -> Bool
const even = n => 0 === n % 2;
// find :: (a -> Bool) -> [a] -> Maybe a
const find = (p, xs) => {
for (let i = 0, lng = xs.length; i < lng; i++) {
if (p(xs[i])) return Just(xs[i]);
}
return Nothing();
};
// fmapMay (<$>) :: (a -> b) -> Maybe a -> Maybe b
const fmapMay = (f, mb) =>
mb.Nothing ? (
mb
) : Just(f(mb.Just));
// foldl :: (a -> b -> a) -> a -> [b] -> a
const foldl = (f, a, xs) => xs.reduce(f, a);
// gcd :: Int -> Int -> Int
const gcd = (x, y) => {
const
_gcd = (a, b) => (0 === b ? a : _gcd(b, a % b)),
abs = Math.abs;
return _gcd(abs(x), abs(y));
};
// iterate :: (a -> a) -> a -> Gen [a]
function* iterate(f, x) {
let v = x;
while (true) {
yield(v);
v = f(v);
}
}
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// mapMaybeGen :: (a -> Maybe b) -> Gen [a] -> [b]
function* mapMaybeGen(mf, gen) {
let v = take(1, gen);
while (0 < v.length) {
let mb = mf(v[0]);
if (!mb.Nothing) yield mb.Just
v = take(1, gen);
}
}
// properFracRatio :: Ratio -> (Int, Ratio)
const properFracRatio = nd => {
const [q, r] = Array.from(quotRem(nd.n, nd.d));
return Tuple(q, ratio(r, nd.d));
};
// quot :: Int -> Int -> Int
const quot = (n, m) => Math.floor(n / m);
// quotRem :: Int -> Int -> (Int, Int)
const quotRem = (m, n) =>
Tuple(Math.floor(m / n), m % n);
// ratio :: Int -> Int -> Ratio Int
const ratio = (n, d) =>
0 !== d ? (() => {
const g = gcd(n, d);
return {
type: 'Ratio',
'n': quot(n, g), // numerator
'd': quot(d, g) // denominator
}
})() : undefined;
// read :: Read a => String -> a
const read = JSON.parse;
// showLog :: a -> IO ()
const showLog = (...args) =>
console.log(
args
.map(JSON.stringify)
.join(' -> ')
);
// snd :: (a, b) -> b
const snd = tpl => tpl[1];
// splitOn :: [a] -> [a] -> [[a]]
// splitOn :: String -> String -> [String]
const splitOn = (pat, src) =>
src.split(pat);
// succ :: Int -> Int
const succ = x =>
1 + x;
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = (n, xs) =>
xs.constructor.constructor.name !== 'GeneratorFunction' ? (
xs.slice(0, n)
) : [].concat.apply([], Array.from({
length: n
}, () => {
const x = xs.next();
return x.done ? [] : [x.value];
}));
// takeWhileGen :: (a -> Bool) -> Gen [a] -> [a]
const takeWhileGen = (p, xs) => {
const ys = [];
let
nxt = xs.next(),
v = nxt.value;
while (!nxt.done && p(v)) {
ys.push(v);
nxt = xs.next();
v = nxt.value
}
return ys;
};
// truncate :: Num -> Int
const truncate = x =>
'Ratio' === x.type ? (
properFracRatio(x)[0]
) : properFraction(x)[0];
// MAIN ---
return main();
})();

View file

@ -0,0 +1,37 @@
# FRACTRAN interpreter implemented as an iterable struct
using .Iterators: filter, map, take
import Base: iterate, show
struct Fractran
rs::Vector{Rational{BigInt}}
i₀::BigInt
end
iterate(f::Fractran, i = f.i₀) =
for r in f.rs
if iszero(i % r.den) # faster than isinteger(i*r)
i = i ÷ r.den * r.num
return (i, i)
end
end
run(f::Fractran) = map(trailing_zeros, filter(ispow2, f))
show(io::IO, f::Fractran) = join(io, take(run(f), 30), ' ')
macro code_str(s)
eval(Meta.parse("[" * replace(s, "/" => "//") * "]"))
end
# Example FRACTRAN program generating primes
primes = Fractran(code"17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23,
77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1", 2)
# Output
println("First 25 iterations of FRACTRAN program 'primes':\n2 ",
join(take(primes, 25), ' '))
println("\nWatch the first 30 primes dropping out within seconds:")
primes

View file

@ -0,0 +1,45 @@
// version 1.1.3
import java.math.BigInteger
class Fraction(val num: BigInteger, val denom: BigInteger) {
operator fun times(n: BigInteger) = Fraction (n * num, denom)
fun isIntegral() = num % denom == BigInteger.ZERO
}
fun String.toFraction(): Fraction {
val split = this.split('/')
return Fraction(BigInteger(split[0]), BigInteger(split[1]))
}
val BigInteger.isPowerOfTwo get() = this.and(this - BigInteger.ONE) == BigInteger.ZERO
val log2 = Math.log(2.0)
fun fractran(program: String, n: Int, limit: Int, primesOnly: Boolean): List<Int> {
val fractions = program.split(' ').map { it.toFraction() }
val results = mutableListOf<Int>()
if (!primesOnly) results.add(n)
var nn = BigInteger.valueOf(n.toLong())
while (results.size < limit) {
val frac = fractions.find { (it * nn).isIntegral() } ?: break
nn = nn * frac.num / frac.denom
if (!primesOnly) {
results.add(nn.toInt())
}
else if (primesOnly && nn.isPowerOfTwo) {
val prime = (Math.log(nn.toDouble()) / log2).toInt()
results.add(prime)
}
}
return results
}
fun main(args: Array<String>) {
val program = "17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
println("First twenty numbers:")
println(fractran(program, 2, 20, false))
println("\nFirst twenty primes:")
println(fractran(program, 2, 20, true))
}

View file

@ -0,0 +1,15 @@
fractionlist = {17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1};
n = 2;
steplimit = 20;
j = 0;
break = False;
While[break == False && j <= steplimit,
newlist = n fractionlist;
isintegerlist = IntegerQ[#] & /@ newlist;
truepositions = Position[isintegerlist, True];
If[Length[truepositions] == 0,
break = True,
Print[ToString[j] <> ": " <> ToString[n]];
n = newlist[[truepositions[[1, 1]]]]; j++;
]
]

View file

@ -0,0 +1,13 @@
fractran[
program : {__ ? (Element[#, PositiveRationals] &)}, (* list of positive fractions *)
n0_Integer, (* initial state *)
maxSteps : _Integer : Infinity] := (* max number of steps *)
NestWhileList[ (* Return a list representing the evolution of the state n *)
Function[n, SelectFirst[IntegerQ][program * n]], (* Select first integer in n*program, if none return Missing *)
n0,
Not @* MissingQ, (* continue while the state is not Missing *)
1,
maxSteps]
$PRIMEGAME = {17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1};
fractran[$PRIMEGAME, 2, 50]

View file

@ -0,0 +1 @@
Select[IntegerQ] @ Log2[fractran[$PRIMEGAME, 2, 500000]]

View file

@ -0,0 +1,54 @@
import strutils
import bignum
const PrimeProg = "17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
iterator values(prog: openArray[Rat]; init: Natural): Int =
## Run the program "prog" with initial value "init" and yield the values.
var n = newInt(init)
var next: Rat
while true:
for fraction in prog:
next = n * fraction
if next.denom == 1:
break
n = next.num
yield n
func toFractions(fractList: string): seq[Rat] =
## Convert a string to a list of fractions.
for f in fractList.split():
result.add(newRat(f))
proc run(progStr: string; init, maxSteps: Natural = 0) =
## Run the program described by string "progStr" with initial value "init",
## stopping after "maxSteps" (0 means for ever).
## Display the value after each step.
let prog = progStr.toFractions()
var stepCount = 0
for val in prog.values(init):
inc stepCount
echo stepCount, ": ", val
if stepCount == maxSteps:
break
iterator primes(n: Natural): int =
# Yield the list of first "n" primes.
let prog = PrimeProg.toFractions()
var count = 0
for val in prog.values(2):
if isZero(val and (val - 1)):
# This is a power of two.
yield val.digits(2) - 1 # Compute the exponent as number of binary digits minus one.
inc count
if count == n:
break
# Run the program to compute primes displaying values at each step and stopping after 10 steps.
echo "First ten steps for program to find primes:"
PrimeProg.run(2, 10)
# Find the first 20 primes.
echo "\nFirst twenty prime numbers:"
for val in primes(20):
echo val

View file

@ -0,0 +1,136 @@
import algorithm
import sequtils
import strutils
import tables
const PrimeProg = "17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
type
Fraction = tuple[num, denom: int]
Factors = Table[int, int]
FractranProg = object
primes: seq[int]
nums, denoms: seq[Factors]
exponents: seq[int] # Could also use a CountTable.
iterator fractions(fractString: string): Fraction =
## Extract fractions from a string and yield them.
for f in fractString.split():
let fields = f.strip().split('/')
assert fields.len == 2
yield (fields[0].parseInt(), fields[1].parseInt())
iterator factors(val: int): tuple[val, exp: int] =
## Extract factors from a positive integer.
# Extract factor 2.
var val = val
var exp = 0
while (val and 1) == 0:
inc exp
val = val shr 1
if exp != 0:
yield (2, exp)
# Extract odd factors.
var d = 3
while d <= val:
exp = 0
while val mod d == 0:
inc exp
val = val div d
if exp != 0:
yield (d, exp)
inc d, 2
func newProg(fractString: string; init: int): FractranProg =
## Initialize a Fractran program.
for f in fractString.fractions():
# Extract numerators factors.
var facts: Factors
for (val, exp) in f.num.factors():
result.primes.add(val)
facts[val] = exp
result.nums.add(facts)
# Extract denominator factors.
facts.clear()
for (val, exp) in f.denom.factors():
result.primes.add(val)
facts[val] = exp
result.denoms.add(facts)
# Finalize list of primes.
result.primes.sort()
result.primes = result.primes.deduplicate(true)
# Allocate and initialize exponent sequence.
result.exponents.setLen(result.primes[^1] + 1)
for (val, exp) in init.factors():
result.exponents[val] = exp
func doOneStep(prog: var FractranProg): bool =
## Execute one step of the program.
for idx, factor in prog.denoms:
block tryFraction:
for val, exp in factor.pairs():
if prog.exponents[val] < exp:
# Not a multiple of the denominator.
break tryFraction
# Divide by the denominator.
for val, exp in factor.pairs():
dec prog.exponents[val], exp
# Multiply by the numerator.
for val, exp in prog.nums[idx]:
inc prog.exponents[val], exp
return true
func `$`(prog: FractranProg): string =
## Display a value as a product of prime factors.
for val, exp in prog.exponents:
if exp != 0:
if result.len > 0:
result.add('.')
result.add($val)
if exp > 1:
result.add('^')
result.add($exp)
proc run(fractString: string; init: int; maxSteps = 0) =
## Run a Fractran program.
var prog = newProg(fractString, init)
var stepCount = 0
while stepCount < maxSteps:
if not prog.doOneStep():
echo "*** No more possible fraction. Program stopped."
return
inc stepCount
echo stepCount, ": ", prog
proc findPrimes(maxCount: int) =
## Search and print primes.
var prog = newProg(PrimeProg, 2)
let oddPrimes = prog.primes[1..^1]
var primeCount = 0
while primeCount < maxCount:
discard prog.doOneStep()
block powerOf2:
if prog.exponents[2] > 0:
for p in oddPrimes:
if prog.exponents[p] != 0:
# Not a power of 2.
break powerOf2
inc primeCount
echo primeCount, ": ", prog.exponents[2]
#------------------------------------------------------------------------------
echo "First ten steps for program to find primes:"
run(PrimeProg, 2, 10)
echo "\nFirst twenty prime numbers:"
findPrimes(20)

View file

@ -0,0 +1,43 @@
open Num
let get_input () =
num_of_int (
try int_of_string Sys.argv.(1)
with _ -> 10)
let get_max_steps () =
try int_of_string Sys.argv.(2)
with _ -> 50
let read_program () =
let line = read_line () in
let words = Str.split (Str.regexp " +") line in
List.map num_of_string words
let is_int n = n =/ (integer_num n)
let run_program num prog =
let replace n =
let rec step = function
| [] -> None
| h :: t ->
let n' = h */ n in
if is_int n' then Some n' else step t in
step prog in
let rec repeat m lim =
Printf.printf " %s\n" (string_of_num m);
if lim = 0 then print_endline "Reached max step limit" else
match replace m with
| None -> print_endline "Finished"
| Some x -> repeat x (lim-1)
in
let max_steps = get_max_steps () in
repeat num max_steps
let () =
let num = get_input () in
let prog = read_program () in
run_program num prog

View file

@ -0,0 +1,15 @@
\\ FRACTRAN
\\ 4/27/16 aev
fractran(val,ft,lim)={
my(ftn=#ft,fti,di,L=List(),j=0);
while(val&&j<lim, listput(L,val);
for(i=1,ftn, fti=ft[i]; di=denominator(fti);
if(val%di==0, break));\\fend i
val= numerator(fti)*val/di; j++);\\wend j
return(Vec(L));
}
{\\ Executing:
my(v=[17/91,78/85,19/51,23/38,29/33,77/29,95/23,77/19,1/17,11/13,13/11,15/14,15/2,55/1]);
print(fractran(2,v,15));
}

View file

@ -0,0 +1,31 @@
use strict;
use warnings;
use Math::BigRat;
my ($n, @P) = map Math::BigRat->new($_), qw{
2 17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1
};
$|=1;
MAIN: for( 1 .. 5000 ) {
print " " if $_ > 1;
my ($pow, $rest) = (0, $n->copy);
until( $rest->is_odd ) {
++$pow;
$rest->bdiv(2);
}
if( $rest->is_one ) {
print "2**$pow";
} else {
#print $n;
}
for my $f_i (@P) {
my $nf_i = $n * $f_i;
next unless $nf_i->is_int;
$n = $nf_i;
next MAIN;
}
last;
}
print "\n";

View file

@ -0,0 +1,107 @@
(phixonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- 8s
--with javascript_semantics -- 52s!! (see note)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">steps</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">primes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">45</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">known_factors</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- nb: no specific order</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">combine_factors</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- (inverse of as_primes)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">*=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">known_factors</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">as_primes</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: #000080;font-style:italic;">-- eg as_primes(55) -&gt; {5,11} -&gt; indexes to known_factors</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">prime_factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">duplicates</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</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: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">known_factors</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">known_factors</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">known_factors</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">known_factors</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">-- atom chk = combine_factors(res)
-- if chk!=n then ?9/0 end if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">parse</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</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: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"%d/%d"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sri</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- oops!</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">}}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sri</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">as_primes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span><span style="color: #000000;">as_primes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">pgm</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">pc</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pgm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
<span style="color: #000080;font-style:italic;">-- sequence d = pgm[pc][2], res = deep_copy(n) -- (see timing note)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">df</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">f</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">df</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">df</span><span style="color: #0000FF;">></span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">f</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">f</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">df</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pgm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">zf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zf</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">zf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">src</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pgm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">parse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">src</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">as_primes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</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: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">steps</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">combine_factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"first %d results: %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">steps</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">as_primes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">known_factors</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">n0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">known_factors</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">iteration</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">primes</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">n0</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k2</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">n0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (ie all non-2 are 0)
-- and the prime itself is ready and waiting...</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k2</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">iteration</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"first %d primes: %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">primes</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%,d iterations in %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">iteration</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>
<!--

View file

@ -0,0 +1,50 @@
load(Program, Fractions) :-
re_split("[ ]+", Program, Split), odd_items(Split, TextualFractions),
maplist(convert_frac, TextualFractions, Fractions).
odd_items(L, L) :- L = [_], !. % remove the even elements from a list.
odd_items([X,_|L], [X|R]) :- odd_items(L, R).
convert_frac(Text, Frac) :-
re_matchsub("([0-9]+)/([0-9]+)"/t, Text, Match, []),
Frac is Match.1 rdiv Match.2.
step(_, [], stop) :- !.
step(N, [F|Fs], R) :-
A is N*F,
(integer(A) -> R = A; step(N, Fs, R)).
exec(Prg, Start, Lz) :-
lazy_list(transition, Prg/Start, Lz).
transition(Prg/N0, Prg/N1, N1) :-
step(N0, Prg, N1).
steps(K, Start, Prg, Seq) :-
exec(Prg, Start, Values),
length(Seq, K), Seq = [Start|Rest], prefix(Rest, Values), !.
% The actual PRIMEGEN program follows...
primegen(Prg) :-
load("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1", Prg).
primes(N, Primes) :-
primegen(Prg), exec(Prg, 2, Steps),
length(Primes, N), capture_primes(Primes, Steps).
capture_primes([], _) :- !.
capture_primes([P|Ps], [Q|Qs]) :- pow2(Q), !, P is lsb(Q), capture_primes(Ps, Qs).
capture_primes(Ps, [_|Qs]) :- capture_primes(Ps, Qs).
pow2(X) :- X /\ (X-1) =:= 0.
main :-
primegen(Prg), steps(15, 2, Prg, Steps),
format("The first 15 steps from PRIMEGEN are: ~w~n", [Steps]),
primes(20, Primes),
format("By running PRIMEGEN we found these primes: ~w~n", [Primes]),
halt.
?- main.

View file

@ -0,0 +1,21 @@
from fractions import Fraction
def fractran(n, fstring='17 / 91, 78 / 85, 19 / 51, 23 / 38, 29 / 33,'
'77 / 29, 95 / 23, 77 / 19, 1 / 17, 11 / 13,'
'13 / 11, 15 / 14, 15 / 2, 55 / 1'):
flist = [Fraction(f) for f in fstring.replace(' ', '').split(',')]
n = Fraction(n)
while True:
yield n.numerator
for f in flist:
if (n * f).denominator == 1:
break
else:
break
n *= f
if __name__ == '__main__':
n, m = 2, 15
print('First %i members of fractran(%i):\n ' % (m, n) +
', '.join(str(f) for f,i in zip(fractran(n), range(m))))

View file

@ -0,0 +1,13 @@
from fractran import fractran
def fractran_primes():
for i, fr in enumerate(fractran(2), 1):
binstr = bin(fr)[2:]
if binstr.count('1') == 1:
prime = binstr.count('0')
if prime > 1: # Skip 2**0 and 2**1
yield prime, i
if __name__ == '__main__':
for (prime, i), j in zip(fractran_primes(), range(15)):
print("Generated prime %2i from the %6i'th member of the fractran series" % (prime, i))

View file

@ -0,0 +1,58 @@
[ $ "bigrat.qky" loadfile ] now!
[ 1 & not ] is even ( n --> b )
[ nip 1 = ] is vint ( n/d --> b )
[ [ dup even while
1 >> again ]
1 = ] is powerof2 ( n --> b )
[ 0 swap
[ dup even while
dip 1+
1 >> again ]
drop ] is lowbit ( n --> n )
[ [] swap nest$
witheach
[ char / over find
space unrot poke
build nested join ] ] is parse$ ( $ --> [ )
[ stack ] is program ( s --> )
[ true temp put
witheach
[ do 2over v*
2dup vint iff
[ false temp replace
conclude ]
else 2drop ]
2swap 2drop
temp take ] is run ( n/d [ --> n/d b )
[ stack ] is primes ( --> s )
$ "17/91 78/85 19/51 23/38 29/33 77/29 95/23"
$ " 77/19 1/17 11/13 13/11 15/14 15/2 55/1" join
parse$ program put
2 n->v
15 times
[ program share run
drop over echo sp ]
cr
2drop
2 n->v
[] primes put
[ program share run
drop over dup powerof2 iff
[ lowbit primes take
swap join primes put ]
else drop
primes share size 20 = until ]
2drop
primes take echo
program release

View file

@ -0,0 +1,28 @@
/*REXX program runs FRACTRAN for a given set of fractions and from a specified N. */
numeric digits 2000 /*be able to handle larger numbers. */
parse arg N terms fracs /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 2 /*Not specified? Then use the default.*/
if terms=='' | terms=="," then terms= 100 /* " " " " " " */
if fracs='' then fracs= "17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23,",
'77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1'
/* [↑] The default for the fractions. */
f= space(fracs, 0) /*remove all blanks from the FRACS list*/
do #=1 while f\==''; parse var f n.# "/" d.# ',' f
end /*#*/ /* [↑] parse all the fractions in list*/
#= # - 1 /*the number of fractions just found. */
say # 'fractions:' fracs /*display number and actual fractions. */
say 'N is starting at ' N /*display the starting number N. */
say terms ' terms are being shown:' /*display a kind of header/title. */
do j=1 for terms /*perform the DO loop for each term. */
do k=1 for # /* " " " " " " fraction*/
if N // d.k \== 0 then iterate /*Not an integer? Then ignore it. */
cN= commas(N); L= length(cN) /*maybe insert commas into N; get len.*/
say right('term' commas(j), 44) "──► " right(cN, max(15, L)) /*show Nth term & N*/
N= N % d.k * n.k /*calculate next term (use %≡integer ÷)*/
leave /*go start calculating the next term. */
end /*k*/ /* [↑] if an integer, we found a new N*/
end /*j*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ?

View file

@ -0,0 +1,39 @@
/*REXX program runs FRACTRAN for a given set of fractions and from a specified N. */
numeric digits 999; d= digits(); w= length(d) /*be able to handle gihugeic numbers. */
parse arg N terms fracs /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 2 /*Not specified? Then use the default.*/
if terms=='' | terms=="," then terms= 100 /* " " " " " " */
if fracs='' then fracs= "17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23,",
'77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1'
/* [↑] The default for the fractions. */
f= space(fracs, 0) /*remove all blanks from the FRACS list*/
do #=1 while f\==''; parse var f n.# "/" d.# ',' f
end /*#*/ /* [↑] parse all the fractions in list*/
#= # - 1 /*adjust the number of fractions found.*/
tell= terms>0 /*flag: show number or a power of 2.*/
!.= 0; _= 1 /*the default value for powers of 2. */
if \tell then do p=1 until length(_)>d; _= _ + _; !._= 1
if p==1 then @._= left('', w + 9) "2**"left(p, w) ' '
else @._= '(prime' right(p, w)") 2**"left(p, w) ' '
end /*p*/ /* [↑] build powers of 2 tables. */
L= length(N) /*length in decimal digits of integer N*/
say # 'fractions:' fracs /*display number and actual fractions. */
say 'N is starting at ' N /*display the starting number N. */
if tell then say terms ' terms are being shown:' /*display header.*/
else say 'only powers of two are being shown:' /* " " */
@a= '(max digits used:' /*a literal used in the SAY below. */
do j=1 for abs(terms) /*perform DO loop once for each term. */
do k=1 for # /* " " " " " " fraction*/
if N // d.k \== 0 then iterate /*Not an integer? Then ignore it. */
cN= commas(N); cj=commas(j) /*maybe insert commas into N. */
if tell then say right('term' cj, 44) "──► " cN /*display Nth term and N.*/
else if !.N then say right('term' cj,15) "──►" @.N @a right(L,w)") " cN
N= N % d.k * n.k /*calculate next term (use %≡integer ÷)*/
L= max(L, length(N) ) /*the maximum number of decimal digits.*/
leave /*go start calculating the next term. */
end /*k*/ /* [↑] if an integer, we found a new N*/
end /*j*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ?

View file

@ -0,0 +1,31 @@
#lang racket
(define (displaysp x)
(display x)
(display " "))
(define (read-string-list str)
(map string->number
(string-split (string-replace str " " "") ",")))
(define (eval-fractran n list)
(for/or ([e (in-list list)])
(let ([en (* e n)])
(and (integer? en) en))))
(define (show-fractran fr n s)
(printf "First ~a members of fractran(~a):\n" s n)
(displaysp n)
(for/fold ([n n]) ([i (in-range (- s 1))])
(let ([new-n (eval-fractran n fr)])
(displaysp new-n)
new-n))
(void))
(define fractran
(read-string-list
(string-append "17 / 91, 78 / 85, 19 / 51, 23 / 38, 29 / 33,"
"77 / 29, 95 / 23, 77 / 19, 1 / 17, 11 / 13,"
"13 / 11, 15 / 14, 15 / 2, 55 / 1")))
(show-fractran fractran 2 15)

View file

@ -0,0 +1,5 @@
sub fractran(@program) {
2, { first Int, map (* * $_).narrow, @program } ... 0
}
say fractran(<17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11
15/14 15/2 55/1>)[^100];

View file

@ -0,0 +1,7 @@
sub fractran(@program) {
2, { first Int, map (* * $_).narrow, @program } ... 0
}
for fractran <17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11
15/14 15/2 55/1> {
say $++, "\t", .msb, "\t", $_ if 1 +< .msb == $_;
}

View file

@ -0,0 +1,24 @@
Red ["Fractran"]
inp: ask "please enter list of fractions, or input file name: "
if exists? inpf: to-file inp [inp: read inpf]
digit: charset "0123456789"
frac: [copy p [some digit] #"/" copy q [some digit]
keep (as-pair to-integer p to-integer q)]
code: parse inp [collect [frac some [[some " "] frac]]]
n: to-integer ask "please enter starting number n: "
x: to-integer ask "please enter the number of terms, hit return for no limit: "
l: length? code
loop x [
forall code [
c: code/1
if n % c/y = 0 [
print n: n / c/y * c/x
code: head code
break
]
if l = index? code [halt]
]
]

View file

@ -0,0 +1,18 @@
ar = %w[17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1]
FractalProgram = ar.map(&:to_r) #=> array of rationals
Runner = Enumerator.new do |y|
num = 2
loop{ y << num *= FractalProgram.detect{|f| (num*f).denominator == 1} }
end
prime_generator = Enumerator.new do |y|
Runner.each do |num|
l = Math.log2(num)
y << l.to_i if l.floor == l
end
end
# demo
p Runner.take(20).map(&:numerator)
p prime_generator.take(20)

View file

@ -0,0 +1,24 @@
class TestFractran extends FunSuite {
val program = Fractran("17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1")
val expect = List(2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290, 770, 910, 170, 156, 132)
test("find first fifteen fractran figures") {
assert((program .execute(2) take 15 toList) === expect)
}
}
object Fractran {
val pattern = """\s*(\d+)\s*/\s*(\d+)\s*""".r
def parse(m: Match) = ((m group 1).toInt, (m group 2).toInt)
def apply(program: String) = new Fractran(
pattern.findAllMatchIn(program).map(parse).toList)
}
class Fractran(val numDem: List[(Int,Int)]) {
def execute(value: Int) = unfold(value) { v =>
numDem indexWhere(v % _._2 == 0) match {
case i if i > -1 => Some(v, numDem(i)._1 * v / numDem(i)._2)
case _ => None
}
}
}

View file

@ -0,0 +1,74 @@
(import (scheme base)
(scheme inexact)
(scheme read)
(scheme write)
(srfi 13)) ;; for string-length and string-ref
(define *string-fractions* ; string input of fractions
"17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19
1/17 11/13 13/11 15/14 15/2 55/1")
(define *fractions* ; create vector of fractions from string input
(list->vector ; convert result to a vector, for constant access times
(read (open-input-string ; read from the string of fractions, as a list
(string-append "(" *string-fractions* ")")))))
;; run a fractran interpreter, returning the next number for n
;; or #f if no next number available
;; assume fractions: ordered vector of positive fractions
;; n: a positive integer
(define (fractran fractions n)
(let ((max-n (vector-length fractions)))
(let loop ((i 0))
(cond ((= i max-n)
#f)
((integer? (* n (vector-ref fractions i)))
(* n (vector-ref fractions i)))
(else
(loop (+ 1 i)))))))
;; Task
(define (display-result max-n)
(do ((i 0 (+ 1 i))
(n 2 (fractran *fractions* n)))
((= i max-n) (newline))
(display n) (display " ")))
(display "Task: ")
(display-result 20) ; show first 20 numbers
;; Extra Credit: derive first 20 prime numbers
(define (generate-primes target-number initial-n)
(define (is-power-of-two? n) ; a binary with only 1 "1" bit is a power of 2
(cond ((<= n 2) ; exclude 2 and 1
#f)
(else
(let loop ((i 0) (acc 0) (binary-str (number->string n 2)))
(cond ((= i (string-length binary-str))
#t)
((and (eq? (string-ref binary-str i) #\1) (= 1 acc))
#f)
((eq? (string-ref binary-str i) #\1)
(loop (+ 1 i) (+ 1 acc) binary-str))
(else
(loop (+ 1 i) acc binary-str)))))))
(define (extract-prime n) ; just gets the number of zeroes in binary
(let ((binary-str (number->string n 2)))
(- (string-length binary-str) 1)))
;
(let loop ((count 0)
(n initial-n))
(when (< count target-number)
(cond ((eq? n #f)
(display "-- FAILED TO COMPUTE N --\n"))
((is-power-of-two? n)
(display (extract-prime n)) (display " ")
(loop (+ 1 count)
(fractran *fractions* n)))
(else
(loop count
(fractran *fractions* n))))))
(newline))
(display "Primes:\n")
(generate-primes 20 2) ; create first 20 primes

View file

@ -0,0 +1,36 @@
$ include "seed7_05.s7i";
include "rational.s7i";
const func array integer: fractran (in integer: limit, in var integer: number, in array rational: program) is func
result
var array integer: output is 0 times 0;
local
var integer: index is 1;
var rational: newNumber is 0/1;
begin
output := [] (number);
while index <= length(program) and length(output) <= limit do
newNumber := rat(number) * program[index];
if newNumber = rat(trunc(newNumber)) then
number := trunc(newNumber);
output &:= number;
index := 1;
else
incr(index);
end if;
end while;
end func;
const proc: main is func
local
const array rational: program is []
(17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1);
var array integer: output is 0 times 0;
var integer: number is 0;
begin
output := fractran(15, 2, program);
for number range output do
write(number <& " ");
end for;
writeln;
end func;

View file

@ -0,0 +1,29 @@
$ include "seed7_05.s7i";
include "bigrat.s7i";
const proc: fractran (in var bigInteger: number, in array bigRational: program) is func
local
var integer: index is 1;
var bigRational: newNumber is 0_/1_;
begin
while index <= length(program) do
newNumber := rat(number) * program[index];
if newNumber = rat(trunc(newNumber)) then
number := trunc(newNumber);
if 2_ ** ord(log2(number)) = number then
writeln(log2(number));
end if;
index := 1;
else
incr(index);
end if;
end while;
end func;
const proc: main is func
local
const array bigRational: program is []
(17_/91_, 78_/85_, 19_/51_, 23_/38_, 29_/33_, 77_/29_, 95_/23_, 77_/19_, 1_/17_, 11_/13_, 13_/11_, 15_/14_, 15_/2_, 55_/1_);
begin
fractran(2_, program);
end func;

View file

@ -0,0 +1,28 @@
var str ="17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1"
const FractalProgram = str.split(',').map{.num} #=> array of rationals
func runner(n, callback) {
var num = 2
n.times {
callback(num *= FractalProgram.find { |f| f * num -> is_int })
}
}
func prime_generator(n, callback) {
var x = 0;
runner(Inf, { |num|
var l = num.log2
if (l.floor == l) {
callback(l.int)
++x == n && return nil
}
})
}
STDOUT.autoflush(true)
runner(20, {|n| print (n, ' ') })
print "\n"
prime_generator(20, {|n| print (n, ' ') })
print "\n"

View file

@ -0,0 +1,19 @@
100->T
2->N
{17,78,19,23,29,77,95,77, 1,11,13,15,15,55}->LA
{91,85,51,38,33,29,23,19,17,13,11,14, 2, 1}->LB
Dim(LA)->U
T->Dim(LC)
For(I,1,T)
1->J: 1->F
While J<=U and F=1
If remainder(N,LB(J))=0
Then
Disp N
N->LC(I)
iPart(N/LB(J))*LA(J)->N
0->F
End
J+1->J
End
End

View file

@ -0,0 +1,49 @@
package require Tcl 8.6
oo::class create Fractran {
variable fracs nco
constructor {fractions} {
set fracs {}
foreach frac $fractions {
if {[regexp {^(\d+)/(\d+),?$} $frac -> num denom]} {
lappend fracs $num $denom
} else {
return -code error "$frac is not a supported fraction"
}
}
if {![llength $fracs]} {
return -code error "need at least one fraction"
}
}
method execute {n {steps 15}} {
set co [coroutine [incr nco] my Generate $n]
for {set i 0} {$i < $steps} {incr i} {
lappend result [$co]
}
catch {rename $co ""}
return $result
}
method Step {n} {
foreach {num den} $fracs {
if {$n % $den} continue
return [expr {$n * $num / $den}]
}
return -code break
}
method Generate {n} {
yield [info coroutine]
while 1 {
yield $n
set n [my Step $n]
}
return -code break
}
}
set ft [Fractran new {
17/91 78/85 19/51 23/38 29/33 77/29 95/23
77/19 1/17 11/13 13/11 15/14 15/2 55/1
}]
puts [$ft execute 2]

View file

@ -0,0 +1,12 @@
oo::objdefine $ft method pow2 {n} {
set co [coroutine [incr nco] my Generate 2]
set pows {}
while {[llength $pows] < $n} {
set item [$co]
if {($item & ($item-1)) == 0} {
lappend pows $item
}
}
return $pows
}
puts [$ft pow2 10]

View file

@ -0,0 +1,19 @@
#! /bin/bash
program="1/1 455/33 11/13 1/11 3/7 11/2 1/3"
echo $program | tr " " "\n" | cut -d"/" -f1 | tr "\n" " " > "data"
read -a ns < "data"
echo $program | tr " " "\n" | cut -d"/" -f2 | tr "\n" " " > "data"
read -a ds < "data"
t=0
n=72
echo "steps of computation" > steps.csv
while [ $t -le 6 ]; do
if [ $(($n*${ns[$t]}%${ds[$t]})) -eq 0 ]; then
let "n=$(($n*${ns[$t]}/${ds[$t]}))"
let "t=0"
factor $n >> steps.csv
fi
let "t=$t+1"
done

View file

@ -0,0 +1,116 @@
Option Base 1
Public prime As Variant
Public nf As New Collection
Public df As New Collection
Const halt = 20
Private Sub init()
prime = [{2,3,5,7,11,13,17,19,23,29,31}]
End Sub
Private Function factor(f As Long) As Variant
Dim result(10) As Integer
Dim i As Integer: i = 1
Do While f > 1
Do While f Mod prime(i) = 0
f = f \ prime(i)
result(i) = result(i) + 1
Loop
i = i + 1
Loop
factor = result
End Function
Private Function decrement(ByVal a As Variant, b As Variant) As Variant
For i = LBound(a) To UBound(a)
a(i) = a(i) - b(i)
Next i
decrement = a
End Function
Private Function increment(ByVal a As Variant, b As Variant) As Variant
For i = LBound(a) To UBound(a)
a(i) = a(i) + b(i)
Next i
increment = a
End Function
Private Function test(a As Variant, b As Variant)
flag = True
For i = LBound(a) To UBound(a)
If a(i) < b(i) Then
flag = False
Exit For
End If
Next i
test = flag
End Function
Private Function unfactor(x As Variant) As Long
result = 1
For i = LBound(x) To UBound(x)
result = result * prime(i) ^ x(i)
Next i
unfactor = result
End Function
Private Sub compile(program As String)
program = Replace(program, " ", "")
programlist = Split(program, ",")
For Each instruction In programlist
parts = Split(instruction, "/")
nf.Add factor(Val(parts(0)))
df.Add factor(Val(parts(1)))
Next instruction
End Sub
Private Function run(x As Long) As Variant
n = factor(x)
counter = 0
Do While True
For i = 1 To df.Count
If test(n, df(i)) Then
n = increment(decrement(n, df(i)), nf(i))
Exit For
End If
Next i
Debug.Print unfactor(n);
counter = counter + 1
If num = 31 Or counter >= halt Then Exit Do
Loop
Debug.Print
run = n
End Function
Private Function steps(x As Variant) As Variant
'expects x=factor(n)
For i = 1 To df.Count
If test(x, df(i)) Then
x = increment(decrement(x, df(i)), nf(i))
Exit For
End If
Next i
steps = x
End Function
Private Function is_power_of_2(x As Variant) As Boolean
flag = True
For i = LBound(x) + 1 To UBound(x)
If x(i) > 0 Then
flag = False
Exit For
End If
Next i
is_power_of_2 = flag
End Function
Private Function filter_primes(x As Long, max As Integer) As Long
n = factor(x)
i = 0: iterations = 0
Do While i < max
If is_power_of_2(steps(n)) Then
Debug.Print n(1);
i = i + 1
End If
iterations = iterations + 1
Loop
Debug.Print
filter_primes = iterations
End Function
Public Sub main()
init
compile ("17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1")
Debug.Print "First 20 results:"
output = run(2)
Debug.Print "First 30 primes:"
Debug.Print "after"; filter_primes(2, 30); "iterations."
End Sub

View file

@ -0,0 +1,31 @@
import "/big" for BigInt, BigRat
var isPowerOfTwo = Fn.new { |bi| bi & (bi - BigInt.one) == BigInt.zero }
var fractran = Fn.new { |program, n, limit, primesOnly|
var fractions = program.split(" ").where { |s| s != "" }
.map { |s| BigRat.fromRationalString(s) }
.toList
var results = []
if (!primesOnly) results.add(n)
var nn = BigInt.new(n)
while (results.count < limit) {
var fracs = fractions.where { |f| (f * nn).isInteger }.toList
if (fracs.count == 0) break
var frac = fracs[0]
nn = nn * frac.num / frac.den
if (!primesOnly) {
results.add(nn.toSmall)
} else if (primesOnly && isPowerOfTwo.call(nn)) {
var prime = (nn.toNum.log / 2.log).floor
results.add(prime)
}
}
return results
}
var program = "17/91 78/85 19/51 23/38 29/33 77/29 95/23 77/19 1/17 11/13 13/11 15/14 15/2 55/1"
System.print("First twenty numbers:")
System.print(fractran.call(program, 2, 20, false))
System.print("\nFirst ten primes:")
System.print(fractran.call(program, 2, 10, true))

View file

@ -0,0 +1,15 @@
var fracs="17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17,"
"11/13, 13/11, 15/14, 15/2, 55/1";
fcn fractranW(n,fracsAsOneBigString){ //-->Walker (iterator)
fracs:=(fracsAsOneBigString-" ").split(",").apply(
fcn(frac){ frac.split("/").apply("toInt") }); //( (n,d), (n,d), ...)
Walker(fcn(rn,fracs){
n:=rn.value;
foreach a,b in (fracs){
if(n*a%b == 0){
rn.set(n*a/b);
return(n);
}
}
}.fp(Ref(n),fracs))
}

View file

@ -0,0 +1 @@
fractranW(2,fracs).walk(20).println();

View file

@ -0,0 +1,11 @@
var [const] BN=Import("zklBigNum"); // libGMP
fcn fractranPrimes{
foreach n,fr in ([1..].zip(fractranW(BN(2),fracs))){
if(fr.num1s==1){
p:=(fr.toString(2) - "1").len(); // count zeros
if(p>1)
println("Prime %3d from the nth Fractran(%8d): %d".fmt(p,n,fr));
}
}
}
fractranPrimes();