Task

Write a program that solves the odd word problem with the restrictions given below.



Description

You are promised an input stream consisting of English letters and punctuations.

It is guaranteed that:

 the words (sequence of consecutive letters) are delimited by one and only one punctuation,
 the stream will begin with a word,
 the words will be at least one letter long,   and 
 a full stop (a period, [.]) appears after, and only after, the last word.


Example

A stream with six words:

 what,is,the;meaning,of:life. 


The task is to reverse the letters in every other word while leaving punctuations intact, producing:

 what,si,the;gninaem,of:efil. 
while observing the following restrictions:

 Only I/O allowed is reading or writing one character at a time, which means: no reading in a string, no peeking ahead, no pushing characters back into the stream, and no storing characters in a global variable for later use;
 You are not to explicitly save characters in a collection data structure, such as arrays, strings, hash tables, etc, for later reversal;
 You are allowed to use recursions, closures, continuations, threads, co-routines, etc., even if their use implies the storage of multiple characters.


Test cases

Work on both the   "life"   example given above, and also the text:

 we,are;not,in,kansas;any,more.


/*REXX program solves the  odd word problem  by only using  (single) byte  input/output.*/
                           iFID_ = 'ODDWORD.IN'  /*Note:  numeric suffix is added later.*/
                           oFID_ = 'ODDWORD.'    /*  "       "       "    "   "     "   */
     do case=1  for 2;                #= 0       /*#:  is the number of characters read.*/
     iFID= iFID_  ||  case                       /*read   ODDWORD.IN1  or  ODDWORD.IN2  */
     oFID= oFID_  ||  case                       /*write  ODDWORD.1    or  ODDWORD.2    */
     say;   say;    say '════════ reading file: '        iFID        "════════"                /* ◄■■■■■■■■■ optional. */
 
         do  until x==.                          /* [↓]  perform until reaching a period*/
                do  until \datatype(x, 'M')      /* [↓]     "      "   punctuation found*/
                call rChar                       /*read  a single character.            */
                call wChar                       /*write "    "       "                 */
                end   /*until \data···*/         /* [↑]  read/write until punctuation.  */
         if x==.  then leave                     /*is this the end─of─sentence (period)?*/
         call readLetters;            punct= #   /*save the location of the punctuation.*/
                do j=#-1  by -1                  /*read some characters backwards.      */
                call rChar j                     /*read previous word (backwards).      */
                if \datatype(x, 'M')  then leave /*Found punctuation?   Then leave  J.  */
                call wChar                       /*write a character (which is a letter)*/
                end   /*j*/                      /* [↑]  perform for  "even"  words.    */
         call rLett                              /*read letters until punctuation found.*/
         call wChar;                  #= punct   /*write a char;  punctuation location. */
         end      /*until x==.*/
     end          /*case*/                       /* [↑]  process both of the input files*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
rLett: do  until  \datatype(x, 'M');         call rChar;             end;         return
wChar: call charout , x  /*console*/;        call charout oFID, x  /*file*/;      return
/*──────────────────────────────────────────────────────────────────────────────────────*/
rChar: if arg()==0  then do; x= charin(iFID); #= #+1; end  /*read  next  char*/
                    else     x= charin(iFID, arg(1) );     /*  " specific  " */   return