언덕의 왕-소방관


27

대초원의 건조한 여름입니다. 이 지역의 네 농부는 이웃 농작물을 태워 옥수수 시장을 구할 수 있다는 것을 알고 있습니다. 그러나 그렇게하기위한 전략이 필요합니다. 그것이 당신이 들어오는 곳입니다.

당신의 임무는 농부들에게 무엇을 태울 것인지 알려주는 봇을 작성하는 것입니다. 목표는 불타 지 않은 땅의 가장 넓은 지역에서 게임을 끝내는 것입니다. 경기장은 32x32 그리드입니다. 각 셀은 다음 중 하나 일 수 있습니다.

. - Ground

@ - A bot

# - Ash

W - Wet ground

1,2,3,4,5, or 6 - Fire

불은 1 턴마다 1 씩 증가합니다. 3 이상이되면 셀이 옆에 (가로 또는 세로) 불에 놓입니다. 화재가 6을당한 후에는 재로 바뀝니다.

각 턴에서 봇은 STDIN으로 봇 시작 x, 봇 시작 y, 봇 현재 x 위치, 봇 현재 y 위치 및 보드를 줄 바꿈으로 구분하여받습니다. 예를 들면 :

8
22
6
24
................................
................................
................................
.....................1..........
....................1#1.........
...................1#363........
....................16@1........
.....................31.........
................................
.........1.1....................
........15#62...................
........15@2....................
.........32.....................
................................
................................
................................
................................
................................
................................
................................
................................
................................
....4.1.........................
.....1#3........................
.....@3.........................
.....W..........................
................................
................................
................................
................................
................................
................................

(이 경우 왼쪽 하단의 봇입니다).

다음을 나타내는 선택적 개행과 함께 세 개의 문자를 출력해야합니다.

이동 중 하나 L, R, U, D, or S (stay)

액션-중 하나 B (burn), P (pour water) or X (do nothing)

방향-중 하나 L, R, U, D or S -작업을 수행 할 셀을 제어합니다.

불은 봇에 영향을 미치지 않습니다.

턴 순서는 다음과 같습니다 : 모든 봇이 움직입니다. 모든 봇은 행동을 수행합니다. 환경 규칙이 발생합니다. 땅에 물을 부으면 물 W이 한 번 젖습니다 ( ). 불은 젖은 땅으로 퍼지지 않습니다. 젖은 땅에 물을 부으면 계속 젖게됩니다. 불에 물을 부으면 일반 땅으로 돌아갑니다. 재에는 아무것도 할 수 없습니다.

라운드는 한 번에 4 개의 봇으로 진행됩니다. 라운드는 50 턴 후 또는 하나의 봇이 타지 않은지면에서 부족할 때 종료됩니다. 점수는 봇이 시작된 위치를 중심으로 9x9 사각형의 접지 또는 습식 접지 셀 수로 계산됩니다.

여기 봇 예제가 있습니다. 그것은 세 글자를 무작위로 골라 내며 일반적으로 자신의 필드를 불태 웁니다.

랜덤 버너 :

#!/usr/bin/env python
import random
print random.choice('LRUDS')+random.choice('BPX')+random.choice('LRUDS')

규칙 :

  • 자신의 폴더 외부에서 파일 시스템에 액세스 할 수 없습니다.
  • 턴 사이에 영구 데이터를 저장해야하지만 봇당 최대 1kb까지만 파일에 쓸 수 있습니다.
  • 다른 사람의 봇을 덮어 쓸 수 없습니다
  • 유효하지 않은 움직임을 출력하면 봇은 여전히 ​​앉아있을 것입니다. 유효하지 않은 동작을 출력하면 봇은 아무 작업도 수행하지 않습니다.
  • OSX 또는 Linux 상자에서 실행할 수있는 공통 언어를 사용하십시오.

컨트롤러 코드는 여기 에서 찾을 수 있습니다.

초기 결과 :

Average of 15 rounds:
---------------------
81 Farmer
56 CautiousBot
42 GetOff
41 Visigoth
40 DontBurnMeBro
37 FireFighter
35 Pyro
11 Protector

업데이트 : Farmer, CautiousBot, GetOff, FireFighter 및 Pyro가 추가되었습니다.


1
보드가 가장자리를 감싸지 않습니다.
Zgarb

1
권리. 당신이 가장자리를 넘어 이동하려고하면, 당신은 여전히 ​​서 있습니다.
Skyler

4
하나의 세부 사항을 이해하지 못합니다. 내 땅은 무엇이고 당신의 땅은 무엇입니까?
kaine

3
당신의 땅은 당신이 시작한 곳을 중심으로 9x9 블록 구역 안에 있던 곳입니다. 모든 봇은 서로 최소 8 블록의 라운드를 시작하므로 겹치지 않습니다.
Skyler

2
제공되지 않습니다. 어떻게 든 기록하고 싶다면 옵션입니다. 그것을 숨기기 위해 불에 앉아있는 것은 유효한 전략입니다.
Skyler

답변:


5

서 고트족

Visigoth는 적을 땅에 태우려고합니다. 다른 사람이 그 땅에 오기 전에 이것을하기를 희망합니다.

운영: python visigoth.py

#!/usr/bin/python

''' Charge the enemy and burn them to the ground. '''

import sys

data = sys.stdin.readlines()

startx, starty, x, y = [int(i) for i in data[0:4]]
field = [list(i) for i in data[4:]]

otherbots = []
for i in range(32):
    for j in range(32):
        if field[i][j]=='@': #bot
            if i!=y and j!=x:
                otherbots.append([j,i])

min_bot = otherbots[0]
for bot in otherbots:
    if abs(bot[0]-x)+abs(bot[1]-y) < abs(min_bot[0]-x)+abs(min_bot[1]-y):
        min_bot = bot

dx = min_bot[0]-x
dy = min_bot[1]-y

if abs(dy)>abs(dx):
    if dy>0:
        move = 'U'
    else:
        move = 'D'
else:
    if dx>0:
        move = 'R'
    elif dx<0:
        move = 'L'
    else:
        move = 'S'

if max(abs(x-startx), abs(y-starty))>4:
    if 0<x<31 and 0<y<31:
        dirs = {'U':(-1,0), 'D':(1,0), 'L':(0,-1), 'R':(0,1)}
        for i in dirs:
            if field[dirs[i][0]][dirs[i][1]] in ('.', 'W'):
                action = 'B'+i
                break
        else:
            # No free land nearby, go out in a blaze of glory
            action = 'BS'
    else:
        action = 'BS'
else:
    # Don't set own field on fire
    action = 'XS'

print move+action

이것은 나의 첫 번째 항목이며, 건설적인 비판은 높이 평가됩니다!


"화재는 봇에 영향을 미치지 않습니다"
Conor O'Brien

Visigoth는 거의 화상을 입지 않는 것 같습니다.
Skyler

오, 방금 내가 가지고 min있어야 할 곳이 있다는 것을 알았 습니다 max. 나는 그것을 고쳤다.
taixzo

@ CᴏɴᴏʀO'Bʀɪᴇɴ 자신의 기지 근처에 머물러 있다고 가정하는 것만으로 실제로 적 로봇을 태우려고하지 않습니다. 자체에 대해 매우 약합니다.
taixzo

아, 알겠습니다 더 이해가 되네요.
Conor O'Brien

4

자바, 수호자

그의 울타리를 재 울타리로 둘러싼 다.

편집 : 논리가 약간 향상되었습니다. 아마 차이가 없을 것입니다.

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

/**
 * Created 10/6/15
 *
 * @author TheNumberOne
 */
public class Protecter {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        Point current = new Point(in.nextInt(), in.nextInt());
        in.nextLine();
        String output = "";
        char[][] board = new char[32][];
        for (int i = 0; i < 32; i++){
            board[i] = in.nextLine().toCharArray();
        }
        List<Point> danger = new ArrayList<>();
        List<Point> close = new ArrayList<>();
        List<Point> closeDanger = new ArrayList<>();
        List<Point> fence = new ArrayList<>();
        for (int i = 0; i < 32; i++){
            for (int j = 0; j < 32; j++){
                Point p = new Point(i, j);
                char c = board[j][i];
                if (Math.abs(p.x - start.x) < 10 && Math.abs(p.y - start.y) < 10){
                    if ((c + "").matches("\\d")){
                        danger.add(p);
                    }
                }
                if (distance(current, p) == 1){
                    close.add(p);
                }
                if ((Math.abs(p.x - start.x) == 10 || Math.abs(p.y - start.y) == 10) && !(c + "").matches("#|\\d|@")){
                    fence.add(p);
                }
            }
        }
        closeDanger = new ArrayList<>(danger);
        closeDanger.retainAll(close);
        danger.sort(Comparator.comparingInt(a -> distance(current, a) / (board[a.y][a.x] - '0')));
        if (danger.size() > 0){
            output += moveTo(current, danger.get(0));
        } else {
            fence.sort(Comparator.comparingInt(a -> distance(current, a)));
            if (fence.size() == 0){
                output += "S";
            } else {
                output += moveTo(current, fence.get(0));
            }
        }
        closeDanger.sort(Comparator.comparingInt(a -> board[a.y][a.x] - '0'));
        if (closeDanger.size() > 0){
            output += "P";
            output += moveTo(current, closeDanger.get(0));
        } else {
            if (danger.size() == 0) {
                List<Point> closeFence = new ArrayList<>(fence);
                closeFence.retainAll(close);
                if (closeFence.size() > 0) {
                    output += "B";
                    output += moveTo(current, closeFence.get(0));
                } else {
                    if (!fence.contains(current)){
                        output += "PS";
                    } else {
                        output += "BS";
                    }
                }
            } else {
                if (!fence.contains(current)){
                    output += "PS";
                } else {
                    output += "BS";
                }
            }
        }
        System.out.println(output);
    }

    private static String moveTo(Point from, Point to) {
        if (from.x > to.x){
            return "L";
        }
        if (from.x < to.x){
            return "R";
        }
        if (from.y > to.y){
            return "U";
        }
        if (from.y < to.y){
            return "D";
        }
        return "S";
    }

    private static int distance(Point p1, Point p2){
        return Math.abs(p1.x - p2.x) + Math.abs(p2.y - p1.y);
    }

}

라는 파일에 배치하십시오 Protector.java.

다음으로 컴파일 javac Protector.java
:java Protector


먼저 Protecter.java로 이름을 바꿔 컴파일해야했습니다. 그러나, 그것을 실행하면 29 행에서 java.lang.ArrayIndexOutOfBoundsException이 발생합니다.
Skyler

@Skyler는 그것을 고쳤습니다 :)
TheNumberOne

감사합니다. 결과에 추가했습니다. 수호자는 자신이 시작한 불을 항상 꺼낼 수는 없습니다.
Skyler


@Fatalize 그것이 숲 / 사막 화재에 걸렸을 때 내가 가르쳐 준 것입니다 :)
TheNumberOne

2

GetOff, Python

GetOff는 단지 자신의 땅을 유지하기를 원하며, 땅 전체에서 저 봇을 쫓아 나가기 전까지 물총으로 물총을 뿜어내는 것을 두려워하지 않습니다. 재산을 침해하지 않는 동안, 그의 땅이 타지 않도록 최선을 다합니다.

#!/usr/bin/env python

import sys

fire = ['1','2','3','4','5','6']

move = ''
ad = ''

data = sys.stdin.readlines()

startx, starty, x, y = [int(i) for i in data[0:4]]
board = [list(i) for i in data[4:]]

top = starty-4
bottom = starty+5
right = startx+5
left = startx-4

bots = []
for i in range(32):
    for j in range(32):
        if board[i][j]=='@':
            if i != y and j != x:
                bots.append([j,i])

fires = []
for i in range(32):
    for j in range(32):
        if board[i][j] in fire: #fire
            fires.append([j,i])

for bot in bots:
    if left < bot[0] < right and top < bot[1] < bottom: # if there's a bot in the field
        if bot[0] > x:
            move = 'R'
        elif bot[0] < x:
            move = 'L'
        elif bot[1] > y:
            move = 'D'
        elif bot[1] < y:
            move = 'U'
        else:
            move = 'S'
    else:
        nearest_fire = []
        for f in fires:
            if left < f[0] < right and top < f[1] < bottom:
                if nearest_fire == []:
                    nearest_fire = f
                elif (f[0]-x)+(f[1]-y) < (nearest_fire[0]-x)+(nearest_fire[1]-y):
                    nearest_fire = f
        if nearest_fire == []:
            move = 'S'
        else:
            if nearest_fire[0] > x:
                move = 'R'
            elif nearest_fire[0] < x:
                move = 'L'
            elif nearest_fire[1] > y:
                move = 'D'
            elif nearest_fire[1] < y:
                move = 'U'
            else:
                move = 'S'

if board[x-1][y] in fire: # position immediately to the left
    ad = 'L'
elif board[x+1][y] in fire: # position immediately to the right
    ad = 'R'
elif board[x][y-1] in fire: # position immediately up
    ad = 'U'
elif board[x][y+1] in fire: # position immediately down
    ad = 'D'
else:
    ad = 'S'

print(move+'P'+ad)

a < b < c구문이 파이썬에서 작동 합니까 ? 나는 (a < b) < c, 1 < c또는로 평가된다고 생각했다 0 < c. 내가 틀렸다면 나를 바로 잡으십시오. (bot 루프의 첫 번째 조건에서 발견됨)
Conor O'Brien

그것은 항상 나를 위해 일했지만 모든 버전의 파이썬에서하는지 확실하지 않습니다 ...
The Beanstalk

CᴏɴᴏʀO'Bʀɪᴇɴ @ 그것이 않는 생각 1<3>2으로 평가를 True내 컴퓨터에 (:이 그룹을했다 false를 반환하는 경우 1>21<1가능성이다).
cole

@Cole 감사합니다. JavaScript 사고 모드에있었습니다. repl.it에서 사용해보십시오. 파이썬이 아름다운 이유 더.
Conor O'Brien

2

파머, 자바

농부는 그의 작물에만 관심이 있습니다. 그는 화재 나 침입자에 대해 자신의 필드를 지속적으로 감시합니다.

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Farmer {

    public static void main(String[] args) {
        //row == y
        //col == x
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        Point current = new Point(in.nextInt(), in.nextInt());
        in.nextLine();
        char[][] board = new char[32][];
        for (int row = 0; row < 32; row++){
            board[row] = in.nextLine().toCharArray();
        }
        final List<Point> firesInField = new ArrayList<>();
        final List<Point> enemiesInField = new ArrayList<>();
        for (int row = 0; row < 32; row++) {
            for (int col = 0; col < 32; col++) {
                Point p = new Point(col, row);
                if (!isInField(start, p))
                    continue;
                char c = board[row][col];
                if (isFire(c)) {
                    firesInField.add(p);
                } else if (c == '@' && col != current.x && row != current.y) {
                    enemiesInField.add(p);
                } 
            }
        }
        List<Point> destinations = firesInField.size() > 0 ? firesInField : enemiesInField;

        if (destinations.size() > 0) {
            //take short paths to eliminate more fires
            destinations.sort(Comparator
                    .comparingInt((Point p) -> distance(p, current))
                    .thenComparingInt(p -> -1 * (board[p.y][p.x] - '0')));
            Point dest = destinations.get(0);
            print(moveTo(current, dest), "P", moveTo(current, dest));
        }

        //TODO start fires if an enemy has more intact ground

        //walk back to center
        print(moveTo(current, start), "P", moveTo(current, start));
    }

    private static void print(String move, String action, String actionMove) {
        System.out.println(move + action + actionMove);
        System.exit(0);
    }

    private static boolean isInField(Point centerOfField, Point toTest) {
        //add one extra, to prevent fires that are very near
        return distance(centerOfField, toTest) <= 10 && Math.abs(centerOfField.x - toTest.x) <= 5 && Math.abs(centerOfField.y - toTest.y) <= 5;
    }

    private static boolean isFire(char c) {
        return c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6';
    }

    private static String moveTo(Point from, Point to) {
        if (from.x > to.x){
            from.x--;
            return "L";
        }
        if (from.x < to.x){
            from.x++;
            return "R";
        }
        if (from.y > to.y){
            from.y--;
            return "U";
        }
        if (from.y < to.y){
            from.y++;
            return "D";
        }
        return "S";
    }

    private static int distance(Point p1, Point p2){
        return Math.abs(p1.x - p2.x) + Math.abs(p2.y - p1.y);
    }
}

1
작은 개선으로 대신 isFire사용할 수 있습니다 Character.isDigit.
J Atkin

2

파이로, 파이썬

파이로는 불을 좋아합니다. 파이로는 불을 좋아합니다. 파이로는 불 속에 산다. "TF2의 파이로"를 생각하고 있습니다. 파이로는 물건을 태우는 것을 좋아합니다. 그는 자신의 영역을 태우지 않지만 간단한 "경로 찾기"알고리즘을 사용하여 영역을 벗어나려고합니다.

import sys
import random
inpu          = sys.stdin.readlines()
ox,oy,x,y     = [int(i) for i in inpu[0:4]]
board         = [list(i) for i in inpu[4:]]
adjacentcells = [[[board[y+b][x+c],b,c] for b in range(-1,2)] for c in range(-1,2)]
action        = ""
infield=max(abs(ox-x),abs(oy-y))<=9
# let's find out what Pyro will do!
if not infield: # Pyro won't burn what's in his field.
    for row in adjacentcells:
        for entry in row:
            cell,a,b=entry
            if(a!=b):   # Can't act on these cells.
                if cell==".":   # burn it!!!!!!
                    action = "B"
                    if(a==0):
                        direction = {-1:"L",1:"R"}[b]
                    else:
                        direction = {-1:"D",1:"U"}[a]
            if action: break;
        if action: break;
    # Pyro doesn't care where he goes, so long as
    # Pyro's not in the field of Pyro.
    move = random.choice("LRUDS")
else:   # Thought Pyro hates water, Pyro must protect SOMETHING.
    action    = "P"
    direction = "S"
    # get the direction towards the center
    # Pyro will move away from ox and oy to
    # towards the center, if in the field.
    # Pyro will do this by first going right/left,
    # then going up/down. (This behaviour is
    # removed when he leaves his field.)
    cx = cy = 16
    while max(abs(cx-x),abs(cy-y))<=9:
        cx = random.randint(0,31)
        cy = random.randint(0,31)
    if(cx-x>0): #is to the left of the center
        move = "R"
    elif(cx-x<0): #is to the right of the cenetr
        move = "L"
    elif(cy-y>0): # is above center
        move = "D"
    elif(cy-y<0): # is below center
        move = "U"
    else:   # is at center (something went wrong!)
        move   = "S"
        action = "B"
if not move:
    move = "S"
if not action:
    action = "B"
if not direction:
    direction = "S"
print(move+action+direction)


""" Here, have a face!
MMMMMMMMMMMMMMMMMMMMMMMdyo/:-.````.:+sdMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMNs/....----...``````.omMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMh/``..-://+//:-..````````/mMMMMMMMMMMM
MMMMMMMMMMMMMMMm:````..-:////:--..``````````sMMMMMMMMMM
MMMMMMMMMMMMMMs```````....--....`````````````/NMMMMMMMM
MMMMMMMMMMMMM/````````````````````````````````:NMMMMMMM
MMMMMMMMMMMM/```......``````````````````.......+mMMMMMM
MMMMMMMMMMMo.:::::::::::-````````````.-:::::::::/+yNMMM
MMMMMMMMMNs:-..-------::::.`````````://:-------..-:/hMM
MMMMMMMMm+:..---:::::---:::.```````::::---:::::--.`-/sM
MMMMMMMN+:`.---:::/:/:---:::``````.:::.--:::/:/:--.`:/h
MMMMMMMh:-`---://o+///:---::.`````-::---://oo///:--..:+
MMMMMMMs:..--:/+/sss+//:-.::.`````-::.-://+osyo//:-.-::
MMMMMMMs:----///+sosso/:--::``````.::.-://+oosso+:-.::/
MMMMMMMd:::-:/++/osyso+/--::```````::-://+/osyso+/--::s
MMMMMMMMs:/::::+ooos+o+/:::.```````.::::/+ooos/o+/:/:+N
MMMMMMMMMs://:+osooo+o+/::.``.....``.:/:/osoos+o+//:+mM
MMMMMMMMMM--:/++ysyoo+/:-...........`.-:/+ssso++/:-yNMM
MMMMMMMMMMs``.-:://::-..`.....---....``..--::::-.`.MMMM
MNNMddhyys+-.```````````...--:::::-...````````````+MMMM
////.-:///:-..``````````.:///++o/o+/:/.```````````yMMMM
---.`.-:::--..`````````..+//+ooo+++///.```````````mMMMM
/.--``..--...``````````..--:/+oo+/:--..``````````.MMMMM
s --.```...````````````...--/+++++/-...````````.`/MMMMM
d .--```````````````````...-::::::-...````````.-/+MMMMM
M.`--`  ````````````````....------....````````.-/.dMMMM
M+ .-.  `````````````````.:::::::::::.`````````.-sMMMMM
Mm``--`  ``````````````-://///////////:-````````/MMMMMM
MM: --.  ````````````.://::--......-::///-``````yMMMMMM
MMd`.-.  ``````````.:/::-..-:::::::.``-::::.````NMMMMMM
MMM+.--`  `````````:::-.-::-.......-::-`--::```+MMMMMMM
MMMN---`  ````````.--..:-.```````````..-`.--.``dMMMMMMM
MMMMd--.` `````..`.-.`-````````````````.-`...`/MMMMMMMM
MMMMMNh+ss/oydNMd``.`.`````````````````````.`.NMMMMMMMM
MMMMMMMMMMMMMMMMMd.``.```````````````````````dMMMMMMMMM
MMMMMMMMMMMMMMMMMMm:```````````````````````-dMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMy.```````````````````.oNMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMNs-```````````````:sNMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMmy+:-.````.:+ymMMMMMMMMMMMMMMMM
"""

2
설명과 의견에 파이로의 성별에 대해 모호하지 않습니다.
cole

@Cole 아 젠장. 나는 그 단점을 잊었다. 나는 확실하게 약간의 모호성을 편집 할 것이다;)
Conor O'Brien

21 행의 else 문 뒤에 아무것도 없기 때문에 실행되지 않습니다.
Skyler

이제 5 번 줄에서 끊어짐 ( '데이터'는 정의되지 않음)
Skyler

@Skyler 다시 고정되었습니다. 정말 죄송합니다. 파이썬 인터프리터 없이이 작업을 수행했습니다.
Conor O'Brien

2

DontBurnMeBro

또 다른 파이썬 항목. 가장 먼저 죽는 것이 아니라고 확신합니다.

#!/usr/bin/python

print "SPS"

4
사양에 따라 물을 붓지 P않습니다 W.
randomra

고마워요
taixzo

1

파이어 파이터, 자바

싸움 의 모든 불을.

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

/**
 * Created 10/7/15
 *
 * @author TheNumberOne
 */
public class FireFighter {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        Point current = new Point(in.nextInt(), in.nextInt());
        in.nextLine();
        String output = "";
        char[][] board = new char[32][];
        for (int i = 0; i < 32; i++) {
            board[i] = in.nextLine().toCharArray();
        }

        List<Point> danger = new ArrayList<>();
        List<Point> close = new ArrayList<>();
        List<Point> closeDanger;
        for (int i = 0; i < 32; i++){
            for (int j = 0; j < 32; j++){
                Point p = new Point(i, j);
                char c = board[j][i];
                if ((c + "").matches("\\d")){
                    danger.add(p);
                }
                if (distance(current, p) == 1){
                    close.add(p);
                }
            }
        }
        closeDanger = new ArrayList<>(danger);
        closeDanger.retainAll(close);

        Comparator<Point> comparator = Comparator.comparingInt((Point a) -> board[a.y][a.x]).reversed();

        danger.sort(comparator);
        danger.sort(Comparator.comparingInt(a -> distance(start, a)));
        if (danger.size() > 0){
            output += moveTo(current, danger.get(0));
        } else {
            output += moveTo(current, start);
        }
        closeDanger.sort(comparator);
        if (closeDanger.size() > 0){
            output += "P" + moveTo(current, closeDanger.get(0));
        } else {
            output += "PS";
        }
        System.out.println(output);
    }

    private static String moveTo(Point from, Point to) {
        if (from.x > to.x){
            return "L";
        }
        if (from.x < to.x){
            return "R";
        }
        if (from.y > to.y){
            return "U";
        }
        if (from.y < to.y){
            return "D";
        }
        return "S";
    }

    private static int distance(Point p1, Point p2){
        return Math.abs(p1.x - p2.x) + Math.abs(p2.y - p1.y);
    }

}

0

파수꾼, 파이썬 2

import sys

Out = ["S", "P", "S"]

StX = int(sys.stdin.readline()) - 1
StY = int(sys.stdin.readline()) - 1
NowX = int(sys.stdin.readline()) - 1
NowY = int(sys.stdin.readline()) - 1
Map = []
for i in range(32):
    Map.append(sys.stdin.readline())

Pos = [NowX, NowY]
Area = [[StX, StY]]
for x in range(StX-4, StX+4):
    for y in range(StY-4, StY+4):
        Area.append([x, y])

Fires = []
for y in range(32):
    for x in range(32):
        if Map[y][x] in "123456":
            Fires.append([x, y])

Danger = []
for Tile in Area:
    if Map[Tile[1]][Tile[0]] in "123456":
        Danger.append(Tile)

Distance = {}
i = -1
for Fire in Danger:
    i += 1
    Distance[(Pos[0] - Fire[0], Pos[1] - Fire[1])] = i

i = min(Distance)
Closest = Danger[Distance[i]]

if Closest[0] > Pos[0]:
    Out[0] = Out[2] = "R"
    Pos[0] += 1
if Closest[0] < Pos[0]:
    Out[0] = Out[2] = "L"
    Pos[0] -= 1
if Closest[0] == Pos[0]:
    if Closest[1] > Pos[1]:
        Out[0] = Out[2] = "D"
        Pos[1] += 1
    if Closest[1] < Pos[1]:
        Out[0] = Out[2] = "U"
        Pos[1] -= 1

if Closest[0] + 1 == Pos[0] and Closest[1] == Pos[1]:
    Out[2] = "L"
if Closest[0] - 1 == Pos[0] and Closest[1] == Pos[1]:
    Out[2] = "R"
if Closest[1] + 1 == Pos[1] and Closest[0] == Pos[0]:
    Out[2] = "U"
if Closest[1] - 1 == Pos[1] and Closest[0] == Pos[0]:
    Out[2] = "D"
if Closest[0] == Pos[0] and Closest[1] == Pos[1]:
    Out[2] = "S"


print "".join(Out)

단순화 될 수는 있지만 피곤합니다.

파수꾼은 들판이 피해를 입지 않도록 노력합니다. 화재가 발생하면 서둘러 화재가 발생하면 최대한 빨리 꺼냅니다.

들어오는 화재에 대한 편의 시설도 추가 할 수 있습니다.


36 행 : ValueError: min() arg is an empty sequence-아직 불이 없으면 오류가 발생합니다.
Skyler

@Skyler 조금만 수정하겠습니다. 죄송합니다.
The_Basset_Hound

0

CautiousBot, Node.js (ES5)

이 봇은 나가서 다른 봇의 땅에 불을 붙입니다. 심지어 불 위에 숨어서 3 개의 진드기가 숨겨져 있습니다! 그러나 너무 조심해서는 안되므로 항상 자신의 땅에 불을 낼 수있을 정도로 가까이 있어야합니다.

노트:

  • state.json작업 디렉토리에 저장된 상태 파일을 사용하여 다른 봇의 초기 위치에 대한 정보를 저장하고 시작된 화재를 숨기는 시간을 결정합니다. 라운드가 끝나면 (예 : 일부 봇이 승리 한 경우) 삭제해야합니다. 그렇지 않으면 다음 라운드에서 봇이 혼동됩니다. (이것이 규칙을 어기는지 알려주세요.)
  • split모듈이 필요합니다 .
#!/usr/bin/env node

// imports
var fs       = require("fs");
var splitmod = require("split");

// variables
var startX, startY, currentX, currentY, board = [], state = {};
var DEBUG = false;

// utility functions
function debug(){
    if(DEBUG) console.log.apply(console, arguments);
}

// calculates manhattan distance which is also the number of turns it will take to get somewhere
function manhattan(x1, y1, x2, y2){
    return Math.abs(x2 - x1) + Math.abs(y2 - y1);
}

// calculates chebyshev distance (mostly used for determining if a bot is within someone's plot)
function chebyshev(x1, y1, x2, y2){
    return Math.max(Math.abs(x2 - x1), Math.abs(y2 - y1));
}

// gets the board character at x, y
function get(x, y){
    return board[y][x];
}

function readState(){
    try {
        state = JSON.parse(fs.readFileSync('state.json').toString());
        debug("Opened state file");
    } catch(e){
        // it must be the first turn
        createState();
    }
}

function writeState(){
    fs.writeFileSync('state.json', JSON.stringify(state));
    debug("Wrote state file");
}

// finds out where all the other bots are
function getBotPositions(){
    var positions = [];
    for(var x = 0; x < 32; x++){
        for(var y = 0; y < 32; y++){
            if(get(x, y) == '@' && x != currentX && y != currentY){
                positions.push({x: x, y: y});
            }
        }
    }
    return positions;
}

function createState(){
    debug("Creating state");
    // take a loot at where other bots are to record their land locations
    var botLands = getBotPositions();
    state['botLands'] = botLands;

    state['turn'] = 0; // which turn is it?
    state['lastFireTurn'] = -999; // which turn was the last one where this bot set a fire?
}


// finds whether a plot of land (defined by its center) has fire on it
function isLandBurning(x, y){
    for(var dx = -4; dx < 5; dx++){
        for(var dy = -4; dy < 5; dy++){
            if(get(x + dx, y + dy).match(/[1-6]/) != null) return true;
        }
    }
    return false;
}

// finds the fire with the highest number (and therefore the one to put out first)
function findFire(x, y){
    var highestNum = 0;
    var fire = {x: x, y: y};
    for(var dx = -4; dx < 5; dx++){
        for(var dy = -4; dy < 5; dy++){
            if(get(x + dx, y + dy).match(/[1-6]/) != null){
                var num = parseInt(get(x + dx, y + dy));
                if(num > highestNum){
                    highestNum = num;
                    fire = {x: x + dx, y: y + dy};
                }
            }
        }
    }
    return fire;
}

// figures out where to go to get somewhere
function getDirection(x1, y1, x2, y2){
    var direction = 'S';
    var cycx = Math.abs(y2 - y1) / Math.abs(x2 - x1);

    if(cycx < 1){
        if(x2 > x1) direction = 'R';
        if(x2 < x1) direction = 'L';
    } else {
        if(y2 > y1) direction = 'D';
        if(y2 < y1) direction = 'U';
    }

    debug("Getting direction", x1, y1, x2, y2, "result", direction);

    return direction;
}

// read input
var dataCycle = 0;
process.stdin.pipe(splitmod()).on('data', function(line){
    switch(dataCycle){
    case 0:
        startX = parseInt(line);
        break;
    case 1:
        startY = parseInt(line);
        break;
    case 2:
        currentX = parseInt(line);
        break;
    case 3:
        currentY = parseInt(line);
        break;
    default:
        board.push(line);
    }

    dataCycle++;
}).on('end', function(){
    // main bot code
    readState();
    state['turn']++;
    debug("It is turn", state['turn']);

    // get bot positions
    var botPositions = getBotPositions();

    var action = {type:'X', direction:'S'};
    var move   = 'S';

    var isMyLandBurning = isLandBurning(startX, startY);
    if(isMyLandBurning){ // hurry over there ASAP!
        debug("Bot land is burning!");
        var pos = findFire(startX, startY);
        debug("Fire found at", pos);
        move = getDirection(currentX, currentY, pos.x, pos.y);
        // simulate the move and figure out if/where to dump the water
        var newX = currentX + (move == 'R') - (move == 'L');
        var newY = currentY + (move == 'D') - (move == 'U');
        if(chebyshev(newX, newY, pos.x, pos.y) < 5){
            // on its own land, start dropping water like a madman
            debug("Dropping water");
            action.type = 'P';

            // if it can put out the target fire, then do that
            if(manhattan(newX, newY, pos.x, pos.y) == 1) action.direction = getDirection(newX, newY, pos.x, pos.y);
            // it's not in range of the target fire, so use the time to put out other fires
            // if it's moving on top of a fire, put that out
            else if(get(newX, newY).match(/[1-6]/) != null) action.direction = 'S';
            // if there's a fire around it then put that out
            else if(get(newX + 1, newY).match(/[1-6]/) != null) action.direction = 'R';
            else if(get(newX - 1, newY).match(/[1-6]/) != null) action.direction = 'L';
            else if(get(newX, newY + 1).match(/[1-6]/) != null) action.direction = 'D';
            else if(get(newX, newY - 1).match(/[1-6]/) != null) action.direction = 'U';
            else action.direction = 'S';
        }
    } else {
        // are there any bots that could start a fire when this bot is 6+ tiles away?
        var headBack = false;
        for(var i = 0; i < botPositions.length; i++){
            var otherBot = botPositions[i];
            var dist = manhattan(otherBot.x, otherBot.y, startX, startY) - 4;
            var myDist = manhattan(currentX, currentY, startX, startY);
            if(dist + 6 < myDist){
                headBack = true;
                break;
            }
        }
        if(headBack){ // they're probably up to no good
            debug("Bots are dangerously close, heading back");
            move = getDirection(currentX, currentY, startX, startY);
        } else if(state['turn'] - state['lastFireTurn'] < 3) { // no bots near own plot, time to consider other options
            debug("Hiding fire");
            // sneakily hide the fire if one was set :)
        } else { // last option is to go find land to burn
            debug("Finding land to burn");
            var closestX = 999, closestY = 999;
            for(var i = 0; i < state.botLands.length; i++){
                var otherLand = state.botLands[i];
                if(!isLandBurning(otherLand.x, otherLand.y) && chebyshev(currentX, currentY, otherLand.x, otherLand.y) > 4){ // find someone to burn
                    // use [-3, 3] here because on the first turn, the bots could have moved before this bot had a chance to see them
                    // meaning that the [-3, 3] region is the only one that is guaranteed to be on their land
                    for(var dx = -3; dx < 4; dx++){
                        for(var dy = -3; dy < 4; dy++){
                            var type = get(otherLand.x + dx, otherLand.y + dy);
                            var distThere = manhattan(currentX, currentY, otherLand.x + dx, otherLand.y + dy);
                            var distShortest = manhattan(currentX, currentY, closestX, closestY);
                            // find normal land, or wet land that will dry by the time the bot gets to it
                            if((type == '.' || type == '@' || (type == 'W' && distThere > 1)) && distThere < distShortest){
                                closestX = otherLand.x + dx;
                                closestY = otherLand.y + dy;
                            }
                        }
                    }
                }
            }
            if(closestX != 999 && closestY != 999){ // land found; go there
                debug("Target acquired", closestX, closestY);
                debug("Burning land");
                move = getDirection(currentX, currentY, closestX, closestY);
                if(move == 'S'){ // is it on the land? If so, then burn it
                    action.type = 'B';
                    action.direction = 'S';
                    state['lastFireTurn'] = state['turn']; // record when the fire was set
                }
            } else { // everyone else's land already has a fire
                debug("Default action");
                // default to heading back; one can never be too safe!
                move = getDirection(currentX, currentY, startX, startY);
            }
        }
    }

    // save the state file
    writeState();
    // output the action
    console.log(move + action.type + action.direction);
});

340 행에서 오류가 발생 Error: Cannot find module 'split'합니다. Node.js v0.10.30을 사용하고 있습니다.
Skyler

cd botdir npm install split어떤 이유로 노드는 전 세계에 설치되는 것을 좋아하지 않지만 시도해 볼 수도 있습니다.
DankMemes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.