We’ve all seen those number puzzles where you are given a sequence of integers and have to work out the next number in the sequence. Once you’ve got the hang of them, they tend to be pretty straightforward, involving adding some of the previous numbers in the sequence, possibly skipping one or more. There are, however, much more complex ways of generating sometimes interesting and useful sequences. In this edition of Free Data Friday, we will be looking at The Online Encyclopaedia of Integer Sequences which holds data for over a quarter of a million integer sequences of varying complexity and usefulness. We will see how you can use SAS to create custom functions to generate the nth number in a sequence. Even where there is no immediate practical value to a sequence, they can be useful for practicing your programming techniques, setting problems for trainees or even code golf type puzzles for the more experienced, so don’t dismiss any sequence out of hand.
There’s no real data which needs to be downloaded here. Instead, each encyclopaedia entry consists of a web page giving the first few numbers of a sequence along with a description, formula for calculating the sequence, cross references to other sequences, programs for generating the sequence in mathematica and other languages (but not SAS) and other information. You can also search for a particular sequence or request a random sequence to be displayed.
In this 9-minute tutorial, SAS instructor @DomWeatherspoon shows you how to get your data into SAS OnDemand for Academics and other key steps:
We’re going to choose two sequences to show the process of creating custom SAS functions to generate the nth number in each sequence.
A triangular number is a number that can be represented by a pattern of dots arranged in an equilateral triangle. For example, 1, 3, 6 and 10 are all triangular numbers.
We can use the following code to create a function which calculates a triangular number.
proc fcmp outlib=work.maths.intseqs; function gettriangular(n); retval=n*(n+1)/2; return(retval); endsub; run; options cmplib=work.maths; data triangular; do i=0 to 53; triangular=gettriangular(i); output; end; run;
As you can see the data step generates the first 54 triangular numbers (starting at zero). You can check the output against the list supplied in the encyclopaedia.
We are using the FCMP Procedure with the outlib option. This saves the function to the specified library, dataset and package removing the need to regenerate the function every time you need to use it if you save it to a permanent library (as here I usually save to the temporary work library when I am developing functions). However, I strongly recommend saving the source code in case the dataset gets lost or accidentally deleted.
Triangular numbers have quite a few different uses including solving “handshake problems” e.g. In a room of x number of people how many unique handshakes must take place before everyone is introduced to everyone else?
Padovan numbers are defined by the following sequence and have applications in number theory and architecture.
This is much more complex to program as in order to calculate a number in the sequence beyond P(2) we need to know two other numbers in the sequence, which are themselves also Padovan numbers. We could, of course, calculate the full sequence of numbers every time we run the function but that would be very inefficient. Instead we will store all previously calculated numbers in a hash object and check to see if we have already calculated the required numbers. If we have, we will use them, if not then the function will call itself in a process known as recursion.
Here is the code (I've tried to make it and the comments as easy to follow as possible).
proc fcmp outlib=work.maths.intseqs; function padovan(n); /* Create a hash table - this persists for the life of */ /* the data step in which it will be called. It will */ /* NOT be recreated on subsequent calls within the */ /* data step */ declare hash h(); rc=h.definekey("seqno"); rc=h.definedata("padno"); rc=h.definedone(); /* Set the first 3 padovan numbers */ seqno=n; if n=0 then do; notfound=h.check(); if notfound ne 0 then do; padno=1; rc=h.add(); end; retval=padno; end; else if n=1 then do; notfound=h.check(); if notfound ne 0 then do; padno=0; rc=h.add(); end; retval=padno; end; else if n=2 then do; notfound=h.check(); if notfound ne 0 then do; padno=0; rc=h.add(); end; retval=padno; end; /* Calculate subsequent padovan numbers */ else do; seqno=n-2; notfound=h.find(); if notfound ne 0 then do; /* The Function calls itself recursively */ padno=padovan(seqno); rc=h.add(); end; prev=padno; seqno=n-3; notfound=h.find(); if notfound ne 0 then do; /* The Function calls itself recursively */ padno=padovan(seqno); rc=h.add(); end; prevprev=padno; retval=prev+prevprev; end; num=h.num_items(); return(retval); endsub; run; options cmplib=work.maths; /* Calculate a single Padovan Number */ data padosingle; i=30; b=padovan(i); run; /* Calculate a sequence of Padovan numbers */ data test; do i=0 to 60; b=padovan(i); output; end; run;
There are two things to note:
Again, you can check the output from the list in the encyclopaedia.
Did you find a better way to generate these sequences or another really interesting sequence in the encyclopaedia? Share in the comments. I’m glad to answer any questions.
Hit the orange button below to see all the Free Data Friday articles.
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.