• 数独求解


    最近公司大肆流行数独之风,自从学会了编程之后,人就变得越来越懒了,能用计算机算的东西就不大愿意用人脑来算了,记得我以前写过一个数独求解的文章,现在看来,觉得当时写得有点烂,就把它重写了一下。

         class Sudoku
        {
            int[,] Numbers { getset; }

            Sudoku(int[,] numbers)
            {
                this.Numbers = numbers.Clone() as int[,];
            }

            bool Process()
            {
                var point = GetAvaiblePoints().FirstOrDefault();
                if (point == null)   //
    所有空格都已经填充
                    return true;

                foreach (var item in GetAvaibleNumbers(point))
                {
                    Numbers[point.X, point.Y] = item;
                    if (Process())
                        return true;
                }

                //
    填遍所有可用数字(无可用数字),仍不能正确求解
                Numbers[point.X, point.Y] = 0;
                return false;
            }

            readonly int[] avaible = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            IEnumerable<int> GetAvaibleNumbers(Point p)
            {
                return avaible.Except(Horizontal(p))
                    .Except(Vertical(p))
                    .Except(Rectangle(p));
            }

            readonly int[] indexs = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };

            IEnumerable<int> Horizontal(Point p) { return indexs.Select(i => Numbers[i , p.Y]); }

            IEnumerable<int> Vertical(Point p) { return indexs.Select(i => Numbers[p.X, i]); }

            IEnumerable<int> Rectangle(Point p)
            {
                var x = p.X - p.X % 3;
                var y = p.Y - p.Y % 3;

                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                        yield return Numbers[x + i, y + j];
            }

            IEnumerable<Point> GetAvaiblePoints()
            {
                return from x in indexs
                       from y in indexs
                       where Numbers[x, y] == 0
                       select new Point(x, y);
            }

            /// <summary>
            ///
    数独求解
            /// </summary>
            /// <param name="numbers">
    9*9数组,空格用0代替,已有值的范围1~9,本函数不对参数有效性检测,不要测试程序的健壮性</param>
            /// <returns>
    返回一个可行的数独解,无解返回null</returns>
            public static int[,] Process(int[,] numbers)
            {
                var soudu = new Sudoku(numbers);
               
                if (soudu.Process())
                    return soudu.Numbers;
                else
                    return null;
            }

            //
    坐标点,可以用Tuple<int,int>代替
            class Point
            {
                public int X { get; set; }
                public int Y { get; set; }

                public Point(int x, int y)
                {
                    this.X = x;
                    this.Y = y;
                }

                public override string ToString() { return X + "," + Y; }
            }
        }

    两个算法没有什么本质上的区别,但这个更容易看懂,并且这个大量使用了linq,算法是更加容易改造(改顺序尝试为随机尝试,改线性求解为并发)的,有点函数式编程的影子,什么时候有空再用F#来写一下。

  • 相关阅读:
    js属性对象的hasOwnProperty方法
    利用递归的方式在JSON 数据中找到某个节点的多有父节点
    数组中的方法 --- 不改变原数组的方法
    数组中的方法-- 会改变原数组的
    break continue return 的区别
    解决vue中对象属性改变视图不更新的问题
    怎么实现无痛刷新token
    正则的使用记录
    一级域名的登录信息在二级域名中获取
    没有什么问题是不能通过增加一个抽象层解决的
  • 原文地址:https://www.cnblogs.com/TianFang/p/1827674.html
Copyright © 2020-2023  润新知