Validating Pilish

Validating Pilish

Have you ever sat down at your old Olympia typewriter and felt compelled to write poetry in which each word is the same length as successive digits of Pi?

Me too!!!

This is called a Pilish:

The idea of writing a sentence (or longer piece of poetry or prose) in which the lengths of successive words represent the digits of the number π (=3.14159265358979...) has been around since the early 1900's. - Writing in Pilish

If you have, then David Amos's Curious About Code (currently requires an invitation) has a puzzle for you! David runs a coding enthusiasts group and posts a weekly puzzle for members to work on and share approaches.

Naturally, this is in our wheelhouse, and the temptation to do these on vintage computers is strong. David has been doing challenges in one form or another for years. Last year I did the Border Crossings challenge on Commodore hardware.

I'm going to plagiarize his actual puzzle description to save some time and keep from introducing any ambiguity:

The Challenge

Given a string of arbitrary length, determine whether or not the string is valid Pilish.

Some assumptions:

  • The string always starts at the beginning of the digits of π
  • A “word” is a maximal unit of text not containing a whitespace character
  • A “letter” is any character that isn’t punctuation

For example "don't" is a word with five characters but only four letters. So, in Pilish, the length of "don't" is four.

A Test Case

Here’s a string that should pass your Pilish test:

But a time I spent wandering in gloomy night; Yon tower, tinkling chimewise, loftily opportune. Out, up, and together came sudden to Sunday rite, The one solemnly off to correct plenilune.

Excerpt from Playing With Words by Joseph Shipley.

My solution in Julia

There are some clever solutions in David's group, you should check them out. I decided to try a different (maybe less elegant) approach in Julia:

phrase = "But a time I spent wandering in gloomy night; Yon tower, tinkling chimewise, loftily opportune. Out, up, and together came sudden to Sunday rite, The one solemnly off to correct plenilune."

phrase = replace(phrase,r"[\n,.:;?!()]"=>"")
phrase = split(phrase, " ")

setprecision(BigFloat, 1024) do
    pi1024 = filter(!ispunct, string(BigFloat(pi)));
    for (i,word) in enumerate(phrase)
        if length(word) != parse(Int8, pi1024[i])
            println("Not a Pilish")
            break
        end
    end
end

And now for the star of the show

Removing line 17 here will save you 20 minutes for a Commodore 64 to generate the first 254 digits of Pi and use the prefilled strings in lines 20-35. Up to you.

1 rem phish in basic
5 ti$="000000"
10 printchr$(14): rem switch to lowercase/mixed
17 gosub 3000: goto 100: rem generate
20 p$="3141592653589793238462643383279502884197169399375105820974944592307816"
25 p1$="4062862089986280348253421170679821480865132823066470938446095505822317"
30 p2$="2535940812848111745028410270193852110555964462294895493038196442881097"
35 p3$="566593344612847564823378678316527120190914564"
40 p$=p$+p1$+p2$+p3$
100 s1$="But a time I spent wandering in gloomy night; "
102 s2$="Yon tower, tinkling chimewise, loftily opportune. Out, up, and "
105 s3$="together came sudden to Sunday rite, The one solemnly off "
106 s4$="to correct plenilune"
110 s$=s1$+s2$+s3$+s4$
120 gosub 1000
130 printss$
140 wc = 1:rem word counter
150 gosub 2000
160 print "Looks like a phish to me."
170 gosub 5000
199 end
1000 rem strip string
1010 for i=1tolen(s$)
1020 c=asc(mid$(s$,i,1))
1025 if c = 32 then 1050
1030 if c > 64 and c<91 or c>192and c<219 then 1050
1040 goto 1060
1050 ss$=ss$+chr$(c)
1060 next 
1099 return
2000 rem check for phish
2010 for i=1tolen(ss$)
2020 c$=mid$(ss$,i,1)
2030 if c$=" "then gosub4000:w$="":next:rem go to next word
2040 w$=w$+c$
2050 next 
2099 return
3000 rem pi
3020 n = 254: rem more really slows this down
3030 ln = int(10*n/3)+16
3040 nd = 1
3050 dim a(ln)
3060 n9 = 0
3070 pd = 0:rem first pre-digit is a 0
3080 rem
3090 for j = 1 to ln
3100    a(j-1) = 2:rem start with 2s
3110 next j
3120 rem
3130 for j = 1 to n
3140     q = 0
3150     for i = ln to 1 step -1:rem work backwards
3160         x = 10*a(i-1) + q*i
3170         a(i-1) = x - (2*i-1)*int(x/(2*i-1)):rem x - int ( x / y) * y
3180         q = int(x/(2*i - 1))
3190     next i
3200     a(0) = q-10*int(q/10)
3210     q = int(q/10)
3220     if q=9 then n9 = n9 + 1: goto 3450
3240     if q<>10 then goto 3350
3250     rem q == 10
3260        d = pd+1: gosub 3500
3270        if n9 <= 0 then goto 3320
3280           for k = 1 to n9
3290              d = 0: gosub 3500
3300           next k
3310        rem end if
3320        pd = 0
3330        n9 = 0
3335        goto 3450
3340     rem q <> 10
3350        d = pd: gosub 3500
3360        pd = q
3370        if n9 = 0 then goto 3450
3380           for k = 1 to n9
3390              d = 9: gosub 3500
3400           next k
3410           n9 = 0
3450 next j
3460 print(pi$)
3470 return : rem we are done
3500 rem make string
3510 if d=0 then return
3520 print mid$(str$(d),2);
3530 p$=p$+mid$(str$(d),2)
3550 return
4000 rem check against pi
4005 rem debug print len(w$),val(mid$(p$,wc,1)), wc
4010 if len(w$) = val(mid$(p$,wc,1))then wc=wc+1:return
4020 print"Not a phish, sorry"
4030 gosub 5000
4099 end
5000 rem time it
5010 print"took"ti/60"seconds"
5099 return
0:00
/
Yes, the Phish/Pilish "typo" was intentional. Keep your pantyhose on

Join the fun

I'd highly recommend joining a small(ish) coding group and working on these problems with more than one platform. Sometimes slow computers are better at seeing how things work.

And check out David's site. He's awesome.