簡単な経路探索をしてみたよ

再帰とかラムダ式の勉強をするために、Lispを触ってました。参考にしたのはこちらのページ。
M.Hiroi's Home Page / xyzzy Lisp Programming
なんか、Lispよりも同ページのパズルにハマったり。さて、Lispも色々面白いんですけれどもまだ僕には読みづらくて、少し複雑なプログラムになると頭で組み立てづらくなります。そこで、上のリンクにあるバックトラックによる経路の探索を、練習のためにPerlで書き直してみました。アルゴリズムは把握したので、なるべく上のお手本を見ないで作ってみました。
なお、元となるグラフは上記リンクとまったく同じです。

#!perl
use strict;

# ハッシュでグラフを表現。
my %adjacent = (
  'A' => [qw(B C)],
  'B' => [qw(A C D)],
  'C' => [qw(A B E)],
  'D' => [qw(B E F)],
  'E' => [qw(C D G)],
  'F' => [qw(D)],
  'G' => [qw(E)],
  );

sub backtrack_search {
  my ($path, $goal) = @_;
  my $point = $path->[0];

  if ($point eq $goal) {
    # ゴールに到着
    @$path = reverse @$path;
    print "found: @$path\n";}
  else {
    my @next_point;
    for my $q ( @{ $adjacent{$point}} ) {
      # 探索に現在までの経路を含まない
      next if grep { $_ eq $q } @$path;
      push @next_point, $q;
    }
    for (@next_point) {
      backtrack_search([$_, @$path], $goal);
    }
  }
}

backtrack_search([ qw(A) ], 'G');
  • 一番最後の配列を手に入れる方法が思いつかなかったので、リストを反転して出力してます。
  • グラフはハッシュで表現してます。すごく見づらいです。
  • 特にアップする必要もないんだけど、更新がとまってたので。

幅優先探索はまた明日。