Odd word problem: Difference between revisions
Line 33: | Line 33: | ||
func owp(dst io.Writer, src io.Reader) { |
func owp(dst io.Writer, src io.Reader) { |
||
byte_in := func () byte { |
|||
bs := make([]byte, 1) |
|||
⚫ | |||
⚫ | |||
} |
|||
byte_out := func (b byte) { dst.Write([]byte{b}) } |
|||
var odd func(byte) byte |
|||
odd = func(s byte) byte { |
|||
if unicode.IsPunct(rune(s)) { |
if unicode.IsPunct(rune(s)) { |
||
return s |
return s |
||
} |
} |
||
b := odd(byte_in()) |
|||
byte_out(s) |
|||
return b |
|||
⚫ | |||
⚫ | |||
} |
} |
||
for { |
for { |
||
for { |
for { |
||
b := byte_in() |
|||
byte_out(b) |
|||
if b |
if b == '.' { |
||
return |
return |
||
} |
} |
||
if unicode.IsPunct(rune(b |
if unicode.IsPunct(rune(b)) { |
||
break |
break |
||
} |
} |
||
} |
} |
||
b := odd(byte_in()) |
|||
byte_out(b) |
|||
if b == '.' { |
|||
⚫ | |||
return |
return |
||
} |
} |
||
Line 87: | Line 90: | ||
func owp(dst io.Writer, src io.Reader) { |
func owp(dst io.Writer, src io.Reader) { |
||
byte_in := func () byte { |
|||
bs := make([]byte, 1) |
|||
src.Read(bs) |
|||
⚫ | |||
} |
|||
byte_out := func (b byte) { dst.Write([]byte{b}) } |
|||
odd := func() byte { |
|||
for { |
for { |
||
b := byte_in() |
|||
if unicode.IsPunct( |
if unicode.IsPunct(int(b)) { |
||
return |
return b |
||
} |
} |
||
defer |
defer byte_out(b) |
||
} |
} |
||
panic("impossible") |
|||
} |
} |
||
for { |
for { |
||
for { |
for { |
||
b := byte_in() |
|||
byte_out(b) |
|||
if b |
if b == '.' { |
||
return |
return |
||
} |
} |
||
if unicode.IsPunct(rune(b |
if unicode.IsPunct(rune(b)) { |
||
break |
break |
||
} |
} |
||
} |
} |
||
odd() |
b := odd() |
||
byte_out(b) |
|||
if b |
if b == '.' { |
||
return |
return |
||
} |
} |
Revision as of 03:56, 4 November 2011
Write a program that solves the odd word problem.
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.
Test case: work on both the "life" example given above, and the text we,are;not,in,kansas;any,more.
Go
<lang go>package main
import (
"bytes" "fmt" "io" "os" "unicode"
)
func main() {
owp(os.Stdout, bytes.NewBufferString("what,is,the;meaning,of:life.")) fmt.Println() owp(os.Stdout, bytes.NewBufferString("we,are;not,in,kansas;any,more.")) fmt.Println()
}
func owp(dst io.Writer, src io.Reader) {
byte_in := func () byte { bs := make([]byte, 1) src.Read(bs) return bs[0] } byte_out := func (b byte) { dst.Write([]byte{b}) } var odd func(byte) byte odd = func(s byte) byte { if unicode.IsPunct(rune(s)) { return s } b := odd(byte_in()) byte_out(s) return b } for { for { b := byte_in() byte_out(b) if b == '.' { return } if unicode.IsPunct(rune(b)) { break } } b := odd(byte_in()) byte_out(b) if b == '.' { return } }
}</lang> Output:
what,si,the;gninaem,of:efil. we,era;not,ni,kansas;yna,more.
A different approach, using defer
:
<lang go>package main
import (
"bytes" "fmt" "io" "os" "unicode"
)
func main() {
owp(os.Stdout, bytes.NewBufferString("what,is,the;meaning,of:life.")) fmt.Println() owp(os.Stdout, bytes.NewBufferString("we,are;not,in,kansas;any,more.")) fmt.Println()
}
func owp(dst io.Writer, src io.Reader) {
byte_in := func () byte { bs := make([]byte, 1) src.Read(bs) return bs[0] } byte_out := func (b byte) { dst.Write([]byte{b}) } odd := func() byte { for { b := byte_in() if unicode.IsPunct(int(b)) { return b } defer byte_out(b) } panic("impossible") } for { for { b := byte_in() byte_out(b) if b == '.' { return } if unicode.IsPunct(rune(b)) { break } } b := odd() byte_out(b) if b == '.' { return } }
}</lang>
Java
This is translated from the first C version on the solutions page. <lang java>import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader;
public class OddWord { public static void processStream(BufferedReader in) throws IOException{ if(checkEnd(in))return; while(true){ forward(in); if(checkEnd(in))return; reverse(in); if(checkEnd(in))return; } }
private static boolean checkEnd(BufferedReader in) throws IOException{ if(peek(in) == '.'){ System.out.println((char)in.read()); return true; }else{ System.out.print((char)in.read()); return false; } }
private static char peek(BufferedReader in) throws IOException{ in.mark(1); char retVal = (char)in.read(); in.reset(); return retVal; }
private static void forward(BufferedReader in) throws IOException{ while(Character.isLetter(peek(in))){ System.out.print((char)in.read()); } }
private static void reverse(BufferedReader in) throws IOException{ if(Character.isLetter(peek(in))){ char character = (char)in.read(); reverse(in); System.out.print(character); } }
public static void main(String[] args) throws IOException{ processStream(new BufferedReader(new StringReader("what,is,the;meaning,of:life."))); processStream(new BufferedReader(new StringReader("we,are;not,in,kansas;any,more."))); processStream(new BufferedReader(new StringReader(";what,is,the;meaning,of:life."))); processStream(new BufferedReader(new StringReader("'we,are;not,in,kansas;any,more."))); } }</lang> Output:
what,si,the;gninaem,of:efil. we,era;not,ni,kansas;yna,more. ;what,si,the;gninaem,of:efil. 'we,era;not,ni,kansas;yna,more.
Python
<lang python>from sys import stdin, stdout
def char_in(): return stdin.read(1) def char_out(c): stdout.write(c)
def odd(prev = lambda: None): a = char_in() if not a.isalpha(): prev() char_out(a) return a != '.'
# delay action until later, in the shape of a closure def clos(): char_out(a) prev()
return odd(clos)
def even(): while True: c = char_in() char_out(c) if not c.isalpha(): return c != '.'
e = False while odd() if e else even(): e = not e</lang> Running:<lang>$ echo "what,is,the;meaning,of:life." | python odd.py what,si,the;gninaem,of:efil. $ echo "we,are;not,in,kansas;any,more." | python odd.py we,era;not,ni,kansas;yna,more.</lang>
Scheme
Output is identical to python. <lang lisp>(define (odd)
(let ((c (read-char))) (if (char-alphabetic? c) (let ((r (odd)))
(write-char c) r)
(lambda () (write-char c) c))))
(define (even)
(let ((c (read-char))) (write-char c) (if (char-alphabetic? c) (even) c)))
(let loop ((i #f))
(let ((c (if i ((odd)) (even)))) (if (char=? c #\.) (exit) (loop (not i)))))</lang>