LoginSignup
1
0

More than 1 year has passed since last update.

Ruby で 数独 の2

Last updated at Posted at 2022-03-01

はじめに

前回の記事から一年近くたっていますが、Numo::NArrayの学習を含めて、久々に取り組みたいと思います。

Numo::NArray

require.rb
require 'numo/narray'
include Numo
new.rb
@banmen = UInt32.zeros(h, w)

XXX.zerosで、初期値0 hw列の行列を生成します。

cast.rb
@uramen = NArray.cast(Array.new(h){ Array.new(w){ (1..9).to_a } })

NArray.castを使用するとRubyの配列から行列を生成することができます。
ここでは、3次元の行列をイメージします。

20220301a.png

初期状態では、1~9のすべての数値の可能性があります。
ここで、角に3が設定されたとします。
すると行、列、ブロックの三つで3を消すことができます。

20220301b.png

初期の配置が決まるたびに、積まれたダイスが次々に落とされるイメージをコーディングします。

今回のソース

narray01.rb
require 'numo/narray'
include Numo

h = w = 9
@banmen = UInt32.zeros(h, w)
@uramen = NArray.cast(Array.new(h){ Array.new(w){ (1..9).to_a } })

def mask(h, w, num)
  return if num == 0
  h2 = (h / 3) * 3
  w2 = (w / 3) * 3
  maskarray = @uramen[h, w, 0..].eq(num)
  @uramen[h, w, 0..] *= maskarray            # 数値の設置用マスク
  maskarray = @uramen[h, 0.., 0..].ne(num)
  @uramen[h, 0.., 0..] *= maskarray          # 行のマスク
  maskarray = @uramen[0.., w, 0..].ne(num)
  @uramen[0.., w, 0..] *= maskarray          # 列のマスク
  maskarray = @uramen[h2..h2+2, w2..w2+2, 0..].ne(num)
  @uramen[h2..h2+2, w2..w2+2, 0..] *= maskarray # ブロックのマスク
end

h.times do |i|
  a = gets.chomp.split('').map(&:to_i)
  a.each_with_index do |x, j|
    @banmen[i, j] = x
    mask(i, j, x)
  end
end

今回のポイントはマスク処理です。

maskarray.rb
require 'numo/narray'
include Numo

@uramen = NArray.cast([1, 2, 3, 4, 5, 6, 7, 8, 9])

maskarray = @uramen.eq(3)
p maskarray
# Numo::Bit#shape=[9]
# [0, 0, 1, 0, 0, 0, 0, 0, 0]

@uramen *= maskarray
p @uramen
# Numo::Int32#shape=[9]
# [0, 0, 3, 0, 0, 0, 0, 0, 0]

eqで等しいとき、neで等しくないとき、01で構成された行列を生成し行列演算を行うことにより、不要な数値を0に置換します。

まとめ

今回は、画像生成で力尽きました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0