Hancurkan tembok dalam labirin

10

Aturan:

Dalam permainan ini Anda mulai di bagian atas kotak persegi panjang ukuran N x M yang terdiri dari dinding dan ruang terbuka. Input adalah N baris karakter M, di mana .menentukan ruang terbuka dan xmenentukan dinding. Program Anda harus menampilkan angka K terkecil sehingga terdapat jalur dari sudut kiri atas ke sudut kanan bawah (tanpa diagonal) yang melintasi dinding K.

Misalnya, diberi input:

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

output program Anda 2.

Contoh lain:

keluaran 4:

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

keluaran 0:

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

keluaran 6:

xx
xx
xx
xx
xx

Berita tambahan:

Jika itu membuat hidup Anda lebih mudah, Anda dapat menentukan N dan M sebagai parameter baris perintah.

Kredit ekstra jika Anda dapat membuat program Anda mencetak jalur dalam beberapa bentuk atau lainnya.

Tidak mengerti
sumber
4
: menguap: Dijkstra, dengan tumpukan yang merupakan V [2] [] dan penghitung.
Peter Taylor
4
@ Peter Taylor Tapi seberapa pendek Anda bisa membuat kode itu?
migimaru

Jawaban:

3

Ruby 1.9 (235) (225) (222) (214)

Saya tidak tahu apakah ini lebih pendek dari program yang didasarkan pada Dijkstra, tetapi saya pikir saya akan mencoba pendekatan yang berbeda. Ini menggunakan regex dalam satu lingkaran untuk menandai setiap ruang dengan jumlah minimal dinding yang diperlukan untuk mencapainya.

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)

Input ditentukan sebagai file pada baris perintah, yaitu

> ruby1.9.1 golf.rb maze.txt

Tidak Disatukan:

# 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)
migimaru
sumber
2

Perl 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"

Sangat mirip dengan solusi migimaru, hanya dengan sentuhan Perl ekstra. 5.10 diperlukan untuk \Kmasuk s///.

hobbs
sumber
Apakah ini benar menangani labirin yang membutuhkan melewati lebih dari 9 dinding?
migimaru
@migimaru No.
hobbs
2

Python 406 378 360 348 418 karakter

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

Dijkstra Sederhana, karena bergerak dengan berat berada di xlapangan. Hal ini dilakukan dalam "gelombang", loop pertama dengan menemukan .bidang yang menyentuh depan dan mengaturnya pada berat yang sama, daripada sekali menemukan xbidang yang menyentuh depan dan mengaturnya pada +1berat. Ulangi sementara tidak ada lagi bidang yang belum dikunjungi.

Pada akhirnya kita tahu berat untuk setiap bidang.

Input ditentukan sebagai file pada baris perintah:

python m.py m1.txt

Perbarui: mencetak jalur.

Sokongan
sumber
1

Versi 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)}}}

Menerapkan algoritma Dijkstra.

Tidak golf:

#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)));
        }
    }
}
Martin York
sumber