ARTS(07)

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

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

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)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

PHP Web 2.0开发实战

PHP Web 2.0开发实战

泽瓦斯 / 苏金国 / 人民邮电出版社 / 2008-10-1 / 59.00元

本书通过一个完整的Web 2.0应用——带有动态图库、搜索和地图功能的博客系统详细介绍了Web开发的全过程。首先讨论了Web应用的规划与设计,然后逐章实现各个具体特性,包括网站主页、用户主页、用户注册页面、账户登录和管理页面、用户博客系统、网站搜索以及应用管理等,最后介绍部署和维护。 本书适合中、高级的PHP程序员阅读。一起来看看 《PHP Web 2.0开发实战》 这本书的介绍吧!

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

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换