새끼 고양이 찾기


52

도전

로봇이 새끼 고양이를 가능한 한 적은 단계로 찾는 데 도움이되는 문자 수로 가장 짧은 코드.

골퍼들, 이것은 위기의 시간입니다-새끼 고양이가 사라졌고 그것을 찾는 로봇의 일입니다! 로봇은 가능한 가장 짧은 경로에서 새끼 고양이에게 도달해야합니다. 그러나 로봇 방식에는 많은 장애물이 있으며, 솔루션을 프로그래밍해야합니다.

로봇은 그에게 프로그램을 제공했지만 그 프로그램을 잃어 버렸고 로봇에는 백업이 없습니다.

로봇의 런타임은 최고가 아니며 로봇이 소스 코드에서 읽어야하는 최소 문자, 처리 시간이 가장 짧기 때문에 Kitten을 더 빨리 찾을 수 있습니다!

로봇의 기억에는 그가 현재 위치의지도가 포함되어 있으며, 위쪽은 북쪽, 아래쪽은 남쪽, 오른쪽은 동쪽, 왼쪽은 서쪽입니다 로봇은 항상 #자신의 레이더 맵에 표시된 벽으로 둘러싸인 알 수없는 크기의 직사각형 방에 있습니다. 로봇이 걸을 수있는 영역은 공백으로 표시됩니다 .

로봇의 레이더는 또한 실내의 많은 장애물을 스캔하여 다양한 ASCII 문자로 표시합니다. 로봇은 이러한 장애물을 가로 질러 걸을 수 없습니다. 레이더는 Kitten을 특수 ASCII 문자 K로 표시하고 로봇의 위치는로 표시됩니다 R.

로봇의 내비게이션 시스템은 다음과 같이 작동합니다. 그는 이동해야하는 방향과 이동 유닛의 수를 이해할 수 있습니다 N 3. 로봇의 레이더 맵은 이동 단위가 하나의 ASCII 문자가되도록 만들어집니다. 로봇은 4 방향으로 만 갈 수 있으며 대각선으로 이동할 수 없습니다.

용감한 새끼 고양이 보호기의 임무는 로봇의 레이더 맵을 한 번 읽고 최소한의 이동 단위 이동 거리로 최소량의 방향을 출력하는 것입니다. 로봇은 적어도 하나의 새끼 고양이 경로가 있어야합니다.

로봇이 새끼 고양이를 찾는 데 도움이되지 않는 오작동 프로그램을 실행하는 데 시간을 허비하지 않기 위해, 용감한 새끼 고양이 보호기는 로봇의 과거 프로그램의이 출력을 사용하여 새끼 고양이를 찾는 데 시간이 낭비되지 않도록하십시오.

테스트 사례

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
Nabb


4
목표는 분명하지 않습니다. "가장 적은 이동 단위 이동 거리로 최소량의 방향을 출력합니다." n 방향과 m 단계를 가진 방법이있을 수 있으며, n 방향보다 작지만 더 많은 단계 또는 더 많은 방향과 더 적은 단계를 가진 다른 방법이있을 수 있습니다. 환율이 있습니까?
사용자 알 수 없음

2
단계 수는 방향 수보다 낫습니다.
LiraNuna

1
아이디어가 가장 적은 단계 수를 가지고 있고 가장 적은 수의 방향으로 연결을 끊는 경우 두 번째 예는 잘못된 해결책을 갖습니다. 최단 경로에 대한 내 대답을 참조하십시오.
Daniel C. Sobral

답변:


10

C ++ 1002 899 799 문자

템플릿에서>> 사이의 공백을 제거하려면 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

스칼라 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

스칼라 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

문제에서 주어진 것보다 두 번째 예의 짧은 경로를 발견했습니다.

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,"")))

이것은 최소한의 단계를 선호하여 유대를 해결하지 않는 것 같습니다.
Daniel C. Sobral

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 * 구현으로 압축을 풉니 다. stdin을 읽습니다. 총 거리가 최소 인 솔루션을 검색합니다. 최소한의 방향을 선호하여 관계를 끊습니다. stdout으로 이동을 나열합니다. 새끼 고양이를 찾습니다.

포장 풀기 :

작은 압축 표현을 얻기 위해 소스를 몇 군데에서 수동으로 안티 골프했습니다. 예를 들어 나침반 방향의 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);}

그것은 첫째로와지도에있는 모든 장애물을 대체 #의 (그리고 값을 변경 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 자

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.