Write a program that defines a function that can check if a string variable called "anything you want or inputted by the user" is or not a piem. (piem = a story or poem in which the word lengths represent the digits of π (from Wikipedia))

Some examples:

myfunction("I am clearly wrong") # False
myfunction("How I want a drink, alcoholic of course, after the heavy lectures involving quantum mechanics") #True (Taken from Wikipedia)
myfunction("Law ' s fine") # True

You should delete any kind of punctuation or newline before processing. Pure code golf, the shortest wins

End date: evening of 1/10/2014

Various answers

  • How many digits do we need to handle? More than 10
  • As a matter of interest, how should 0's in PI be interpreted? Skipped or 10 letter words? As 10 letters words
  • "a variable called piem" – so the name of the parameter must be piem? No, it hasn't, question text corrected
  • A fun bonus might be a solution that is itself a piem If your solution is a piem you get *0.5 bonus
  • For the sake of argument, is _ always punctuation? You can decide if it is punctuation or if it isn't
  • It's unclear what is meant by "any kind of punctuation" I mean ,.'"?!;;()
  • So digits should be counted? And Law's fine would be false? Digits should be treated as letters, Law's fine = False; Law ' s fine = True


  • The APL solution should be counted in Bytes
  • If your solution works for 100+ digits of pi you get *0.8 bonus
  • Because of the great interest the end date is one day more in the future.
  • 6
    \$\begingroup\$ How many digits do we need to handle? \$\endgroup\$ – marinus Sep 28 '14 at 9:18
  • 5
    \$\begingroup\$ "a variable called piem" – so the name of the parameter must be piem? That renders all current answers incorrect. \$\endgroup\$ – Ingo Bürk Sep 28 '14 at 11:37
  • 2
    \$\begingroup\$ A fun bonus might be a solution that is itself a piem. \$\endgroup\$ – britishtea Sep 28 '14 at 13:36
  • 5
    \$\begingroup\$ As a matter of interest, how should 0's in PI be interpreted? Skipped or 10 letter words? \$\endgroup\$ – MickyT Sep 29 '14 at 1:38
  • 3
    \$\begingroup\$ It's kind of a shame that you don't reply to very important questions, yet you already edited in an end date. \$\endgroup\$ – Ingo Bürk Sep 29 '14 at 14:53

12 Answers 12


APL (39)

{N≡(≢N←≢¨('\w+'⎕S'\0')⍵)↑⍎¨'_. '~⍨99⍕○1}

It uses all the digits the APL interpreter's pi constant provides, to a limit of 99. In my case (Dyalog APL 14 32-bit) that was 16 digits. The 64-bit version likely has more digits. 16 digits is enough for the given examples to work, though.

Strings that have more than that amount of words will fail, even if all the digits it could check were true. (The same is true of other posts, as of this writing.) For example, if there were only 10 digits, the 'How I want a drink' one would fail. This can be fixed, but at the cost of 14 characters:

{(≢¨('\w+'⎕S'\0')⍵){∧/(⌊/≢¨⍺⍵)↑∨⌿⍺∘.=⍵}⍎¨'_. '~⍨99⍕○1}

That version will accept any string where the first N digits are correct.

  • \$\begingroup\$ Your code is the shortes but it is not Unicode... I'll have to think about if you deserve the win or not, the javascript version is just a little bit longer than this... Anyway I upvoted this answer. \$\endgroup\$ – Caridorc Sep 29 '14 at 11:56
  • 1
    \$\begingroup\$ @marinus The question doesn't specify whether submissions should be scored by characters or bytes, but the default is bytes (as per the tag wiki), so I think your score is closer to 60. \$\endgroup\$ – Martin Ender Sep 29 '14 at 13:48
  • 1
    \$\begingroup\$ Given the right encoding it's 1 byte per character. APL predates Unicode by decades after all. \$\endgroup\$ – marinus Sep 29 '14 at 13:51
  • 1
    \$\begingroup\$ @marinus Fair point! Do you know any particular (existing) encoding in which that would actually work? \$\endgroup\$ – Martin Ender Sep 29 '14 at 14:16
  • 2
    \$\begingroup\$ @MartinBüttner: IBM codepage 907 is one, but there are loads. \$\endgroup\$ – marinus Sep 29 '14 at 17:10

JavaScript (169)(140)(137)(135) (63)for 17 digits of pi

In my version Law's fine and Law ' s fine return both true.

Newest Version (63) by Ingo Bürk and hsl


New Version (135) for 17 digits of pi (Thanks to Ingo Bürk):

s=s.split(/[!"#$%&'()*+, \-.\/:;<=>?@[\\\]^_`{|}~]+/);
    return !r

Old version (169) for 32 digits of pi:

s=s.split(/[!"#$%&'()*+, \-.\/:;<=>?@[\\\]^_`{|}~]+/);
    return r;
  • \$\begingroup\$ You can save 3 bytes with: 1e15*Math.PI+"2384626433832795" \$\endgroup\$ – xem Sep 28 '14 at 11:25
  • \$\begingroup\$ Thanks=) In meantime i changed it using this idea but now only using the first 17 digits. \$\endgroup\$ – flawr Sep 28 '14 at 11:41
  • \$\begingroup\$ @IngoBürk Thank you very much, just checking what works. \$\endgroup\$ – flawr Sep 28 '14 at 11:41
  • \$\begingroup\$ Sorry, never mind. That doesn't seem to work. :/ The for loop can't be added this way. \$\endgroup\$ – Ingo Bürk Sep 28 '14 at 11:43
  • \$\begingroup\$ But what does work is initializing r=0 and then just looping over r+=s[a].length!=p[a] (you can omit the ; in the end). Then, return !r. \$\endgroup\$ – Ingo Bürk Sep 28 '14 at 11:49

Ruby, 113 101 79 (98 * 0.8)



  • Input is taken as the argument to a lambda. It expects a String.
  • Pi is calculated up to 999 decimals and turned into a String with the . removed.
  • Punctuation marks are removed from the poem and it is split into individual words. "Let's" is counted as two words: "Let" and "s".
  • Use Array#map to convert each word to the size of the word, concatenate them into a String.
  • Using a Regexp, check if the two created Strings begin with the same characters.

I have applied the bonus for handling 100+ digits. _ is not handled as punctuation in this solution.

  • \$\begingroup\$ Note that you're not treating _ as punctuation. \$\endgroup\$ – Martin Ender Sep 28 '14 at 13:24
  • \$\begingroup\$ Well spotted. For the sake of argument, is _ always punctuation? What about sentences such as My nickname on Stack Overflow is britishtea_500. \$\endgroup\$ – britishtea Sep 28 '14 at 13:30
  • \$\begingroup\$ It was just an observation. The OP isn't exactly specific about the details here. \$\endgroup\$ – Martin Ender Sep 28 '14 at 13:31
  • \$\begingroup\$ Fair enough. I'll leave the answer up for now until it's specified in the problem :) \$\endgroup\$ – britishtea Sep 28 '14 at 13:36
  • \$\begingroup\$ Using bigdecimal you have no limit on PI digits? Nice (+1) \$\endgroup\$ – edc65 Sep 28 '14 at 14:45

Mathematica, 123 bytes * 0.8 = 98.4

"->""]/. 10->0]]==d&;

Almost the longest submission so far, but:

  • It works for any number of digits of Pi.
  • It removes all the required ASCII characters and the line break, without splitting the words in those places.
  • It handles 0-digits in Pi correctly (as 10-letter words)
  • \$\begingroup\$ if it works for number of digits of Pi you get a 0.8 bonus \$\endgroup\$ – Caridorc Sep 30 '14 at 11:50

Python - 130 127 116 - 17 digits of pi

As in @flawr 's answer, Law ' s fine and Law's fine both return True.

Thanks to @Emil for removing 12 characters from the program.

import re
f=lambda x:all(j==int("31415926535897932"[i])for i,j in enumerate([len(s)for s in re.findall("[\w]+",x)]))
  • \$\begingroup\$ You can save 12 characters by not saving l in a variable and by defining the function using lambda. \$\endgroup\$ – Emil Sep 28 '14 at 12:26

Java, 185

boolean f(String...s){s=s[0].replaceAll("\\W","~").replaceAll("~+","~").split("~");for(int i=0;i<s.length;){if(s[i].length()!=(int)(Math.PI*Math.pow(10,i++)%10))return 0>1;}return 1>0;}

python 3, 17 digits of pi, 104

import re;f=lambda s:all(map(int.__eq__, map(int, '31415926535897932'), map(len,re.findall('[\w]+',s))))
  • \$\begingroup\$ You can replace the ; with a newline for readability. Also, a number of spaces can be removed. \$\endgroup\$ – tomsmeding Oct 2 '14 at 11:11

Python 3 - 129

Doesn't account for punctuation:

import math
f=lambda p:all(1if len(p.split(' ')[i])!=int(str(math.pi).replace('.','')[i])else 1for i in range(len(p.split(' '))))

T-SQL 488 383

And now for a large T-SQL solution :)

CREATE FUNCTION F(@s VARCHAR(MAX))RETURNS CHAR(6) AS BEGIN DECLARE @ CHAR='T',@p VARCHAR(50)='31415926535897932384626433832795028841971693993751',@i INT=0WHILE @='T'AND @s<>''BEGIN SET @i=PATINDEX('%[^a-z0-9]%',@s)IF @i=0RETURN'#True'IF @i-1<>LEFT(@p,1)RETURN'#False'SET @p=STUFF(@p,1,1,'')SET @s=STUFF(@s,1,@i,'')SET @s=STUFF(@s,1,PATINDEX('%[a-z0-9]%',@s)-1,'')END RETURN'#True'END

This creates an inline table valued function that uses a recursive CTE to detect word boundaries.

Creates a scalar function that chews it's way through the words and PI to 31 decimals (first 0). It is called in the following way

SELECT dbo.f('SQL I golf, a large procedure is normal. Hefty not terse') --#True

CJam, 40


It's unclear what is meant by "any kind of punctuation"; this solution removes the ,.'"?!;; characters.


Bash and unix tools, 111

f() { grep ^"$(echo "$@"|grep -Po '[\w]+'|xargs -n1 sh -c 'echo ${#0}'|xargs|tr -d ' ')"<<<31415926535897932; 

NodeJS 32 digits 230 Bytes

I can't get it shorter with JS :D

var p = "31415926535897932384626433832795", i = 0;
console.log(process.argv[2].split(/[\s,.]+/).every(function(w) {
    if (parseInt(p.charAt(i)) !== w.length) {
        return false;
    return true;
}) ? 'True' : 'False');
  • \$\begingroup\$ remove whitespace. \$\endgroup\$ – Rohan Jhunjhunwala Jan 2 '17 at 1:49

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.