file - 如何优化从 Go 中的文本文件中查找字谜
问题描述
我正在尝试解决一个编码挑战,即必须从与输入字符串匹配的文本文件中打印所有字谜。程序必须尽可能快地执行。工作代码:
package main
import (
"bufio"
"fmt"
"log"
"os"
"sort"
"strings"
"time"
)
func timeTrack(start time.Time, name string) {
elapsed := time.Since(start)
log.Printf("%s took %s", name, elapsed)
}
func SortString(w string) string {
s := strings.Split(w, "")
sort.Strings(s)
return strings.Join(s, "")
}
func FindWord(dict map[string]string, w string) {
if val, ok := dict[w]; ok {
fmt.Println("Found anagrams: ", val)
}
}
func main() {
defer timeTrack(time.Now(), "factorial")
file_fullpath := os.Args[1]
anagram_word := os.Args[2]
f, err := os.Open(file_fullpath)
defer f.Close()
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(f)
scanner.Split(bufio.ScanLines)
var txtlines = make(map[string]string)
for scanner.Scan() {
k := scanner.Text()
v := SortString(k)
txtlines[v] += string(k) + ","
}
FindWord(txtlines, SortString(anagram_word))
}
目前,我将它降低到大约 160 毫秒。
显然使用 Array 会比 Map 更高效,但需要将原始单词打印到控制台。
有什么方法可以提高创建地图的效率吗?
解决方案
TL;DR:peterSO 比 strom73 快 10 倍。
斯特罗姆73:
$ go build strom73.go && ./strom73 "/usr/share/dict/words" "restful"
Found anagrams: fluster,restful,
2019/02/26 02:50:47 anagrams took 150.733904ms
$
彼得索:
$ go build peterso.go && ./peterso "/usr/share/dict/words" "restful"
Found anagrams: [restful fluster]
2019/02/26 02:50:52 anagrams took 15.093098ms
$
如何优化从 Go 中的文本文件中查找字谜
我正在尝试解决一个编码挑战,即必须从与输入字符串匹配的文本文件中打印所有字谜。程序必须尽可能快地执行。
目前,我将它降低到大约 160 毫秒。
没有提供测试用例。
XY 问题是询问您尝试的解决方案,而不是您的实际问题:XY 问题。
如果我们查看维基百科 -字谜,我们会看到:字谜是通过重新排列不同单词或短语的字母而形成的单词或短语,通常只使用所有原始字母一次。例如,“宁静”=“慌乱”,“葬礼”=“真正的乐趣”,“铁路安全”=“童话”。
为了解决 Go 中的这个问题,我们使用 Go 测试包基准测试工具来测量性能。例如,字母值的总和、字母值的排序以及整体算法。我们不懈地剖析每一行代码以提高性能。我们从最便宜的开始订购字谜测试。例如,对字母进行排序很昂贵,所以我们首先检查字母的数量,然后对字母进行简单的求和以廉价地过滤掉许多非字谜。
我们需要一些东西来充当字谜文本文件。Linux 词典文件 ( /usr/share/dict/words
) 很容易获得,但仅限于单个单词。它使用大写和小写。
详尽的基准测试令人筋疲力尽。收益递减规律已经开始。现在,速度提高十倍就足够了。
peterso.go:
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"sort"
"strings"
"time"
)
func findAnagrams(find string, text io.Reader) []string {
find = strings.ToLower(find)
findSum := 0
findRunes := []rune(find)
j := 0
for i, r := range findRunes {
if r != ' ' {
findSum += int(r)
if i != j {
findRunes[j] = r
}
j++
}
}
findRunes = findRunes[:j]
sort.Slice(findRunes, func(i, j int) bool { return findRunes[i] < findRunes[j] })
findStr := string(findRunes)
anagrams := []string{find}
s := bufio.NewScanner(text)
for s.Scan() {
word := strings.ToLower(s.Text())
wordSum := 0
wordRunes := []rune(word)
j := 0
for i, r := range wordRunes {
if r != ' ' {
wordSum += int(r)
if i != j {
wordRunes[j] = r
}
j++
}
}
wordRunes = wordRunes[:j]
if len(wordRunes) != len(findRunes) {
continue
}
if wordSum != findSum {
continue
}
sort.Slice(wordRunes, func(i, j int) bool { return wordRunes[i] < wordRunes[j] })
if string(wordRunes) == findStr {
if word != find {
anagrams = append(anagrams, word)
}
}
}
if err := s.Err(); err != nil {
panic(err)
}
return anagrams
}
func timeTrack(start time.Time, name string) {
elapsed := time.Since(start)
log.Printf("%s took %s", name, elapsed)
}
func main() {
defer timeTrack(time.Now(), "anagrams")
textPath := os.Args[1]
findWord := os.Args[2]
text, err := os.Open(textPath)
if err != nil {
panic(err)
}
defer text.Close()
anagrams := findAnagrams(findWord, text)
fmt.Println("Found anagrams: ", anagrams)
}
推荐阅读
- java - 为什么我的 Apache Nutch warc 和 commoncrawldump 在爬网后失败?
- flutter - flutter_pagewise 一次加载所有图像,而不是延迟加载
- azure - azure 自托管代理 linux 不使用“--once”参数运行
- javascript - 每次获取请求时自动更新 HTML 页面上的标签
- java - 获取从 Java 客户端连接到 IBM MQ 的 JMSException
- tensorflow2.x - AttributeError:模块“tensorflow_core.keras.layers.experimental.preprocessing”没有属性“RandomFlip”
- c# - 如何获取指向 Array 实例内存的指针?
- node.js - 有没有办法检查用户是否在 quick.db 中有特定项目
- asp.net-mvc - 从 mvc3 升级的 ASP.net mvc5 丢失 HTTPContext.User
- django - 将用户重定向到主页 django 的问题