-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 271ea36
Showing
10 changed files
with
434 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Package: Rfractran | ||
Type: Package | ||
Title: A 'FRACTRAN' Interpreter and Some Helper Functions | ||
Version: 1.0 | ||
Date: 2020-06-09 | ||
Author: Carl Witthoft | ||
Maintainer: Carl Witthoft <carl@witthoft.com> | ||
Depends: gmp | ||
Description: 'FRACTRAN' is an obscure yet tantalizing programming language invented by John Conway of 'Game of Life' fame. The code consists of a sequence of fractions. The rules are simple. First, select an integer to initialize the process. Second, multiply the integer by the first fraction. If an integer results, start again with the new integer. If not, try the next fraction. Finally, if no such multiplication yields an integer, terminate the program. For more information, see <https://en.wikipedia.org/wiki/FRACTRAN> . | ||
License: LGPL-3 | ||
NeedsCompilation: no | ||
Packaged: 2020-06-24 00:56:29 UTC; cgw | ||
Repository: CRAN | ||
Date/Publication: 2020-06-25 16:20:11 UTC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
358bbba639e47280b22acd0f0c866aff *DESCRIPTION | ||
7bd8c8b436803e87fe5b18e94be130f0 *NAMESPACE | ||
6a5c6eaf701920b9bd0be475cbc37638 *R/fractran.r | ||
e15afcdc07fad3f71403c5d429e15820 *build/partial.rdb | ||
bb390e6903920f06875d329e98b2f114 *man/Rfractran-package.Rd | ||
48f447d32b95f30ba4092c8052ab990d *man/fracAns.Rd | ||
f9c584539de28071e1944500dffee4e9 *man/fracDo.Rd | ||
498c6136ec954d3bcf135f3079b67ad3 *man/fracMake.Rd | ||
87337f547db5a96bba60052ebdbd91f1 *man/stopPrime.Rd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export("fracAns", "fracDo", "fracMake", "stopPrime") | ||
importFrom("grDevices", "xy.coords") | ||
importFrom("utils", "flush.console") | ||
import("gmp") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# for the first fraction f in the list for which nf is an integer, replace n by nf | ||
# repeat this rule until no fraction in the list produces an integer when multiplied by n, then halt. | ||
|
||
# validation tests: | ||
# addition: { 3/2 } . enter 2^a*3^b and get 3^(a+b) answer when terminated | ||
|
||
# multiplication: complicated because the sequence "bounces" between two subsets of the fraction set. Notice that the bigger denom, 33=11*3 in this case, ALWAYS has to be listed first before the denom 3, or it will never be reached. | ||
# { 455/33, 11/13, 1/11, ; 3/7, 11/2, 1/3 } ( ";" there for emphasis only) | ||
|
||
# then 2^a*3^b terminates with 5^(a*b) | ||
# fracmul <-makefrac(c(455,11,1,3,11,1),c(33,13,11,7,2,3)) | ||
|
||
|
||
# prime generator; moves a lot faster/farther than Conway's | ||
#start with 10, feed {7/3 99/98 13/49 39/35 36/91 10/143 49/13 7/11 1/2 91/1} and result includes a series of values 10^p , p prime | ||
# fracp10 <- fracMake(c(7,99,13,39,36,10,49,7,1,91), c(3,98,49,35,91,143,13,11,2,1)) | ||
|
||
#Conway's original prime gen : feed it 2, get 2^(primes) here and ther | ||
#fracpc <-makefrac(c(17,78,19,23,29,77,95,77,1,11,13,15,1,55), c(91,85,51,38,33,29,23,19,17,13,11,2,7,1)) | ||
|
||
#Remember - if you run N 'tries' you can restart with the Nth output integer. | ||
|
||
|
||
|
||
|
||
# first, a "set maker" which takes n,d vectors or matrix and makes the right bigq out of them . | ||
fracMake <- function(n, d = NULL){ | ||
#notice that entering a vector 'n' and no 'd' will produce the sequence 1/n[1],2/n[2], ... | ||
nd <-xy.coords(as.bigz(n),as.bigz(d)) | ||
return(invisible(as.bigq(nd$x,nd$y))) | ||
} | ||
|
||
# A Q&D logulator to pull numbers of interest out of the returned set of bigqs | ||
|
||
fracAns <- function(intvec, logbase, logprec = 1e-5) { | ||
logall <- log(numerator(intvec),logbase) | ||
frist <- which(abs(logall - round(logall)) < logprec ) # use 1e-4 as a solid place | ||
return(invisible(logall[frist])) | ||
|
||
} | ||
|
||
# 2) Figure out how to get it at least 10X faster. | ||
# 1) Notice that this returns nothing (empty) if the value of 'input' is a winner. | ||
# Change so first returned value is the input value | ||
# Here's the fraccinator engine. | ||
# 'tries' is default terminator so things don't go blooey | ||
fracDo <-function(input, fractions=NULL, nums, denoms, tries = 100, stopFun=NULL, liveUpdate=TRUE , ...) { | ||
input <- as.bigq(input) # for safety, do everything in bigq rather than bigz | ||
if (length(fractions)) { | ||
set <- fractions | ||
if (!is.bigq(set)) stop('fraction set must be bigq') | ||
} else { | ||
set <-as.bigq(floor(nums), floor(denoms)) | ||
} | ||
setlen <- length(set) | ||
intvec = input # will store 'wins' here # but bigq(NULL) is weird. | ||
itry = 1 | ||
while (itry <= tries) { | ||
if (liveUpdate) { | ||
if(!itry%%1000){ | ||
cat(' .') | ||
# moved inside to reduce if-loading | ||
if (!itry%%20000) { | ||
cat('\n') | ||
# flush.console() | ||
} | ||
flush.console() | ||
} #, appendLF = FALSE) | ||
} | ||
idx = 1 # index for grabbing a fraction | ||
gotit = 1 # set to zero if new integer found | ||
while (gotit) { | ||
tmpterm <- mul.bigq(input, set[idx]) | ||
if (denominator(tmpterm ) == 1){ | ||
intvec <- c(intvec,tmpterm) | ||
# if termination desired, do it here | ||
if(!is.null(stopFun)) { | ||
foundit <- stopFun(tmpterm, ...) #must return a single logical | ||
flush.console() | ||
if (foundit){ | ||
return(invisible(intvec)) | ||
} | ||
} | ||
gotit <- 0 | ||
input <- tmpterm # start again with new integer | ||
} else { | ||
idx <- idx + 1 | ||
} | ||
if (idx > setlen){ | ||
gotit = 0 | ||
itry <- tries + 1 # terminate because didn't find another int | ||
} | ||
} #end of gotit | ||
itry = itry + 1 # work on new "input" integer | ||
} # end of tries | ||
if (liveUpdate) cat('\n') # just to get a newline | ||
return(invisible(intvec )) | ||
} | ||
|
||
# Let's create a "stopFun" whose only job is to cat() a found prime without stopping the main function. | ||
# TODO: | ||
#2: see if simple unique(factorize) test works better than my goofball code | ||
#1: modify to work with either the 10^prime or the 2^prime code. | ||
# Logb x = Loga x/Loga b so log(x,mant) = log(x)/log(mant) | ||
# this will require 'mantissa' to be in the '...' of fracDo .See if neater way | ||
|
||
# cheap time test. catPrime: | ||
# user system elapsed | ||
# 64.613 0.712 65.737 | ||
# stopPrime | ||
# user system elapsed | ||
# 63.588 0.398 63.879 | ||
|
||
stopPrime <- function(x,mantissa,returnVal = 0) { | ||
mantissa = round(mantissa) # safety | ||
manfac <- factorize(mantissa) | ||
facs <- factorize(numerator(x)) # x is a bigq | ||
# cyclically remove sets of 'facs' which make up one manfac | ||
if (prod(unique(manfac) == unique(facs)) ) { | ||
# no extraneous values in factorization | ||
manle <-rle(as.numeric(manfac)) | ||
numle <- rle(as.numeric(facs)) | ||
# see if all factors are proportional quantities | ||
if (length(unique(manle$lengths/numle$lengths)) == 1) { | ||
cat(c('found ',log(numerator(x) )/log(mantissa),'\n') ) | ||
flush.console() | ||
} | ||
} | ||
return(invisible(returnVal)) # typically don't want to terminate fracDo | ||
} | ||
|
||
# catPrime <-function(x){ | ||
# # x will always be a bigq | ||
# aa <- as.numeric(unlist(strsplit(as.character(numerator(x)),''))) | ||
# if (aa[1] == 1 && sum(aa[2:length(aa)]) == 0) { | ||
# cat(c('found ',length(aa)-1),'\n') | ||
# flush.console() | ||
# } | ||
# return(invisible(0)) # Since I don't want to terminate fracDo | ||
# } | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
\name{Rfractran-package} | ||
\alias{Rfractran-package} | ||
\alias{Rfractran} | ||
\docType{package} | ||
\title{ | ||
\packageTitle{Rfractran} | ||
} | ||
\description{ | ||
\packageDescription{Rfractran} | ||
} | ||
\details{ | ||
The DESCRIPTION file: | ||
\packageDESCRIPTION{Rfractran} | ||
\packageIndices{Rfractran} | ||
FRACTRAN is an obscure yet tantalizing programming "language" | ||
invented by John Conway of "Game of Life" fame. The code consists | ||
of a sequence of fractions. The operation is simple. | ||
1 - Initalize with an integer | ||
2 - Multiply the integer by the first fraction. If an integer results, | ||
start again with the new integer. If not, try the next fraction. | ||
3 - If no such multiplication yields an integer, terminate the program. | ||
One warning: there is a FRACTRAN program that can be found on the web | ||
which is supposed to generate the digits of pi. Unfortunately, it's | ||
known to have a bug which causes it not to work. | ||
So far nobody has found a correction for it. | ||
} | ||
\author{ | ||
\packageAuthor{Rfractran} | ||
Maintainer: \packageMaintainer{Rfractran} | ||
} | ||
\references{ | ||
\url{https://esolangs.org/wiki/Fractran} | ||
\url{https://oeis.org/wiki/List_of_FRACTRAN_programs_to_compute_core_sequences} | ||
} | ||
\examples{ | ||
##Not Run | ||
# addition: { 3/2 } . Enter 2^a*3^b and get 3^(a+b) answer when terminated | ||
# multiplication: | ||
# { 455/33, 11/13, 1/11, 3/7, 11/2, 1/3 } | ||
# then enter 2^a*3^b Terminates with 5^(a*b) | ||
# prime generator (This function never terminates.) | ||
#start with 10, feed to [7/3 99/98 13/49 39/35 36/91 10/143 49/13 7/11 1/2 91/1] | ||
# and whenever the result of a run is of the form 10^p , p is prime | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
\name{fracAns} | ||
\alias{fracAns} | ||
|
||
\title{ | ||
A Q&D "Logulator" to Find Numbers of Interest From \code{fracDo} Output | ||
} | ||
\description{ | ||
In nearly all cases FRACTRAN's "result" is the exponent of some number. | ||
This function takes the logarithm of the specified base and | ||
identifies values which are integers (or nearly so, to the specified precision). | ||
} | ||
\usage{ | ||
fracAns(intvec, logbase, logprec = 1e-05) | ||
} | ||
\arguments{ | ||
\item{intvec}{ | ||
A vector of \code{bigq} values, as returned from \code{fracDo} | ||
} | ||
\item{logbase}{ | ||
The base of the desired logarithm, e.g. 2 or 10 in many cases. | ||
} | ||
\item{logprec}{ | ||
A reasonably small value used to check whether the returned double should be considered to be an integer (thus ignoring binary precision errors) | ||
} | ||
} | ||
\value{ | ||
A vector of the integer values found | ||
} | ||
\author{ | ||
Carl Witthoft <carl@witthoft.com> | ||
} | ||
\examples{ | ||
##---The prime generator doesn't terminate, so look for values. | ||
#start with 10, and result includes a series of values 10^p , p prime | ||
fracp10 <- fracMake(c(7,99,13,39,36,10,49,7,1,91), c(3,98,49,35,91,143,13,11,2,1)) | ||
p10 <-fracDo(10,fractions = fracp10, tries = 1000) | ||
foundp10 <-fracAns(p10,logbase = 10) | ||
# [1] 1 2 3 5 7 # sorry about the "1" :-) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
\name{fracDo} | ||
\alias{fracDo} | ||
%- Also NEED an '\alias' for EACH other topic documented here. | ||
\title{ | ||
The FRACTRAN Interpreter Function | ||
} | ||
\description{ | ||
This implements the FRACTRAN process, to wit | ||
For the first fraction f in the list for which nf is an integer, | ||
replace n by nf. | ||
Repeat this rule until no fraction in the list produces | ||
an integer when multiplied by n, then halt. | ||
} | ||
\usage{ | ||
fracDo(input, fractions = NULL, nums, denoms, tries = 100, | ||
stopFun = NULL, liveUpdate = TRUE, ...) | ||
} | ||
%- maybe also 'usage' for other objects documented here. | ||
\arguments{ | ||
\item{input}{ | ||
The starting integer for the given FRACTRAN code (fraction sequence) | ||
} | ||
\item{fractions}{ | ||
The sequence of fractions. Must be in \code{bigq} form. If NULL, then | ||
\code{nums} and \code{denoms} must be supplied. | ||
} | ||
\item{nums}{ | ||
Vector of integers (or \code{bigz} values ) representing the numerators | ||
of the FRACTRAN fractions. If \code{fractions} is supplied, this is ignored. | ||
} | ||
\item{denoms}{ | ||
Vector of integers (or \code{bigz} values ) representing the denominators | ||
of the FRACTRAN fractions. If \code{fractions} is supplied, this is ignored. | ||
} | ||
\item{tries}{ | ||
A 'safety' limiter on the number of times to process the next integer | ||
generated. This avoids possible infinite runs or other time-wasters. | ||
} | ||
\item{stopFun}{ | ||
Optional user-supplied function that can be used to terminate a FRACTRAN | ||
run early, or to take min-run actions such as sending information to | ||
the console. See Details for more information. | ||
} | ||
\item{liveUpdate}{ | ||
If set to TRUE, a few dots and words are sent to the console to indicate | ||
that the algorithm is still running. | ||
} | ||
\item{\dots}{ | ||
Possible additional arguments for \code{stopFun} or future use. | ||
} | ||
} | ||
\details{ | ||
Some FRACTRAN programs do not terminate, most famously the prime generators. | ||
If a specific value is being looked for, an appropriate \code{stopFun} | ||
can be supplied to check for that value. \code{stopFun} must return a | ||
single logical value (R, as always will convert numerics to logical if | ||
necessary) indicating success as TRUE. The first argument | ||
to \code{stopFun} must accept a single \code{bigq} value. | ||
If there are more arguments, they must be entered after all named | ||
arguments. Note that this function does not have to send TRUE; it could be | ||
used solely to execute other commands mid-run. | ||
See \code{\link[Rfractran]{stopPrime}} for one such example. | ||
|
||
} | ||
\value{ | ||
A vector of all the \code{bigq} values generated. | ||
These all have denominator == 1, as they are the integers found in | ||
each iteration of the FRACTRAN algorithm. | ||
} | ||
\references{ | ||
\url{https://esolangs.org/wiki/Fractran} | ||
\url{https://oeis.org/wiki/List_of_FRACTRAN_programs_to_compute_core_sequences} | ||
} | ||
\author{ | ||
Carl Witthoft <carl@witthoft.com | ||
} | ||
|
||
|
||
\seealso{ | ||
\code{\link[Rfractran]{fracMake}} | ||
} | ||
\examples{ | ||
# addition: { 3/2 } . enter 2^a*3^b and get 3^(a+b) answer when terminated | ||
addit <- fracDo(2^5*3^8,nums = 3, denoms = 2) | ||
# Last value returned is what we want. But can't take log(bigq) | ||
log(numerator(addit[length(addit)]),3) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
\name{fracMake} | ||
\alias{fracMake} | ||
%- Also NEED an '\alias' for EACH other topic documented here. | ||
\title{ | ||
Function to Create a Sequence of \code{bigq} Fractions | ||
} | ||
\description{ | ||
Feed this function a collection of numerator and denominator values; | ||
get a vector of \code{bigq} fractions suitable for use as a FRACTRAN program. | ||
} | ||
\usage{ | ||
fracMake(n, d = NULL) | ||
} | ||
%- maybe also 'usage' for other objects documented here. | ||
\arguments{ | ||
\item{n}{ | ||
Vector of integers to be used as numerators, or a Nx2 array of integers | ||
where each row contains a num, denom pair. If this is an arry, the input | ||
\code{d} is ignored. | ||
} | ||
\item{d}{ | ||
Vector of integers to be used as denominators. Ignored if \code{n} is an array | ||
} | ||
} | ||
|
||
\value{ | ||
Vector of \code{bigq} fractions. | ||
} | ||
|
||
\author{ | ||
Carl Witthoft <carl@witthoft.com> | ||
} |
Oops, something went wrong.