init
This commit is contained in:
commit
7a6b109e78
4 changed files with 164 additions and 0 deletions
32
cmd/namecount/main.go
Normal file
32
cmd/namecount/main.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"tallin/internal/counter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s <filename>\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "open file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
counts, err := counter.Count(file)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "read file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, result := range counter.Sorted(counts) {
|
||||
fmt.Printf("%s:%d\n", result.Name, result.Count)
|
||||
}
|
||||
}
|
||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module tallin
|
||||
|
||||
go 1.22
|
||||
53
internal/counter/counter.go
Normal file
53
internal/counter/counter.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package counter
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const maxLineSize = 1024 * 1024
|
||||
|
||||
type Result struct {
|
||||
Name string
|
||||
Count int
|
||||
}
|
||||
|
||||
func Count(r io.Reader) (map[string]int, error) {
|
||||
counts := make(map[string]int)
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Buffer(make([]byte, 64*1024), maxLineSize)
|
||||
|
||||
for scanner.Scan() {
|
||||
name := scanner.Text()
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
counts[name]++
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return counts, nil
|
||||
}
|
||||
|
||||
func Sorted(counts map[string]int) []Result {
|
||||
results := make([]Result, 0, len(counts))
|
||||
for name, count := range counts {
|
||||
results = append(results, Result{Name: name, Count: count})
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
if results[i].Count != results[j].Count {
|
||||
return results[i].Count > results[j].Count
|
||||
}
|
||||
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
|
||||
return results
|
||||
}
|
||||
76
internal/counter/counter_test.go
Normal file
76
internal/counter/counter_test.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package counter
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
counts, err := Count(strings.NewReader("Алена\nМиша\nАлена\nДима\n\n"))
|
||||
if err != nil {
|
||||
t.Fatalf("Count() error = %v", err)
|
||||
}
|
||||
|
||||
want := map[string]int{
|
||||
"Алена": 2,
|
||||
"Миша": 1,
|
||||
"Дима": 1,
|
||||
}
|
||||
if !reflect.DeepEqual(counts, want) {
|
||||
t.Fatalf("Count() = %#v, want %#v", counts, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCountPreservesSpaces(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
counts, err := Count(strings.NewReader("Anna\n Anna \nAnna\n"))
|
||||
if err != nil {
|
||||
t.Fatalf("Count() error = %v", err)
|
||||
}
|
||||
|
||||
want := map[string]int{
|
||||
"Anna": 2,
|
||||
" Anna ": 1,
|
||||
}
|
||||
if !reflect.DeepEqual(counts, want) {
|
||||
t.Fatalf("Count() = %#v, want %#v", counts, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCountEmptyInput(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
counts, err := Count(strings.NewReader("\n\n"))
|
||||
if err != nil {
|
||||
t.Fatalf("Count() error = %v", err)
|
||||
}
|
||||
|
||||
if len(counts) != 0 {
|
||||
t.Fatalf("Count() = %#v, want empty map", counts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSorted(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
counts := map[string]int{
|
||||
"Миша": 1,
|
||||
"Алена": 2,
|
||||
"Дима": 1,
|
||||
}
|
||||
|
||||
got := Sorted(counts)
|
||||
want := []Result{
|
||||
{Name: "Алена", Count: 2},
|
||||
{Name: "Дима", Count: 1},
|
||||
{Name: "Миша", Count: 1},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("Sorted() = %#v, want %#v", got, want)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue