ナンプレを解く秀丸マクロ

前準備

  1. rubyをインストール
  2. TEXCELL Ruby用クリップボードライブラリをインストール
  3. clipboard_v100.7z をダウンロード
  4. lhaplusなどで解凍
  5. できた clipboard.rb を C:\Ruby\lib\ruby\site_ruby\2.X.X とかにコピー
//ナンプレを解く
//前準備
//1.ruby をインストール
//2.TEXCELL Ruby用クリップボードライブラリをインストール
//    ・https://www.texcell.co.jp/ruby/Lib/clipboard_v100.7z をダウンロード
//    ・lhaplus(https://forest.watch.impress.co.jp/library/software/lhaplus/)などで解凍
//    ・できた clipboard.rb を C:\Ruby\lib\ruby\site_ruby\2.X.X とかにコピー
//使い方
//1.問題となるテキストを準備
//    ・空欄には1~9以外の文字を入力
//    ・以降が空欄の場合省略可
//2.問題全体を範囲選択してマクロ実行
//3.末尾に回答が書き込まれる
//4.解題の過程は tmp_log.txt に書き出される

copy;
runsync2 "rubyw -x "+currentmacrofilename;
paste;endmacro;

/*
#/
#! ruby
# encoding: utf-8

$stdout=open("tmp_log.txt","w")
$stderr=open("tmp_err.txt","w")

require 'clipboard'

class Array
  def to_masu
    e=self
    [e[0][0..2]+e[1][0..2]+e[2][0..2],
     e[0][3..5]+e[1][3..5]+e[2][3..5],
     e[0][6..8]+e[1][6..8]+e[2][6..8],
     e[3][0..2]+e[4][0..2]+e[5][0..2],
     e[3][3..5]+e[4][3..5]+e[5][3..5],
     e[3][6..8]+e[4][6..8]+e[5][6..8],
     e[6][0..2]+e[7][0..2]+e[8][0..2],
     e[6][3..5]+e[7][3..5]+e[8][3..5],
     e[6][6..8]+e[7][6..8]+e[8][6..8]]
  end

  def to_n
    self.map{|e| e.map{|f| f.is_a?(Array) && f.size==1 ? f[0] : f}}
  end

  def to_p
    return "error" if self==["error"]
    self.map{|e| e.map{|f| f.is_a?(Array) ? "[#{f.join}]" : f}
      .join(",")}.join("\n")
  end

  def solve
    ay=self
    at=ay.transpose
    as=ay.to_masu
    ay.map!{|e|
      n=e.reject{|f| f.is_a?(Array)}.to_a
      e.map{|f| f.is_a?(Array) ? f-n : f}}.to_n
    at.map!{|e|
      n=e.reject{|f| f.is_a?(Array)}.to_a
      e.map{|f| f.is_a?(Array) ? f-n : f}}.to_n
    as.map!{|e|
      n=e.reject{|f| f.is_a?(Array)}.to_a
      e.map{|f| f.is_a?(Array) ? f-n : f}}.to_n
    puts "ay=";puts ay.to_p
    puts "at=";puts at.to_p
    puts "as=";puts as.to_p
    jy=ay.map{|e| e.select{|f| e.count(f)==f.size}.uniq}
    jt=at.map{|e| e.select{|f| e.count(f)==f.size}.uniq}
    js=as.map{|e| e.select{|f| e.count(f)==f.size}.uniq}
    ck=(ay+at+as).map{|e| e.reject{|f| f.is_a?(Array)}}.
      map{|e| e.map{|f| e.count(f)}.uniq}.uniq-[[1]]
    if ck.flatten.size>0
      return ay=["error"]
    end
    ay=ay.map.with_index{|e,i|#p jy[i][0]
      if jy[i]!=[]
        e.map{|f| f.is_a?(Array) && f!=jy[i][0] ? f-jy[i][0] : f}
      else
        e
      end}
    at=at.map.with_index{|e,i|#p jt[i][0]
      if jt[i]!=[]
        e.map{|f| f.is_a?(Array) && f!=jt[i][0] ? f-jt[i][0] : f}
      else
        e
      end}
    as=as.map.with_index{|e,i|#p js[i][0]
      if js[i]!=[]
        e.map{|f| f.is_a?(Array) && f!=js[i][0] ? f-js[i][0] : f}
      else
        e
      end}
    at=at.transpose
    as=as.to_masu
    ay=ay.map.with_index{|e,i| e.map.with_index{|f,j|
      f.is_a?(Array) ? f&at[i][j]&as[i][j] : f}}.to_n
  end
  def solves(n)
    ay=self
    100.times{|i|
      puts "\n#{i+n}回目"
      ar=ay.solve
      puts "ar=";puts ar.to_p
      return [ar,i+n] if ar==ay
      return [ar,i+n+1] if ar==["error"]
      ay=ar}
    ay
  end
  def has_arr?
    self.map{|e| e.map{|f| 1 if f.is_a?(Array)}.compact}.flatten.uniq[0]
  end
end

CBd = ClipBoard.new(__ENCODING__)
st=CBd.getText

ay=st.split("\r\n").map{|e| e.split("").values_at(0...9).
  map{|f| /[1-9]/=~f ? f.to_i : (1..9).to_a}}

arr,ans,cnt=[ay],[],1
arr.each{|ay|
  ay,cnt=ay.solves(cnt)
  if ay==["error"]
    puts "ダメだった orz"
    next
  elsif ay.has_arr?
    a0,i=[],1
    a1=ay.map{|e| e.map{|f|
      if (i==1 && f.is_a?(Array) && f.size==2)
        i,a0=2,[f,f[0]]
        f=f[0]
      else
        f
      end}}
    i=1
    a2=ay.map{|e| e.map{|f|
      if (i==1 && f.is_a?(Array) && f.size==2)
        i=2
        f=f[1]
      else
        f
      end}}
    puts "#{a0[0]} が #{a0[1]} として検討"
    arr<<a1
    arr<<a2
    cnt+=1
    next
  else
    ans=ay
    break
  end}

st="\n"+ans.map.with_index{|e,i|
  s=e.each_slice(3).map{|f| f.join}.join(" ")
  i%3==2 ? s+"\n" : s}.join("\n")+"\n"
st="\nerror\n" if st=="\n\n"
CBd.setText(st)

__END__
*/

使い方

  1. 問題となるテキストを準備
  2. 空欄には1~9以外の文字を入力
  3. 以降が空欄の場合省略可
  4. 問題全体を範囲選択してマクロ実行
  5. 末尾に回答が書き込まれる
  6. 解題の過程は tmp_log.txt に書き出される

コメント