Validating Pilish
By Michael Doornbos
- 5 minutes read - 926 wordsHave 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
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.