101 lines
3.6 KiB
Factor
101 lines
3.6 KiB
Factor
! Copyright (c) 2012 Anonymous
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: continuations kernel io io.streams.string locals unicode ;
|
|
IN: rosetta-code.odd-word
|
|
|
|
! http://rosettacode.org/wiki/Odd_word_problem
|
|
|
|
! 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; that
|
|
! * the stream will begin with a word; that
|
|
! * the words will be at least one letter long; and that
|
|
! * a full stop (.) appears after, and only after, the last word.
|
|
|
|
! For example, what,is,the;meaning,of:life. is such a stream
|
|
! with six words. Your task is to reverse the letters in every
|
|
! other word while leaving punctuations intact, producing e.g.
|
|
! "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, coroutines, etc., even if their use implies the storage
|
|
! of multiple characters.
|
|
|
|
! Test case: work on both the "life" example given above, and
|
|
! the text we,are;not,in,kansas;any,more.
|
|
|
|
<PRIVATE
|
|
! Save current continuation.
|
|
: savecc ( -- continuation/f )
|
|
[ ] callcc1 ; inline
|
|
|
|
! Jump back to continuation, where savecc will return f.
|
|
: jump-back ( continuation -- )
|
|
f swap continue-with ; inline
|
|
PRIVATE>
|
|
|
|
:: read-odd-word ( -- )
|
|
f :> first-continuation!
|
|
f :> last-continuation!
|
|
f :> reverse!
|
|
! Read characters. Loop until end of stream.
|
|
[ read1 dup ] [
|
|
dup Letter? [
|
|
! This character is a letter.
|
|
reverse [
|
|
! Odd word: Write letters in reverse order.
|
|
last-continuation savecc dup [
|
|
last-continuation!
|
|
2drop ! Drop letter and previous continuation.
|
|
] [
|
|
! After jump: print letters in reverse.
|
|
drop ! Drop f.
|
|
swap write1 ! Write letter.
|
|
jump-back ! Follow chain of continuations.
|
|
] if
|
|
] [
|
|
! Even word: Write letters immediately.
|
|
write1
|
|
] if
|
|
] [
|
|
! This character is punctuation.
|
|
reverse [
|
|
! End odd word. Fix trampoline, follow chain of continuations
|
|
! (to print letters in reverse), then bounce off trampoline.
|
|
savecc dup [
|
|
first-continuation!
|
|
last-continuation jump-back
|
|
] [ drop ] if
|
|
write1 ! Write punctuation.
|
|
f reverse! ! Begin even word.
|
|
] [
|
|
write1 ! Write punctuation.
|
|
t reverse! ! Begin odd word.
|
|
! Create trampoline to bounce to (future) first-continuation.
|
|
savecc dup [
|
|
last-continuation!
|
|
] [ drop first-continuation jump-back ] if
|
|
] if
|
|
] if
|
|
] while
|
|
! Drop f from read1. Then print a cosmetic newline.
|
|
drop nl ;
|
|
|
|
: odd-word ( string -- )
|
|
[ read-odd-word ] with-string-reader ;
|