ARTS(07)

栏目: C# · 发布时间: 6年前

内容简介:所以调用者会这样做一些人不喜欢这样,但是我非常喜欢这种方式,因为它能够表达出更清晰的意图。在但是控制流被

1 Algorithm

八皇后问题 是一道经典的算法题目,有多种解决问题的思路,甚至知乎上出现出现了 如何使用10行代码完成八皇后 问题。

基本的解决问题的思路就是回溯法,不断的尝试每一行的皇后的位置,如果改行无可行的位置的,则回溯上一行皇后的位置。如果上一行皇后的位置也无法放置,则继续回溯,直至第一行。如有甚者,则算法结束。如果到达最后一行,如果位置合法,则表示一个完整的解决方案。
package main

import "fmt"

var solutionCount = 0

// Queue for queue's position
type Queue struct {
    X int
    Y int
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

func (q Queue) string() string {
    return fmt.Sprintf("{%d, %d}", q.X, q.Y)
}

func (q Queue) conflict(other Queue) bool {
    if q.X == other.X || q.Y == other.Y || abs(q.X-other.X) == abs(q.Y-other.Y) {
        return true
    } else {
        return false
    }
}

// QueueProblem solving
func QueueProblem(n int) {
    queues := make([]Queue, n, n)
    for idx := range queues {
        queues[idx] = Queue{idx, -1}
    }
    i := 0
    for i >= 0 {
        if i == n {
            printQueues(queues, n)
            i--
        }
        queues[i].Y++
        if queues[i].Y >= n {
            queues[i] = Queue{i, -1}
            i--
        } else {
            if satisfied(queues, i) {
                i++
            }
        }
    }
}

func satisfied(queues []Queue, n int) bool {
    for i := 0; i < n; i++ {
        if queues[i].conflict(queues[n]) {
            return false
        }
    }
    return true
}

func printQueues(queues []Queue, n int) {
    solutionCount++
    fmt.Println("position")
    for i := 0; i < n; i++ {
        fmt.Println(queues[i].string())
    }
}

func main() {
    QueueProblem(8)
    fmt.Printf("solution Count: %d\n", solutionCount)
}

2 Review

Return in Go and C#

Go 语言用户中,大家经常抱怨 Go 的异常处理机制,但是我却认为它是 Go 语言中最有趣的地方。我在这不着重讨论错误处理机制,而是 Go 语言中的多返回值的特性。

举例来讲, Go 中常见的代码模式如下:
func Divide(a, b float64)(float64, error){
    if b==0{
        return 0.0, errors.New("divide by zero")
    }
    return a / b, nil
}

所以调用者会这样做

result, err := Divide(x, y)
if err != nil {
    // do err handling
}

一些人不喜欢这样,但是我非常喜欢这种方式,因为它能够表达出更清晰的意图。在 C# 中没有多个返回值,那么我们是怎么做的呢?

  • 抛出异常
public SomeObject GetObjectById(int id){
    if (!SomeObjectRepo.Has(id))
        throw new ArgumentOutOfRangeException(nameof(id));
    //...
}
//...
try{
    var obj = GetObjectById(1);
    // do tome thing obj
}
catch(ArgumentOutOfRangeException ex ){
    // error handling
}

但是控制流被 try-catch 打断了,有些变量被 try-catch 的作用域切割开来,需要在进入 try 之前定义变量。

  • 返回null
public SomeObject GetObjectById(int id){
    if (!SomeObjectRepo.Has(id))
        return null
    // go get the object
}
//...
var obj = GetObjectById(1);
if (obj == null){
    // do error handling
}

这个方法虽然看上去好多了,但是还是有严重的问题,你没有得到任何错误的信息。而且对于返回是值类型的, null 是无法返回的。当然也可以返回诸如 int? , bool? 等等。

  • 泛型返回值
public class Result<T>
{
    public T Value {get;protected set;}
    public Exception Exception {get; protected set;}

    public bool IsError => Exception != null;

    public Result() : this(default(T)) {}
    public Result(T value)
    {
        Value = value;
    }

    public static Result<T> MakeError(Exception exception)
    {
        return new Result<T>
        {
            Value = default(T),
            Exception = exception
        };
    }
}

有了通用的结果,就可以这样使用

public Result<int> Divide(int a, int b)
{
    if (b == 0)
    {
        return Result<int>.MakeError(new DivideByZeroException());
    }
    return new Result<int>(a / b);
}
//...
var res = Divide(8, 4);
if (res.IsError)
{
    // do error handling, e.g.
    throw res.Exception;
}
// do something with res.Value (2)

代码看上去非常丑陋,接下来就能看到在 C# 7.0 中如何做到。

  • 语法糖
public (int, Exception) Divide(int a, int b)
{
    if (b == 0)
        return (0, new DivideByZeroException());

    return (a / b, null);
}
// ...
var (res, err) = Divide(1, 2);
if (err != null) 
{
    // do error handling
}

现在代码和 Go 非常相似了,实际上就是利用了返回值为 tuple 的特性,但是 Go 语言的方式却更加优雅

3 Tips

使用 golang 中的 pprof 工具进行性能分析,首先对于 web 应用程序,添加

import _"net/http/pprof"

可以在 localhost:port/debug/pprof 中查看性能分析, 选择 pprof 选线,可以对CPU进行采样分析,经过一段时间,生成 pprof 文件,使用如下命令可以生成 svg 文件

go tool pprof ./proff > pprof.svg

使用浏览器打开该文件,可以查看每个函数消耗时间。

ARTS(07) 颜色越深,表明该函数消耗时间越长。

4 Share


以上所述就是小编给大家介绍的《ARTS(07)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

思想的未来

思想的未来

(美)劳伦斯﹒莱斯格 / 李旭 / 中信出版社 / 2004-10 / 29.00元

因特网革命已到来,一些人说它已经过去,革命缘何而来?又缘何而去呢? 劳伦斯·莱斯格对因特网革命中为何会出现一种反革命的破坏性力量及后果做出了解释。创作之所以繁荣,是因为因特网保护了创新的公共资源。是因为因特网保护了创新的公共资源。因特网的独特设计营造出一个中立的平台。最广大范围的作者们可在此平台上进行试验。围绕此平台的法律架构对这一自由空间给予了保护,以使文化和信息——我们这个时代的......一起来看看 《思想的未来》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具