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

查看所有标签

猜你喜欢:

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

逆向工程核心原理

逆向工程核心原理

[韩] 李承远 / 武传海 / 人民邮电出版社 / 2014-4-25 / 109.00元

本书十分详尽地介绍了代码逆向分析的核心原理。作者在Ahnlab 研究所工作多年,书中不仅包括其以此经验为基础亲自编写的大量代码,还包含了逆向工程研究人员必须了解的各种技术和技巧。彻底理解并切实掌握逆向工程这门技术,就能在众多IT 相关领域进行拓展运用,这本书就是通向逆向工程大门的捷径。 想成为逆向工程研究员的读者或正在从事逆向开发工作的开发人员一定会通过本书获得很大帮助。同时,想成为安全领域......一起来看看 《逆向工程核心原理》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具