查看完整版本: 2008-05-04 Ruby 测试题(00015)

jmouse 2008-5-4 11:15

2008-05-04 Ruby 测试题(00015)

青年节,我是挨不上边了,上班了,出题。
今天做数独,最近比较流行的一个小游戏。
数独的游戏规则:
9x9个格子里,已有若干数字,其它宫位留白,玩家需要自己按照逻辑推敲出剩下的空格里是什么数字,使得每一行与每一列都有1到9的数字,每个小九宫格里也有1到9的数字,并且一个数字在每个行列及每个小九宫格里都只能出现一次。
输入及输出方式随意,能说明清楚就行。
测试用例一:
003020600
900305001
001806400
008102900
700000008
006708200
002609500
800203009
005010300
测试用例二:
000000907
000420180
000705026
100904000
050000040
000507009
920108000
034059000
507000000

PS:数独也是EULER上的一道题目,况且我拿这个来说事,也是为了延续“回溯”这个话题。

司马睿风 2008-5-4 15:13

帖个不完整的,最近心情不好,想不出好方法[code]class Array < Object
def devide
  all = [[nil,nil,nil],[nil,nil,nil],[nil,nil,nil]]
  self.clone.each {|v|
  all[0][self.index(v)] = v if self.index(v) < 3
  all[1][self.index(v) - 3] = v if [3,4,5].include?(self.index(v))
  all[2][self.index(v) - 6] = v if self.index(v) > 5
  }
  return all
end
end[/code]

司马睿风 2008-5-4 15:14

看错题了,这是3*3的,呃,不过9*9应该一样的说

bbschat 2008-5-4 19:07

这题难度很高,PU目前能答出的也就1000人左右,
最近比较忙,我也一直没做这题,既然J出题了,还是做一下吧。
但是直接贴程序感觉有违 PU 的宗旨。

先贴答案吧

"483921657"
"967345821"
"251876493"
"548132976"
"729564138"
"136798245"
"372689514"
"814253769"
"695417382"
""
"462831957"
"795426183"
"381795426"
"173984265"
"659312748"
"248567319"
"926178534"
"834259671"
"517643892"

PS:全50题出解在我机器上大约150秒左右,平均3秒解出一道,难题一般也在10秒以内,最慢的是第41和49题,要花11,12秒左右才出答案。
核心伪代码如下[code]  读取输入,构建数独对象(以下简称对象)
  对该对象进行检查(持续填入可能情况只有1个的数字,同时判断冲突),设定对象的解决状态。
    while 对象未解决
      break if 对象无解并且尝试列表为空
   
      if 对象解决状态为可以继续尝试
    选取该对象可选值最少的单元
      删除并记录该单元的第一个尝试值
     尝试列表(数组)追加该对象
        对设定尝试值的对象进行检查(调用上面使用的检查函数)
      else
        尝试列表 pop,除非尝试列表最后一个对象的可选值最少的那个单元有尝试值
         设定对象为尝试列表的最后一个对象
      end
    end[/code]说穿了就是用计算机模仿一般人解数独的实际做法,想看完整代码的话,请短消息沟通?:)

追加2个Case

Grid 41
000900002
050123400
030000160
908000000
070000090
000000205
091000050
007439020
400007000

Grid 49
000003017
015009008
060000000
100007000
009000200
000500004
000000020
500600340
340200000

[[i] 本帖最后由 bbschat 于 2008-5-4 19:53 编辑 [/i]]

jmouse 2008-5-5 10:12

我用一维数组来回溯解的,所以时间差很大,但是笨也有笨的好处,比如,49我只要1秒。。。

[[i] 本帖最后由 jmouse 于 2008-5-5 10:14 编辑 [/i]]

jmouse 2008-5-13 11:34

最近比较忙,这里也不够火热。
先把我的96贴上来[code]def Euler96()
  arr = IO.readlines("sudoku.txt")
  sum = 0
  ii = 1
  for k in (0...arr.size/10)
    tmp=[]
    (0).upto(8){|i|
      tmp[i] = arr[k*10 + i+1]
    }
    $matrix = ""
    $ori = ""
    0.upto(8) {|x|
      0.upto(8) {|y|
        $ori += tmp[x][y].chr
        $matrix += tmp[x][y].chr
      }
    }
    #puts k
    t0 = Time.now
    sum += solve()
    printf "i=%d, time=%d\n",ii,Time.now-t0
    ii+=1
    STDOUT.flush
  end
  puts sum
end
def solve()
  n = 0
  while true
    if $ori[n] == 48
      $matrix[n] += 1
      if $matrix[n] == 58
        $matrix[n] = 48
        j = n - 1
        while j >= 0
          break if $ori[j] == 48
          j -= 1
        end
        if j == -1
          puts "No"
          break
        end
        n = j
      else        
        if check(n)
          j = n + 1
          while j < 81
            break if $matrix[j] == 48
            j += 1
          end
          if j == 81
=begin            
            0.upto(8) {|x|
              0.upto(8) {|y|
                nn = x * 9 + y
                printf "%s",$matrix[nn].chr
              }
              printf "\n"
            }
=end      
            tt = $matrix[0].chr + $matrix[1].chr + $matrix[2].chr
            return tt.to_i
          end
          n = j
        end
      end
    else
      n += 1
    end
  end
end
def check(n)
  x = n / 9
  y = n % 9
  count_x = 0
  count_y = 0
  0.upto(8) {|i|
    count_x += 1 if $matrix[n] == $matrix[i * 9 + y]
    count_y += 1 if $matrix[n] == $matrix[x * 9 + i]   
  }
  return false if count_x > 1 or count_y > 1
  xx = (x / 3)*3
  yy = (y / 3)*3
  count = 0
  0.upto(2) {|i|
    count += 1 if $matrix[n] == $matrix[xx*9+yy + i]
    count += 1 if $matrix[n] == $matrix[(xx+1)*9+yy + i]
    count += 1 if $matrix[n] == $matrix[(xx+2)*9+yy + i]
  }
  return false if count > 1
  return true
end
#test
Euler96()[/code]
页: [1]
查看完整版本: 2008-05-04 Ruby 测试题(00015)