미로에서 벽을 노크


10

규칙 :

이 게임에서는 벽과 열린 공간으로 구성된 N x M 크기의 직사각형 그리드의 맨 위에서 시작합니다. 입력은 N 문자의 M 문자이며, 여기서 a .는 열린 공간을 x지정하고 a는 벽을 지정합니다. 프로그램은 K 벽을 가로 지르는 왼쪽 상단 모서리에서 오른쪽 하단 모서리 (대각선 없음)까지의 경로가 있도록 가장 작은 숫자 K를 출력해야합니다.

예를 들어, 입력이 주어지면 :

..x..
..x..
xxxxx
..x..
..x..

프로그램이 출력되어야합니다 2.

다른 예 :

출력 4:

xxxxx
x.x.x
x.x.x
x..xx

출력 0:

.xxxxxxxx
.x...x...
.x.x.x.x.
.x.x...x.
...xxxxx.

출력 6:

xx
xx
xx
xx
xx

추가 음식 :

보다 쉽게 ​​사용할 수 있도록하려면 명령 줄 매개 변수로 N 및 M을 지정할 수 있습니다.

프로그램이 어떤 형태로든 경로를 인쇄하도록 할 수 있다면 추가 크레딧.


4
: yawn : Dijkstra, 힙은 V [2] [] 및 카운터입니다.
피터 테일러

4
@ 피터 테일러 그러나 얼마나 짧은 코드를 만들 수 있습니까?
migimaru

답변:


3

루비 1.9 (235) (225) (222) (214)

이것이 Dijkstra 기반의 프로그램보다 짧은 지 모르겠지만 다른 접근법을 시도 할 것이라고 생각했습니다. 이것은 루프에서 정규 표현식을 사용하여 각 공간에 도달하는 데 필요한 최소 수의 벽으로 표시합니다.

w=".{#{/\s/=~s=$<.read}}?"
j="([.x])"
s[0]=v=s[0]<?x??0:?1
(d=v[-1];n=v.succ![-1]
0while(s.sub!(/#{j}(#{w+d})/m){($1<?x?d: n)+$2}||s.sub!(/(#{d+w})#{j}/m){$1+($2<?x?d: n)}))while/#{j}/=~q=s[-2]
p v.to_i-(q==n ?0:1)

입력은 명령 행에서 파일로 지정됩니다. 즉

> ruby1.9.1 golf.rb maze.txt

언 골프 드 :

# read in the file
maze = $<.read

# find the first newline (the width of the maze)
width = /\s/ =~ maze

# construct part of the regex (the part between the current cell and the target cell)
spaces = ".{#{width}}?"

# construct another part of the regex (the target cell)
target = "([.x])"

# set the value of the first cell, and store that in the current wall count
maze[0] = walls = (maze[0] == "x" ? "1" : "0")

# loop until the goal cell is not "." or "x"
while /#{target}/ =~ (goal = s[-2])

  # store the current wall count digit and the next wall count digit, while incrementing the wall count
  current = walls[-1]; next = walls.succ![-1]

  # loop to set all the reachable cells for the current wall count
  begin

    # first regex handles all cells above or to the left of cells with the current wall count
    result = s.sub!(/#{target}(#{spaces + current})/m) {
      ($1 == 'x' ? next : current) + $2
    }

    # second regex handles all cells below or to the right of cells with the current wall count
    result = result || s.sub!(/(#{current + spaces})#{target}/m) {
      $1 + ($2 == 'x' ? next : current)
    }
  end while result != nil
end

# we reached the goal, so output the wall count if the goal was a wall, or subtract 1 if it wasn't
puts walls.to_i - (goal == next ? 0 : 1)

2

펄 5.10 (164)

undef$/;$_=<>;/\n/;$s="(.{$-[0]})?";substr$_,0,1,($n=/^x/||0);
until(/\d$/){1while s/([.x])($s$n)/$n+($1eq x).$2/se
+s/$n$s\K[.x]/$n+($&eq x)/se;$n++}
/.$/;print"$&\n"

여분의 Perl 터치만으로 migimaru의 솔루션과 동일한 라인을 따라 이동합니다. 5.10이 필요합니다 \K에서 s///.


9 개 이상의 벽을 통과해야하는 미로를 올바르게 처리합니까?
migimaru

@migimaru 아니요. 문자를 약간만 늘려서 최대 45 정도까지 얻을 수 있고, 조금만 더 늘리면 거의 무제한으로 얻을 수 있지만 꽤 예쁘지는 않습니다.
hobbs

2

파이썬 406 378 360 348418 문자

import sys
d={}
n=0
for l in open(sys.argv[1]):
 i=0
 for c in l.strip():m=n,i;d[m]=c;i+=1
 n+=1
v=d[0,0]=int(d[0,0]=='x')
X=lambda *x:type(d.get(x,'.'))!=str and x
N=lambda x,y:X(x+1,y)or X(x-1,y)or X(x,y+1)or X(x,y-1)
def T(f):s=[(x,(v,N(*x))) for x in d if d[x]==f and N(*x)];d.update(s);return s
while 1:
 while T('.'):pass
 v+=1
 if not T('x'):break
P=[m]
s,p=d[m]
while p!=(0,0):P.insert(0,p);x,p=d[p]
print s, P

무게를 가진 움직임이 x현장 에 있기 때문에 단순화 된 Dijkstra . 그것은 "파도"에서 이루어지며, 첫 번째 루프는 .앞을 터치 하는 필드 를 찾아서 같은 무게로 x설정합니다 +1. 더 이상 방문하지 않은 필드가없는 동안 반복하십시오.

결국 우리는 모든 분야의 무게를 알고 있습니다.

입력은 명령 행에서 파일로 지정됩니다.

python m.py m1.txt

업데이트 : 경로를 인쇄합니다.


1

C ++ 버전 (610 607 606 584)

#include<queue>
#include<set>
#include<string>
#include<iostream>
#include<memory>
#define S second
#define X s.S.first
#define Y s.S.S
#define A(x,y) f.push(make_pair(s.first-c,make_pair(X+x,Y+y)));
#define T typedef pair<int
using namespace std;T,int>P;T,P>Q;string l;vector<string>b;priority_queue<Q>f;set<P>g;Q s;int m,n,c=0;int main(){cin>>m>>n;getline(cin,l);while(getline(cin,l))b.push_back(l);A(0,0)while(!f.empty()){s=f.top();f.pop();if(X>=0&&X<=m&&Y>=0&&Y<=n&&g.find(s.S)==g.end()){g.insert(s.S);c=b[X][Y]=='x';if(X==m&&Y==n)cout<<-(s.first-c);A(1,0)A(-1,0)A(0,1)A(0,-1)}}}

Dijkstra의 알고리즘을 구현합니다.

언 골프 :

#include<queue>
#include<set>
#include<string>
#include<iostream>
#include<memory>

using namespace std;
typedef pair<int,int>P;
typedef pair<int,P>Q;

int main()
{
    int             m,n;
    string          line;
    vector<string>  board;

    cin >> m >> n;getline(cin,l);
    while(getline(cin,line))
    {
        board.push_back(line);
    }

    priority_queue<Q>   frontList;
    set<P>              found;
    frontList.push(make_pair(0,make_pair(0,0)));
    while(!frontList.empty())
    {
        Q s=frontList.top();
        frontList.pop();
        if(   s.second.first>=0
           && s.second.first<=m
           && s.second.second>=0
           && s.second.second<=n
           && found.find(s.second)==found.end()
        )
        {
            found.insert(s.second);
            int c=board[s.second.first][s.second.second]=='x';
            if(  s.second.first==m
              && s.second.second==n
            )
            {   cout<<-(s.first-c);
            }
            frontList.push(make_pair(s.first-c,make_pair(s.second.first+1,s.second.second)));
            frontList.push(make_pair(s.first-c,make_pair(s.second.first-1,s.second.second)));
            frontList.push(make_pair(s.first-c,make_pair(s.second.first,s.second.second+1)));
            frontList.push(make_pair(s.first-c,make_pair(s.second.first,s.second.second-1)));
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.