最終更新: 2013-08-20T01:04+0900
「makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ」経由で「人生を書き換える者すらいた。: 人材獲得作戦・4 試験問題ほか」
粘菌でも迷路問題を解けるというのだから負けてはいられない。Rubyで一時間半弱かかった。
#! ruby # coding: Shift_JIS # 迷路データ maze = <<MAZE ************************** *S* * * * * * * ************* * * * * ************ * * * * ************** *********** * * ** *********************** * * G * * * *********** * * * * ******* * * * * * ************************** MAZE # マップ class Point def initialize(x, y) @x, @y = x, y end attr_reader :x, :y def ==(other) @x == other.x && @y == other.y end def to_s "(#{@x},#{@y})" end def left Point.new(@x-1, @y) end def right Point.new(@x+1, @y) end def up Point.new(@x, @y-1) end def down Point.new(@x, @y+1) end end class Map def initialize(maze) lines = maze.strip.split(/\r\n?|\n/) @height = lines.length @width = lines.first.length y = -1 @map = lines.map{|line| y += 1 x = -1 line.split(//).map{|ch| x += 1 if(ch == 'G') @goal = Point.new(x, y) nil elsif(ch == 'S') @start = Point.new(x, y) nil elsif(ch == '*') -1 else nil end } } end attr_reader :height, :width attr_reader :start, :goal def []=(point, value) @map[point.y][point.x] = value end def [](point) @map[point.y][point.x] end def up(point) return -1 if point.y-1 < 0 return @map[point.y-1][point.x] end def down(point) return -1 if self.height <= point.y+1 return @map[point.y+1][point.x] end def left(point) return -1 if point.x-1 < 0 return @map[point.y][point.x-1] end def right(point) return -1 if self.width <= point.x+1 return @map[point.y][point.x+1] end end map = Map.new(maze) #puts "width×height = #{map.width}×#{map.height}" #puts "start:#{map.start} / goal:#{map.goal}" map[map.goal] = 0; #puts "goal=#{map[map.goal]}" # 先端 nodes = [map.goal] while node = nodes.shift next if node == map.start [node.left, node.right, node.up, node.down].each{|nxt| case(map[nxt]) when -1 # 壁 when nil # 未踏 map[nxt] = map[node] + 1 nodes.push(nxt) else # 既に到達したルートがある if(map[node] + 1 < map[nxt]) map[nxt] = map[node] + 1 nodes.push(nxt) unless nodes.include?(nxt) end end } end # Map to result map.height.times{|y| map.width.times{|x| point = map[Point.new(x,y)] print point == -1 ? '***' : ("% 3d"%point) } puts } if false result = maze.strip.split(/\r\n?|\n/) node = map.start until node == map.goal [node.left, node.right, node.up, node.down].each{|nxt| if(map[nxt] == map[node] - 1) node = nxt result[nxt.y][nxt.x] = '$' break end } end puts result.join("\n")
ノードっていうのはひとマスのこと。「先端」っていうコメントが適当すぎる(植物では頂端分裂組織っていうらしい)。方針はゴールからスタートに向けて、一マス移動するごとに一ポイントを加算しながら全方位に触手を伸ばしていき、すでに他の触手が通過した道は、自分が最適な場合にのみ侵入するこの判断は不要。全ての触手が行き場を失うかスタートに到達するかしたら終了。スタートから一ずつ減っていく数字をたどると(一少ない数をもつ隣接マスが二つ以上あっても解答に求められていないので無視する)ゴールへ着き、それが最短経路(だったらいいな)。
最初は粘菌方式をまねようと思ったが、通路をすべて覆った状態からスタートして、スタートとゴールにつながっていない島を切り捨て、袋小路から撤退するのはいい。遠回りと近道を取捨選択するためにどういう評価をすればいいのかを決められなかった。どうすればいいの?粘菌は何を考えてる?例えば
二番目のリンク先のトラックバックを見てる。みんな優秀なのね、C++で一時間もかかってないし。何人かが言及している「BFS」。それって一般的知識? 幅優先探索(Breadth-First Search)か最良優先探索(Best-First Search)の略だということはわかった。
壁のもつポイントを -1 に設定したことで、壁に侵入しないことを保証する when節を省略してもよかったんじゃないだろうか。気付くのが遅れたが。
ゴールにも $ って書き込んでら。(スタートには書きこまんように気をつけたんだが)
粘菌すごい。
培地に、三個以上の餌を置く。粘菌は迷路の実験のように最短距離を結ぶか?
結果は違った。
粘菌は、丸く、複数の経路を持つ管を作った。「最短経路だと一カ所故障したら必ず孤立する場所が出ます。だから粘菌は、一カ所が故障しても全体はつながり、なおかつ距離がなるべく短い経路を作ったのです」
部分部分がどういう反応をするとそういう結果になるんだろ???
粘菌の行動原理は、量子ドット間の近接場光を介したエネルギー移動プロセスに類似している
BS GE VC KX LJ UZ ZY RW MS IS ML JE AL FWUN BR EJ AV DD XQ TV RR NM BQ PAME YG CX XB FJ LQ AT OC ZY GG IM WU XN IQ KMYA XT KU TW MOFREI.EDU JG KG NN GY VSMD QJ UU AF LS VP MB GG EPFA NJ OJ AB JD MS IUBU EZ GJQI CS OV LA
解析班はどこだ?