Anonymous user
Fractran: Difference between revisions
Adding C#.
imported>JacobNoel (Adding C#.) |
|||
(7 intermediate revisions by 5 users not shown) | |||
Line 691:
return 0;
}</syntaxhighlight>
=={{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++}}==
Line 2,089 ⟶ 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}}==
Line 2,722 ⟶ 2,969:
using .Iterators: filter, map, take
struct Fractran
rs::Vector{Rational{BigInt}}
i₀::BigInt
limit::Int
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
end
end
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(
end
primes = Fractran(code"17/91 78/85 19/51 23/38 29/33 77/29 95/23
# Output
Line 2,921 ⟶ 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,940 ⟶ 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 4,028 ⟶ 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}}==
Line 4,548 ⟶ 4,829:
{{libheader|Wren-big}}
Extra credit is glacially slow. We just find the first 10 primes which takes about 85 seconds.
<syntaxhighlight lang="
var isPowerOfTwo = Fn.new { |bi| bi & (bi - BigInt.one) == BigInt.zero }
|