ロボットが子猫を見つける


52

挑戦

ロボットが可能な限り少ないステップで子猫を見つけるのに役立つ文字数による最短コード。

ゴルファー、これは危機の時です-子猫が行方不明になり、それを見つけるのはロボットの仕事です!ロボットは最短距離で子猫に到達する必要があります。しかし、ロボットのやり方には多くの障害があり、彼はあなたに彼のために解決策をプログラムする必要があります。

以前はロボットがプログラムを実行させていましたが、そのプログラムは失われ、ロボットにはバックアップがありません:(。

ロボットのランタイムは最適ではなく、ロボットがソースコードから読み取る必要のある文字数が少なく、処理に費やす時間が最短であるため、子猫がより早く見つかります。

ロボットのメモリには、現在の場所の地図が含まれており、上部は北、下部は南、右は東、左は西を表しています。ロボットは常に、壁に囲まれた未知のサイズの長方形の部屋にあり、#レーダーマップで表されています。ロボットが入ることができる領域は、スペースで表されます

ロボットのレーダーは、部屋の多くの障害物もスキャンし、さまざまなASCII文字でマークします。ロボットはこれらの障害物を横断できません。レーダーは子猫を特別なASCII文字としてマークし、Kロボットの位置はでマークされRます。

ロボットのナビゲーションシステムはこのように動作します。彼は、移動する方向と移動ユニットの数のデュオを理解できます。たとえば、N 3「北3移動ユニット」を意味します。ロボットのレーダーマップは、移動単位が1つのASCII文字になるように作成されます。ロボットは4方向にのみ移動でき、斜めに移動することはできません。

勇敢な子猫セーバーであるあなたの仕事は、ロボットのレーダーマップを1回読み取り、最小の移動単位移動距離で、最小量の方向を出力することです。ロボットには、子猫へのパスが少なくとも1つあることが保証されています。

ロボットが子猫を見つけるのに役立たない誤動作プログラムを実行する時間を無駄にしないように、勇敢な子猫のセーバー、ロボットの過去のプログラムのこの出力を使用して、子猫を見つけるのに時間を無駄にしないことをお勧めします!

テストケース

Input:
    ######################
    #  d      3    Kj    #
    #                    #
    # R                  #
    #      q             #
    ######################
Output:
    E 13
    N 2

Input:
    ######################
    #  d  r   3    Kj    #
    #    p        p      #
    #         T        X #
    #      q   s   t     #
    #                    #
    #  R o    d     W    #
    #                    #
    #    g      t     U  #
    #                    #
    ######################
Output:
    N 1
    E 10
    N 4
    E 2

Input:
    ######################
    #  spdfmsdlwe9mw WEK3#
    #    we    hi        #
    #   rdf         fsszr#
    #     sdfg  gjkti    #
    #   fc  d g i        #
    #     dfg    sdd     #
    #    g        zfg    #
    #  df   df           #
    #             xcf   R#
    ######################
Output:
    N 1
    W 9
    N 5
    E 4
    N 1
    E 4
    N 1

コードカウントには、入力/出力(プログラム全体)が含まれます。


1
このゲームに触発されたのでしょうか?kongregate.com/games/Hamumu/robot-wants-kitty
ナブ


4
目標は明確です。「最小移動単位移動距離で、最小量の方向を出力します。」n方向とmステップの方法と、n方向より少ないがより多くのステップ、またはより多くの方向とより少ないステップを持つ別の方法があるかもしれません。為替レートはありますか?
ユーザー不明

2
ステップの数は方向の数よりも優れています。
リラヌナ

1
アイデアのステップ数が最も少なく、方向の数が最も少ない場合は、2番目の例には間違った解決策があります。最短経路については私の答えをご覧ください。
ダニエルC.ソブラル

回答:


10

C ++ 1002 899 799chars

注では、テンプレート内の>>間のスペースを除去するためにC ++ 0xを使用する必要があります。

最小のターン数でルートを見つけます。

#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<memory>
#define D make_pair
#define F first
#define S second
using namespace std;typedef pair<int,int>L;typedef vector<L>R;typedef multiset<pair<float,pair<L,R>>>B;vector<string> M;string l;int z,c,r=0;set<L> s;B b;L n;B::iterator f;R v;void A(int x,int y,int w){n=f->S.F;for(c=1;(z=M[n.S+=y][n.F+=x])==32||(z==75);++c)v.back()=D(w,c),b.insert(D(f->F+c+1./c,D(n,v)));}int main(){for(;getline(cin,l);++r){if((c=l.find(82))!=string::npos)b.insert(D(0,D(D(c,r),R())));M.push_back(l);}while(!b.empty()){f=b.begin();n=f->S.F;v=f->S.S;if(M[n.S][n.F]==75)break;if(s.find(n)==s.end()){s.insert(n);v.push_back(L());A(0,1,83);A(0,-1,78);A(1,0,69);A(-1,0,87);}b.erase(f);}for(c=v.size(),r=0;r<c;++r)n=v[r],printf("%c %d\n",n.F,n.S);}

またDijkstra's Algorithm、最短経路問題を解くため。
複数の等しいサイズのルートを区別するために、長い直線は複数の短い線よりも重みが小さくなります(これにより、曲がり角が少ない経路が優先されます)。

Cost of a path:  Len + 1/Len

Looking at Test Case 1:
========================
Thus Path E13 + N2 has a cost of 
      13 + 1/13 + 2 + 1/2
An alternative path E9 + N2 + E4 has a cost of
      9 + 1/9 + 2 + 1/2 + 4 + 1/4

The difference is
      Straight Path:   1/13 <   Bendy Path: (1/9 + 1/4)

より読みやすい形式で:

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

using namespace std;
typedef pair<int,int>                   L;
typedef vector<L>                       R;
typedef multiset<pair<float,pair<L,R>>> B;
vector<string>                          M;

string      l;
int         z,c,r=0;
set<L>      s;
B           b;
L           n;
B::iterator f;
R           v;

void A(int x,int y,int w)
{
    n=f->second.first;
    for(c=1;(z=M[n.second+=y][n.first+=x])==32||(z==75);++c)
        v.back()=make_pair(w,c),
        b.insert(make_pair(f->first+c+1./c,make_pair(n,v)));
}

int main()
{
    for(;getline(cin,l);++r)
    {
        if((c=l.find(82))!=string::npos)
            b.insert(make_pair(0,make_pair(make_pair(c,r),R())));
        M.push_back(l);
    }

    while(!b.empty())
    {
        f=b.begin();
        n=f->second.first;
        v=f->second.second;

        if(M[n.second][n.first]==75)
            break;

        if(s.find(n)==s.end())
        {
            s.insert(n);
            v.push_back(L());
            A(0,1,83);
            A(0,-1,78);
            A(1,0,69);
            A(-1,0,87);
        }
        b.erase(f);
    }

    for(c=v.size(),r=0;r<c;++r)
        n=v[r],
        printf("%c %d\n",n.first,n.second);
}

9

Scala 2.8(451文字)

...しかし、最小量の方向を優先して関係を解決するわけではありません(ただし、最小量のステップを見つけます)。

val m=io.Source.stdin.getLines.map(_.toArray).toSeq
var l=m.indexWhere(_ contains'R')
var c=m(l)indexOf'R'
val q=collection.mutable.Queue(l->c->"")
def s{val((l,c),p)=q.dequeue
if("R "contains m(l)(c))for((i,j,k)<-Seq((-1,0,"N"),(0,1,"E"),(1,0,"S"),(0,-1,"W")))q.enqueue(((l+i,c+j),p+k))
m(l)(c)='X'}
def P(s:String){if(s.nonEmpty){val (h,t)=s.span(s.head==)
println(s.head+" "+h.size)
P(t)}}
def Q{s
val((l,c),p)=q.head
if (m(l)(c)=='K')P(p)else Q}
Q

Scala 2.8、642文字は、タイを正しく解決します。

val m=io.Source.stdin.getLines.toSeq
var b=Map(0->0->0).withDefault(_=>Int.MaxValue)
var l=m.indexWhere(_ contains'R')
var c=m(l)indexOf'R'
val q=collection.mutable.PriorityQueue(l->c->List((' ',0)))(Ordering.by(t=>(-t._2.map(_._2).sum,-t._2.size)))
def s{val(p@(l,c),u@(h@(d,n))::t)=q.dequeue
if("R ".contains(m(l)(c))&&u.map(_._2).sum<=b(p)){b=b.updated(p,u.map(_._2).sum)
for((i,j,k)<-Seq((-1,0,'N'),(0,1,'E'),(1,0,'S'),(0,-1,'W'))){
val o=if(k==d)(d,n+1)::t else (k,1)::h::t
q.enqueue(((l+i,c+j),o))}}}
def P(l:List[(Char,Int)]){l.reverse.tail.foreach{t=>println(t._1+" "+t._2)}}
def Q{s;val((l,c),p)=q.head;if (m(l)(c)=='K')P(p)else Q}
Q

2番目の例では、問題で指定されているものよりも短いパスが見つかりました。

N 1
E 10
N 4
E 2

4

Python 2.6(504文字)

import sys,itertools
W,Q=len,list   
M=[]
B=[]
for l in sys.stdin.readlines():
    r=Q(l.strip())
    B.append([0]*W(r))
    M.append(r)
    if "R" in r:x,y=r.index("R"),W(B)-1
def S(B,M,x,y,P):
    c=M[y][x]
    b=B[y][x]
    if b and W(P)>b:return 0
    B[y][x]=W(P)
    if c=="K":return P  
    elif c=="R" and P:return 0
    if c in "R ":
        b=[]
        for q,w,s in((1,0,"E"),(-1,0,"W"),(0,-1,"N"),(0,1,"S")):
            r=S(B,M,x+q,y+w,P+s)
            if r and(W(r)<W(b)or not b):b=r
        if b:return b
    return 0
print "\n".join(k+str(W(Q(g)))for k,g in itertools.groupby(S(B,M,x,y,"")))

これは、最小限のステップを優先して関係を解決するようには見えません。
ダニエルC.ソブラル

4

Python 2.6(535文字)

exec 'eJzNlLFugzAQhneewhki2/KBworksVOkDu3QgVqVE2hBioFgCDhV371nJ1VbKR3SKYtl/jvs77MwtenafiBVqbs9WGcjLW05MB69tj05QEfqhpTNaMpeDyXDhsQORd3wLCK+YwT7u6PzFVK/Ep9Tsn6gmU50UTA2woHzc01KuqYZ20PPZSh85/iCO2etzBnTG8tcvlLxnovTPFVxzyGEC4lpiBay5xiuYMXBcRVtzxqTfP+IpqrelaRFsheoYJbBNvFj13asxd23gXHGmZU7bTaFDgiZH+MUYydtKBuZRuS0nvPmOt564Sl3CmlxcWAG6D3lXIkpeUMGB7nyfj82HW3FWvjTTVSYCXNJEUupEimannu+nl04WyM8XoB1F13E9S6Pt+ki0vDZXOdyd5su8X9cnm7DBa/tLGW4yh7yKCn1rIF+9vSTj/HiBeqCS1M3bMrnwOvbl5Ysi+eGLlkBhosjxl1fNwM5Ak7xH6CiT3SdT4U='.decode('base64').decode('zlib')

ひどく虐待されたA *実装に展開します。標準入力を読み取ります。最短距離でソリューションを検索します。方向の最小数を優先することにより、関係を切断します。リストは標準出力に移動します。子猫を見つけます。

開梱

ソースは、より小さな圧縮表現を取得するために、いくつかの場所で手動でアンチゴルフされました。たとえば、コンパスの方向に対するforループが展開されました。

import heapq,sys 
a=set() 
for v,p in enumerate(sys.stdin): 
 for u,s in enumerate(p): 
  if s in' KR':a.add((u,v)) 
  if s=='K':(q,r)=(u,v) 
  if s=='R':y=(u,v) 
o=[((abs(y[0]-q)+abs(y[1]-r),(y[0]!=q)+(y[1]!=r)),(0,0),y)] 
c=set() 
w={} 
while o: 
 _,h,x=heapq.heappop(o) 
 c.add(x) 
 s=lambda(u,v):(u,v-1) 
 y=s(x) 
 m=1 
 while y in a-c: 
  w[y]=[(h,x,(m,'N'))]+w.get(y,[]) 
  heapq.heappush(o,((abs(y[0]-q)+abs(y[1]-r)+h[0]+m,(y[0]!=q)+(y[1]!=r)+h[1]+1),(h[0]+m,h[1]+1),y)) 
  m+=1 
  y=s(y) 
 s=lambda(u,v):(u,v+1) 
 y=s(x) 
 m=1 
 while y in a-c: 
  w[y]=[(h,x,(m,'S'))]+w.get(y,[]) 
  heapq.heappush(o,((abs(y[0]-q)+abs(y[1]-r)+h[0]+m,(y[0]!=q)+(y[1]!=r)+h[1]+1),(h[0]+m,h[1]+1),y)) 
  m+=1 
  y=s(y) 
 s=lambda(u,v):(u+1,v) 
 y=s(x) 
 m=1 
 while y in a-c: 
  w[y]=[(h,x,(m,'E'))]+w.get(y,[]) 
  heapq.heappush(o,((abs(y[0]-q)+abs(y[1]-r)+h[0]+m,(y[0]!=q)+(y[1]!=r)+h[1]+1),(h[0]+m,h[1]+1),y)) 
  m+=1 
  y=s(y) 
 s=lambda(u,v):(u-1,v) 
 y=s(x) 
 m=1 
 while y in a-c: 
  w[y]=[(h,x,(m,'W'))]+w.get(y,[]) 
  heapq.heappush(o,((abs(y[0]-q)+abs(y[1]-r)+h[0]+m,(y[0]!=q)+(y[1]!=r)+h[1]+1),(h[0]+m,h[1]+1),y)) 
  m+=1 
  y=s(y) 
 if x==(q,r): 
  z='' 
  while x in w: 
   _,x,(m,d)=min(w[x]) 
   z='%s %d\n'%(d,m)+z 
  print z, 
  o=[]

3

c ++-681の必要な文字

#include <string>
#include <iostream>
#include <sstream>
using namespace std;
int d[]={-1,0,1,0},i,j,k,l,L=0,p=41,S;string I,m,D("ESWN");
int r(int o,int s){S=s;while((m[o]==32||m[o]==37)&&m[o+S]-35)
if(m[o+S]-p)S+=s;else return o+S;return 0;}
void w(int o){for(i=0;i<m.length();++i)for(j=0;j<4;++j)
if(k=r(o,d[j])){stringstream O;O<<D[j]<<" "<<int((k-o)/d[j])<<"\n"<<I;
I=O.str();if(p-41)--p,m[k]=37,w(k);cout<<I;exit(0);}}
int main(){while(getline(cin,I))m+=I,l=I.length();
d[1]-=d[3]=l;I="";for(i=0;i<m.length();++i)
switch(m[i]){case 82:case 75:m[i]/=2;case 32:break;default:m[i]=35;}
do{for(i=0;i<m.length();++i)if(r(i,-1)+r(i,-l)+r(i,1)+r(i,l))
{if(m[i]==37)w(i);m[i]=p+1;}}while(++p);}

これは、最初にしてマップ上のすべての障害を置き換え#S(との値を変更Kし、R非常に長いパスの文字スペースにヘッドルームを残すために、。そして、それは地図上の落書き。反復プロセスマークはすべての逐次アクセスの正方形を、それまでその後、同じアクセシビリティチェックルーチンを使用して、最小限の命令で開始に戻る位置の文字列を見つけます。これらの命令は、事前に保留することで文字列に読み込まれます。適切な順序で印刷します。

それは適切に関係を解決せず、そうするように簡単に適応させることができないので、私はそれをさらにゴルフするつもりはありません。

失敗する

#####
#   #
# # #
#R#K#
#   #
#####

生産

 $ ./a.out < kitten_4.txt
N 2
E 2
S 2

多かれ少なかれ読みやすいバージョン:

#include <string>
#include <iostream>
#include <sstream>
using namespace std;

int d[]={-1,0,1,0}
  , i, j, k
  , l      /* length of a line on input */
  , L=0    /* length of the whole map */
  , p=41   /* previous count  ( starts 'R'/2 ) */
  , S      /* step accumulator for step function */
  ; 
string I/*nput line, later the instructions*/
  , m/*ap*/
  , D("ESWN"); /* Reversed sence for back tracking the path */

int r/*eachable?*/(int o/*ffset*/, int s/*step*/){
//   cerr << "\tReachable?" 
//        << endl
//        << "\t\tOffset: " << o << " (" << o/5 << ", " << o%5 << ")" 
//        << "  [" << m[o] << "]" << endl
//        << "\t\tStep: " << s 
//        << endl
//        << "\t\tSeeking: " << "[" << char(p) << "]" 
//        << endl
//        << "\t\tWall:    " << "[" << char(35) << "]" 
//        << endl;
  S=s;
  while ( ( (m[o]==32)      /* Current character is a space */ 
        || (m[o]==37) ) /* Current character is a kitten */ 
      && (m[o+S]-35) /* Target character is not a wall */ 
      )
    {
//     cerr << "\t\tTry: " << o+S << "(" << (o+S)/5 << ", " << (o+S)%5 << ")" 
//   << "  [" << m[o+S] << "]" << endl;
    if (m[o+S]-p       /* Target character is not the previous count */ 
    ) {
//       cerr << "\t\twrong " << "  [" << m[o+S] << "] !!!" << endl;
      S+=s;
    }
    else  {             /* Target character *is* the previous count */
//       cerr << "\t\tFound " << "  [" << m[o+S] << "] !!!" << endl;
      return o+S;
    } 
  /* while ends */
      }
  return 0;
}

void w/*on*/(int o/*ffset*/){
//   cerr << "\tWON" << endl
//        << "\t\tOffset: " << o << "(" << o/5 << ", " << o%5 << ")" 
//        << "  [" << m[o] << "]" 
//        << endl
//        << "\t\tSeeking: " << "[" << char(p) << "]" 
//        << endl;
  for(i=0;i<m.length();++i) /* On all map squares */
    for(j=0;j<4;++j)
      if (k=r(o,d[j])) {
//  cerr << "found path segment..." 
//       << (k-o)/d[j] << " in the " << d[j] << " direction." << endl;
    stringstream O;
    O << D[j] 
      << " " 
      << int((k-o)/d[j]) 
      << "\n" 
      << I;
    I = O.str();
//  cerr << I << endl;
    /* test for final solution */
    if (p-41) 
      --p,m[k]=37, w(k); /* recur for further steps */
    cout << I;
    exit(0);
      }
    /* inner for ends */
  /* outer for ends */
}


int main(){
  while(getline(cin,I))
    m+=I,l=I.length();
//   cerr << "Read the map: '" << m << "'." << endl;
  d[1]-=d[3]=l;I="";
//   cerr << "Direction array:    " << D << endl;
//   cerr << "Displacement array: " << d[0] << d[1] << d[2] << d[3] << endl;
//   cerr << "Line length: " << l << endl;
  /* Rewrite the map so that all obstacles are '#' and the start and
     goal are '%' and ')' respectively. Now I can do pathfinding *on*
     the map. */
  for(i=0;i<m.length();++i)
    switch (m[i]) {
    case 82:         /* ASCII 82 == 'R' (41 == ')'  ) */
    case 75:m[i]/=2; /* ASCII 75 == 'K' (37 == '%' ) */
    case ' ':break;
    default: m[i]=35; /* ASCII 35 == '#' */ 
    };
//   cerr << "Re-wrote the map: '" << m << "'." << endl;
  do { /* For each needed count */
//     cerr << "Starting to mark up for step count " 
//   << p-41+1  << " '" << char(p) << "'" << endl;
    for(i=0;i<m.length();++i){ /* On all map squares */
//        cerr << "\tTrying position (" << i/l << ", " << i%l << ")" 
//      << "  [" << m[i] << "]"
//      << endl;
      if ( r(i, -1) /* west  */ +
       r(i, -l) /* north */ +
       r(i,  1) /* east  */ +
       r(i,  l) /* south */ 
       ) {
//    cerr << "Got a hit on : '" << m << "'." << endl;
//    cerr << "\twith '" << char(m[i]) <<" at position " << i << endl;
//    cerr << "target is " << char(37) << endl;
    if(m[i]==37)
      w(i); /* jump into the win routine which never returns */
    m[i]=p+1;
//  cerr << "Marked on map: '" << m << "'." << endl;
      }
    }
  } while(++p);
}

3

ルビー-539文字

多くの改善を行うことができますが、最短の手順と方向性で機能します。

M=[*$<]
r=M.map{|q|q.index('R')||0}
k=M.map{|q|q.index('K')||0}
D=M.map{|q|q.split('').map{[99,[]]}} 
def c h 
h.map{|i|i.inject([[]]){|a,b|a.last[0]!=b ? a<<[b, 1]:a.last[1]+=1;a}}.sort_by{|a|a.length}[0]
end
def t x,y,s,i
z,w=D[x][y][0],D[x][y][1]
if [' ','R','K'].index(M[x][y, 1])&&(z>s||z==s&&c(w).length>=c([i]).length)
D[x][y]=[s,z==s ? w<<i:[i]]
s+=1
t x+1,y,s,i+['S']
t x-1,y,s,i+['N']
t x,y+1,s,i+['E']
t x,y-1,s,i+['W']
end
end
t r.index(r.max), r.max, 0, []
puts c(D[k.index(k.max)][k.max][1]).map{|a|a*''}

1

ルビー-648文字

もう1つは、A *に簡単な方法で埋め込むことができないため、方向テストの数が最も少ないテストです。

m=$<.read.gsub /[^RK\n ]/,'#'
l=m.index($/)+1
s=m.index'R'
g=m.index'K'
h=->y{(g%l-y%l).abs+(g/l-y/l).abs}
n=->y{[y+1,y-1,y+l,y-l].reject{|i|m[i]=='#'}}
a=o=[s]
d=Array.new(m.length,9e9)
c,k,f=[],[],[]
d[s]=0
f[s]=h[s]
r=->y,u{u<<y;(y=k[y])?redo:u}
(x=o.min_by{|y|f[y]}
x==g ? (a=r[x,[]].reverse;break):0
o-=[x];c<<x
n[x].map{|y|c&[y]!=[]?0:(t=d[x]+1
o&[y]==[]?(o<<y;b=true):b=t<d[y]
b ? (k[y]=x;d[y]=t;f[y]=t+h[y]):0)})until o==[]
k=a.inject([[],nil]){|k,u|(c=k[1]) ? (k[0]<<(c==u-1?'E':c==u+1?'W':c==u+l ? 'N':'S')) : 0;[k[0],u]}[0].inject(["","",0]){|k,v|k[1]==v ? k[2]+=1 : (k[0]+=k[1]+" #{k[2]}\n";k[1]=v;k[2]=1);k}
puts k[0][3,9e9]+k[1]+" #{k[2]}\n"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.