Module: Sudoku::Logic

Included in:
Grid
Defined in:
lib/sudoku/logic.rb

Overview

Logique de base du Sudoku

Instance Method Summary collapse

Instance Method Details

#baseFixnum

Renvoie la base du sudoku

Returns:

  • (Fixnum)


123
124
125
126
127
128
129
# File 'lib/sudoku/logic.rb', line 123

def base
  if @base
    @base
  else
    @base = (size**0.5).to_i
  end
end

#col(x) ⇒ Array

Renvoie le contenu de la ligne x

Returns:

  • (Array)


6
7
8
9
10
11
12
13
# File 'lib/sudoku/logic.rb', line 6

def col x
  res = []
  size.times do |y|
    val = get x, y
    res << val if val != 0
  end
  res
end

#completable?Boolean

Renvoie true si chaque case a au moins 1 possibilité à ce stade

Returns:

  • (Boolean)


50
51
52
53
54
55
56
# File 'lib/sudoku/logic.rb', line 50

def completable?
  completed = 0
  each do |x, y, val|
    return false if possibilities(x, y).empty?
  end
  return true
end

#complete?Boolean

Renvoie true si le sudoku ne contient aucune case vide

Returns:

  • (Boolean)


44
45
46
47
# File 'lib/sudoku/logic.rb', line 44

def complete?
  each{|x,y,val| return false if val == 0}
  true
end

#count(*values) ⇒ Hash #countHash

Compte le nombre d’occurences pour les valeurs

Overloads:

  • #count(*values) ⇒ Hash

    Compte les occurences pour les valeurs passées en paramètres

    Parameters:

    • values (*Fixnum)

      Les valeurs à compter

  • #countHash

    Compte les occurences de chaque valeur

Returns:

  • (Hash)

    L’association valeur => occurences



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/sudoku/logic.rb', line 148

def count *values
  values = Array.new(size){|i| i+1} if values.empty?
  
  res = {}
  values.each do |val| 
    if val<0 || val>size
      raise ArgumentError, "Impossible value #{val} in a #{size}x#{size} sudoku"
    end
    res[val] = 0
  end
  
  each do |x, y, val|
    res[val] += 1 if values.include? val
  end
  
  res
end

#import(other) ⇒ self

Charge un sudoku depuis un autre sudoku

Parameters:

  • l'autre (Grid)

    Sudoku

Returns:

  • (self)

Raises:



234
235
236
237
238
239
240
# File 'lib/sudoku/logic.rb', line 234

def import other
  unless size == other.size
    raise NotCompatibleError, "Cannot import a #{other.base} sudoku in a #{base} sudoku"
  end
  other.each{|x,y,v| set x, y, v}
  self
end

#inspectString

Représentation courte (utile dans irb)

Returns:

  • (String)


187
188
189
# File 'lib/sudoku/logic.rb', line 187

def inspect
  "#<#{self.class} #{size}x#{size} [#{get 0, 0}, #{get 0, 1}, ... , #{get size-2, size-1}, #{get size-1, size-1}]>"
end

#lengthFixnum

Renvoie le nombre de cases dans le sudoku

Returns:

  • (Fixnum)


133
134
135
136
137
138
139
# File 'lib/sudoku/logic.rb', line 133

def length
  if @length
    @length
  else
    @length = size*size
  end
end

#load(sutxt_str) ⇒ self

Charge un Sudoku depuis une chaine Sutxt

Returns:

  • (self)

Raises:



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/sudoku/logic.rb', line 207

def load sutxt_str
  unless sutxt_str =~ /(\d+):(.+);/
    raise MalformedSutxtError, "It doesn't seem to be a sutxt line..."
  end

  sutxt_base = $1.to_i
  unless sutxt_base == base
    raise NotCompatibleError, "A #{base} sudoku cannot load a #{sutxt_base} Sutxt"
  end
  
  data = $2.split(/\s+/).delete_if(&:empty?).map(&:to_i)
  unless data.length == length
    raise MalformedSutxtError, "Expecting #{length} numbers, #{data.length} given"
  end
  
  size.times do |y|
    size.times do |x|
      set x, y, data.shift
    end
  end
  self
end

#possibilities(x, y) ⇒ Array

Renvoie toutes les possibilités pour la case x,y

Returns:

  • (Array)


60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/sudoku/logic.rb', line 60

def possibilities x, y
  res = Array.new(size){|i| i+1}
  xmin = x-x%base
  ymin = y-y%base
  
  size.times do |i|
    res.delete get(x,i) if i!=y
    res.delete get(i,y) if i!=x
    xx, yy = xmin+i%base, ymin+i/base
    res.delete get(xx, yy) if xx!=x && yy!=y
  end
  
  res
end

#row(y) ⇒ Array

Renvoie le contenu de la ligne y

Returns:

  • (Array)


17
18
19
20
21
22
23
24
# File 'lib/sudoku/logic.rb', line 17

def row y 
  res = []
  size.times do |x|
    val = get x, y
    res << val if val != 0
  end
  res
end

#square(x, y) ⇒ Array

Renvoie le contenu du carré contenant la case x,y

Returns:

  • (Array)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/sudoku/logic.rb', line 28

def square x, y
  xmin = x - (x%base)
  ymin = y - (y%base)
  res = []
  
  base.times do |xx|
    base.times do |yy|
      val = get xx+xmin, yy+ymin
      res << val if val != 0
    end
  end
  
  res
end

#to_sString

Représentation texte humainement lisible

Returns:

  • (String)


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/sudoku/logic.rb', line 168

def to_s
  res  = ""
  width = size.to_s.length
  zero = ".".center width+1
  
  size.times do |y|
    res += "\n" if y>0 && y%base == 0
    size.times do |x|
      res += " " if x>0 && x%base == 0
      val = get x, y
      res += val.zero? ? zero : "#{val.to_s.center width} "
    end
    res += "\n"
  end
  res
end

#to_sutxtString

Représentation pour l’enregistrement

Returns:

  • (String)


193
194
195
196
197
198
199
200
201
# File 'lib/sudoku/logic.rb', line 193

def to_sutxt
  res = "#{base}:"
  size.times do |y|
    size.times do |x|
      res << " #{get x, y}"
    end
  end
  res+';'
end

#valid?(x, y, val) ⇒ Boolean #valid?Boolean

Overloads:

  • #valid?(x, y, val) ⇒ Boolean

    Vérifie si val est valide en x,y

    Parameters:

    • x (Fixnum)

      La colonne de la valeur à vérifier

    • y (Fixnum)

      La ligne de la valeur à vérifier

    • val (Fixnum)

      La valeur à vérifier

    Returns:

    • (Boolean)

      true si la valeur est valide, false sinon

  • #valid?Boolean

    Vérifie que toutes les valeurs du Sudoku sont vlaides

    Returns:

    • (Boolean)

      true si toutes les valeurs sont valides, false sinon



111
112
113
114
115
116
117
118
119
# File 'lib/sudoku/logic.rb', line 111

def valid? *args
  if args.empty?
    valid_grid?
  elsif args.length == 3
    valid_cell? *args
  else
    raise ArgumentError, "wrong number of arguments(#{args.length} for 0 or 3)"
  end
end

#valid_cell?(x, y, val) ⇒ Boolean

Renvoie true si val est possible en x,y

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/sudoku/logic.rb', line 86

def valid_cell? x, y, val
  return true if val.zero?
  val  = val.to_i
  xmin = x-x%base
  ymin = y-y%base
  
  size.times do |i|
    return false if i!=y && get(x,i)==val
    return false if i!=x && get(i,y)==val
    xx, yy = xmin+i%base, ymin+i/base
    return false if xx!=x && yy!=y && get(xx, yy) == val
  end
  
  true
end

#valid_grid?Boolean

Renvoie true si tous les nombres de la grille sont valides

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
# File 'lib/sudoku/logic.rb', line 76

def valid_grid?
  each do |x, y, val|
    next if val.zero?
    return false unless valid_cell? x, y, val
  end
  
  true
end