書いてみた > 人生を書き換える者すらいた。: 人材獲得作戦・4 試験問題ほか

まずは元ネタ:

これを解いてみました.

久し振りにRubyを書いたので,かなり微妙.
さらにいくつかまずいと思う部分があるけど,無視してガーっと書いたので,突っ込み大歓迎です:

def parse_input(io)
  io.read.split("\n").map {|row| row.split(//)}
end

def size_of_maze(maze)
  [maze.size, maze[0].size]
end

def find_position(maze, char)
  row_p = maze.find_index {|row|
    row.include?(char)
  }
  col_p = maze[row_p].find_index {|elm|
    elm == char
  }
  [row_p, col_p]
end

def init_cstr_mat(size_of_maze, pos_goal, maze)
  cost_mat = Array.new(size_of_maze[0]) {|i|
    Array.new(size_of_maze[1]) {|j|
      size_of_maze[0]*size_of_maze[1]
    }
  }
  cost_mat[pos_goal[0]][pos_goal[1]] = 0
  maze.each_with_index {|row, i|
    row.each_with_index {|elm, j|
      if elm == "*"
        cost_mat[i][j] = nil
      end
    }
  }
  cost_mat
end

def do_arounds(i, j, &p)
  [[i, j - 1],
   [i + 1, j],
   [i, j + 1],
   [i - 1, j],
  ].each {|pos|
    yield pos
  }
end

def update(i, j, current_turn, cost_mat, maze)
  do_arounds(i, j) {|ni, nj|
    if cost_mat[ni]
      if cost_mat[ni][nj]
        if cost_mat[ni][nj] > current_turn + 1
          cost_mat[ni][nj] = current_turn + 1
        end
      end
    end
  }
end

def search(maze, cost_mat, pos_goal)
  current_turn = 0
  loop {
    maze.each_with_index {|row, i|
      row.each_with_index {|elm, j|
        if cost_mat[i][j] == current_turn
          update(i, j, current_turn, cost_mat, maze)
        end
      }
    }
    break if current_turn > 1000
    current_turn += 1
  }
end

def path_extract(maze, cost_mat, pos_start)
  cur_pos = pos_start
  cur_cost = cost_mat[cur_pos[0]][cur_pos[1]]
  loop {
    do_arounds(cur_pos[0], cur_pos[1]) {|ni, nj|
    if cost_mat[ni]
      if cost_mat[ni][nj]
        if cost_mat[ni][nj] < cur_cost
          return if maze[ni][nj] == "G"
          maze[ni][nj] = "$"
          cur_pos = [ni, nj]
          cur_cost = cost_mat[ni][nj]
        end
      end
    end      
    }
  }
end

def main
  maze = parse_input($stdin)
  maze_size = size_of_maze(maze)
  pos_goal = find_position(maze, "G")
  cost_mat = init_cstr_mat(maze_size, pos_goal, maze)
  search(maze, cost_mat, pos_goal)
  pos_start = find_position(maze, "S")
  path_extract(maze, cost_mat, pos_start)
  puts maze.map{|row| row.join }.join("\n")
end

main

長いことRubyを書くことが無かったので,かなり変な(Ruby好きからすると「らしくない」?)感じになっていると思います.
それにアルゴリズムとして見ても,かなりオーダーがひどいでしょう.

しかし,問題を解くコードを速く書くのならば,こんな感じで十分でしょう.

しかし…見れば見る程,改善の余地があるな…これ…