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.


isWordChar = (c) -> /^\w/.test c
isLastChar = (c) -> c is '.'
 
# Pass a function that returns an input character and one that outputs a
# character. JS platforms' ideas of single-character I/O vary widely, but this
# abstraction is adaptable to most or all.
oddWord = (get, put) ->
	forwardWord = ->
		loop
			# No magic here; buffer then immediately output.
			c = get()
			put(c)
			unless isWordChar(c)
				return not isLastChar(c)
 
	# NB: (->) is a CoffeeScript idiom for no-op.
	reverseWord = (outputPending = (->)) ->
		c = get()
		if isWordChar(c)
			# Continue word.
			# Tell recursive call to output this character, then any previously
			# pending characters, after the next word character, if any, has
			# been output.
			reverseWord ->
				put(c)
				outputPending()
		else
			# Word is done.
			# Output previously pending characters, then this punctuation.
			outputPending()
			put(c)
			return not isLastChar(c)
 
	# Alternate between forward and reverse until one or the other reports that
	# the end-of-input mark has been reached (causing a return of false).
	continue while forwardWord() and reverseWord()