Go 以字符串形式返回步骤实现河内塔的有效方法

Go 以字符串形式返回步骤实现河内塔的有效方法,go,towers-of-hanoi,Go,Towers Of Hanoi,我正在比较JS、Rust和Go中的几种算法。我在围棋中采用了这种方式: func Hanoi()(Hanoi func(n int,from,via,to string)字符串){ var移动字符串.Builder var hanoiRe func(n int,from,via,to string) hanoiRe=func(n int、from、via、to字符串){ 如果n>0{ 哈内尔(n-1,从,到,通过) 移动。写入字符串(从) moves.WriteString(->) 移动。写入限

我正在比较JS、Rust和Go中的几种算法。我在围棋中采用了这种方式:

func Hanoi()(Hanoi func(n int,from,via,to string)字符串){
var移动字符串.Builder
var hanoiRe func(n int,from,via,to string)
hanoiRe=func(n int、from、via、to字符串){
如果n>0{
哈内尔(n-1,从,到,通过)
移动。写入字符串(从)
moves.WriteString(->)
移动。写入限制(到)
moves.WriteString(“\n”)
哈内尔(n-1,经,自,至)
}
}
hanoi=func(n int,from,via,to string)字符串{
哈内尔(北,自,经,至)
return moves.String()
}
返回
}
但是这个实现比JS或Rust慢得多。所以我认为,这可以做得更快。但是怎么做呢

我已经用
func(h*hanoi)
尝试了
type hanoi struct{moves strings.Builder}
,速度稍慢。使用字符串和
移动+=…
的方式要慢得多

编辑:

class HanoiJS {
    constructor() {
        this.moves = "";
    }
    hanoi(n, from, via, to) {
        if (n > 0) {
            this.hanoi(n - 1, from, to, via);
            this.moves += from + "->" + to + "\n";
            this.hanoi(n - 1, via, from, to);
        }
        return this.moves;
    }
}
我的比较:

JS:

class HanoiJS {
    constructor() {
        this.moves = "";
    }
    hanoi(n, from, via, to) {
        if (n > 0) {
            this.hanoi(n - 1, from, to, via);
            this.moves += from + "->" + to + "\n";
            this.hanoi(n - 1, via, from, to);
        }
        return this.moves;
    }
}
锈蚀:

class HanoiJS {
    constructor() {
        this.moves = "";
    }
    hanoi(n, from, via, to) {
        if (n > 0) {
            this.hanoi(n - 1, from, to, via);
            this.moves += from + "->" + to + "\n";
            this.hanoi(n - 1, via, from, to);
        }
        return this.moves;
    }
}
pub结构河内{
移动:字符串
}
河内工业园区{
pub fn new()->河内{
河内{
移动:String::new()
}
}
河内的酒吧(&mut self,n:i32,发件人:&str,途经:&str,收件人:&str)->&str{
如果n>0{
河内(n-1,从,到,经);
自我移动推送(从);
self.moves.push_str(“->”);
自我。移动。按下按钮(到);
self.moves.push_str(“\n”);
河内(n-1,经,自,至);
}
返回和自我移动;
}
}
与n=20和5次相比:

编写基准测试并进行性能优化。一个起点可能是(有点过时)这篇文章。要点是:编写一个func BenchmarkHanoi(b*testing.b)并运行这个基准,生成cpuprofile和memoryprofile(请参阅go help testflag),然后通过go工具pprof对它们进行任意处理。好的,我想我知道时间花在哪里了。如果我删除
moves.WriteString()
调用,速度会快得多。但是,有什么比使用
string.Builder
更有效的方法来构建字符串呢?在Rust中,我使用的是
String.push_str()
,在JS中,我只需通过
moves+=“…”
添加。定义一个带有“到”和“从”字段的Steps结构。传入一段步骤,并附加到其中。之后渲染切片。仅供参考:与性能问题无关,闭包函数在开始工作之前不会重置
移动。因此,对该函数的后续调用将附加到仍然存储在
moves
中的先前结果。实际上,上述注释可能会影响基准测试-如果在基准测试调用之间不重置moves字符串,则字符串结果将随每次迭代而增长(即
hanoi(20,“A”,“B”,“C”)
应始终返回相同的结果)