## Introduction

You use Twitter (let's pretend, if not), where you are limited to 140 characters per individual tweet you care to share with the world. If you wanted to tweet to your followers Abraham Lincoln's Gettysburg Address, then you would need to break up the text into multiple 140-character chunks in order to get the whole message out. However, those chunks should not always be exactly 140 characters long. Say for example, we broke the speech into 17-character chunks, we'd end up with these tweets:

• FOUR SCORE AND SE
• VEN YEARS AGO OUR
• FATHERS BROUGHT
• FORTH ON THIS CON
• TINENT A NEW NATI
• ON CONCEIVED IN L
• (and so on)

That's no good! When individual words are broken up, then it can get difficult to understand what you are trying to say. Also, in the twitterverse, one of your followers may come across a specific tweet and not realize that there's more to the message, so you'll want to number your tweets so they have some context to work with (still using 17-character chunks):

• (1/7) FOUR SCORE AND
• (2/7) SEVEN YEARS AGO
• (3/7) OUR FATHERS
• (4/7) BROUGHT FORTH ON
• (5/7) THIS CONTINENT A
• (6/7) NEW NATION
• (7/7) CONCEIVED IN...

You could manually figure out the best configuration for your tweets by hand, but that's what we have computers for!

## Challenge

In the shortest code possible, parse the Gettysburg Address (or any text, but we'll stick with this one as an example) into a set of tweets consisting of no more than 140 characters (assume ASCII, since our example text should not have any uncommon/unusual bits in it).

## Details

• Your function/program/etc should take in a single string argument and output one line of text for each tweet.
• Assume this input will never result in more than 99 total tweets when parsed, regardless of how you choose to parse (so long as that choice still fits the other points of the challenge).
• Tweets need to include a tweet number of total tweets indicator in the format "(x/y)" preceding the body of the tweet.
• This count will take up part of your 140-character space!
• Tweet chunks may only be split on newlines or spaces.
• No hyphens, periods, commas or other punctuation is allowed, unless immediately preceded or followed by a space or newline.
• Tweets should consist of as many complete words as possible.
• This constraint is a little flexible, e.g. when your final tweet only has one word
• This is code golf, so the shortest code wins.

## Full Text of Gettysburg Address

(Your code should still be able to handle any ASCII string passed to it.)

FOUR SCORE AND SEVEN YEARS AGO OUR FATHERS BROUGHT FORTH ON THIS CONTINENT A NEW NATION CONCEIVED IN LIBERTY AND DEDICATED TO THE PROPOSITION THAT ALL MEN ARE CREATED EQUAL. NOW WE ARE ENGAGED IN A GREAT CIVIL WAR TESTING WHETHER THAT NATION OR ANY NATION SO CONCEIVED AND SO DEDICATED CAN LONG ENDURE. WE ARE MET ON A GREAT BATTLEFIELD OF THAT WAR. WE HAVE COME TO DEDICATE A PORTION OF THAT FIELD AS A FINAL RESTING PLACE FOR THOSE WHO HERE GAVE THEIR LIVES THAT THAT NATION MIGHT LIVE. IT IS ALTOGETHER FITTING AND PROPER THAT WE SHOULD DO THIS. BUT IN A LARGER SENSE WE CAN NOT DEDICATE, WE CAN NOT CONSECRATE, WE CAN NOT HALLOW, THIS GROUND. THE BRAVE MEN LIVING AND DEAD WHO STRUGGLED HERE HAVE CONSECRATED IT FAR ABOVE OUR POOR POWER TO ADD OR DETRACT. THE WORLD WILL LITTLE NOTE NOR LONG REMEMBER WHAT WE SAY HERE BUT IT CAN NEVER FORGET WHAT THEY DID HERE. IT IS FOR US THE LIVING RATHER TO BE DEDICATED HERE TO THE UNFINISHED WORK WHICH THEY WHO FOUGHT HERE HAVE THUS FAR SO NOBLY ADVANCED. IT IS RATHER FOR US TO BE HERE DEDICATED TO THE GREAT TASK REMAINING BEFORE US, THAT FROM THESE HONORED DEAD WE TAKE INCREASED DEVOTION TO THAT CAUSE FOR WHICH THEY GAVE THE LAST FULL MEASURE OF DEVOTION, THAT WE HERE HIGHLY RESOLVE THAT THESE DEAD SHALL NOT HAVE DIED IN VAIN, THAT THIS NATION UNDER GOD SHALL HAVE A NEW BIRTH OF FREEDOM, AND THAT GOVERNMENT OF THE PEOPLE BY THE PEOPLE FOR THE PEOPLE SHALL NOT PERISH FROM THE EARTH.

• In your example tweets, you've broken words -- but in the rules, you say not to. Please make this consistent -- either change the rules or the examples. Mar 16, 2013 at 22:23
• @boothby Well, the example is to explicitly show what's not allowed... I'll see if I can't re-word that. Mar 16, 2013 at 22:23
• Please clarify the question to make it clear whether or not answers must deal with possibility of having to recompute word -> tweet packings due to the (X/Y) part. This makes the problem significantly harder and introduces a cap on the largest message one may communicate without encoding data in the (X/Y) part. Mar 16, 2013 at 23:51
• @rmckenzie Sorry, not sure if I get you? You mean to account for the fact that you could have 100+ tweets in a set? Mar 17, 2013 at 0:26
• @Gaffi - Yes, is there a maximum number of parts into which our messages will be divided (in which cases assumptions may be made and grc's sol is valid) or do we have to support the general case such as serializing a multi-thousand word to a tweet which your problem statement as is suggests. Mar 17, 2013 at 0:33

## Python, 140

^ 140 chars was actually a coincidence.

def f(s):
s=s.split();i=0;l=[]
while s:
i+=1;t='(%d/%%d)'%i
while s and len(t+s[0])<140:t+=' '+s.pop(0)
l+=[t]
for t in l:print t%i


While there are words left, the solution will create new tweets from the supply of words and append them to a list. For each tweet, it will keep trying to add words until the tweet's length reaches over 140 characters. Two characters are reserved for the total tweets, which are filled in later as each tweet in the list is printed.

Example output:

(1/11) FOUR SCORE AND SEVEN YEARS AGO OUR FATHERS BROUGHT FORTH ON THIS CONTINENT A NEW NATION CONCEIVED IN LIBERTY AND DEDICATED TO THE
(2/11) PROPOSITION THAT ALL MEN ARE CREATED EQUAL. NOW WE ARE ENGAGED IN A GREAT CIVIL WAR TESTING WHETHER THAT NATION OR ANY NATION SO
(3/11) CONCEIVED AND SO DEDICATED CAN LONG ENDURE. WE ARE MET ON A GREAT BATTLEFIELD OF THAT WAR. WE HAVE COME TO DEDICATE A PORTION OF THAT
(4/11) FIELD AS A FINAL RESTING PLACE FOR THOSE WHO HERE GAVE THEIR LIVES THAT THAT NATION MIGHT LIVE. IT IS ALTOGETHER FITTING AND PROPER
(5/11) THAT WE SHOULD DO THIS. BUT IN A LARGER SENSE WE CAN NOT DEDICATE, WE CAN NOT CONSECRATE, WE CAN NOT HALLOW, THIS GROUND. THE BRAVE
(6/11) MEN LIVING AND DEAD WHO STRUGGLED HERE HAVE CONSECRATED IT FAR ABOVE OUR POOR POWER TO ADD OR DETRACT. THE WORLD WILL LITTLE NOTE NOR
(7/11) LONG REMEMBER WHAT WE SAY HERE BUT IT CAN NEVER FORGET WHAT THEY DID HERE. IT IS FOR US THE LIVING RATHER TO BE DEDICATED HERE TO THE
(8/11) UNFINISHED WORK WHICH THEY WHO FOUGHT HERE HAVE THUS FAR SO NOBLY ADVANCED. IT IS RATHER FOR US TO BE HERE DEDICATED TO THE GREAT
(9/11) TASK REMAINING BEFORE US, THAT FROM THESE HONORED DEAD WE TAKE INCREASED DEVOTION TO THAT CAUSE FOR WHICH THEY GAVE THE LAST FULL
(10/11) MEASURE OF DEVOTION, THAT WE HERE HIGHLY RESOLVE THAT THESE DEAD SHALL NOT HAVE DIED IN VAIN, THAT THIS NATION UNDER GOD SHALL HAVE
(11/11) A NEW BIRTH OF FREEDOM, AND THAT GOVERNMENT OF THE PEOPLE BY THE PEOPLE FOR THE PEOPLE SHALL NOT PERISH FROM THE EARTH.

• It was exactly what I needed. This solution is cool. Thanks @grc Jun 9, 2014 at 8:17

Perl, 51 Characters

s#\G(.{1,132})(\s+|$)#(${\++$a}/~)$1\n#g;s#~#$a#g  Requires -p command line prompt, 1 char included. Explanation: insert the count portion before and newline after word groups of up to 132 characters. Insert a placeholder (~) for the total, which is then replaced by a second substitution. This breaks if the message contains ~, but one could easily use an unprintable character instead. It cheats slightly: it always allows seven characters for the count portion, (nn/nn). Really, if it is (n/n) it should allow two extra characters. However, an arbitrary solution to this would greatly increase the complexity of the problem. • \G is useless here, isn't it? Feb 5, 2014 at 10:32 ### Ruby, 77 characters f=->t{i=0;$><<t.gsub(/(.{1,132})([ \n]|$)/m){"(#{i+=1}/%{i}) #{$1}\n"}%{i:i}}


Packed the logic into a single regular expression. Output of f[text]:

(1/11) FOUR SCORE AND SEVEN YEARS AGO OUR FATHERS BROUGHT FORTH ON THIS CONTINENT A NEW NATION CONCEIVED IN LIBERTY AND DEDICATED TO THE
(2/11) PROPOSITION THAT ALL MEN ARE CREATED EQUAL. NOW WE ARE ENGAGED IN A GREAT CIVIL WAR TESTING WHETHER THAT NATION OR ANY NATION SO
(3/11) CONCEIVED AND SO DEDICATED CAN LONG ENDURE. WE ARE MET ON A GREAT BATTLEFIELD OF THAT WAR. WE HAVE COME TO DEDICATE A PORTION OF
(4/11) THAT FIELD AS A FINAL RESTING PLACE FOR THOSE WHO HERE GAVE THEIR LIVES THAT THAT NATION MIGHT LIVE. IT IS ALTOGETHER FITTING AND
(5/11) PROPER THAT WE SHOULD DO THIS. BUT IN A LARGER SENSE WE CAN NOT DEDICATE, WE CAN NOT CONSECRATE, WE CAN NOT HALLOW, THIS GROUND. THE
(6/11) BRAVE MEN LIVING AND DEAD WHO STRUGGLED HERE HAVE CONSECRATED IT FAR ABOVE OUR POOR POWER TO ADD OR DETRACT. THE WORLD WILL LITTLE
(7/11) NOTE NOR LONG REMEMBER WHAT WE SAY HERE BUT IT CAN NEVER FORGET WHAT THEY DID HERE. IT IS FOR US THE LIVING RATHER TO BE DEDICATED
(8/11) HERE TO THE UNFINISHED WORK WHICH THEY WHO FOUGHT HERE HAVE THUS FAR SO NOBLY ADVANCED. IT IS RATHER FOR US TO BE HERE DEDICATED TO
(9/11) THE GREAT TASK REMAINING BEFORE US, THAT FROM THESE HONORED DEAD WE TAKE INCREASED DEVOTION TO THAT CAUSE FOR WHICH THEY GAVE THE
(10/11) LAST FULL MEASURE OF DEVOTION, THAT WE HERE HIGHLY RESOLVE THAT THESE DEAD SHALL NOT HAVE DIED IN VAIN, THAT THIS NATION UNDER GOD
(11/11) SHALL HAVE A NEW BIRTH OF FREEDOM, AND THAT GOVERNMENT OF THE PEOPLE BY THE PEOPLE FOR THE PEOPLE SHALL NOT PERISH FROM THE EARTH.


## Ruby, 75

Can't beat Perl, but at least it marginally beats the other Ruby solution. Note that it prints the tweets in reverse order (the problem does not specify one).

f=->t,i=1{t=~/\S.{,130}\S(?!\S)/?puts("(#{i}/%d) #$&"%n=f[$',i+1])||n :i-1}

• Hm... I suppose I did not specify the order. Good job hijacking the rules. ;-) Mar 20, 2013 at 19:12

## VBA, 251

Tried another method... Not quite as good as my original, but I'm still working on it...

Sub a(s)
Dim n(99)
m=1
r=Split(StrConv(s,64),Chr(0))
For i=0 To Len(s)
If i-g>132 Then n(m)=Mid(s,g+1,u-g):i=u:g=i:m=m+1
If r(i)=" " Or r(i)=vbCr Then i=i+1:u=i
Next
n(m)=Mid(s,g+1)
For o=1 To m
Debug.Print "(" & o & "/" & m & ") " & n(o)
Next
End Sub


Outputs:

(1/11) FOUR SCORE AND SEVEN YEARS AGO OUR FATHERS BROUGHT FORTH ON THIS CONTINENT A NEW NATION CONCEIVED IN LIBERTY AND DEDICATED TO THE
(2/11) PROPOSITION THAT ALL MEN ARE CREATED EQUAL. NOW WE ARE ENGAGED IN A GREAT CIVIL WAR TESTING WHETHER THAT NATION OR ANY NATION SO
(3/11) CONCEIVED AND SO DEDICATED CAN LONG ENDURE. WE ARE MET ON A GREAT BATTLEFIELD OF THAT WAR. WE HAVE COME TO DEDICATE A PORTION OF
(4/11) THAT FIELD AS A FINAL RESTING PLACE FOR THOSE WHO HERE GAVE THEIR LIVES THAT THAT NATION MIGHT LIVE. IT IS ALTOGETHER FITTING AND
(5/11) PROPER THAT WE SHOULD DO THIS. BUT IN A LARGER SENSE WE CAN NOT DEDICATE, WE CAN NOT CONSECRATE, WE CAN NOT HALLOW, THIS GROUND. THE
(6/11) BRAVE MEN LIVING AND DEAD WHO STRUGGLED HERE HAVE CONSECRATED IT FAR ABOVE OUR POOR POWER TO ADD OR DETRACT. THE WORLD WILL LITTLE
(7/11) NOTE NOR LONG REMEMBER WHAT WE SAY HERE BUT IT CAN NEVER FORGET WHAT THEY DID HERE. IT IS FOR US THE LIVING RATHER TO BE DEDICATED
(8/11) HERE TO THE UNFINISHED WORK WHICH THEY WHO FOUGHT HERE HAVE THUS FAR SO NOBLY ADVANCED. IT IS RATHER FOR US TO BE HERE DEDICATED TO
(9/11) THE GREAT TASK REMAINING BEFORE US, THAT FROM THESE HONORED DEAD WE TAKE INCREASED DEVOTION TO THAT CAUSE FOR WHICH THEY GAVE THE
(10/11) LAST FULL MEASURE OF DEVOTION, THAT WE HERE HIGHLY RESOLVE THAT THESE DEAD SHALL NOT HAVE DIED IN VAIN, THAT THIS NATION UNDER GOD
(11/11) SHALL HAVE A NEW BIRTH OF FREEDOM, AND THAT GOVERNMENT OF THE PEOPLE BY THE PEOPLE FOR THE PEOPLE SHALL NOT PERISH FROM THE EARTH.


# BASH (88 Chars)

fold -132 -s |tac|cat -n |tac|awk '{if(NR==1)a=$1;$1="";printf "(%d/%d) %s\n",NR,a,$0 }'  Fold the line at 132 characters (to allow for our tweet count), on spaces (-s), Read text backwards (tac), number the text (cat -n), re-reverse (tac). Inside Awk: First line (NR==1), assign the letter 'a' the value in the first . Blank the number column. Print (NR/'a') then the line. Output: (1/12) FOUR SCORE AND SEVEN YEARS AGO OUR FATHERS BROUGHT FORTH ON THIS CONTINENT A NEW NATION CONCEIVED IN LIBERTY AND DEDICATED TO THE (2/12) PROPOSITION THAT ALL MEN ARE CREATED EQUAL. NOW WE ARE ENGAGED IN A GREAT CIVIL WAR TESTING WHETHER THAT NATION OR ANY NATION SO (3/12) CONCEIVED AND SO DEDICATED CAN LONG ENDURE. WE ARE MET ON A GREAT BATTLEFIELD OF THAT WAR. WE HAVE COME TO DEDICATE A PORTION OF (4/12) THAT FIELD AS A FINAL RESTING PLACE FOR THOSE WHO HERE GAVE THEIR LIVES THAT THAT NATION MIGHT LIVE. IT IS ALTOGETHER FITTING AND (5/12) PROPER THAT WE SHOULD DO THIS. BUT IN A LARGER SENSE WE CAN NOT DEDICATE, WE CAN NOT CONSECRATE, WE CAN NOT HALLOW, THIS GROUND. (6/12) THE BRAVE MEN LIVING AND DEAD WHO STRUGGLED HERE HAVE CONSECRATED IT FAR ABOVE OUR POOR POWER TO ADD OR DETRACT. THE WORLD WILL (7/12) LITTLE NOTE NOR LONG REMEMBER WHAT WE SAY HERE BUT IT CAN NEVER FORGET WHAT THEY DID HERE. IT IS FOR US THE LIVING RATHER TO BE (8/12) DEDICATED HERE TO THE UNFINISHED WORK WHICH THEY WHO FOUGHT HERE HAVE THUS FAR SO NOBLY ADVANCED. IT IS RATHER FOR US TO BE HERE (9/12) DEDICATED TO THE GREAT TASK REMAINING BEFORE US, THAT FROM THESE HONORED DEAD WE TAKE INCREASED DEVOTION TO THAT CAUSE FOR WHICH (10/12) THEY GAVE THE LAST FULL MEASURE OF DEVOTION, THAT WE HERE HIGHLY RESOLVE THAT THESE DEAD SHALL NOT HAVE DIED IN VAIN, THAT THIS (11/12) NATION UNDER GOD SHALL HAVE A NEW BIRTH OF FREEDOM, AND THAT GOVERNMENT OF THE PEOPLE BY THE PEOPLE FOR THE PEOPLE SHALL NOT PERISH (12/12) FROM THE EARTH.  • I'm confident there is a shorter bash command, one that abused wc -l Jan 31, 2014 at 7:19 ## Javascript (FF only), 92 chars r=(s)=>{s.match(/.{1,132}(\s|$)/gm).map((v,i,a)=>console.log(v,'('+(i+1)+'/'+a.length+')'))}


Formatted, that's a rip-off of the Perl script:

r=(s)=>{
s.match(/.{1,132}(\s|$)/gm).map((v,i,a) => console.log(v,'('+(i+1)+'/'+a.length+')')) }  ## VBA, 227 Sub a(s) Dim n(99) m=1 x=133 While Len(s)>x t=Left(s,x):p=InStrRev(t," "):q=InStrRev(t,vbCr):i=IIf(p>q,p,q):t=Left(s,i):s=Mid(s,i+1):n(m)=t:m=m+1 Wend n(m)=s For o=1 To m Debug.Print "(" & o & "/" & m & ") " & n(o) Next End Sub  Outputs: (1/11) FOUR SCORE AND SEVEN YEARS AGO OUR FATHERS BROUGHT FORTH ON THIS CONTINENT A NEW NATION CONCEIVED IN LIBERTY AND DEDICATED TO THE (2/11) PROPOSITION THAT ALL MEN ARE CREATED EQUAL. NOW WE ARE ENGAGED IN A GREAT CIVIL WAR TESTING WHETHER THAT NATION OR ANY NATION SO (3/11) CONCEIVED AND SO DEDICATED CAN LONG ENDURE. WE ARE MET ON A GREAT BATTLEFIELD OF THAT WAR. WE HAVE COME TO DEDICATE A PORTION OF (4/11) THAT FIELD AS A FINAL RESTING PLACE FOR THOSE WHO HERE GAVE THEIR LIVES THAT THAT NATION MIGHT LIVE. IT IS ALTOGETHER FITTING AND (5/11) PROPER THAT WE SHOULD DO THIS. BUT IN A LARGER SENSE WE CAN NOT DEDICATE, WE CAN NOT CONSECRATE, WE CAN NOT HALLOW, THIS GROUND. THE (6/11) BRAVE MEN LIVING AND DEAD WHO STRUGGLED HERE HAVE CONSECRATED IT FAR ABOVE OUR POOR POWER TO ADD OR DETRACT. THE WORLD WILL LITTLE (7/11) NOTE NOR LONG REMEMBER WHAT WE SAY HERE BUT IT CAN NEVER FORGET WHAT THEY DID HERE. IT IS FOR US THE LIVING RATHER TO BE DEDICATED (8/11) HERE TO THE UNFINISHED WORK WHICH THEY WHO FOUGHT HERE HAVE THUS FAR SO NOBLY ADVANCED. IT IS RATHER FOR US TO BE HERE DEDICATED TO (9/11) THE GREAT TASK REMAINING BEFORE US, THAT FROM THESE HONORED DEAD WE TAKE INCREASED DEVOTION TO THAT CAUSE FOR WHICH THEY GAVE THE (10/11) LAST FULL MEASURE OF DEVOTION, THAT WE HERE HIGHLY RESOLVE THAT THESE DEAD SHALL NOT HAVE DIED IN VAIN, THAT THIS NATION UNDER GOD (11/11) SHALL HAVE A NEW BIRTH OF FREEDOM, AND THAT GOVERNMENT OF THE PEOPLE BY THE PEOPLE FOR THE PEOPLE SHALL NOT PERISH FROM THE EARTH.  ## Javascript (FF only), 135 chars n=(s)=>{for(g=[],i=1,a=s.split(/(\s)/),r='';c=a.shift();g[i]=r+=c)if((c+r)[132]&&i++)r='';g.map((v,k)=>console.log(v,'('+k+'/'+i+')'))}  Formatted, that's: n=(s)=>{ for (g=[],i=1,a=s.split(/(\s)/),r=''; c=a.shift(); g[i]=r+=c) { if((c+r)[132]&&i++) { r=''; } } g.map((v,k)=>console.log(v,'('+k+'/'+i+')')) }  • I think this is more clever than my shorter answer Feb 5, 2014 at 9:53 # PHP, 233 Am I correct in assuming that this is the first answer that does not cheat on the count portion? (It also works with more than 99 tweets; I could shave off two more bytes if I would allow an infinite loop in that case.) function t($s,$e=1){$a=explode(' ',$s);while($a){$t=++$n;while($a&&strlen($t.$a[0])<137-$e)$t.=' '.array_shift($a);$r[]=$t;}if($n>=10**$e)t($s,$e+1);else foreach($r as$i=>$s)echo preg_replace('%(^\d+)%',"($1/n)",s),' ';}  ungolfed: function t(s,e=1) { a=explode(' ',s); while(a) { t=++n; while(a&&strlen(t.a[0])<137-e)t.=' '.array_shift(a); r[]=t; } if(n>=10**e) // if tweet count has more than e digits t(s,ceil(log10(n+1))); // use correct length (golfed: try with length+1) else foreach(r asi=>s) echo preg_replace('%(^\d+)%',"($1/$n)",\$s),"\n";
}