美文网首页
数独求解

数独求解

作者: 阿狸小朋友 | 来源:发表于2020-06-24 16:24 被阅读0次
    • OC版本
    - (instancetype)initWithArray:(NSArray *)array
    {
        self = [super init];
        if (self) {
            _array = [NSMutableArray array];
            for (NSArray *sub in array) {
                [_array addObject:[NSMutableArray arrayWithArray:sub]];
            }
        }
        return self;
    }
    
    //求解数独
    - (BOOL)solve
    {
        Item *item = [self nextFreeCell];
        
        if (!item) {
            if ([self validateSolution]) {
                return YES;
            }else{
                return NO;
            }
        }
        
        for (int v = 1; v <= 9; v++) {
            self.array[item.y][item.x] = @(v);
            if ([self validateSolution]) {
                if ([self solve]) {
                    return YES;
                }
            }
        }
        self.array[item.y][item.x] = @0;
        
        return NO;
    }
    
    - (Item *)nextFreeCell{
        
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if ([self.array[i][j] integerValue] == 0) {
                    Item *item = [Item new];
                    item.x = j;
                    item.y = i;
                    return item;
                }
            }
        }
        
        return nil;
    }
        
    - (BOOL)validateSolution
    {
        BOOL res = YES;
        
        for (int i = 0; i < 9; i++) {
            if (![self validSlice:[self getRow:i]]) {
                res = NO;
                break;
            }
            
            if (![self validSlice:[self getCol:i]]) {
                res = NO;
                break;
            }
    
            NSInteger y = i / 3 * 3;
            NSInteger x = i % 3 * 3;
            
            if (![self validBlock:[self getBlock:x y:y]]) {
                res = NO;
                break;
            }
        }
        return res;
    }
    
    - (BOOL)validSlice:(NSArray *)s
    {
        NSMutableDictionary *d = [NSMutableDictionary dictionary];
        
        for (NSNumber *v in s) {
            NSNumber *r = [d valueForKey:v.stringValue];
            d[v.stringValue] = @(r.integerValue + 1);
        }
    
        for (NSString *k in d.allKeys) {
            NSNumber *v = d[k];
            
            if (k.integerValue != 0 && v.integerValue > 1) {
                return NO;
            }
        }
        return YES;
    }
    
    - (BOOL)validBlock:(NSArray *)bl
    {
        NSMutableArray *s = [NSMutableArray array];
        
        int i = 0;
        for (NSArray *v in bl) {
            for (NSNumber *j in v) {
                s[i] = j;
                i++;
            }
        }
        return [self validSlice:s];
    }
    
    - (NSArray *)getRow:(int)y
    {
        return self.array[y];
    }
    
    - (NSArray *)getCol:(int)x {
        NSMutableArray *c = [NSMutableArray array];
    
        for (int k = 0; k < 9; k++) {
            NSArray *v = self.array[k];
            c[k] = v[x];
        }
        return c;
    }
    
    - (NSArray *)getBlock:(NSInteger)x y:(NSInteger)y
    {
        x = x / 3 * 3;
        y = y / 3 * 3;
        
        NSMutableArray *res = [NSMutableArray array];
    
        for (int i = 0; i < 3; i++) {
            NSMutableArray *sub = [NSMutableArray arrayWithArray:@[@0,@0,@0]];
            [res addObject:sub];
        }
        
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                res[i][j] = self.array[i+y][j+x];
            }
        }
    
        return res;
    }
    
    
    • Go版本
    func (s *Sudoku) Solve() bool {
        x, y, err := s.nextFreeCell()
    
        //fmt.Println(s)
    
        if err != nil {
            if s.validateSolution() {
                return true
            }
            return false
        }
    
        for v := 1; v <= 9; v++ {
            s.m[y][x] = v
            if s.validateSolution() {
                if s.Solve() {
                    return true
                }
            }
        }
        s.m[y][x] = 0
        return false
    }
    
    func (s *Sudoku) nextFreeCell() (int, int, error) {
        for i := 0; i < len(s.m); i++ {
            for j := 0; j < len(s.m[0]); j++ {
                if s.m[i][j] == 0 {
                    return j, i, nil
                }
            }
        }
        return 0, 0, errors.New("Could not found free cell")
    }
    
    type Sudoku struct {
        m [][]int
    }
    
    // Создание нового класса Sudoku
    func NewSudoku(m [][]int) *Sudoku {
        s := new(Sudoku)
        s.m = m
        return s
    }
    
    // Проверка всего поля.
    // Входные: полне
    // Выходные: ложь или истина
    func (s *Sudoku) validateSolution() (res bool) {
        res = true
        for i := 0; i < len(s.m); i++ {
            if !validSlice(s.getRow(i)) {
                res = false
                break
            }
            if !validSlice(s.getCol(i)) {
                res = false
                break
            }
            y := i / 3 * 3
            x := i % 3 * 3
            if !validBlock(s.getBlock(x, y)) {
                res = false
                break
            }
        }
        return
    }
    
    // Получение строки.
    // Входные: поле, y координата.
    // Выходные: слайс содержащий строку
    func (s *Sudoku) getRow(y int) []int {
        return s.m[y]
    }
    
    // Получить колонку.
    // Входные параметры: поле, х координата.
    // Выходные: слайс содержащий колонку
    func (s *Sudoku) getCol(x int) []int {
        c := make([]int, len(s.m))
        for k, v := range s.m {
            c[k] = v[x]
        }
        return c
    }
    
    // Получить блок.
    // Входные: поле, x и y координаты любой точки на поле
    // Выходные: квадратное поле, в котором находится данная точка
    func (s *Sudoku) getBlock(x, y int) [][]int {
        x = x / 3 * 3
        y = y / 3 * 3
        res := make([][]int, 3)
    
        for i := 0; i < 3; i++ {
            res[i] = make([]int, 3)
        }
    
        for i := 0; i < 3; i++ {
            for j := 0; j < 3; j++ {
                res[i][j] = s.m[i+y][j+x]
            }
        }
    
        return res
    }
    
    // Проверка валидности слайса. Слайс не должен содержать одинаковых цифр, кроме нуля (нули - пустые места в случае нерешённого поля)
    func validSlice(s []int) bool {
        // создаём словарь значений
        d := make(map[int]int, len(s))
    
        // проходим по всему массиву считая каждое число, встреченное в массиве
        for _, v := range s {
            d[v]++
        }
    
        // проверяем нет ли повторов любых цифр, кроме нуля
        for k, v := range d {
            if k != 0 && v > 1 {
                return false
            }
        }
        return true
    }
    
    // Проверка валидности блока.
    // Входные: блок 3x3
    // Выходные: истина, если блок валидный, ложь, если нет.
    func validBlock(bl [][]int) bool {
        s := make([]int, len(bl)*len(bl[0]))
        var i int
        for _, v := range bl {
            for _, j := range v {
                s[i] = j
                i++
            }
        }
        return validSlice(s)
    }
    
    func (s *Sudoku) String() string {
        var res string
        res = "┌───────┬───────┬───────┐\n"
        for k, v := range s.m {
            res = res + "│"
            for i := 0; i < len(v); i += 3 {
                res = res + fmt.Sprintf(" %d %d %d │", v[i], v[i+1], v[i+2])
            }
            res = res + "\n"
            if k == 2 || k == 5 {
                res = res + "├───────┼───────┼───────┤\n"
            }
        }
        res = res + "└───────┴───────┴───────┘"
        return res
    }
    

    相关文章

      网友评论

          本文标题:数独求解

          本文链接:https://www.haomeiwen.com/subject/inbrrqtx.html