2020年5月12日火曜日

開発環境

入門Goプログラミング (Nathan Youngman(著)、Roger Peppé(著)、吉川 邦夫(監修, 翻訳)、翔泳社)のUNIT 6(ネズミの穴を下って)、LESSON 29(チャレンジ:数独ルール)の解答を求めてみる。

コード

package main

import (
 "errors"
 "fmt"
 "math/rand"
 "os"
 "time"
)

const (
 rows = 9
 cols = 9
)

var (
 errBound = errors.New("ます目外")
 errDigit = errors.New("1から9の数値ではない")
 errRow   = errors.New("行に既に存在する数")
 errCol   = errors.New("列に既に存在する数")
 errGrid  = errors.New("グリッドに既に存在する数")
)

func inBound(i int) bool {
 return i >= 0 && i < rows
}
func validDigit(n int8) bool {
 return n >= 1 && n <= 9
}

type sudoku [rows][cols]int8

func (s *sudoku) validRow(row int, n int8) bool {
 for _, m := range s[row] {
  if n == m {
   return false
  }
 }
 return true
}
func (s *sudoku) validCol(col int, n int8) bool {
 for row := 0; row < rows; row++ {
  if s[row][col] == n {
   return false
  }
 }
 return true
}
func (s *sudoku) validGrid(row, col int, n int8) bool {
 k := row / 3 * 3
 l := col / 3 * 3
 for i := k; i < k+3; i++ {
  for j := l; j < l+3; j++ {
   if i != row && j != col && s[i][j] == n {
    return false
   }
  }
 }
 return true
}
func (s *sudoku) set(row, col int, n int8) error {
 if !inBound(row) || !inBound(col) {
  return errBound
 }
 if !validDigit(n) {
  return errDigit
 }
 if !s.validRow(row, n) {
  return errRow
 }
 if !s.validCol(col, n) {
  return errCol
 }
 if !s.validGrid(row, col, n) {
  return errGrid
 }
 s[row][col] = n
 return nil
}
func (s *sudoku) clear(row, col int) error {
 if !inBound(row) || !inBound(col) {
  return errBound
 }
 s[row][col] = 0
 return nil
}
func (s sudoku) String() string {
 a := ""
 for _, row := range s {
  for _, col := range row {
   a += fmt.Sprintf("%v ", col)
  }
  a += "\n"
 }
 return a
}
func main() {
 rand.Seed(time.Now().UnixNano())
 s := sudoku([rows][cols]int8{
  {5, 3, 0, 0, 7, 0, 0, 0, 0},
  {6, 0, 0, 1, 9, 5, 0, 0, 0},
  {0, 9, 8, 0, 0, 0, 0, 6, 0},
  {8, 0, 0, 0, 6, 0, 0, 0, 3},
  {4, 0, 0, 8, 0, 3, 0, 0, 1},
  {7, 0, 0, 0, 2, 0, 0, 0, 6},
  {0, 6, 0, 0, 0, 0, 2, 8, 0},
  {0, 0, 0, 4, 1, 9, 0, 0, 5},
  {0, 0, 0, 0, 8, 0, 0, 7, 9},
 })
 for i := 0; i < 50; i++ {
  row := rand.Intn(10)
  col := rand.Intn(10)
  n := int8(rand.Intn(11))
  err := s.set(row, col, n)
  if err != nil {
   fmt.Fprintln(os.Stderr, err)
  } else {
   fmt.Println(row+1, col+1, n)
   fmt.Print(s)
  }
 }
 for i := 0; i < 10; i++ {
  row := rand.Intn(10)
  col := rand.Intn(10)
  err := s.clear(row, col)
  if err != nil {
   fmt.Fprintln(os.Stderr, err)
  } else {
   fmt.Println(row+1, col+1)
   fmt.Print(s)
  }
 }
}

入出力結果(Zsh、PowerShell、Terminal)

% go build sudoku.go
% ./sudoku 
3 9 2
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 0 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 0 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
4 6 7
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 0 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
列に既に存在する数
行に既に存在する数
列に既に存在する数
ます目外
行に既に存在する数
1から9の数値ではない
1から9の数値ではない
ます目外
列に既に存在する数
行に既に存在する数
1から9の数値ではない
ます目外
1から9の数値ではない
ます目外
行に既に存在する数
列に既に存在する数
行に既に存在する数
行に既に存在する数
ます目外
6 3 5
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
列に既に存在する数
行に既に存在する数
行に既に存在する数
1から9の数値ではない
2 7 8
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
ます目外
列に既に存在する数
ます目外
ます目外
行に既に存在する数
9 3 4
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 9 
行に既に存在する数
行に既に存在する数
列に既に存在する数
7 8 4
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 9 
列に既に存在する数
ます目外
列に既に存在する数
1から9の数値ではない
ます目外
1から9の数値ではない
1から9の数値ではない
行に既に存在する数
1から9の数値ではない
3 6 4
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 4 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 9 
行に既に存在する数
列に既に存在する数
行に既に存在する数
3 4
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 4 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 9 
9 9
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 4 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
4 8
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 4 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
ます目外
3 6
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
3 4
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
7 9
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
2 2
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
5 5
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 8 0 0 
0 9 8 0 0 0 0 6 2 
8 0 0 0 6 7 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 5 0 2 0 0 0 6 
0 6 0 0 0 0 2 4 0 
0 0 0 4 1 9 0 0 5 
0 0 4 0 8 0 0 7 0 
ます目外
% ./sudoku          
1から9の数値ではない
行に既に存在する数
1から9の数値ではない
6 3 1
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 6 0 
8 0 0 0 6 0 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
列に既に存在する数
4 7 9
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 6 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
列に既に存在する数
3 8 3
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
1から9の数値ではない
1から9の数値ではない
行に既に存在する数
7 4 3
5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
0 6 0 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
列に既に存在する数
行に既に存在する数
1 4 2
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
0 6 0 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
1から9の数値ではない
列に既に存在する数
1から9の数値ではない
行に既に存在する数
ます目外
7 1 1
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 6 0 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
行に既に存在する数
2 8 4
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 6 0 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
行に既に存在する数
行に既に存在する数
ます目外
1から9の数値ではない
ます目外
行に既に存在する数
7 3 7
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 6 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
行に既に存在する数
列に既に存在する数
行に既に存在する数
7 2 5
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 9 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
行に既に存在する数
ます目外
列に既に存在する数
ます目外
グリッドに既に存在する数
4 7 5
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 
1から9の数値ではない
グリッドに既に存在する数
1から9の数値ではない
ます目外
ます目外
行に既に存在する数
行に既に存在する数
9 8 6
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
1から9の数値ではない
列に既に存在する数
4 6
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
ます目外
8 7
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
ます目外
4 6
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
4 3
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
ます目外
4 4
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
6 8
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
9 2
5 3 0 2 7 0 0 0 0 
6 0 0 1 9 5 0 4 0 
0 9 8 0 0 0 0 3 0 
8 0 0 0 6 0 5 0 3 
4 0 0 8 0 3 0 0 1 
7 0 1 0 2 0 0 0 6 
1 5 7 3 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 6 9 
% 

0 コメント:

コメントを投稿