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,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)