26
\$\begingroup\$

We see a lot of challenges here asking for a function to create a sequence from the OEIS. While these challenges are fun, as a programmer I see an opportunity for automation.

Your challenge is to make a program that takes the index of a sequence (e.g. A172141) and some integer n (e.g. 7), and pulls the appropriate value from the appropriate webpage.

I/O

As mentioned, your program should take a sequence index and some value n as input and output the nth term in that sequence. You accept any index in the sequence's B-files. If the index is greater than the largest index listed in the B-files you may throw an exception or output whatever you choose (these are not in the test cases). Standard methods of input and output are permitted.

Restrictions on web use

You should not access any websites other than https://oeis.org and http://oeis.org. This includes url shorteners, your own personal website, and this question itself. If you would like to access some other website and you believe that it is not unfair to allow you to do so, you can leave a comment and I will arbitrate.

Scoring

This is a code golf challenge so the program with the least bytes used in its source code wins. Standard loopholes are disallowed.

Test Cases

Assuming that your machine has proper internet connection and the OEIS servers are up and running the following inputs and outputs should correspond.

A172141, 7   -> 980
A173429, 4   -> 276
A190394, 6   -> 16
A002911, 11  -> 960
A052170, 3   -> 24
A060296, 8   -> 3
A178732, 5   -> 27
A000001, 1   -> 1
A000796, 314 -> 3
A001622, 162 -> 8
A002206, -1  -> 1

Tip

  • When accessing the B-files http://oeis.org/b<A-number>.txt will redirect to the proper B-file.
\$\endgroup\$
  • 1
    \$\begingroup\$ It's not clear to me up which indices we have to support. The last two test cases hint that we should query, e.g., oeis.org/A000796/b000796.txt rather than oeis.org/A000796/list. Is the fomer what you mean by B-files? In that case, mentioning the offset is rather superfluous. \$\endgroup\$ – Dennis Aug 10 '16 at 16:35
  • \$\begingroup\$ @Dennis Sorry I think that was the result of multiple edits over time. I will edit for clarity, \$\endgroup\$ – Wheat Wizard Aug 10 '16 at 16:38
  • \$\begingroup\$ I think this should have spent more time in the sandbox, because I'm sure it wasn't your intention that sequences without B-files should be unsupported. \$\endgroup\$ – Peter Taylor Aug 10 '16 at 18:24
  • 1
    \$\begingroup\$ @PeterTaylor according to the OeisWiki "If no b-file has been uploaded for a particular sequence, the server generates a b-file containing exactly the terms displayed, for convenience with automated tools." so there should be a B-file for every sequence. Although you may be right about prematurely moving this challenge from the sandbox. \$\endgroup\$ – Wheat Wizard Aug 10 '16 at 18:29
  • 1
    \$\begingroup\$ Well, I've learnt something useful today. \$\endgroup\$ – Peter Taylor Aug 10 '16 at 20:07

14 Answers 14

11
\$\begingroup\$

Bash + coreutils + w3m, 51 45 42 bytes

w3m oeis.org/b${1:1}.txt|sed "s/^$2 //p;d"

Thanks to @EamonOlive for golfing off 3 bytes!

Example run

$ bash oeis.sh A172141 7
980

How it works

w3m is a text-based web browser, which displays both HTML and plain text in readable format. Unlike curl, it follows redirects by default (this is required, since oeis.org/bxxxxxx.txt redirects to oeis.org/Axxxxxx/bxxxxxx.txt), doesn't produce any stray output to STDERR, and has a three-byte name.

The command

w3m oeis.org/b${1:1}.txt

the desired URL, where ${1:1} is the first command-line argument without its first character.

The output is piped to the command

sed "s/^$2 //p;d"

which extracts the desired output. s/^$2 //p attempts to replace ^$2  (start of line, followed by the second command-line argument, followed by a space) with the empty string. If the substitution is successful, p prints its result. Afterwards, d unconditionally deletes the pattern to prevent sed from printing the entire input.

\$\endgroup\$
  • \$\begingroup\$ You can save a few bytes by using oeis.org/b${1:1}.txt instead of oeis.org/$1/b${1:1}.txt \$\endgroup\$ – Wheat Wizard Aug 10 '16 at 16:35
  • \$\begingroup\$ Heh, I would normally have used sed -n ..., but that would be one more character. \$\endgroup\$ – Vatine Aug 11 '16 at 11:19
  • 1
    \$\begingroup\$ @Vatine With -n, the double quotes could be replaced with an escaped space, for the same byte count. \$\endgroup\$ – Dennis Aug 11 '16 at 17:27
3
\$\begingroup\$

Perl, 59 bytes

($_,$v)=@ARGV;/./;say`curl oeis.org/$_/b$'.txt`=~/$v (.*)/m

Needs -M5.010 or -E to run. For instance :

$ cat oeis.pl
($_,$v)=@ARGV;/./;say`curl oeis.org/$_/b$'.txt`=~/$v (.*)/m
$ perl -M5.010 oeis.pl A178932 5 2>&-
27

Saved 8 bytes thanks to @Dennis answer, by removing http://, as he did.

\$\endgroup\$
2
\$\begingroup\$

CJam, 36 bytes

"oeis.org/b"r1>+".txt"+gN%Sf%z~\ra#=

Example run

$ cjam oeis.cjam <<< 'A172141 7'
980
\$\endgroup\$
2
\$\begingroup\$

Python 2, 125 118 113 bytes

7 12 bytes saved thanks to Lynn

import re,urllib2 as u;lambda x,y:re.findall("(?<=%d ).*"%y,u.urlopen("http://oeis.org/b%s.txt"%x[1:]).read())[0]

Well heres my go at my own problem. It is likely suboptimal but I think I did a pretty decent job. It creates an anonymous function that takes a string and integer as arguments and returns a string as the result or throws an error if the index is out of range.

This can be made into a 124 bytes full program.

import re,urllib2 as u;print re.findall("(?<=%d ).*"%input(),u.urlopen("http://oeis.org/b%s.txt"%raw_input()[1:]).read())[0]

This prompts the user for the input. First asking for the index and then the A-number of the sequence.

\$\endgroup\$
  • \$\begingroup\$ Some tiny saves: import re,urllib2 as u;lambda x,y:re.search("%d (.*)\n"%y,u.urlopen("http://oeis.org/b%s.txt"%x[1:]).read()).group(1) \$\endgroup\$ – Lynn Aug 10 '16 at 16:39
  • \$\begingroup\$ And lambda x,y:re.split("%d (.*)"%y,u.urlopen("http://oeis.org/b%s.txt"%x[1:]).read())[1] is shorter still! \$\endgroup\$ – Lynn Aug 10 '16 at 16:45
2
\$\begingroup\$

Python 3, 153 146 135 bytes

7 bytes thanks to FryAmTheEggman.

6 bytes thanks to Eamon Olive.

5 bytes thanks to Rod.

from urllib.request import*
def f(a,n):
 for l in urlopen("http://oeis.org/b%s.txt"%a[1:]):
  p,q=l.split()
  if n==p.decode():return q

Call it like this:

print(f("A000796","314"))

Run on a machine where the default is utf-8.

\$\endgroup\$
  • 1
    \$\begingroup\$ In my opinion requiring a string for one argument, and a byte array for another is too lenient an input format, and you should just add the bytes required to encode into bytes yourself. Nothing about this challenge makes it reasonable to require raw bytes as input. \$\endgroup\$ – orlp Aug 10 '16 at 15:49
  • \$\begingroup\$ Can’t you change A%s to %s and then the first a[1:] to a? \$\endgroup\$ – Lynn Aug 10 '16 at 15:52
  • \$\begingroup\$ @orlp Alright, done. \$\endgroup\$ – Leaky Nun Aug 10 '16 at 15:55
  • \$\begingroup\$ @Lynn Yes, because apparently I'm stupid. \$\endgroup\$ – Leaky Nun Aug 10 '16 at 15:55
  • 1
    \$\begingroup\$ @FryAmTheEggman Yes and no. The default is the environment's locale. \$\endgroup\$ – Dennis Aug 10 '16 at 15:59
2
\$\begingroup\$

PHP 5.6, 93 92 bytes

function f($i,$l){echo explode(' ',file('http://oeis.org/b'.substr($i,1).'.txt')[--$l])[1];}

This one is pretty straight forward. Pull the page with file(), get the line at $line - 1 (0-index), explode on the space and print out the second array element from that.

\$\endgroup\$
2
\$\begingroup\$

Nim, 123 115 113 bytes

import httpclient,nre,future
(a,n)=>get getContent("http://oeis.org/b"&a[1..^0]&".txt").find re "(?<="&n&r" )\d+"

This is a lambda expression; to use it, it must be passed as an argument to a testing procedure. A complete program that can be used for testing is given here:

import httpclient,nre,future
proc test(x: (string, string) -> RegexMatch) = echo x("A172141", "7") # Your input here
test((a,n)=>get getContent("http://oeis.org/b"&a[1..^0]&".txt").find re "(?<="&n&r" )\d+")

Expects input as two strings. Example usage:

$ nim c oeis.nim
$ ./oeis
980

We use httpclient's getContent proc to get the OEIS b-file, then use a regex to find the line with the index. find returns an Option[RegexMatch], so we use get to retrieve the value from the Option. echo automatically stringifies, so we leave stringification out.

\$\endgroup\$
2
\$\begingroup\$

Mathematica + OEIS.m, 31

(OEISFunction@ToString@#;#@#2)&

example usage: %[A172141,36]


Mathematica, 85

#2/.Rule@@@Import["http://oeis.org/b"<>#~StringDrop~1<>".txt","Data"]~DeleteCases~{}&

example usage: %["A002206",-1]

\$\endgroup\$
2
\$\begingroup\$

R, 94 89 bytes

t=read.table(paste0("http://oeis.org/b",substring(scan(,""),2),".txt"));t[t$V1==scan(),2]

Using sprintf instead of paste0 results in the same bytecount:

t=read.table(sprintf("http://oeis.org/b%s.txt",substring(scan(,""),2)));t[t$V1==scan(),2]

Five bytes saved thanks to plannapus.

\$\endgroup\$
  • \$\begingroup\$ Too bad you can library(stringr) for free and use str_sub for -2 bytes ^^ \$\endgroup\$ – AlexR Aug 11 '16 at 13:52
  • \$\begingroup\$ @AlexR I don't think I can import a library for free ;-) \$\endgroup\$ – pajonk Aug 12 '16 at 17:40
  • \$\begingroup\$ Oops, there was a typo in my comment -- Too bad you can't. It was just a first thought for golfing, because stringr is one of my default packages loaded in the .Rprofile of all my projects. \$\endgroup\$ – AlexR Aug 12 '16 at 17:41
  • 1
    \$\begingroup\$ You don't need to use url, argument file of read.table can be the URL as a character string. \$\endgroup\$ – plannapus Dec 26 '16 at 10:16
  • \$\begingroup\$ @plannapus Indeed, that's right. Thanks! \$\endgroup\$ – pajonk Dec 26 '16 at 19:01
1
\$\begingroup\$

Clojure, 103

#(read-string((re-find(re-pattern(str %2" (\\d+)"))(slurp(str"http://oeis.org/b"(subs % 1)".txt")))1)))

re-find finds a vector of first matche's regex groups, it is used as a function and 1 gets the string at position 1. read-string converts string to int. I'm not 100% sure if this regex always finds the correct row.

\$\endgroup\$
1
\$\begingroup\$

R, 87 bytes

f=function(A,n)(R<-read.table(gsub("A(\\d+)","http://oeis.org/b\\1.txt",A)))[R$V1==n,2]

Build the URL string with regexes instead of paste or sprintf.

\$\endgroup\$
0
\$\begingroup\$

Node.js + request, 109 bytes

x=>n=>require('request')(`http://oeis.org/b${x.slice(1)}.txt`,(a,b)=>console.log(b.body.match(n+` (.+)`)[1]))

Takes the sequence ID and a number.

\$\endgroup\$
0
\$\begingroup\$

Julia, 88 bytes

x\y=match(Regex("$y (.*)"),readall(Requests.get("http://oeis.org/b$(x[2:end]).txt")))[1]

Golfed with some help from @Dennis!

Make sure you have Requests.jl installed before running.

\$\endgroup\$
0
\$\begingroup\$

ListSharp, 266 bytes

STRG a=READ[<here>+"\\a.txt"]
ROWS x=ROWSPLIT a BY [","]
STRG a=GETRANGE x[0] FROM [2] TO [a LENGTH]
NUMB y=<c#int.Parse(x[1])c#>
STRG a=DOWNLOAD["http://oeis.org/b"+a+".txt"]
ROWS x=ROWSPLIT a BY [<newline>]
STRG a=GETLINE x [y]
ROWS x=ROWSPLIT a BY [" "]
SHOW=x[1]

Its sad when a language made for web scraping needs so many lines because nesting statements in ListSharp is taboo

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.