This site is supported by donations to The OEIS Foundation.

Sequence Tools

From OeisWiki
Jump to: navigation, search

This page is dedicated to links and code snippets for checking and formatting sequences.

Restricting a list to a fixed number of characters

Historically, the Data OEIS sequence entry field had enough terms to fill about three lines on the screen—maybe 260 characters including [decimal] digits, signs, commas and whitespaces (spaces and newlines; tabs NOT ALLOWED). For a larger number of terms, the contributors can submit a b-file containing an index and a term on each line and as many lines as needed.

Mathematica

(From: T.D. Noe)

OEISTrim[lst_List, maxLen_Integer: 260] :=
Module[{newLst = {}, len = 0},
Do[len = len + 2 + Length[IntegerDigits[term]] + Boole[term < 0];
 If[len <= maxLen, AppendTo[newLst, term], Break[]], {term, lst}];
newLst]

It defaults to a length of 260 characters, which seems perfect. Example: the sequence of numbers 1 to 100 is trimmed by

OEISTrim[Range[100]]

producing a list of just the first 67 numbers.

Maple

(From Peter Luschny)

OEIStrim := proc(f, offset) 
local L, n, len, fn, s, islist;
L := NULL; len := 0; 
islist := whattype(f) = list;
n := `if`(islist, 1, offset);  
do
  fn := `if`(islist, f[n], f(n));
  s  := `if`(fn <= 0, 1, 0);
  len := len + s + length(fn);
  if len > 260 then break fi;
  len := len + 2;
  L := L, fn;
  n := n + 1;
od;
L end:

Usage:

OEIStrim(n -> n, 0);

f := n -> -n: 
OEIStrim(f, 0);

F := [seq(n, n = 0..100)]:
OEIStrim(F, ignore);

Pari/GP

(from Robert Gerbicz)

{ OEISTrim(v) = 
  L=260;
  len=0;
  w=[];
  for(i=1,length(v),
    len+=3+(v[i]<0);
    x=abs(v[i])\10;
    while(x,len++;x\=10);
    if(len>L,break);
    w=concat(w,v[i]);
  );
  return(w)
}

Usage:

OEISTrim(vector(100,i,i)) 

returns the first 67 positive integers.

Alternate code:

(from MFH)

Allows to specify the desired length as a 2nd optional argument. The order of the arguments in select() changed between versions; to use in 2.4.2 change select(function, vector) to select(vector, function).

OEIS_trim(v,L=260)=local(L=L);select(t->-3<L-=#Str(t)+2,v)   \\ (correct syntax for PARI/GP version 2.4.3 and later) 

Haskell

(from Reinhard Zumkeller)

import Data.List (unfoldr)
oeisTrim xs = take (length $ unfoldr t (260, xs)) xs where
   t (_, [])                     = Nothing
   t (still, u:us) | len > still = Nothing
                   | otherwise   = Just (len, (still - len, us))
     where len = length (show u) + 2

Usage:

oeisTrim [] == []          
oeisTrim [1..] == [1..67]       
oeisTrim [1..10] == [1..10]        
oeisTrim [1..100] == [1..67]       
oeisTrim [10..1000] == [10..74]   

Sage

(from Peter Luschny)

def OEIStrim(L) :
    n = 0
    leng = 0
    T = []
    for l in L :
        s = 1 if l < 0 else 0
        leng = leng + s + len(str(l)) 
        if leng > 260 : break
        leng += 2
        T.append(l)
        n += 1
    print n, "terms"   
    return T

For example:

OEIStrim(range(100))     

GAP

(from Eric M. Schmidt)

OEISTrim := function(seq)
    local i, len;
    i := 0;
    len := -2;
    while len <= 260 do
        i := i + 1;
        if i > Length(seq) then break; fi;
        len := len + Length(String(seq[i])) + 2;
    od;
    return seq{[1..i-1]};
end;

Example:

OEISTrim([1..100]);

Formatting a b-file

An important point is the format of line ends, which should be Unix (single LF).

Mathematica

(from Charles Greathouse)

This is a basic implementation that needs polishing, but it will output a b-file given an A-number, a List, and an optional offset.

bFile[aNum_Integer, v_List, offset_Integer: 1] := 
 Module[{s = 
    OpenWrite[
     "b" <> StringTake["00000", 6 - IntegerLength[aNum]] <>
       ToString[aNum] <> ".txt"]}, 
  For[i = 1, i <= Length[v], i++, 
   WriteString[s, i + offset - 1, " ", v[[i]], "\n"]]; Close[s]]
bFile::usage = 
  "bFile[aNum, v] writes a b-file with terms given in the List v, \
using offset 1.\nbFile[aNum, v, offset] writes a b-file with the \
specified offset.";

PARI/GP

(from Charles Greathouse)

This GP script takes a name (as a string or as a number, e.g. "b000000.txt" or 0) and a vector, plus an optional offset. It outputs a b-file along with boilerplate text for inclusion into the OEIS. The created b-file follows the strict format, including the recommendation that numbers not exceed 1000 digits.

bfile(name, v, offset=1, limit=1000)={
	my(cur=offset-1);
	name = Str(name);
	while(#name < 6, name = Str(0,name));
	name = Str("b"name".txt");
	for(i=1,#v,
		if (#Str(v[i]) > limit,
			print("Next term has "#Str(v[i])" digits; exiting.");
			break
		);
		write(name, cur++" "v[i]);
	)
};
addhelp(bfile, "bfile(name, v, offset=1): Creates a b-file with the values of v for A-number name (given as a number or a filename).");

Reading b-files

PARI/GP

Unfortunately, PARI has very limited power for handling files and even strings. The following may be used to get a vector of values from a b-file, using #Axxx=b2v(readstr("/tmp/bxxx.txt")); in particular it supports empty and comment lines (starting with "#") in the b-file. The argument v is a vector of strings as it results from readstr("bxxx.txt").

b2v(v)=apply(s->for(i=2,#s=Vecsmall(s),s[i-1]>=48&&s[i]<48&&return(eval(Strchr(s[i+1..#s])))),select(s->#s>2&&Vecsmall(s)[1]!=35,v)) \\ (c) 2014 by M. F. Hasler.

Guess generating function

See also User:Charles_R_Greathouse_IV/Pari#Recurrences for snippets to detect linear recurrences.

PARI/GP

(From M. F. Hasler. IIRC, this was originally inspired by code from Max Alekseyev, but as of today I'm unable to trace back, e.g. via his page of GP scripts.)

This PARI/GP script takes a vector of at least 8 elements and looks for a (rational) generating function. In case of failure, it returns various error messages. It also does some additional checks: In particular, after computation of the g.f., it checks whether this indeed reproduces all terms of the vector.

ggf(v)={ my( p, q, B=#v\2 ); if( B<4, "Need at least 8 values!",
 if( !#q=qflll(matrix(B,B,x,y,v[x-y+B+1]),4)[1], "QFLLL returned empty result.",
  polcoeff(p=Ser(q[,1]),0)<0 && p=-p; /* adjust sign */
  q=Pol(Ser(v)*p);
  if( Ser(v)==q/=Pol(p), q,
   Str("I guessed ",q,", but it doesn't reproduce the last value!")
)))}

A drawback of this code is PARI's representation of numerator and denominator as polynomials printed in order of decreasing powers. They can be reformatted using the following snippets:

p( P )=concat( vecextract( Vec(Str( P+O(x^99) )), "..-11"))   /* write polynomial with increasing powers */

pgf( f )=Str/*or: print*/("(",p(numerator(f)),")/(",p(denominator(f)),")")  /* prettyprint rational g.f. */

Formatting a linear recurrence signature

AutoHotKey

(from Harvey P. Dale)

This script runs in the background, and when you type "indexp " it replaces those characters with a link to the recurrence index page. You can either install AutoHotKey and run this script or use the executable.