User defined pipe and redirection operators: Difference between revisions
Content added Content deleted
m (reduce task description...) |
(Go solution) |
||
Line 173: | Line 173: | ||
Number of Algol pioneers: 6 |
Number of Algol pioneers: 6 |
||
Number of scientists: 15 |
Number of scientists: 15 |
||
</pre> |
|||
=={{header|Go}}== |
|||
<lang go>package main |
|||
import ( |
|||
"bufio" |
|||
"bytes" |
|||
"fmt" |
|||
"io" |
|||
"io/ioutil" |
|||
"regexp" |
|||
"sort" |
|||
"strings" |
|||
) |
|||
// fake file system |
|||
var fs = make(map[string]string) |
|||
// role of > operator |
|||
func toName(name string, src io.Reader) { |
|||
b, _ := ioutil.ReadAll(src) |
|||
fs[name] = string(b) |
|||
} |
|||
// role of < operator |
|||
func fromName(name string) io.Reader { |
|||
return bytes.NewBufferString(fs[name]) |
|||
} |
|||
func tee(in io.Reader, name string) io.Reader { |
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
b := make([]byte, 512) |
|||
for { |
|||
readN, readErr := in.Read(b) |
|||
if readN > 0 { |
|||
writeN, writeErr := pw.Write(b[:readN]) |
|||
fs[name] += string(b[:writeN]) |
|||
if writeErr != nil { |
|||
return |
|||
} |
|||
} |
|||
switch readErr { |
|||
case nil: |
|||
continue |
|||
case io.EOF: |
|||
pw.Close() |
|||
default: |
|||
pw.CloseWithError(readErr) |
|||
} |
|||
return |
|||
} |
|||
}() |
|||
return pr |
|||
} |
|||
func grep(in io.Reader, pat string) io.Reader { |
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
bf := bufio.NewReader(in) |
|||
for { |
|||
line, readErr := bf.ReadString('\n') |
|||
if match, _ := regexp.MatchString(pat, line); match { |
|||
_, writeErr := io.WriteString(pw, line) |
|||
if writeErr != nil { |
|||
return |
|||
} |
|||
} |
|||
if readErr != nil { |
|||
pw.CloseWithError(readErr) |
|||
return |
|||
} |
|||
} |
|||
pw.Close() |
|||
}() |
|||
return pr |
|||
} |
|||
func uniq(in io.Reader) io.Reader { |
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
bf := bufio.NewReader(in) |
|||
var last string |
|||
for { |
|||
s, readErr := bf.ReadString('\n') |
|||
switch readErr { |
|||
case nil: |
|||
if s != last { |
|||
_, writeErr := io.WriteString(pw, s) |
|||
if writeErr != nil { |
|||
return |
|||
} |
|||
last = s |
|||
} |
|||
continue |
|||
case io.EOF: |
|||
if s > "" && s+"\n" != last { |
|||
_, writeErr := io.WriteString(pw, s+"\n") |
|||
if writeErr != nil { |
|||
return |
|||
} |
|||
} |
|||
pw.Close() |
|||
default: |
|||
pw.CloseWithError(readErr) |
|||
} |
|||
return |
|||
} |
|||
}() |
|||
return pr |
|||
} |
|||
func head(in io.Reader, lines int) io.Reader { |
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
if lines <= 0 { |
|||
lines = 10 |
|||
} |
|||
for bf := bufio.NewReader(in); lines > 0; lines-- { |
|||
s, readErr := bf.ReadString('\n') |
|||
_, writeErr := io.WriteString(pw, s) |
|||
if writeErr != nil { |
|||
return |
|||
} |
|||
if readErr == nil { |
|||
continue |
|||
} |
|||
if readErr == io.EOF { |
|||
if s > "" { |
|||
io.WriteString(pw, "\n") |
|||
} |
|||
break |
|||
} |
|||
pw.CloseWithError(readErr) |
|||
return |
|||
} |
|||
pw.Close() |
|||
}() |
|||
return pr |
|||
} |
|||
func tail(in io.Reader, lines int) io.Reader { |
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
if lines <= 0 { |
|||
lines = 10 |
|||
} |
|||
ring := make([]string, lines) |
|||
rn := 0 |
|||
full := false |
|||
bf := bufio.NewReader(in) |
|||
var readErr error |
|||
var s string |
|||
for { |
|||
s, readErr = bf.ReadString('\n') |
|||
if readErr == nil { |
|||
ring[rn] = s |
|||
rn++ |
|||
if rn == lines { |
|||
rn = 0 |
|||
full = true |
|||
} |
|||
continue |
|||
} |
|||
if readErr == io.EOF && s > "" { |
|||
ring[rn] = s + "\n" |
|||
rn++ |
|||
} |
|||
break |
|||
} |
|||
writeLines := func(start, end int) { |
|||
for i := start; i < end; i++ { |
|||
if _, err := io.WriteString(pw, ring[i]); err != nil { |
|||
return |
|||
} |
|||
} |
|||
} |
|||
if full { |
|||
writeLines(rn, lines) |
|||
} |
|||
writeLines(0, rn) |
|||
if readErr == io.EOF { |
|||
pw.Close() |
|||
} else { |
|||
pw.CloseWithError(readErr) |
|||
} |
|||
}() |
|||
return pr |
|||
} |
|||
func sortPipe(in io.Reader) io.Reader { |
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
b, err := ioutil.ReadAll(in) |
|||
if err != nil { |
|||
pw.CloseWithError(err) |
|||
return |
|||
} |
|||
if len(b) > 0 { |
|||
if b[len(b)-1] == '\n' { |
|||
b = b[:len(b)-1] |
|||
} |
|||
list := strings.Split(string(b), "\n") |
|||
sort.Strings(list) |
|||
for _, s := range list { |
|||
if _, err := io.WriteString(pw, s+"\n"); err != nil { |
|||
return |
|||
} |
|||
} |
|||
} |
|||
pw.Close() |
|||
}() |
|||
return pr |
|||
} |
|||
func main() { |
|||
fs["List_of_computer_scientists.lst"] = |
|||
`Wil van der Aalst business process management, process mining, Petri nets |
|||
Hal Abelson intersection of computing and teaching |
|||
Serge Abiteboul database theory |
|||
Samson Abramsky game semantics |
|||
Leonard Adleman RSA, DNA computing |
|||
Manindra Agrawal polynomial-time primality testing |
|||
Luis von Ahn human-based computation |
|||
Alfred Aho compilers book, the 'a' in AWK |
|||
Stephen R. Bourne Bourne shell, portable ALGOL 68C compiler |
|||
Kees Koster ALGOL 68 |
|||
Lambert Meertens ALGOL 68, ABC (programming language) |
|||
Peter Naur BNF, ALGOL 60 |
|||
Guido van Rossum Python (programming language) |
|||
Adriaan van Wijngaarden Dutch pioneer; ARRA, ALGOL |
|||
Dennis E. Wisnosky Integrated Computer-Aided Manufacturing (ICAM), IDEF |
|||
Stephen Wolfram Mathematica |
|||
William Wulf compilers |
|||
Edward Yourdon Structured Systems Analysis and Design Method |
|||
Lotfi Zadeh fuzzy logic |
|||
Arif Zaman Pseudo-random number generator |
|||
Albert Zomaya Australian pioneer of scheduling in parallel and distributed systems |
|||
Konrad Zuse German pioneer of hardware and software |
|||
` |
|||
toName("aa", grep(tee(uniq(sortPipe(io.MultiReader( |
|||
head(fromName("List_of_computer_scientists.lst"), 4), |
|||
tee(grep(fromName("List_of_computer_scientists.lst"), "ALGOL"), |
|||
"ALGOL_pioneers.lst"), |
|||
tail(fromName("List_of_computer_scientists.lst"), 4)))), |
|||
"the_important_scientists.lst"), "aa")) |
|||
fmt.Print("Pioneer: ", fs["aa"]) |
|||
showCount("Number of ALGOL pioneers", "ALGOL_pioneers.lst") |
|||
showCount("Number of scientists", "the_important_scientists.lst") |
|||
} |
|||
func showCount(heading, name string) { |
|||
if data, ok := fs[name]; ok { |
|||
lines := strings.Split(data, "\n") |
|||
n := len(lines) |
|||
if lines[n-1] == "" { |
|||
n-- |
|||
} |
|||
fmt.Printf("%s: %v\n", heading, n) |
|||
} else { |
|||
fmt.Println(name, "not found") |
|||
} |
|||
}</lang> |
|||
Output: |
|||
<pre> |
|||
Pioneer: Adriaan van Wijngaarden Dutch pioneer; ARRA, ALGOL |
|||
Number of ALGOL pioneers: 5 |
|||
Number of scientists: 13 |
|||
</pre> |
</pre> |
||