This site is supported by donations to The OEIS Foundation.

# Sequence Tools

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

## Contents

## 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.