Anonymous user
Fractran: Difference between revisions
Adding C#.
m (→{{header|Phix}}: added syntax colouring, marked p2js compatible, with timing disclaimer) |
imported>JacobNoel (Adding C#.) |
||
(24 intermediate revisions by 9 users not shown) | |||
Line 50:
{{trans|D}}
<
V fracts = prog.split(‘ ’).map(p -> p.split(‘/’).map(i -> Int(i)))
[Float] r
Line 61:
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))</
{{out}}
Line 69:
=={{header|360 Assembly}}==
<
FRACTRAN CSECT
USING FRACTRAN,R13 base register
Line 116:
XDEC DS CL12 temp
REGEQU
END FRACTRAN</
{{out}}
<pre>
Line 136:
=={{header|Ada}}==
<
procedure Fractan is
Line 178:
2, 15);
-- output is "0: 2 1: 15 2: 825 3: 725 ... 14: 132 15: 116"
end Fractan;</
{{out}}
Line 185:
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.win32}}
<
# we use Algol 68G's LONG LONG INT with a precision of 100 digits #
PR precision 100 PR
Line 258:
print( ( whole( pos, -12 ) + " " + whole( power of 2, -6 ) + " (" + whole( n OF pf, 0 ) + ")", newline ) )
FI
OD</
{{out}}
<pre>
Line 284:
507519 71 (2361183241434822606848)
</pre>
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">fractran←{
parts ← ' '∘≠⊆⊢
frac ← ⍎¨'/'∘≠⊆⊢
simp ← ⊢÷∨/
mul ← simp×
prog ← simp∘frac¨parts ⍺
step ← {⊃⊃(1=2⊃¨next)/next←⍺ mul¨⊂(⍵ 1)}
(start nstep)←⍵
rslt ← ⊃(⊢,⍨prog∘step∘⊃)⍣nstep¨start
⌽(⊢(/⍨)(∨\0∘≠))rslt
}</syntaxhighlight>
{{out}}
<syntaxhighlight lang="apl"> '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</syntaxhighlight>
=={{header|AutoHotkey}}==
<
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"
Line 309 ⟶ 326:
}
break
}</
{{out}}
<pre>0: 2
Line 334 ⟶ 351:
the "factor" command allows one to decrypt the data. For example, the program below computes the product of a and b, entered as 2<sup>a</sup> and 3<sup>b</sup>, the product being 5<sup>a×b</sup>. Two arrays are computed from the fractions, ns for the numerators and ds for the denominators. Then, every time where the multiplication by a fraction yields an integer, the output of the division is stored into a csv file in factored format.
<
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"
Line 353 ⟶ 370:
let "t=$t+1"
done
</syntaxhighlight>
If at the beginning n=72=2<sup>3</sup>×3<sup>2</sup> (to compute 3×2), the steps of the computation look like this:
Line 390 ⟶ 407:
=={{header|Batch File}}==
<
setlocal enabledelayedexpansion
Line 445 ⟶ 462:
echo.
pause
exit /b 1</
{{Out}}
<pre>Input:
Line 479 ⟶ 496:
Note that in some interpreters you may need to press <Return> twice after entering the fractions if the ''Starting value'' prompt doesn't at first appear.
<
v"Starting value: "_^#-*84~p6p00+1<
>:#,_&0" :snoitaretI">:#,_#@>>$&\:v
:$_\:10g5g*:10g6g%v1:\1$\$<|!:-1\.<
g0^<!:-1\p01+1g01$_10g6g/\^>\010p00</
{{out}}
Line 491 ⟶ 508:
Iterations: 16
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116</pre>
=={{header|BQN}}==
The function <code>RunFractran</code> runs a fractran program, given max iterations on the left, and input, program string on the right. It returns a list of generated numbers.
<code>Fractran</code> performs a single iteration of fractran on a given input, list of numerators and list of denominators.
<syntaxhighlight lang="bqn"># Fractran interpreter
# Helpers
_while_ ← {𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}
ToInt ← 10⊸×⊸+˜´·⌽-⟜'0'
ToFrac ← {
i ← ⊑/'/'=𝕩
ToInt¨i(↑⋈1⊸+⊸↓)𝕩
}
Split ← ((¬-˜⊢×·+`»⊸>)∘≠⊔⊢)
Fractran ← {
𝕊 n‿num‿den:
ind ← ⊑/0=den|num×n
⟨(n×ind⊑num)÷ind⊑den ⋄ num ⋄ den⟩
}
RunFractran ← {
steps 𝕊 inp‿prg:
num‿den ← <˘⍉>ToFrac¨' 'Split prg
step ← 1
list ← ⟨inp⟩
{
step +↩ 1
out ← Fractran 𝕩
list ∾↩ ⊑out
out
} _while_ {𝕊 n‿num‿den: (step<steps)∧ ∨´0=den|num} inp‿num‿den
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 1↓⌊2⋆⁼(⌈=⌊)∘(2⊸(⋆⁼))⊸/ seq</syntaxhighlight>
<syntaxhighlight lang="text"> )ex fractran.bqn
Generated numbers: 2‿15‿825‿725‿1925‿2275‿425‿390‿330‿290‿770‿910‿170‿156‿132‿116‿308‿364‿68‿4‿30‿225‿12375‿10875‿28875‿25375‿67375‿79625‿14875‿13650‿2550‿2340‿1980‿1740‿4620‿4060‿10780‿12740‿2380‿2184‿408‿152‿92‿380‿230‿950‿575‿2375‿9625‿11375‿2125‿1950‿1650‿1450‿3850‿4550‿850‿780‿660‿580‿1540‿1820‿340‿312‿264‿232‿616‿728‿136‿8‿60‿450‿3375‿185625‿163125‿433125‿380625‿1010625‿888125‿2358125‿2786875‿520625‿477750‿89250‿81900‿15300‿14040‿11880‿10440‿27720‿24360‿64680‿56840‿150920‿178360‿33320‿30576‿5712‿2128‿1288‿5320‿3220‿13300‿8050‿33250‿20125‿83125‿336875‿398125‿74375‿68250‿12750‿11700‿9900‿8700‿23100‿20300‿53900‿63700‿11900‿10920‿2040‿1872‿1584‿1392‿3696‿3248‿8624‿10192‿1904‿112‿120‿900‿6750‿50625‿2784375‿2446875‿6496875‿5709375‿15159375‿13321875‿35371875‿31084375‿82534375‿97540625‿18221875‿16721250‿3123750‿2866500‿535500‿491400‿91800‿84240‿71280‿62640‿166320‿146160‿388080‿341040‿905520‿795760‿2112880‿2497040‿466480‿428064‿79968‿29792‿18032‿74480‿45080‿186200‿112700‿465500‿281750‿1163750‿704375‿2909375‿11790625‿13934375‿2603125‿2388750‿446250‿409500‿76500‿70200‿59400‿52200‿138600‿121800‿323400‿284200‿754600‿891800‿166600‿152880‿28560‿26208‿4896‿1824‿1104
Primes: 2‿3</syntaxhighlight>
=={{header|Bracmat}}==
This program computes the first twenty primes. It has to do almost 430000 iterations to arrive at the twentieth prime, so instead of immediately writing each number to the terminal, it adds it to a list. After the set number of iterations, the list of numbers is written to a text file numbers.lst (21858548 bytes), so you can inspect it. Because it takes some time to do all iterations, its is advisable to write the source code below in a text file 'fractran' and run it in batch mode in the background, instead of starting Bracmat in interactive mode and typing the program at the prompt. The primes, together with the largest number found, are written to a file FRACTRAN.OUT.
<
np n fs A Z fi P p N L M
. !arg:(?N,?n,?fs) {Number of iterations, start n, fractions}
Line 529 ⟶ 590:
str$("\ntime: " flt$(clk$+-1*!t0,4) " sec\n")
, "FRACTRAN.OUT",NEW)
);</
In Linux, run the program as follows (assuming bracmat and the file 'fractran' are in the CWD):
<pre>./bracmat 'get$fractran' &</pre>
Line 565 ⟶ 626:
Using GMP. Powers of two are in brackets.
For extra credit, pipe the output through <code>| less -S</code>.
<
#include <stdlib.h>
#include <gmp.h>
Line 629 ⟶ 690:
return 0;
}</
=={{header|C sharp|C#}}==
The use of <code> using Fractype = (BigInteger numerator, BigInteger denominator);</code> requires C# 12.0.
<syntaxhighlight lang="csharp">
namespace System.Numerics
{
using Fractype = (BigInteger numerator, BigInteger denominator);
struct Quotient
{
private Fractype _frac;
public Fractype Fraction
{
get => _frac;
set => _frac = Reduce(value);
}
public bool IsIntegral => _frac.denominator == 1;
public Quotient(BigInteger num, BigInteger den)
{
Fraction = (num, den);
}
public static BigInteger GCD(BigInteger a, BigInteger b)
{
return (b == 0) ? a : GCD(b, a % b);
}
private static Fractype Reduce(Fractype f)
{
if (f.denominator == 0)
throw new DivideByZeroException();
BigInteger gcd = Quotient.GCD(f.numerator, f.denominator);
return (f.numerator / gcd, f.denominator / gcd);
}
public static Quotient operator *(Quotient a, Quotient b)
=> new Quotient(a._frac.numerator * b._frac.numerator, a._frac.denominator * b._frac.denominator);
public static Quotient operator *(Quotient a, BigInteger n)
=> new Quotient(a._frac.numerator * n, a._frac.denominator);
public static explicit operator Quotient(Fractype t) => new Quotient(t.numerator, t.denominator);
}
class FRACTRAN
{
private Quotient[] code;
public FRACTRAN(Fractype[] _code)
{
code = _code.Select(x => (Quotient) x).ToArray();
}
public (BigInteger value, bool success) Compute(BigInteger n)
{
for (int i = 0; i < code.Length; i++)
if ((code[i] * n).IsIntegral)
return ((code[i] * n).Fraction.numerator, true);
return (0, false);
}
}
class Program
{
public static void Main(string[] args)
{
Fractype[] frac_code = args[0].Split(" ")
.Select(x => ((BigInteger)Int32.Parse(x.Split("/")[0]), (BigInteger)Int32.Parse(x.Split("/")[1].Trim(',')))).ToArray();
BigInteger init = new BigInteger(Int32.Parse(args[1].Trim(',')));
int steps = Int32.Parse(args[2].Trim(','));
FRACTRAN FRACGAME = new FRACTRAN(frac_code);
List<BigInteger> sequence = new List<BigInteger>();
sequence.Add(init);
bool halt = false;
for (int i = 0; i < steps - 1; i++)
{
var k = FRACGAME.Compute(sequence[sequence.Count - 1]);
if (k.success)
sequence.Add(k.value);
else
{
halt = true;
break;
}
}
for (int i = 0; i < sequence.Count; i++)
Console.WriteLine((i + 1).ToString() + ": " + sequence[i]);
if (halt)
Console.WriteLine("HALT");
}
}
}
</syntaxhighlight>
Input:
<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, 15 </code>
Output:
<pre>
1: 2
2: 15
3: 825
4: 725
5: 1925
6: 2275
7: 425
8: 390
9: 330
10: 290
11: 770
12: 910
13: 170
14: 156
15: 132
</pre>
Moreover, modifying the class <code>Program</code> to,
<syntaxhighlight lang="csharp">
class Program
{
private static bool PowerOfTwo(BigInteger b)
{
while (b % 2 == 0)
b /= 2;
return b == 1;
}
private static BigInteger BigLog2(BigInteger b)
{
BigInteger r = 0;
while (b > 1)
{
r++;
b /= 2;
}
return r;
}
public static void Main(string[] args)
{
Fractype[] frac_code = args[0].Split(" ")
.Select(x => ((BigInteger)Int32.Parse(x.Split("/")[0]), (BigInteger)Int32.Parse(x.Split("/")[1].Trim(',')))).ToArray();
BigInteger init = new BigInteger(Int32.Parse(args[1].Trim(',')));
int steps = Int32.Parse(args[2].Trim(','));
FRACTRAN FRACGAME = new FRACTRAN(frac_code);
List<BigInteger> sequence = new List<BigInteger>();
List<BigInteger> primes = new List<BigInteger>();
sequence.Add(init);
bool halt = false;
while (primes.Count() < 20)
{
var k = FRACGAME.Compute(sequence[sequence.Count - 1]);
if (k.success)
sequence.Add(k.value);
else
{
halt = true;
break;
}
if (PowerOfTwo(k.value))
primes.Add(BigLog2(k.value));
}
for (int i = 0; i < primes.Count; i++)
Console.WriteLine((i + 1).ToString() + ": " + primes[i]);
if (halt)
Console.WriteLine("HALT");
}
}
</syntaxhighlight>
with the same input, will print the first 20 primes.
<pre>
1: 2
2: 3
3: 5
4: 7
5: 11
6: 13
7: 17
8: 19
9: 23
10: 29
11: 31
12: 37
13: 41
14: 43
15: 47
16: 53
17: 59
18: 61
19: 67
20: 71
</pre>
=={{header|C++}}==
<
#include <iostream>
#include <sstream>
Line 698 ⟶ 968:
return 0;
}
</syntaxhighlight>
{{out}}
<pre>
Line 717 ⟶ 987:
14 : 132
</pre>
=={{header|CLU}}==
<syntaxhighlight lang="clu">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</syntaxhighlight>
{{out}}
<pre> 0: 2
1: 15
2: 825
3: 725
4: 1925
5: 2275
6: 425
7: 390
8: 330
9: 290
10: 770
11: 910
12: 170
13: 156
14: 132
15: 116
16: 308
17: 364
18: 68
19: 4</pre>
=={{header|Common Lisp}}==
<
(lambda ()
(prog1
Line 740 ⟶ 1,157:
for next = (funcall fractran-instance)
until (null next)
do (print next))</
{{out}}
Line 767 ⟶ 1,184:
===Simple Version===
{{trans|Java}}
<
void fractran(in string prog, int val, in uint limit) {
Line 784 ⟶ 1,201:
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);
}</
{{out}}
<pre>0: 2
Line 803 ⟶ 1,220:
===Lazy Version===
<
struct Fractran {
Line 828 ⟶ 1,245:
77/19 1/17 11/13 13/11 15/14 15/2 55/1", 2)
.take(15).writeln;
}</
{{out}}
<pre>[2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290, 770, 910, 170, 156, 132]</pre>
Line 835 ⟶ 1,252:
{{libheader| System.RegularExpressions}}
{{Trans|Java}}
<syntaxhighlight lang="delphi">
program FractranTest;
Line 927 ⟶ 1,344:
TFractan.Create(DATA, 2).Free;
Readln;
end.</
{{out}}
<pre>
Line 949 ⟶ 1,366:
=={{header|Elixir}}==
{{trans|Erlang}}
<
use Bitwise
Line 1,014 ⟶ 1,431:
|> Enum.map(&Fractran.lowbit/1)
|> tl
IO.puts "The first few primes are:\n#{inspect prime}"</
{{out}}
Line 1,027 ⟶ 1,444:
=={{header|Erlang}}==
The exec() function can be passed a predicate which filters steps that satisfy a condition, which for the prime automata is a check to see if the number is a power of 2.
<
-mode(native).
Line 1,086 ⟶ 1,503:
gcd(A, 0) -> A;
gcd(A, B) -> gcd(B, A rem B).
</syntaxhighlight>
{{out}}
<pre>
Line 1,102 ⟶ 1,519:
=={{header|Factor}}==
<
prettyprint sequences splitting ;
IN: rosetta-code.fractran
Line 1,136 ⟶ 1,553:
2bi ;
MAIN: main</
{{out}}
<pre>
Line 1,147 ⟶ 1,564:
=={{header|Fermat}}==
<
;{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}
Line 1,172 ⟶ 1,589:
[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 );</
{{out}}<pre>
2
Line 1,201 ⟶ 1,618:
===The Code===
The source style is F77 except for the use of the I0 format code, though not all F77 compilers will offer INTEGER*8. By not using the MODULE scheme, array parameters can't be declared via P(:) which implies a secret additional parameter giving the size of the array and which can be accessed via the likes of <code>UBOUND(P, DIM = 1)</code> Instead, the old-style specification involves no additional parameters and can be given as P(*) meaning "no statement" as to the upper bound, or P(M) which ''may'' be interpreted as the upper bound being the value of M in the compilers that allow this. The actual upper bound of the parameter is unknown and unchecked, so the older style of P(12345) or similar might be used. Rather to my surprise, this compiler (Compaq F90/95) complained if parameter M was declared after the arrays P(M),Q(M) as it is my habit to declare parameters in the order of their appearance. <
INTEGER P(M),Q(M)!The terms of the fractions.</
So much for multi-pass compilers!
Similarly, without the MODULE protocol, in all calling routines function FRACTRAN would be deemed floating-point so a type declaration is needed in each. <
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.
Line 1,254 ⟶ 1,671:
END DO !The next step.
END !Whee!
</syntaxhighlight>
===The Results===
Line 1,295 ⟶ 1,712:
28 1: 14875
</pre>
Later Fortrans might offer the library function <code>POPCNT(n)</code> which returns the number of on-bits in an integer, most convenient for detecting a straight power of two in a binary computer. Adjusting the interpretation loop to be <
IT = FRACTRAN(N,P,Q,L) !Do it!
IF (POPCNT(N).EQ.1) WRITE (6,11) I,IT,N !Show it!
Line 1,306 ⟶ 1,723:
END IF !So much for overflow.
END DO !The next step.
</syntaxhighlight>
Leads to the following output:
<pre>
Line 1,341 ⟶ 1,758:
===Revised Code===
Because this scheme requires a supply of prime numbers, it is convenient to employ the routines prepared for the [[Extensible_prime_generator|extensible prime generator]] via module PRIMEBAG. So, this means escalating to the F90 style, and given that, some compound data structures can be used (for better mnemonics) in place of collections of arrays. <
USE PRIMEBAG !This is a common need.
INTEGER LASTP,ENUFF !Some size allowances.
Line 1,528 ⟶ 1,945:
Complete!
END !Whee!
</syntaxhighlight>
===Revised Results===
Line 1,643 ⟶ 2,060:
100 7: 3 1 1 1
</pre>
This time, restricting output to only occasions when N is a power of two requires no peculiar bit-counting function. Just change the interpretation loop to <
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.</
Output:
Line 1,761 ⟶ 2,178:
=={{header|FreeBASIC}}==
Added a compiler condition to make the program work with the old GMP.bi header file
<
' compile with: fbc -s console
' uses gmp
Line 1,850 ⟶ 2,267:
Print : Print "hit any key to end program"
Sleep
End</
{{out}}
<pre>2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290, 770, 910, 170, 156, 132, 116
Line 1,881 ⟶ 2,298:
=={{header|Fōrmulæ}}==
{{FormulaeEntry|page=https://formulae.org/?script=examples/FRACTRAN}}
'''Solution'''
[[File:Fōrmulæ - FRACTRAN 01.png]]
It is a function that accepts the program to run (as a list), the initial value of n and the number of values to generate.
It uses a local nested function next() that calculates the next value of . If it can be calculated, it is added to a result array and return true, elsewhere return false.
The main work is to iterate while the next() returns true and the number of values to generate is not reached.
The following is the call with the program for primes, initial n value of 2, and returning 20 values:
[[File:Fōrmulæ - FRACTRAN 02.png]]
[[File:Fōrmulæ - FRACTRAN 03.png]]
'''Bonus''' using the previous FRACTAN program to generate the first 20 primes.
It requires a modification to the previous program.
[[File:Fōrmulæ - FRACTRAN 04.png]]
[[File:Fōrmulæ - FRACTRAN 05.png]]
[[File:Fōrmulæ - FRACTRAN 06.png]]
'''FRACTRAN program for addition'''
[[File:Fōrmulæ - FRACTRAN 07.png]]
[[File:Fōrmulæ - FRACTRAN 08.png]]
[[File:Fōrmulæ - FRACTRAN 09.png]]
'''FRACTRAN program for multiplication'''
[[File:Fōrmulæ - FRACTRAN 10.png]]
[[File:Fōrmulæ - FRACTRAN 11.png]]
[[File:Fōrmulæ - FRACTRAN 12.png]]
=={{header|Go}}==
Basic task: This compiles to produce a program that reads the limit, starting number n, and list of fractions as command line arguments, with the list of fractions as a single argument.
<
import (
Line 1,950 ⟶ 2,405:
}
exec(p, &n, limit)
}</
{{out|Command line usage, with program compiled as "ft"}}
<pre>
Line 1,958 ⟶ 2,413:
Extra credit: This invokes above program with appropriate arguments,
and processes the output to obtain the 20 primes.
<
import (
Line 1,992 ⟶ 2,447:
}
fmt.Println()
}</
{{out}}
<pre>
Line 2,000 ⟶ 2,455:
=={{header|Haskell}}==
===Running the program===
<
import Data.Ratio (Ratio, (%), denominator)
Line 2,007 ⟶ 2,462:
case find (\f -> n `mod` denominator f == 0) fracts of
Nothing -> []
Just f -> fractran fracts $ truncate (fromIntegral n * f)</
Example:
Line 2,017 ⟶ 2,472:
===Reading the program===
Additional import
<syntaxhighlight lang
<
readProgram = map (toFrac . splitOn "/") . splitOn ","
where toFrac [n,d] = read n % read d</
Example of running the program:
Line 2,030 ⟶ 2,485:
===Generation of primes===
Additional import
<
import Data.List (elemIndex)</
<
primes = mapMaybe log2 $ fractran prog 2
where
Line 2,051 ⟶ 2,506:
, 55 % 1
]
log2 = fmap succ . elemIndex 2 . takeWhile even . iterate (`div` 2)</
<pre>λ> take 20 primes
Line 2,059 ⟶ 2,514:
Works in both languages:
<
procedure main(A)
Line 2,085 ⟶ 2,540:
}
write()
end</
{{out}}
Line 2,098 ⟶ 2,553:
===Hybrid version===
'''Solution:'''
<
fractran15=: ({~ (= <.) i. 1:)@(toFrac@[ * ]) ^:(<15) NB. return first 15 Fractran results</
'''Example:'''
<
taskstr fractran15 2
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132</
===Tacit version===
Line 2,110 ⟶ 2,565:
'''Solution'''
This is a variation of the previous solution which it is not entirely tacit due to the use of the explicit standard library verb (function) charsub. The adverb (functional)
<
The argument of
'''Example'''
<
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132</
'''Extra credit'''
The prime numbers are produced via the adverb primes; its argument has the same specifications as the argument for the
<
'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</
primes is also a stateless point-free functional,
<
((((({~ (1 i.~ (= <.)))@:* ::]^:)(`]))(".@:('1234567890r ' {~ '1234567890/ '&i.)@:[`))(`:6))((1 }. 2 ^. (#~ *./@:e.&2 0"1@:q:))@:)</
'''Turing completeness of J's stateless point-free dialect'''
When _ is the limit argument (i.e., when no limit is imposed) the run will halt according to the
<
".@:('1234567890r ' {~ '1234567890/ '&i.)@:[ ({~ (1 i.~ (= <.)))@:* ::]^:_ ]</
Actually, most of the code above is there to comply with the task's requirement of a "''natural'' format." When J's format for fractions is used the
<
which is an indirect concise confirmation that J's fixed tacit dialect is Turing complete.
In the following example,
<
59604644775390625</
=={{header|Java}}==
<
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Line 2,209 ⟶ 2,664:
System.out.println();
}
}</
=={{header|JavaScript}}==
===Imperative===
<
function compile(prog, numArr, denArr) {
let regex = /\s*(\d*)\s*\/\s*(\d*)\s*(.*)/m;
Line 2,257 ⟶ 2,712:
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);</
===Functional===
Line 2,263 ⟶ 2,718:
Here is a functionally composed version, which also derives a few primes. I may have missed something, but this first draft suggests that we may need bigInt support (which JS lacks) to get as far as the sixth prime.
<
'use strict';
Line 2,504 ⟶ 2,959:
// MAIN ---
return main();
})();</
{{Out}}
<pre>"First fifteen steps:" -> [2,15,825,725,1925,2275,425,390,330,290,770,910,170,156,132]
Line 2,510 ⟶ 2,965:
=={{header|Julia}}==
{{works with|Julia|
# FRACTRAN interpreter implemented as an iterable struct
using .Iterators: filter, map, take
struct Fractran
rs::Vector{Rational{BigInt}}
end
Base.iterate(f::Fractran, i = f.i₀) =
for r in f.rs
if iszero(i % r.den)
i = i ÷ r.den * r.num
return i, i
end
end
interpret(f::Fractran) =
take(
map(trailing_zeros,
filter(ispow2, f))
f.limit)
Base.show(io::IO, f::Fractran) =
join(io, interpret(f), ' ')
macro code_str(s)
[eval(Meta.parse(replace(t, "/" => "//"))) for t ∈ split(s)]
end
# 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</syntaxhighlight>
{{output}}
<pre>First 25 iterations of FRACTRAN program 'primes':
2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116 308 364 68 4 30 225 12375 10875 28875 25375
Watch the first 30 primes dropping out within seconds:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113
</pre>
=={{header|Kotlin}}==
<
import java.math.BigInteger
Line 2,614 ⟶ 3,060:
println("\nFirst twenty primes:")
println(fractran(program, 2, 20, true))
}</
{{out}}
Line 2,628 ⟶ 3,074:
This isn't as efficient as possible for long lists of fractions, since it doesn't stop doing n*listelements once it finds an integer. Instead, it computes "is integer?" for n*{all list elements}. For short lists that's probably not a big deal.
<
n = 2;
steplimit = 20;
Line 2,642 ⟶ 3,088:
n = newlist[[truepositions[[1, 1]]]]; j++;
]
]</
{{out}}
<pre>0: 2
Line 2,669 ⟶ 3,115:
Here is a different solution using a functional approach:
<syntaxhighlight lang="mathematica">
fractran[
program : {__ ? (Element[#, PositiveRationals] &)}, (* list of positive fractions *)
Line 2,683 ⟶ 3,129:
$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]
</syntaxhighlight>
{{out}}
Line 2,691 ⟶ 3,137:
Extract the first 20 prime numbers encoded as powers of 2:
<syntaxhighlight lang="mathematica">
Select[IntegerQ] @ Log2[fractran[$PRIMEGAME, 2, 500000]]
</syntaxhighlight>
{{out}}
<pre>{1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67}</pre>
Line 2,703 ⟶ 3,149:
We provide a general function to run any Fractran program and a specialized iterator to find prime numbers.
<syntaxhighlight lang="nim">
import strutils
import bignum
Line 2,726 ⟶ 3,172:
result.add(newRat(f))
proc run(progStr: string; init
## Run the program described by string "progStr" with initial value "init",
## stopping after "maxSteps" (0 means for ever).
Line 2,745 ⟶ 3,191:
if isZero(val and (val - 1)):
# This is a power of two.
yield val.digits(2).int - 1 # Compute the exponent as number of binary digits minus one.
inc count
if count == n:
Line 2,758 ⟶ 3,204:
for val in primes(20):
echo val
</syntaxhighlight>
{{out}}
Line 2,800 ⟶ 3,246:
With this algorithm, we no longer need big numbers. To avoid overflow, value at each step is displayed using
its decomposition in prime factors.
<syntaxhighlight lang="nim">
import algorithm
import sequtils
Line 2,937 ⟶ 3,383:
echo "\nFirst twenty prime numbers:"
findPrimes(20)
</syntaxhighlight>
{{out}}
Line 2,978 ⟶ 3,424:
=={{header|OCaml}}==
This reads a Fractran program from standard input (keyboard or file) and runs it with the input given by the command line arguments, using arbitrary-precision numbers and fractions.
<
let get_input () =
Line 3,020 ⟶ 3,466:
let num = get_input () in
let prog = read_program () in
run_program num prog</
The program
Line 3,070 ⟶ 3,516:
{{Works with|PARI/GP|2.7.4 and above}}
<
\\ FRACTRAN
\\ 4/27/16 aev
Line 3,086 ⟶ 3,532:
print(fractran(2,v,15));
}
</
{{Output}}
Line 3,098 ⟶ 3,544:
This makes the fact that it's a prime-number-generating program much clearer.
<
use warnings;
use Math::BigRat;
Line 3,129 ⟶ 3,575:
print "\n";
</syntaxhighlight>
If you uncomment the <pre>#print $n</pre>, it will print all the steps.
Line 3,144 ⟶ 3,590:
Division (to whole integer) is performed simply by subtracting the corresponding powers, as above not possible if any would be negative.
<!--<
<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>
Line 3,250 ⟶ 3,696:
<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>
<!--</
{{out}}
<pre>
Line 3,263 ⟶ 3,709:
=={{header|Prolog}}==
<
load(Program, Fractions) :-
re_split("[ ]+", Program, Split), odd_items(Split, TextualFractions),
Line 3,314 ⟶ 3,760:
?- main.
</syntaxhighlight>
{{Out}}
<pre>
Line 3,323 ⟶ 3,769:
=={{header|Python}}==
===Python: Generate series from a fractran program===
<
def fractran(n, fstring='17 / 91, 78 / 85, 19 / 51, 23 / 38, 29 / 33,'
Line 3,343 ⟶ 3,789:
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))))</
{{out}}
Line 3,352 ⟶ 3,798:
Use fractran above as a module imported into the following program.
<
from fractran import fractran
Line 3,365 ⟶ 3,811:
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))</
{{out}}
Line 3,392 ⟶ 3,838:
To execute a Fractran program until the halting condition is satisfied, use <code>[ program share run until ]</code>. The Fractran prime generator will never satisfy the halting condition, so in this task the <code>drop</code> after <code>run</code> discards the boolean.
<
[ 1 & not ] is even ( n --> b )
Line 3,450 ⟶ 3,896:
program release
</syntaxhighlight>
{{out}}
Line 3,461 ⟶ 3,907:
=={{header|Racket}}==
{{trans|D}} Simple version, without sequences.
<
(define (displaysp x)
Line 3,491 ⟶ 3,937:
"13 / 11, 15 / 14, 15 / 2, 55 / 1")))
(show-fractran fractran 2 15)</
{{out}}
<pre>First 15 members of fractran(2):
Line 3,500 ⟶ 3,946:
{{works with|rakudo|2015-11-03}}
A Fractran program potentially returns an infinite list, and infinite lists are a common data structure in Raku. The limit is therefore enforced only by slicing the infinite list.
<syntaxhighlight lang="raku"
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];</
{{out}}
<pre>(2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116 308 364 68 4 30 225 12375 10875 28875 25375 67375 79625 14875 13650 2550 2340 1980 1740 4620 4060 10780 12740 2380 2184 408 152 92 380 230 950 575 2375 9625 11375 2125 1950 1650 1450 3850 4550 850 780 660 580 1540 1820 340 312 264 232 616 728 136 8 60 450 3375 185625 163125 433125 380625 1010625 888125 2358125 2786875 520625 477750 89250 81900 15300 14040 11880 10440 27720 24360 64680 56840 150920 178360 33320 30576 5712 2128 1288)</pre>
'''Extra credit:'''
We can weed out all the powers of two into another infinite constant list based on the first list. In this case the sequence is limited only by our patience, and a ^C from the terminal. The <tt>.msb</tt> method finds the most significant bit of an integer, which conveniently is the base-2 log of the power-of-two in question.
<syntaxhighlight lang="raku"
2, { first Int, map (* * $_).narrow, @program } ... 0
}
Line 3,515 ⟶ 3,961:
15/14 15/2 55/1> {
say $++, "\t", .msb, "\t", $_ if 1 +< .msb == $_;
}</
{{out}}
<pre>
Line 3,531 ⟶ 3,977:
=={{header|Red}}==
<
inp: ask "please enter list of fractions, or input file name: "
Line 3,554 ⟶ 4,000:
if l = index? code [halt]
]
]</
{{out}}
<pre>please enter list of fractions, or input file name: 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
Line 3,578 ⟶ 4,024:
Programming note: extra blanks can be inserted in the fractions before and/or after the solidus ['''<big>/</big>'''].
===showing all terms===
<
numeric digits 2000 /*be able to handle larger numbers. */
parse arg N terms fracs /*obtain optional arguments from the CL*/
Line 3,605 ⟶ 4,051:
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 ?</
{{out|output|text= when using the default input:}}
<pre style="height:63ex">
Line 3,715 ⟶ 4,161:
===showing prime numbers===
Programming note: if the number of terms specified (the 2<sup>nd</sup> argument) is negative, then only powers of two are displayed.
<
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*/
Line 3,753 ⟶ 4,199:
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 ?</
{{out|output|text= when using the input (negative fifty million) of: <tt> , -50000000 </tt>}}
<pre>
Line 3,833 ⟶ 4,279:
</pre>
Output note: There are intermediary numbers (that aren't powers of two) that are hundreds of digits long. <br><br>
=={{header|RPL}}==
≪ → text
≪ "{'" 1 text SIZE '''FOR''' j
text j DUP SUB
'''IF''' DUP " " == '''THEN''' DROP "' '" '''END''' +
'''NEXT'''
"'}" + STR→
≫ ≫ '<span style="color:blue">PRECOMPIL</span>' STO <span style="color:grey">@ ( "fractions" → { 'fractions' } )</span>
≪ SWAP 20 → prog steps
≪ {} SWAP
1 steps '''FOR''' n
1 CF
1 prog SIZE '''FOR''' j
prog j GET OVER * EVAL RND
'''IF''' DUP FP '''THEN''' DROP '''ELSE'''
SWAP DROP SWAP OVER + SWAP
prog SIZE 'j' STO 1 SF '''END'''
'''NEXT'''
'''IF''' 1 FC?C '''THEN''' steps 'n' STO '''END'''
'''NEXT''' DROP
≫ ≫ '<span style="color:blue">RUN20</span>' STO <span style="color:grey">@ ( { 'fractions' } n → { results } )</span>
"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 style="color:blue">PRECOMPIL</span>
2 <span style="color:blue">RUN20</span>
{{out}}
<pre>
1: { 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116 308 364 68 4 30 }
</pre>
=={{header|Ruby}}==
<
FractalProgram = ar.map(&:to_r) #=> array of rationals
Line 3,852 ⟶ 4,328:
# demo
p Runner.take(20).map(&:numerator)
p prime_generator.take(20)</
{{Out}}
Line 3,861 ⟶ 4,337:
=={{header|Scala}}==
<
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)
Line 3,884 ⟶ 4,360:
}
}
}</
=={{header|Scheme}}==
Line 3,891 ⟶ 4,367:
{{libheader|Scheme/SRFIs}}
Similar to Python implementation of generating primes, the power of 2 is detected by first converting the number to binary representation, and check if it has only 1 "1" bit.
<
(scheme inexact)
(scheme read)
Line 3,964 ⟶ 4,440:
(display "Primes:\n")
(generate-primes 20 2) ; create first 20 primes</
{{out}}
<pre>Task: 2 15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116 308 364 68 4
Line 3,972 ⟶ 4,448:
=={{header|Seed7}}==
<
include "rational.s7i";
Line 4,007 ⟶ 4,483:
end for;
writeln;
end func;</
{{out}}
Line 4,015 ⟶ 4,491:
Program to compute prime numbers with fractran (The program has no limit, use CTRL-C to terminate it):
<
include "bigrat.s7i";
Line 4,043 ⟶ 4,519:
begin
fractran(2_, program);
end func;</
{{out}}
Line 4,077 ⟶ 4,553:
=={{header|Sidef}}==
{{trans|Ruby}}
<
const FractalProgram = str.split(',').map{.num} #=> array of rationals
Line 4,104 ⟶ 4,580:
prime_generator(20, {|n| print (n, ' ') })
print "\n"</
{{out}}
<pre>
Line 4,113 ⟶ 4,589:
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<
oo::class create Fractran {
Line 4,161 ⟶ 4,637:
77/19 1/17 11/13 13/11 15/14 15/2 55/1
}]
puts [$ft execute 2]</
{{out}}
<pre>
Line 4,167 ⟶ 4,643:
</pre>
You can just collect powers of 2 by monkey-patching in something like this:
<
set co [coroutine [incr nco] my Generate 2]
set pows {}
Line 4,178 ⟶ 4,654:
return $pows
}
puts [$ft pow2 10]</
Which will then produce this additional output:
<pre>
Line 4,186 ⟶ 4,662:
=={{header|TI-83 BASIC}}==
{{works with|TI-83 BASIC|TI-84Plus 2.55MP}}
<
2->N
{17,78,19,23,29,77,95,77, 1,11,13,15,15,55}->LA
Line 4,204 ⟶ 4,680:
J+1->J
End
End</
Note:
-> stands for Store symbol
Line 4,227 ⟶ 4,703:
=={{header|VBA}}==
This implementations follows the Wikipedia description of [[wp:FRACTRAN|FRACTRAN]]. There are test, decrement and increment instructions on an array of variables which are the exponents of the prime factors of the argument, which are the only instructions used to run the program with the function run, or go through it step by step with the function steps. An auxiliary factor function is used to compile the FRACTRAN program.
<
Public prime As Variant
Public nf As New Collection
Line 4,342 ⟶ 4,818:
Debug.Print "First 30 primes:"
Debug.Print "after"; filter_primes(2, 30); "iterations."
End Sub</
<pre>First 20 results:
15 825 725 1925 2275 425 390 330 290 770 910 170 156 132 116 308 364 68 4 30
Line 4,353 ⟶ 4,829:
{{libheader|Wren-big}}
Extra credit is glacially slow. We just find the first 10 primes which takes about 85 seconds.
<
var isPowerOfTwo = Fn.new { |bi| bi & (bi - BigInt.one) == BigInt.zero }
Line 4,383 ⟶ 4,859:
System.print(fractran.call(program, 2, 20, false))
System.print("\nFirst ten primes:")
System.print(fractran.call(program, 2, 10, true))</
{{out}}
Line 4,395 ⟶ 4,871:
=={{header|zkl}}==
<
"11/13, 13/11, 15/14, 15/2, 55/1";
fcn fractranW(n,fracsAsOneBigString){ //-->Walker (iterator)
Line 4,409 ⟶ 4,885:
}
}.fp(Ref(n),fracs))
}</
<
{{out}}
<pre>
Line 4,416 ⟶ 4,892:
</pre>
{{trans|Python}}
<
fcn fractranPrimes{
foreach n,fr in ([1..].zip(fractranW(BN(2),fracs))){
Line 4,426 ⟶ 4,902:
}
}
fractranPrimes();</
{{out}}
<pre>
|