Schlage Mauern in einem Labyrinth nieder

10

Regeln:

In diesem Spiel beginnen Sie oben in einem rechteckigen Raster der Größe N x M, das aus Wänden und Freiflächen besteht. Die Eingabe besteht aus N Zeilen mit M Zeichen, wobei a .einen offenen Raum und a xeine Wand angibt. Ihr Programm sollte die kleinste Zahl K ausgeben, sodass ein Pfad von der oberen linken Ecke zur unteren rechten Ecke (keine Diagonalen) vorhanden ist, der K Wände kreuzt.

Zum Beispiel angesichts der Eingabe:

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

Ihr Programm sollte ausgegeben werden 2.

Andere Beispiele:

Ausgabe 4:

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

Ausgabe 0:

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

Ausgabe 6:

xx
xx
xx
xx
xx

Zusätzliche Leckerbissen:

Wenn es Ihnen das Leben erleichtert, können Sie N und M als Befehlszeilenparameter angeben.

Zusätzliches Guthaben, wenn Ihr Programm den Pfad in der einen oder anderen Form ausdrucken kann.

Ahnungslos
quelle
4
: yawn: Dijkstra, mit einem Haufen, der ein V [2] [] und ein Zähler ist.
Peter Taylor
4
@ Peter Taylor Aber wie kurz kannst du diesen Code machen?
Migimaru

Antworten:

3

Ruby 1,9 (235) (225) (222) (214)

Ich weiß nicht, ob dies kürzer ist als ein auf Dijkstra basierendes Programm, aber ich dachte, ich würde einen anderen Ansatz ausprobieren. Hierbei wird Regex in einer Schleife verwendet, um jeden Raum mit der minimalen Anzahl von Wänden zu markieren, die erforderlich sind, um ihn zu erreichen.

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)

Die Eingabe wird als Datei in der Befehlszeile angegeben, d. H.

> ruby1.9.1 golf.rb maze.txt

Ungolfed:

# 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
quelle
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"

Sehr ähnlich wie Migimarus Lösung, nur mit diesem zusätzlichen Perl-Touch. 5.10 wird für \Kin benötigt s///.

Hobbs
quelle
Behandelt dies Labyrinthe, die mehr als 9 Wände passieren müssen?
Migimaru
@migimaru Nein. Ich könnte es mit nur einer bescheidenen Zunahme der Charaktere auf ungefähr 45 bringen und mit einer weiteren kleinen Zunahme auf eine nahezu unbegrenzte Anzahl - aber es wäre nicht ganz so hübsch.
Hobbs
2

Python 406 378 360 348 418 Zeichen

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

Vereinfachte Dijkstra, da Bewegungen mit Gewicht auf dem xFeld sind. Dies geschieht in "Wellen", einer ersten Schleife, in der .Felder gefunden werden, die die Vorderseite berühren, und auf das gleiche Gewicht eingestellt werden, als wenn xFelder gefunden werden, die die Vorderseite berühren, und auf das +1Gewicht eingestellt werden. Wiederholen Sie diesen Vorgang, solange keine nicht besuchten Felder mehr vorhanden sind.

Am Ende kennen wir das Gewicht für jedes Feld.

Die Eingabe wird als Datei in der Befehlszeile angegeben:

python m.py m1.txt

Update: druckt den Pfad.

Ante
quelle
1

C ++ - Version (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)}}}

Implementiert den Dijkstra-Algorithmus.

Nicht 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
quelle