package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strconv"
)

const (
	maxBufSize = 1024 * 1024 // 1MB
)

type Record struct {
	Sender string
	Count  int
}

func main() {
	var (
		reader *bufio.Reader
		reg    = regexp.MustCompile("; from=<([^>]+)> to=<")
		quota  = 1
	)

	if len(os.Args) > 1 && os.Args[1] != "" {
		f, err := os.Open(os.Args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		reader = bufio.NewReaderSize(f, maxBufSize)
		defer f.Close()
	} else {
		reader = bufio.NewReaderSize(os.Stdin, maxBufSize)
	}

	if len(os.Args) > 2 {
		if n, err := strconv.Atoi(os.Args[2]); err == nil {
			quota = n
		}
	}

	var (
		err   error
		line  string
		parts []string
		ok    bool
		list  = make(map[string]int)
	)

	for {
		line, err = reader.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			fmt.Println(err)
			os.Exit(1)
		}
		parts = reg.FindStringSubmatch(line)
		if parts != nil {
			if _, ok = list[parts[1]]; !ok {
				list[parts[1]] = 1
				continue
			}
			list[parts[1]]++
		}
	}

	records := make([]Record, 0, len(list))
	for k, v := range list {
		records = append(records, Record{k, v})
	}

	sort.Slice(records, func(i, j int) bool { return records[i].Count > records[j].Count })

	for i := range records {
		if records[i].Count < quota {
			continue
		}
		fmt.Printf("%d\t%s\n", records[i].Count, records[i].Sender)
	}
}
