class GoldMaze
attr_accessor :n,:score, :count, :sum, :maze
def initialize n,level,maze=[]
@n = n
@level=level
if maze == []
@maze = n.times.map { |i| n.times.map { |j| rand(10) } }
else
@maze = maze
end
@x = n/2
@y = n/2
@maze[@y][@x] = 0
@score = 0
@bestsofar = 0
@count = 0
@sum = 0
@maze.each do |row|
row.each do |cell|
@sum += cell
end
end
end
# pattern tells which cells have been visited. Bitmap.
# path shows the path being followed. e.g. 'urdl'
def find n, x, y, pattern, score, path
@count += 1
bit = @n*x+y
s2 = score
cell = 0
cell = @maze[y][x] if @maze[y][x] != ' ' and @maze[y][x] != '*' and pattern[bit]==0
s2 += cell
return [0,path] if pattern[bit] == 1
return [0,path] if @maze[y][x] == 0
return [0,path] if s2 + 9 * (@level - n) <= @bestsofar and pattern[bit]==0
@bestsofar = s2 if n == @level and s2 > @bestsofar
return [s2,path] if n == @level
n2 = n+1
p2 = pattern | (1 << @n*x+y)
cands = [['r',(x+1)%@n, y], ['l',(x-1)%@n, y], ['d',x,(y+1)%@n], ['u',x,(y-1)%@n] ].map do |dir,x,y|
bit = @n*x+y
value = 0
value = @maze[y][x] if @maze[y][x] != ' ' and pattern[bit] == 0
[value, dir,x,y]
end
cands.map do |_,dir,x,y|
find(n2, x, y, p2, s2, path+dir)
end.sort.last
end
end
n = 5
level = 20
maze = GoldMaze.new 5,level, [[9, 1, 3, 1, 9], [6, 3, 2, 4, 1], [0, 7, 1, 7, 7], [5, 4, 9, 4, 9], [7, 9, 1, 5, 5]]
maze.maze[n/2][n/2] = ' '
start = Time.now
optimum = maze.find(0,maze.n/2,maze.n/2,0,0,'')
puts "CPU: #{Time.now-start}"
puts optimum
# Result:
#CPU: 16.577948
#115
#rrdrdruuululululdddr
Y2xhc3MgR29sZE1hemUKICBhdHRyX2FjY2Vzc29yIDpuLDpzY29yZSwgOmNvdW50LCA6c3VtLCA6bWF6ZQogIGRlZiBpbml0aWFsaXplIG4sbGV2ZWwsbWF6ZT1bXQogICAgQG4gPSBuCiAgICBAbGV2ZWw9bGV2ZWwKICAgIGlmIG1hemUgPT0gW10KICAgICAgQG1hemUgPSBuLnRpbWVzLm1hcCB7IHxpfCBuLnRpbWVzLm1hcCB7IHxqfCByYW5kKDEwKSB9IH0KICAgIGVsc2UKICAgICAgQG1hemUgPSBtYXplCiAgICBlbmQKICAgIEB4ID0gbi8yCiAgICBAeSA9IG4vMgogICAgQG1hemVbQHldW0B4XSA9IDAKICAgIEBzY29yZSA9IDAKICAgIEBiZXN0c29mYXIgPSAwCiAgICBAY291bnQgPSAwCiAgICBAc3VtID0gMAogICAgQG1hemUuZWFjaCBkbyB8cm93fAogICAgICByb3cuZWFjaCBkbyB8Y2VsbHwKICAgICAgICBAc3VtICs9IGNlbGwKICAgICAgZW5kCiAgICBlbmQKICBlbmQKICAKICAjIHBhdHRlcm4gdGVsbHMgd2hpY2ggY2VsbHMgaGF2ZSBiZWVuIHZpc2l0ZWQuIEJpdG1hcC4KICAjIHBhdGggc2hvd3MgdGhlIHBhdGggYmVpbmcgZm9sbG93ZWQuIGUuZy4gJ3VyZGwnCiAgZGVmIGZpbmQgbiwgeCwgeSwgcGF0dGVybiwgc2NvcmUsIHBhdGgKICAgIEBjb3VudCArPSAxCiAgICBiaXQgPSBAbip4K3kKICAgIHMyID0gc2NvcmUKICAgIGNlbGwgPSAwCiAgICBjZWxsID0gQG1hemVbeV1beF0gaWYgQG1hemVbeV1beF0gIT0gJyAnIGFuZCBAbWF6ZVt5XVt4XSAhPSAnKicgYW5kIHBhdHRlcm5bYml0XT09MAogICAgczIgKz0gY2VsbAogICAgcmV0dXJuIFswLHBhdGhdIGlmIHBhdHRlcm5bYml0XSA9PSAxCiAgICByZXR1cm4gWzAscGF0aF0gaWYgQG1hemVbeV1beF0gPT0gMAogICAgcmV0dXJuIFswLHBhdGhdIGlmIHMyICsgOSAqIChAbGV2ZWwgLSBuKSA8PSBAYmVzdHNvZmFyIGFuZCBwYXR0ZXJuW2JpdF09PTAKCiAgICBAYmVzdHNvZmFyID0gczIgIGlmIG4gPT0gQGxldmVsIGFuZCBzMiA+IEBiZXN0c29mYXIKICAgIHJldHVybiBbczIscGF0aF0gaWYgbiA9PSBAbGV2ZWwgCgogICAgbjIgPSBuKzEKICAgIHAyID0gcGF0dGVybiB8ICgxIDw8IEBuKngreSkKCiAgICBjYW5kcyA9IFtbJ3InLCh4KzEpJUBuLCB5XSwgWydsJywoeC0xKSVAbiwgeV0sIFsnZCcseCwoeSsxKSVAbl0sIFsndScseCwoeS0xKSVAbl0gXS5tYXAgZG8gfGRpcix4LHl8CiAgICAgIGJpdCA9IEBuKngreQogICAgICB2YWx1ZSA9IDAKICAgICAgdmFsdWUgPSBAbWF6ZVt5XVt4XSBpZiBAbWF6ZVt5XVt4XSAhPSAnICcgYW5kIHBhdHRlcm5bYml0XSA9PSAwCiAgICAgIFt2YWx1ZSwgZGlyLHgseV0KICAgIGVuZAoKICAgIGNhbmRzLm1hcCBkbyB8XyxkaXIseCx5fAogICAgICBmaW5kKG4yLCB4LCB5LCBwMiwgczIsIHBhdGgrZGlyKQogICAgZW5kLnNvcnQubGFzdAoKICBlbmQKCmVuZAoKbiA9IDUKbGV2ZWwgPSAyMAptYXplID0gR29sZE1hemUubmV3IDUsbGV2ZWwsIFtbOSwgMSwgMywgMSwgOV0sIFs2LCAzLCAyLCA0LCAxXSwgWzAsIDcsIDEsIDcsIDddLCBbNSwgNCwgOSwgNCwgOV0sIFs3LCA5LCAxLCA1LCA1XV0KbWF6ZS5tYXplW24vMl1bbi8yXSA9ICcgJwoKc3RhcnQgPSBUaW1lLm5vdwpvcHRpbXVtID0gbWF6ZS5maW5kKDAsbWF6ZS5uLzIsbWF6ZS5uLzIsMCwwLCcnKQpwdXRzICJDUFU6ICN7VGltZS5ub3ctc3RhcnR9IgpwdXRzIG9wdGltdW0KCiMgUmVzdWx0OgojQ1BVOiAxNi41Nzc5NDgKIzExNQojcnJkcmRydXV1bHVsdWx1bGRkZHI=