Skip to content

Instantly share code, notes, and snippets.

@limingjie
Last active January 20, 2021 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save limingjie/be429b2eb2c48795f32522337bfd5a1d to your computer and use it in GitHub Desktop.
Save limingjie/be429b2eb2c48795f32522337bfd5a1d to your computer and use it in GitHub Desktop.
The Go Programming Language Exercise 1.4
//
// The Go Programming Language - Excercise 1.4
//
// Mingjie Li (limingjie@outlook.com)
// Jun 16, 2016
//
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]map[string]int)
files := os.Args[1:]
if len(files) == 0 {
countLines(os.Stdin, "os.Stdin", counts)
} else {
for _, arg := range files {
f, err := os.Open(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
continue
}
countLines(f, arg, counts)
f.Close()
}
}
for line, filenames := range counts {
fileCount := len(filenames)
if fileCount == 1 {
total := 0
for _, count := range filenames {
total += count
}
if total <= 1 {
continue
}
}
fmt.Printf("[Found in %d file(s)]\t%s\n", fileCount, line)
for name, count := range filenames {
fmt.Printf("\t%d hit(s) in %s\n", count, name)
}
}
}
func countLines(f *os.File, filename string, counts map[string]map[string]int) {
input := bufio.NewScanner(f)
for input.Scan() {
if counts[input.Text()] == nil {
counts[input.Text()] = make(map[string]int)
}
counts[input.Text()][filename]++
}
// NOTE: ignoring potential errors from input.Err()
}
aaa
aaa
aaa
aaa
aaa
bbb
ccc
aaa
ccc
ddd
ccc
ddd
xxx
xxx
yyy
yyy
yyy
yyy
yyy
www
$ ./dup dup*.txt
[Found in 1 file(s)] yyy
5 hit(s) in dup4.txt
[Found in 2 file(s)] aaa
5 hit(s) in dup1.txt
1 hit(s) in dup2.txt
[Found in 3 file(s)] ccc
1 hit(s) in dup3.txt
1 hit(s) in dup1.txt
1 hit(s) in dup2.txt
[Found in 2 file(s)] ddd
1 hit(s) in dup2.txt
1 hit(s) in dup3.txt
[Found in 2 file(s)] xxx
1 hit(s) in dup4.txt
1 hit(s) in dup3.txt
@zacharysyoung
Copy link

Hi, Mingjie,

I was struggling with how to start this solution. Found this gist and when I saw counts := make(map[string]map[string]int) I knew how to approach the problem.

I posted my own gist, https://gist.github.com/zacharysyoung/e93862dc9a78cfe2ae964cdca71f38f0

https://gist.github.com/zacharysyoung/e93862dc9a78cfe2ae964cdca71f38f0

@elusivenode
Copy link

elusivenode commented Jan 20, 2021

Nice sol for ex 1.4 :)

slight tweak to just track duplicates

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	counts := make(map[string]map[string]int)
	files := os.Args[1:]
	if len(files) == 0 {
		countLines(os.Stdin, "os.Stdin", counts)
	} else {
		for _, arg := range files {
			f, err := os.Open(arg)
			if err != nil {
				fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
				continue
			}
			countLines(f, arg, counts)
			f.Close()
		}
	}

	for line, filenames := range counts {
		for fn, ct := range filenames {
			if ct > 1 {
				fmt.Println(line, "is duplicated in ", fn, ct, "times")
			}
		}
	}
}

func countLines(f *os.File, filename string, counts map[string]map[string]int) {
	input := bufio.NewScanner(f)
	for input.Scan() {
		if counts[input.Text()] == nil {
			counts[input.Text()] = make(map[string]int)
		}
		counts[input.Text()][filename]++
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment