Encontre o queijo


25

Atualização: Existem 6 labirintos. Eles estão incluídos no controlador. Há um tar.gz dos labirintos e seus arquivos .bmp aqui (dropbox). Também existe um utilitário para criar mais labirintos nesse link (o arquivo maze_4.txt está incorreto no arquivo morto). Neste ponto, sinta-se à vontade para executar sua própria inscrição e atualizar sua pontuação. Detalhes sobre como fazer isso estão incluídos na parte inferior. Se você tiver dúvidas ou problemas, envie-me um ping no bate-papo.


Você é um rato. Você está em um labirinto. Encontre o queijo.

Conceito

Você está em um labirinto que existe em uma grade retangular. Cada espaço da grade contém uma das várias coisas:

  • ! - Uma parede intransitável
  • - Um espaço vazio, que pode ser percorrido
  • O Você, o mouse
  • + - O queijo, seu objetivo

Por favor, use os mesmos caracteres para que eu não precise modificar o controlador.

Em cada turno, você receberá as peças que estão ao norte, sul, leste e oeste de sua posição atual. Você deve então emitir a direção que deseja seguir. Você ganha quando chega ao queijo. Menos etapas é melhor.

Entrada

Você receberá informações através do stdin da seguinte maneira:, em neswque cada letra representa o bloco naquele ponto da bússola. Por exemplo, se o estado atual se parecer com

  !          <--- Wall
 !O          <--- You
  +          <--- Cheese

então você receberá a string ! +!.

No final do jogo, o controlador irá enviar-lhe uma série de quatro zeros: 0000. Ao receber essa string, seu programa deve terminar. Nenhuma outra entrada fornecida conterá o 0caractere.

Por favor, ignore todas as outras entradas.

Saída

Você está a uma saída de carta n, s, e, ou w, para indicar qual a direção que você quer viajar, seguido de um caractere de nova linha.

Pontuação

Sua pontuação em cada teste é o número de etapas necessárias para encontrar o queijo.

Sua pontuação geral será a soma da sua pontuação média por labirinto em uma bateria de labirintos de tamanhos variáveis, os quais caberão dentro de um quadrado de comprimento 50.

Por exemplo, se o seu bot 100 leva para completar cada um dos 6 labirintos, sua pontuação é 600.

Se o seu bot não é determinístico, tente cada labirinto 10 vezes e use a média como a pontuação desse labirinto. Sua pontuação final será a soma de todas as médias.

Regras

  • Cada labirinto cabe dentro de um quadrado de 50x50.
  • Cada labirinto terá pelo menos um caminho válido do início ao queijo.
  • Cada labirinto será todo murado, exceto que o queijo estará sempre na parede externa, de modo que sirva essencialmente como uma saída para o labirinto.
  • Se você topar com um muro, sua inscrição será desqualificada.
  • Se o seu envio demorar muito (conforme determinado por mim, quando eu começar a testar), será desqualificado. Isso ocorre em grande parte para evitar loops infinitos. O limite suave será de um minuto por labirinto, embora eu me reserve o direito de alterar isso a qualquer momento, em qualquer direção.
  • As inscrições não precisam ser determinísticas, mas se você for muito aleatório, provavelmente será desqualificado pelo ponto acima.
  • Em algum momento, a bateria de labirintos será liberada, as respostas futuras podem não ser otimizadas em relação a elas e estão sujeitas a alterações.

Submissões :

Sua submissão é um programa completo que recebe entrada via stdin e saída via stdout. Isso é importante porque a submissão estará interagindo com o controlador do labirinto. Não vou proibir idiomas que não estão disponíveis gratuitamente, mas sei que outra pessoa terá que oferecer seu tempo para executar os testes se eu não tiver acesso ao idioma.

Inclua instruções sobre como executar seu envio.

Indique se o seu envio é determinístico ou não, para que eu saiba se preciso executá-lo várias vezes.

Labirintos de teste

Nos labirintos de teste, os .personagens descrevem o caminho mais curto para o queijo. Eles são iguais ao caractere (espaço). Eles não são visíveis para o seu envio. O controlador os substitui por espaços.

!!!!!!!!+!
!O..!....!
! !.!.! !!
! !.!.!  !
! !.!.!! !
!!!.!.!! !
!  .!.! !!
!!!...   !
!!!!!!!!!!

Labirinto de teste 31x31. Roubado descaradamente .

 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
 ! O...!.......!   !  .....!.....!           !             !   ! 
 !!!!!.!.! !!!.! !!! !.!!!.!.!!!.!!!!!!! !!! !!!!!!!!! !!! ! ! ! 
 !   !...!   !.!     !.! !.!.! !.!       !   !         !   ! ! ! 
 ! !!!!! !!! !.!!!!!!!.! !.!.! !.! !!!!!!! !!! ! !!!!!!! !!! ! ! 
 !     !     !.........! !...!...!     !   !   ! !     !   ! ! ! 
 ! !!! !!!!!!!!!!!!!!!!! !!!!!.!!! !!! !!! ! ! !!! !!! !!! !!! ! 
 !   !         !     !   !.....!     !   ! ! ! !     !   !   ! ! 
 !!!!!!!!!!! ! ! !!! !!! !.!!!!!!!!!!!!! ! !!! ! !!!!!!! !!! ! ! 
 !           !   !       !.!             !   !     !     !     ! 
 ! !!!!!!! !!!!!!! !!!!!!!.! !!!!!!!!!!!!!!! !!!!!!! !!!!!!!!!!! 
 ! !     ! !   !     !...!.!           !   !       ! !         ! 
 ! !!! ! ! ! ! !!!!!!!.!.!.! !!!!!!!!! ! ! !!!!!!! ! ! !!!!!!! ! 
 !   ! !   ! !       !.!...! !         ! !       ! ! !   !   ! ! 
 !!! ! !!!!! !!!!!!! !.!!!!!!! !!!!!!!!! !!! !!!!! ! !!! ! !!! ! 
 !   !   ! ! !       !...!     !   !     ! !           ! !   ! ! 
 ! !!!!! ! ! ! !!!!!!!!!.! !!!!! !!! !!!!! !!!!!!!!!!! ! ! ! ! ! 
 ! !       ! !   !   !...! !       ! !       !   !     ! ! ! ! ! 
 ! !!!!!!!!! !!! ! ! !.!!! !!!!!!! ! !!!!!!! ! ! !!!!!!! !!! ! ! 
 !             !   ! !...!       ! !     !   ! !             ! ! 
 !!!!!!!!!!!!!!!!!!! !!!.!!!!!!! ! !!!!! ! !!! !!!!!!!!!!!!!!! ! 
 !               !   !...!       !         !   !     !   !     ! 
 ! !!!!!!!!!!!!! ! ! !.!!! !!!!!!! !!!!!!!!! !!! !!! !!! ! !!! ! 
 ! !   !       !   ! !.! !     ! ! ! !     !     !   !   !   ! ! 
 ! ! ! !!!!! !!!!!!! !.! ! !!! ! ! ! ! !!! !!!!!!! !!! !!!!! !!! 
 !   ! !   !       ! !.!     ! !     ! ! !     !   !       !   ! 
 !!!!! ! ! !!! !!! ! !.!!!!!!! !!!!!!! ! ! !!! ! !!!!!!!!! !!! ! 
 !     ! !   !   !   !.......!       ! ! ! !   !   !         ! ! 
 ! !!!!! !!! !!! !!!!!!!!!!!.!!!!!!! ! ! ! !!!!!!! ! !!!!!!! ! ! 
 !         ! !           !...!       ! ! !     !   ! !       ! ! 
 !!!!!!!!!!! !!!!!!!!!!! !.!!! !!!!!!! ! !!!!! ! !!! !!!!!!!!! ! 
 !         !     !     ! !.!       !   !     ! !     !         ! 
 ! !!!!!!! !!!!! ! !!! !!!.!!!!!!! ! !!!!! ! ! !!!!! ! !!!!!!!!! 
 ! !     !     !   ! !   !.......! !       ! !       !         ! 
 ! ! !!! !!!!! ! !!! !!! !!!!!!!.! !!!!!!!!! !!!!!!!!!!!!!!!!! ! 
 !     !     ! !   !   ! !     !.!       !   ! !     !         ! 
 !!!!!!!!!!! ! !!! !!! ! ! ! !!!.! ! !!!!! !!! ! !!! ! !!!!!!! ! 
 !           ! !       !   ! !...! !       !   ! ! ! !     !   ! 
 ! !!!!!!!!!!! !!!!!!!!!!!!! !.!!! !!!!!!!!!!! ! ! ! ! !!! ! !!! 
 !       !   !             ! !.! !   !         ! !   !   ! ! ! ! 
 !!!!!!! !!! !!!!!!!!!!!!! ! !.! !!! ! !!!!!!! ! !!! !!!!! ! ! ! 
 !       !         !     ! ! !.!   !   !     ! !   !       !   ! 
 ! !!!!!!! !!!!!!! ! !!!!! ! !.!!! !!!!!!! ! ! !!! !!!!!!!!!!!!! 
 !   !         ! !   !       !.!           ! !   !             ! 
 ! ! ! !!!!!!! ! ! !!! !!!!!!!.! !!!!!!!!!!! ! !!!!!!!!!!!!!!! ! 
 ! ! ! !     ! !   !   ! !.....!   !   !     ! !...............! 
 ! ! !!! !!! ! !!!!! !!! !.!!!!! ! ! ! !!!!!!! !.!!!!!!!!!!!!!.! 
 ! !   !   ! !   !       !...!   !   !         !.!         !...! 
 !!!!! !!! ! !!! ! !!!!!!!!!.!!!!!!! !!!!!!!!!!!.!!!!! !!!!!.!!! 
 !     !   !   !   !       !.......!       !...!.....!      .! ! 
 ! !!!!! !!!!! !!!!! !!!!! !!!!!!!.!!!!!!!!!.!.!!!!!.!!!!!!!.! ! 
 !           !     ! !   !   !   !...........!...!...!.....!...! 
 ! !!!!!!!!! !!!!! ! !!! ! !!! ! !!!!!!!!!!!!!!!.!.!!!.!!!.!!!.! 
 ! !     !       ! !     !     !     !         !.!.....  !...!.! 
 !!! !!! !!!!!!!!! !!!!! !!!!!!!!! ! !!!!!!! !!!.! !!!!!!!!!.!.! 
 !   !     !   !   !   ! !       ! !         !...! !.........!.! 
 ! !!!!!!! ! ! ! ! !!! ! !!!!!!! ! !!!!!!!!! !.!!!!!.!!!!!!!!!.! 
 !       !   !   ! !   !         !   ! !   ! !.!.....!       !.! 
 ! !!!!! !!!!!!!!! ! !!!!!!!!!!! !!! ! ! ! ! !.!.!!!!! !!!!! !.! 
 ! !     !           !         ! ! ! !   !   !.!...!   !     !.! 
 ! ! !!!!!!!!!!!!!!!!! !!! !!!!! ! ! !!!!!!!!!.!!!.! !!!!!!!!!.! 
 ! !                     !         !          .....!          .! 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!+! 

Controlador

O controlador está em Rust (1.11 Nightly)

    type Maze = Vec<Vec<char>>;

fn str_to_maze(input: &str) -> Result<Maze,i32> {
    let mut maze: Vec<Vec<char>> = vec![ vec![] ];
    let mut row: Vec<char> = vec![];

    for c in input.chars() {
        if c == '!' || c == '+' || c == 'O'  || c == ' ' {
            row.push(c);
        }
        else if c =='.' {
            row.push(' ');
        }
        else if c == '#' {
            maze.push(row);
            row = vec![];
        }
        else if c =='\0' {
            break;
        }  
        else {
            println!("Bad character in maze: {}, exiting.", c);
            return Err(1);
        }
    }
    return Ok(maze);
}

fn display_maze(maze: &Maze, position: [usize;2]) {
    for y in 0..maze.len() {
        for x in 0..maze[y].len() {
            if [x,y] == position {
                print!("O");
            }
            else if maze[y][x] == '#' {
                println!("\n");
            }
            else {
                print!("{}",maze[y][x]);
            }
        }
        println!("");
    }
    println!("\n");
}

fn get_starting_position(maze: &mut Maze) -> Result<[usize;2],&str> {
    for y in 0..maze.len() {
        for x in 0..maze[y].len() {
            if maze[y][x] == 'O' {
                maze[y][x] = ' ';
                return Ok([x,y]);
            }
        }
    }
    return Err("No mouse found");
}

enum State {
    Continue([char;4]),
    Win,
    Disqualify,
}

fn output(maze: &Maze, position: [usize;2]) -> State {
    let x = position[0];
    let y = position[1];
    if maze[y][x] == '+' {
        return State::Win;
    }
    else if maze[y][x] == '!' {
        return State::Disqualify;
    }

    let n = maze[y-1][x];

    assert!(y+1<maze.len());
    let s = maze[y+1][x];


    let w = maze[y][x-1];

    assert!(x+1<maze[y].len());
    let e = maze[y][x+1];

    return State::Continue([n,e,s,w]);
}

fn get_input() -> char {
    use std::io;
    use std::io::Read;
    let mut buffer: [u8;2] = [0;2];
    io::stdin().read_exact(&mut buffer).unwrap();
    //println!("{:?}", buffer); // to see exactly what the input is
    return buffer[0] as char;
}

fn next_position(current_position: [usize;2], direction: char) -> Result<[usize;2],char> {
    let mut x = current_position[0];
    let mut y = current_position[1];
    if direction == 'n' {
        y -= 1;
    }
    else if direction == 'e' {
        x += 1;
    }
    else if direction == 's' {
        y += 1;
    }
    else if direction == 'w' {
        x -= 1;
    }
    else {
        return Err(direction);
    }
    return Ok([x,y]);
}


fn play(maze: &mut Maze) -> (State, usize) {
    let mut position: [usize;2];
    match get_starting_position(maze) {
        Ok(pos) => position = pos,
        Err(s) => {
            println!("{}",s);
            std::process::exit(2);
        }
    }

    let mut moves = 0;

    loop {

        let state = output(maze, position);

        /* uncomment below to view the maze at each step  */
        //display_maze(&maze, position);                
        /* ----------------------------------------------*/

        match state {
            State::Win => {
                //println!("You found the cheese");
                return(State::Win, moves);
            }
            State::Disqualify => {
                //println!("You were disqualified");
                return(State::Disqualify, moves);
            }
            State::Continue(out) => {
                println!("{}{}{}{}",out[0],out[1],out[2],out[3]);
            }
        }
        // only get here with Continue
        let input = get_input();
        moves += 1;
        match next_position(position, input) {
            Err(c) => {
                println!("Invalid input: {}", c as u8);
                return (State::Disqualify, moves);
            }
            Ok(next_pos) => position = next_pos,
        }
    }    
}

fn main() {

    let mut arg_counter = 0; 
    for argument in std::env::args() {
        if arg_counter != 0 {

            let mut maze = match argument.as_str(){
                "1" => maze_1(),
                "2" => maze_2(),
                "3" => maze_3(),
                "4" => maze_4(),
                "5" => maze_5(),
                "6" => maze_6(),
                _ => {
                    println!("invalid input: {}, breaking", argument);
                    break;
                }

            };

            let game_result = play(&mut maze);

            println!("0000");
            match game_result.0 {
                State::Win => println!("WIN"),
                State::Disqualify => println!("DISQUALIFY"),
                _ => println!("Error"),
            }
            println!("moves: {}", game_result.1 );
        }
        arg_counter += 1;
    }

}

fn maze_1() -> Maze {
    let maze_str = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    !O !                    !      !#\
                    !. ! !!!!!!!!!!!!!!!!!! ! !!!!!!#\
                    !. !                    ! !    !#\
                    !. ! !!!!!!!!!!!!!!!!!!!! ! !! !#\
                    !. !...........           ! !!.+#\
                    !. !.!!!!!!!!!.!!!!!!!!!!!!!!!.!#\
                    !.!..!        ...............!.!#\
                    !.!.!! !!!!!!!!!!!!!!!!!!!!!.!.!#\
                    !.!.!! !!!  !               .!.!#\
                    !.!.!! !!!  !!!!!!!!!!!!!!!!.!.!#\
                    !...!! !!!                  .!.!#\
                    ! ! !! !!!                  .!.!#\
                    ! ! !! !!!  !!!!!!!!! !!!!!!.!.!#\
                    ! ! !! !!!  !      !! !     .!.!#\
                    ! ! !! !!!  ! !!!!!!! !     .!.!#\
                    ! ! !! !!!  !      !! !     .!.!#\
                    ! ! !! !!!  !      !! !     .!.!#\
                    ! ! !!   !  !      !! !     .!.!#\
                    ! ! !! ! !  !!!!!! !! !     .!.!#\
                    ! ! !! ! !  !      !! !     ...!#\
                    ! ! !! ! !  !      !! !        !#\
                    ! ! !! ! !  !      !! !      ! !#\
                    ! ! !! ! !  !  !!!!!! !      ! !#\
                    ! ! !! ! !  !      !! !      ! !#\
                    ! !    !    !      !! !      ! !#\
                    ! !!!!!!  !!!!!!!! !! !      ! !#\
                    !                ! !! !      ! !#\
                    ! !!!!!!!!!!! !!!! !! !      ! !#\
                    !                     !      ! !#\
                    ! !!!!!!!! !!!!       !        !#\
                    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    ";

    match str_to_maze(&maze_str) {
        Ok(x) => return x,
        Err(i) => std::process::exit(i),
    }
}

fn maze_2() -> Maze {
    let maze_str = "!!!!!!!!!!!!!!!#\
                    !      .......!#\
                    ! !!! !.!!!! .!#\
                    !   ! !.!!O!!.!#\
                    !!!   !....! .!#\
                    !   !!!!!!!!!.!#\
                    ! !!        ..!#\
                    !  !!!!!!!!!.!!#\
                    !           ..+#\
                    !!!!!!!!!!!!!!!#\
                    ";

    match str_to_maze(&maze_str) {
        Ok(x) => return x,
        Err(i) => std::process::exit(i),
    }
}

fn maze_3() -> Maze {
    let maze_str = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    !                            !!!#\
                    ! !  !!!  !!!!!!!!!!!!!!!!!!   !#\
                    ! !  ! !!!              !!!  ! !#\
                    ! !  ! !!!!!!!!!!!!!!!!     !! !#\
                    ! !  !                  !!!!   !#\
                    ! !! !!!!!!!!!!        !!    ! !#\
                    !  ! !        !!!! !!!!!   !!! !#\
                    !! ! ! !!!!      !         !   !#\
                    !! ! ! !!!!   !!!!!!!!!!!!!! ! !#\
                    !! ! ! !!!! ! !              ! !#\
                    !! ! ! !!!! ! ! !!!!       ! ! !#\
                    !! ! ! !!!! ! ! !   !!!    ! ! !#\
                    !  ! ! !!!! ! ! !     !!!  ! ! !#\
                    !  ! ! !!!! ! ! !!!!!      !   !#\
                    !  ! ! !!!! !!! !   !!     ! !!!#\
                    !  ! !  !!!  !! !    !!!   ! !!!#\
                    !  ! !     ! !! !!!!   !!  ! !!!#\
                    !  ! !!    ! !! !  !!      ! !!!#\
                    !  !  !   !! !!     !!!    ! !!!#\
                    !  !! !!!!     !!!    !!   !   !#\
                    !!  ! !! !       !!!   !!  !!! !#\
                    !!  !    !    !    !           !#\
                    !!  !!!!!!    !!   !!!!!!!!!!! !#\
                    !             !!!! !!!!!!!!!!! !#\
                    !  ..........O!!!! !!!!!!!!!!!.+#\
                    !! .!!!!!!    !!   !!!!!!!!!!!.!#\
                    !! .!    !    !    !          .!#\
                    !!..! !! !       !!!   !!  !!!.!#\
                    ! .!! !!!!     !!!    !!   !...!#\
                    ! .!  !   !! !!     !!!    !.!!!#\
                    ! .! !!    ! !! !  !!      !.!!!#\
                    ! .! !     ! !! !!!!   !!  !.!!!#\
                    ! .! !  !!!  !! !    !!!   !.!!!#\
                    ! .! ! !!!! !!! !   !!     !.!!!#\
                    ! .! ! !!!! ! ! !!!!!      !...!#\
                    ! .! ! !!!! ! ! !     !!!  ! !.!#\
                    !!.! ! !!!! ! ! !   !!!    ! !.!#\
                    !!.! ! !!!! ! ! !!!!       ! !.!#\
                    !!.! ! !!!! ! !              !.!#\
                    !!.! ! !!!!   !!!!!!!!!!!!!! !.!#\
                    !!.! ! !!!!      !         !  .!#\
                    !..! !        !!!! !!!!!   !!!.!#\
                    !.!! !!!!!!!!!!        !!    !.!#\
                    !.!  !                  !!!!  .!#\
                    !.!  ! !!!!!!!!!!!!!!!!     !!.!#\
                    !.!  ! !!!              !!!  !.!#\
                    !.!  !!!  !!!!!!!!!!!!!!!!!!...!#\
                    !............................!!!#\
                    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    ";

    match str_to_maze(&maze_str) {
        Ok(x) => return x,
        Err(i) => std::process::exit(i),
    }
}

fn maze_4() -> Maze {
    let maze_str = "!!!!!!!!!!!!!!!!!+!!!!!!!!!!!!!!#\
                    !.................           !!!#\
                    !.!  !!!  !!!!!!!!!!!!!!!!!!   !#\
                    !.!  ! !!!              !!!  ! !#\
                    !.!  ! !!!!!!!!!!!!!!!!     !! !#\
                    !.!  !                  !!!!   !#\
                    !.!! !!!!!!!!!!        !!    ! !#\
                    !..! !        !!!! !!!!!   !!! !#\
                    !!.! ! !!!!      !         !   !#\
                    !!.! ! !!!!   !!!!!!!!!!!!!! ! !#\
                    !!.! ! !!!! ! !              ! !#\
                    !!.! ! !!!! ! ! !!!!       ! ! !#\
                    !!.! ! !!!! ! ! !   !!!    ! ! !#\
                    ! .! ! !!!! ! ! !     !!!  ! ! !#\
                    ! .! ! !!!! ! ! !!!!!      !   !#\
                    ! .! ! !!!! !!! !   !!     ! !!!#\
                    ! .! !  !!!  !! !    !!!   ! !!!#\
                    ! .! !     ! !! !!!!   !!  ! !!!#\
                    ! .! !!    ! !! !  !!      ! !!!#\
                    ! .!  !   !! !!     !!!    ! !!!#\
                    ! .!! !!!!     !!!    !!   !   !#\
                    !!. ! !! !       !!!   !!  !!! !#\
                    !!. !    !    !    !           !#\
                    !!. !!!!!!    !!   !!!!!!!!!!! !#\
                    ! ........... !!!! !!!!!!!!!!! !#\
                    !           . !!!! !!!!!!!!!!! !#\
                    !!  !!!!!!  . !!   !!!!!!!!!!! !#\
                    !!  !    !  . !    !           !#\
                    !!  ! !! !  .    !!!   !!  !!! !#\
                    !  !! !!!!  .  !!!    !!   !   !#\
                    !  !  !   !!.!!     !!!    ! !!!#\
                    !  ! !!    !.!! !  !!      ! !!!#\
                    !  ! !     !.!! !!!!   !!  ! !!!#\
                    !  ! !  !!!..!! !    !!!   ! !!!#\
                    !  ! ! !!!!.!!! !   !!     ! !!!#\
                    !  ! ! !!!!.! ! !!!!!      !   !#\
                    !  ! ! !!!!.! ! !     !!!  ! ! !#\
                    !! ! ! !!!!.! ! !   !!!    ! ! !#\
                    !! ! ! !!!!.! ! !!!!       ! ! !#\
                    !! ! ! !!!!.! !              ! !#\
                    !! ! ! !!!!.  !!!!!!!!!!!!!! ! !#\
                    !! ! ! !!!!.....O!         !   !#\
                    !  ! !        !!!! !!!!!   !!! !#\
                    ! !! !!!!!!!!!!        !!    ! !#\
                    ! !  !                  !!!!   !#\
                    ! !  ! !!!!!!!!!!!!!!!!     !! !#\
                    ! !  ! !!!              !!!  ! !#\
                    ! !  !!!  !!!!!!!!!!!!!!!!!!   !#\
                    !                            !!!#\
                    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    ";

    match str_to_maze(&maze_str) {
        Ok(x) => return x,
        Err(i) => std::process::exit(i),
    }
}


fn maze_5() -> Maze {
    let maze_str = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    +......!!!!       !!!        !!!       !!!!     !!#\
                    !     .!       !!                            !!!!!#\
                    !  !!!.! !!      !!!  !!!!  !!!!!!!!!      !!!   !#\
                    ! !!...!   !!!!!   !!    !          !!    !!     !#\
                    !!!..!!         !    !!  !           !    !     !!#\
                    !! .!!........        !! !!!     !    !   !  !  !!#\
                    !!!. !.  !  !.   !      !!!!!    !!   !   ! !! !!!#\
                    !!!. !.  !  !.   !       !!!!!    !   !!    !  !!!#\
                    !!.. !.  !  !..  !        !  !    !!   !    !   !!#\
                    !!.! !.!  ! ! ..  ! !!!!!!  !      !   !    !   !!#\
                    !!.! !.!  ! !! .  ! !      !        !  !    !   !!#\
                    !!.! !.!  !  ! .  ! !!   !!    !!!! !  !    !   !!#\
                    !!.! !.!! !  ! .  !  !!!   !!!!     !  !    !!  !!#\
                    !!.! !. ! !  ! .  !    !!        !  !   !    !  !!#\
                    ! .!!!. ! !  !!.   !    !        !  !   !    !   !#\
                    ! .!!!. ! !   !.   !     !       !   !  !    !   !#\
                    ! .! !. ! !   !.   !     !       !   !   !   !   !#\
                    ! .! !. ! !!  !....!!!   !      !!   !     ! !   !#\
                    ! .!  ..!  !  !   ...!!!!       !    !     ! ! ! !#\
                    ! .!   .!  !  !!!!!!.... !!!!!!!             ! ! !#\
                    ! .! !!.!  !! !  !!!!  .!                        !#\
                    ! .!!!!.!   !!!! !!!   .!   !!!!!   !!!!!!!!!!!  !#\
                    ! .. !!.!    !!!  !!  !.!!                       !#\
                    !!!.. !. !   !!!      !..!        !!!   !   !    !#\
                    !!! .... !  !!!!      ! .!        !             !!#\
                    !!!!!!!!!!!!!!!!!!!!!!! .! !!!!!!!!!!!!!!!!!!!! !!#\
                    !!!  !                  .!                     !!!#\
                    !!   !   !!!  !!        .!                      !!#\
                    !!   !  !     !!  !!!!!!.!  !!!!!!              !!#\
                    !!   !  !    !!   !!!!!!.! !!!!!!!!          !  !!#\
                    !!  !   !   !!   !!!!!!!.! !!!!!! !!   !  !     !!#\
                    !!  !   !   !   !!!!!!!!.! !!!  !  !   !        !!#\
                    !!  !   !   !  !!!!!!!!!.! !!!! !   !  !  !  !  !!#\
                    !!  !   !   !           .!  !!  !   !  !     !  !!#\
                    !! !!!  !   !   !!!!!!  .!      !    !!         !!#\
                    !! ! !   !  !   !     !!. !    !!!    !    !    !!#\
                    !! ! !   !  !   ! !     .  !   ! !!    !     !  !!#\
                    !! ! !   !  !   ! !!  !!.   !!!   !!   !   ! !  !!#\
                    !! ! !   !  !!  ! !!! ! .....     !!   !      ! !!#\
                    !! ! !   !   !  ! !!!!!!!   .     !    !        !!#\
                    !  ! !   !   !  !  !!!  !   .!!!!     !  !       !#\
                    !  ! !   !   !! !       !   .!      !!.......... !#\
                    ! !! !   !    !  !!!!!!!!!  .!    !!  .!   !!!!. !#\
                    ! !  !   !    !!       !!!  .!!!!!   ..   !    . !#\
                    ! !  !    !!   !!!     !!!  .......... !!!!    . !#\
                    ! !  !     !!     !!!!      !!!!!!!!!!!!      !. !#\
                    ! !         !         !!!!!!                  O. !#\
                    !           !                                    !#\
                    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    ";

    match str_to_maze(&maze_str) {
        Ok(x) => return x,
        Err(i) => std::process::exit(i),
    }
}

fn maze_6() -> Maze {
    let maze_str = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    !      !!!!   ....!!!        !!!       !!!!     !!#\
                    !      !      .!!..........                  !!!!!#\
                    !  !!! ! !!   ...!!!  !!!!. !!!!!!!!!      !!!   !#\
                    ! !!   !   !!!!!.. !!    !.         !!    !!     !#\
                    !!!  !!         !.   !!  !.....      !    !     !!#\
                    !!  !!          ..    !! !!!  .  !    !   !  !  !!#\
                    !!!  !   !  !   .!      !!!!! .  !!   !   ! !! !!!#\
                    !!!  !   !  !   .!       !!!!!.   !   !!    !  !!!#\
                    !!   !   !  !   .!        !  !.   !!   !    !   !!#\
                    !! ! ! !  ! !   . ! !!!!!!  ! ..   !   !    !   !!#\
                    !! ! ! !  ! !!  . ! !      !   .....!  !    !   !!#\
                    !! ! ! !  !  !  . ! !!   !!    !!!!.!  !    !   !!#\
                    !! ! ! !! !  !  ..!  !!!   !!!!    .!  !    !!  !!#\
                    !! ! !  ! !  !   .!    !!        ! .!   !    !  !!#\
                    !  !!!  ! !  !!  . !    !        ! .!   !    !   !#\
                    !  !!!  ! !   !  ..!     !       ! . !  !    !   !#\
                    !  ! !  ! !   !   .!     !       ! . !   !   !   !#\
                    !  ! !  ! !!  !   .!!!   !      !! . !     ! !   !#\
                    !  !    !  !  !   ...!!!!       !  . !     ! ! ! !#\
                    !  !    !  !  !!!!!!.... !!!!!!!   .         ! ! !#\
                    !  ! !! !  !! !  !!!!  .!          .             !#\
                    !  !!!! !   !!!! !!!   .!   !!!!!  .!!!!!!!!!!!  !#\
                    !    !! !    !!!  !!  !.!!..........             !#\
                    !!!   !  !   !!!      !. !.       !!!   !   !    !#\
                    !!!      !  !!!!      !. !.       !             !!#\
                    !!!!!!!!!!!!!!!!!!!!!!!. !.!!!!!!!!!!!!!!!!!!!! !!#\
                    !!!  !                 . !.....................!!!#\
                    !!   !   !!!  !!  O..... !                    ..!!#\
                    !!   !  !     !!  !!!!!! !  !!!!!!             .!!#\
                    !!   !  !    !!   !!!!!! ! !!!!!!!!          ! .!!#\
                    !!  !   !   !!   !!!!!!! ! !!!!!! !!   !  !    .!!#\
                    !!  !   !   !   !!!!!!!! ! !!!  !  !   !       .!!#\
                    !!  !   !   !  !!!!!!!!! ! !!!! !   !  !  !  ! .!!#\
                    !!  !   !   !            !  !!  !   !  !     ! .!!#\
                    !! !!!  !   !   !!!!!!   !      !    !!        .!!#\
                    !! ! !   !  !   !     !!  !    !!!    !    !   .!!#\
                    !! ! !   !  !   ! !        !   ! !!    !     ! .!!#\
                    !! ! !   !  !   ! !!  !!    !!!   !!   !   ! ! .!!#\
                    !! ! !   !  !!  ! !!! !           !!   !      !.!!#\
                    !! ! !   !   !  ! !!!!!!!         !    !       .!!#\
                    !  ! !   !   !  !  !!!  !    !!!!     !  !     . !#\
                    !  ! !   !   !! !       !    !      !!         . !#\
                    ! !! !   !    !  !!!!!!!!!   !    !!   !   !!!!. !#\
                    ! !  !   !    !!       !!!   !!!!!        !    . !#\
                    ! !  !    !!   !!!     !!!   !         !!!!    . !#\
                    ! !  !     !!     !!!!      !!!!!!!!!!!!      !..+#\
                    ! !         !         !!!!!!                     !#\
                    !           !              !                     !#\
                    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\
                    ";

    match str_to_maze(&maze_str) {
        Ok(x) => return x,
        Err(i) => std::process::exit(i),
    }
}

Para testar o labirinto maior, basta substituir a corda do labirinto na maze_1função. Certifique-se de acrescentar os #\caracteres corretos a cada linha.

Testando sua entrada

Este script pode ser usado para testar entradas

#!/bin/bash

mkfifo /tmp/pipe1
mkfifo /tmp/pipe2

for arg in "$@"; do
    <path to controller> $arg < /tmp/pipe1 | tee /tmp/pipe2 trascript.txt &
    ( <path to entry> < /tmp/pipe2 | tee /tmp/pipe1 ) > /dev/null
done

rm /tmp/pipe1
rm /tmp/pipe2

Por exemplo, meu script se parece com:

#!/bin/bash

mkfifo /tmp/pipe1
mkfifo /tmp/pipe2

for arg in "$@"; do
    ./maze/target/release/maze $arg < /tmp/pipe1 | tee /tmp/pipe2 trascript.txt &
    ( ./maze_test/main < /tmp/pipe2 | tee /tmp/pipe1 ) > /dev/null
done

rm /tmp/pipe1
rm /tmp/pipe2

É usado da seguinte maneira:

./script <mazes to test>

Por exemplo

./script 1 2 3 4 5 6

Ele imprimirá tudo no console e gravará tudo em um arquivo chamado transcript.txt

Para desenvolver sua entrada, você pode descomentar o

display_maze(&maze, position)

linha na playfunção. Isso fará com que o controlador exiba o labirinto a cada passo.


8
Então as paredes são feitas de armadilhas para ratos. Consegui.
mbomb007

2
@JuliePelletier Não acho que precisamos de prazos, podemos executar os programas independentemente. A maioria dos concursos aqui é aberta.
flawr

1
@Liam Não vejo sentido em reter a bateria de teste, pois a otimização para os casos de teste era considerada uma brecha padrão e, portanto, não é permitida.
flawr

1
@JuliePelletier Sim, eu vou tentar fazer isso o mais fácil possível
Liam

1
@JuliePelletier Está feito.
Liam

Respostas:


4

Localizando limites Bot, Java 1.5+, 124 + 37 + 206 + 324 + 248 + 223 = 1172 etapas

insira a descrição da imagem aqui

Esse bot tenta localizar e seguir os limites do labirinto, sabendo que o queijo sempre estará localizado no limite.

Isso é feito atualizando sua visão interna do labirinto e construindo candidatos atuais para as muralhas norte, sul, leste e oeste.

Uma descoberta de caminho * é realizada para todas as células inexploradas nessas paredes e o caminho mais curto é escolhido a seguir. No entanto, apenas as paredes limite candidatas que não contêm espaços em branco podem ser a parede limite "verdadeira" e, portanto, aquelas que contêm células em branco não são consideradas para encontrar o caminho. As células inexploradas dentro de um caminho recebem pontuação menos desejável, com células inexploradas consecutivas compondo a indesejabilidade.

Nesta edição mais recente, o bot agora tem um peso negativo para as células já visitadas. Isso dá uma ligeira melhora.

Existe um mecanismo de seleção de movimento à prova de falhas que garante a escolha de movimentos válidos no caso de nenhum caminho ser encontrado.

Observe que essa implementação é bastante ineficiente e pode levar muitos segundos para resolver um labirinto no pior dos casos.

Determinístico. Correr comjava BoundryFindingBot

import java.io.IOException;
import java.io.InputStream;

public class BoundryFindingBot {
    private static final char[] DIRECTION = {'n','e','s','w'};
    private static final int MAP_SIZE = 102;
    private static final int PATH_FINDING_MAX_STEPS = 50000;
    private static final int[][] offsets = new int[][]{{0,-1},{1,0},{0,1},{-1,0}};

    public static void main(String[] args) throws Exception
    {
        char[][] map = new char[MAP_SIZE][MAP_SIZE];
        int[][] visitCount = new int[MAP_SIZE][MAP_SIZE];
        int mx=MAP_SIZE/2-1, my=MAP_SIZE/2-1;
        int direction=0;

        String line=readLine(System.in);
        out:
        while (line!=null && !"0000".equals(line))
        {
            // update map with new information
            for (int i=0;i<4;i++)
            {
                map[mx+offsets[i][0]][my+offsets[i][1]] = line.charAt(i);

                // immediately move toward cheese if found.
                if (line.charAt(i) == '+')
                {
                    System.out.println(DIRECTION[i]);
                    break out;
                }
            }

            // determine the current boundary walls information
            int currentNorthWallY=-1,currentSouthWallY=-1,currentWestWallX=-1,currentEastWallX=-1;
            boolean currentNorthWallHasBlanks=false,currentSouthWallHasBlanks=false,currentEastWallHasBlanks=false,currentWestWallHasBlanks=false;
            for (int y=0;y<MAP_SIZE;y++)
            {
                for (int x=0;x<MAP_SIZE;x++)
                {
                    if (map[x][y]!=0)
                    {
                        if (currentNorthWallY > -1)
                        {
                            if (currentSouthWallY !=y)
                            {
                                currentSouthWallHasBlanks = false;
                            }
                            currentSouthWallY=y;
                            currentSouthWallHasBlanks|=map[x][y]==' ';
                        }
                        else
                        {
                            currentNorthWallY=y;
                        }

                        if (currentNorthWallY == y)
                        {
                            currentNorthWallHasBlanks|=map[x][y]==' ';
                        }

                    }
                }
            }
            for (int x=0;x<MAP_SIZE;x++)
            {
                for (int y=0;y<MAP_SIZE;y++)
                {
                    if (map[x][y]!=0)
                    {

                        if (currentWestWallX > -1)
                        {
                            if (currentEastWallX !=x)
                            {
                                currentEastWallHasBlanks = false;
                            }
                            currentEastWallX=x;
                            currentEastWallHasBlanks|=map[x][y]==' ';
                        }
                        else
                        {
                            currentWestWallX=x;
                        }

                        if (currentWestWallX == x)
                        {
                            currentWestWallHasBlanks|=map[x][y]==' ';
                        }

                    }
                }
            }

            int closestUnvisitedWallCellResult =0xFFFFFF; 

            // attempt to find paths to undiscovered cells in the current north wall, setting the shortest path if shortest of any path
            if (!currentNorthWallHasBlanks)
            {
                for (int x=currentWestWallX;x<=currentEastWallX;x++)
                {
                    if (map[x][currentNorthWallY] == 0)
                    {
                        int result = pathFind(mx, my, x, currentNorthWallY, map,visitCount,currentWestWallX,currentNorthWallY,currentEastWallX,currentSouthWallY);
                        if ((result &0xFFFFFF) <(closestUnvisitedWallCellResult &0xFFFFFF))
                        {
                            closestUnvisitedWallCellResult = result;
                        }
                    }

                }
            }

            // attempt to find paths to undiscovered cells in the current south wall, setting the shortest path if shortest of any path
            if (!currentSouthWallHasBlanks)
            {
                for (int x=currentWestWallX;x<=currentEastWallX;x++)
                {
                    if (map[x][currentSouthWallY] == 0)
                    {
                        int result = pathFind(mx, my, x, currentSouthWallY, map,visitCount,currentWestWallX,currentNorthWallY,currentEastWallX,currentSouthWallY);
                        if ((result &0xFFFFFF) <(closestUnvisitedWallCellResult &0xFFFFFF))
                        {
                            closestUnvisitedWallCellResult = result;
                        }
                    }

                }
            }

            // attempt to find paths to undiscovered cells in the current east wall, setting the shortest path if shortest of any path
            if (!currentEastWallHasBlanks)
            {
                for (int y=currentNorthWallY;y<=currentSouthWallY;y++)
                {
                    if (map[currentEastWallX][y] == 0)
                    {
                        int result = pathFind(mx, my, currentEastWallX, y, map,visitCount,currentWestWallX,currentNorthWallY,currentEastWallX,currentSouthWallY);
                        if ((result &0xFFFFFF) <(closestUnvisitedWallCellResult &0xFFFFFF))
                        {
                            closestUnvisitedWallCellResult = result;
                        }
                    }

                }
            }

            // attempt to find paths to undiscovered cells in the current west wall, setting the shortest path if shortest of any path
            if (!currentWestWallHasBlanks)
            {
                for (int y=currentNorthWallY;y<=currentSouthWallY;y++)
                {
                    if (map[currentWestWallX][y] == 0 )
                    {
                        int result = pathFind(mx, my, currentWestWallX, y, map,visitCount,currentWestWallX,currentNorthWallY,currentEastWallX,currentSouthWallY);
                        if ((result &0xFFFFFF) <(closestUnvisitedWallCellResult &0xFFFFFF))
                        {
                            closestUnvisitedWallCellResult = result;
                        }
                    }
                }
            }

            // fail-safe if we are unable to find a path to a wall (i.e. initial game frame or all current boundary walls are known to have blanks and thus
            // not wall to head for. Simply tries to go north if possible or failing that try to head east, south, west consecutively
            if (closestUnvisitedWallCellResult == 0xFFFFFF)
            {
                for (int i=0;i<4;i++)
                {
                    if (map[mx+offsets[i][0]][my+offsets[i][1]] == ' ')
                    {
                        direction = i;
                        break;
                    }
                }
            }
            else
            {
                direction = closestUnvisitedWallCellResult >> 24;
            }

            mx +=offsets[direction][0];
            my +=offsets[direction][1];
            visitCount[mx][my]+=5;

            System.out.println(DIRECTION[direction]);

//// uncomment to bot's view of maze solving
//          System.err.println();
//          for (int y=currentNorthWallY;y<=currentSouthWallY;y++)
//          {
//              for (int x=currentWestWallX;x<=currentEastWallX;x++)
//              {
//                  if (x==mx && y==my)
//                  {
//                      System.err.print("O");
//                  }
//                  else
//                  {
//                      System.err.print(map[x][y]);
//                  }
//              }
//              System.err.println();
//          }
            line=readLine(System.in);
        }
        System.err.println("Exited");
    }

/**
 * returns a result that is the combination of movement direction and path length of a path found from the given start position to the target
 * position for cells within the given bounding box. Only empty cells and unexplored cells are traversable. Sequential cells of unexplored cells 
 * are given increasing magnitude negative score to reduce desirability.
 */
static int pathFind(int startX, int startY, int targetX,int targetY,char[][] map,int[][] visitCount,int boundMinX,int boundMinY,int boundMaxX,int boundMaxY)
{
    // A*
    if (!(startX==targetX && startY==targetY))
    {

        int[] tileX = new int[PATH_FINDING_MAX_STEPS];
        int[] tileY = new int[PATH_FINDING_MAX_STEPS];
         int[] fscore = new int[PATH_FINDING_MAX_STEPS];
         int[] gscore = new int[PATH_FINDING_MAX_STEPS];
         int[] openList = new int[PATH_FINDING_MAX_STEPS];
         int[] tileParent = new int[PATH_FINDING_MAX_STEPS];
         int[] unexploredCellRun = new int[PATH_FINDING_MAX_STEPS];
         int[][] tileIsClosed = new int[MAP_SIZE][MAP_SIZE];
         int currentIndex = -1;     

        int openListSize=1;
        int tileId=1;

        tileX[0]=targetX;
        tileY[0]=targetY;
        fscore[0]=1;
        gscore[0]=1;



        do
        {
          int currentBestIndex=-1;
          int currentBestScore=Integer.MAX_VALUE;
          //  Look for the lowest F cost square on the open list
          for (int ii=0;ii<openListSize;ii++)
          {
            if (fscore[openList[ii]]<currentBestScore)
            {
              currentBestScore=fscore[openList[ii]];
              currentBestIndex=ii;
            }
          }
          if (currentBestIndex==-1)
          {
            break;
          }
          currentIndex=openList[currentBestIndex];
          int currentTileX=tileX[currentIndex];
          int currentTileY=tileY[currentIndex];

          // found path
          if (startX==currentTileX && startY==currentTileY)
          {
            break;
          }

          // if not in closed list
          if (tileIsClosed[currentTileX][currentTileY]==0)
          {
                // Switch it to the closed list.
                tileIsClosed[currentTileX][currentTileY]=1;
                // remove from openlist
                openList[currentBestIndex]=openList[--openListSize];   

                // add neigbours to the open list if necessary
                for (int i=0;i<4;i++)
                {

                        int surroundingCurrentTileX=currentTileX+offsets[i][0];
                        int surroundingCurrentTileY=currentTileY+offsets[i][1];
                        if (surroundingCurrentTileX>=boundMinX-1 && surroundingCurrentTileX<=boundMaxX+1 &&
                            surroundingCurrentTileY>=boundMinY-1 && surroundingCurrentTileY<=boundMaxY+1 )
                        {
                          tileX[tileId]=surroundingCurrentTileX;
                          tileY[tileId]=surroundingCurrentTileY;
                          if (map[surroundingCurrentTileX][surroundingCurrentTileY]==0)
                          {
                              unexploredCellRun[tileId]=0;
                          }
                          else if (map[surroundingCurrentTileX][surroundingCurrentTileY]=='!')
                          {
                              continue;
                          }
                          else
                          {
                              unexploredCellRun[tileId]=unexploredCellRun[currentIndex]+1;
                          }
                          int surroundingCurrentGscore=gscore[currentIndex]+visitCount[surroundingCurrentTileX][surroundingCurrentTileY]+1+((int) (unexploredCellRun[tileId]*10));
                          gscore[tileId]=surroundingCurrentGscore;
                          fscore[tileId]=surroundingCurrentGscore+Math.abs( surroundingCurrentTileX-startX)+Math.abs( surroundingCurrentTileY-startY);
                          tileParent[tileId]=currentIndex;
                          openList[openListSize++]=tileId++;
                     }
                }
          }
          else
          {
          // remove from openlist
          openList[currentBestIndex]=openList[--openListSize];    
          }
        } while(true);

        if (tileX[tileParent[currentIndex]]-startX<0) return (3 <<24) + currentIndex;
        else if (tileX[tileParent[currentIndex]]-startX>0) return (1 <<24) + currentIndex;
        else if (tileY[tileParent[currentIndex]]-startY<0) return (0 <<24) + currentIndex;
        else if (tileY[tileParent[currentIndex]]-startY>0) return (2 <<24) + currentIndex;
    }
    throw new RuntimeException("Path finding failed");
 }

    /**
     * Reads a line of text from the input stream. Blocks until a new line character is read.
     * NOTE: This method should be used in favor of BufferedReader.readLine(...) as BufferedReader buffers data before performing
     * text line tokenization. This means that BufferedReader.readLine() will block until many game frames have been received. 
     * @param in a InputStream, nominally System.in
     * @return a line of text or null if end of stream.
     * @throws IOException
     */
    private static String readLine(InputStream in) throws IOException
    {
       StringBuilder sb = new StringBuilder();
       int readByte = in.read();
       while (readByte>-1 && readByte!= '\n')
       {
          sb.append((char) readByte);
          readByte = in.read();
       }
       return readByte==-1?null:sb.toString();
    }

}

3

Python, 132 + 23 + 228 + 218 + 764 + 213 = 1578 etapas

Isso segue o caminho mais curto que passa pelos espaços vazios conhecidos e desconhecidos até o retângulo delimitador do mundo conhecido, até que o queijo se torne visível.

Determinístico. Execute com python SCRIPTou python3 SCRIPT(testado em 2.7 e 3.5).

import collections, sys

def neighbors(p):
    x, y = p
    return [("n", (x, y + 1)), ("e", (x + 1, y)), ("s", (x, y - 1)), ("w", (x - 1, y))]

ne = sw = loc = 0, 0
maze = {loc: ' '}

while True:
    cells = sys.stdin.readline()
    if cells == '0000\n':
        break
    for (dir1, loc1), cell in zip(neighbors(loc), cells):
        maze[loc1] = cell
        if cell == ' ':
            ne = tuple(map(max, loc1, ne))
            sw = tuple(map(min, loc1, sw))
    visited = {loc}
    queue = collections.deque()
    for dir1, loc1 in neighbors(loc):
        visited.add(loc1)
        queue.append((dir1, loc1, loc1))
    while True:
        dir1, loc1, loc2 = queue.popleft()
        if maze.get(loc2, ' ') == ' ':
            if loc2 not in maze and \
               (any(a >= b for a, b in zip(loc2, ne)) or
                any(a <= b for a, b in zip(loc2, sw))):
                break
            for dir3, loc3 in neighbors(loc2):
                if loc3 not in visited:
                    visited.add(loc3)
                    queue.append((dir1, loc1, loc3))
        elif maze[loc2] == '+':
            break
    sys.stdout.write(dir1 + "\n")
    sys.stdout.flush()
    loc = loc1

2

MATLAB, 210 + 23 + 394 + 270 + 1272 + 707 = 2876 etapas

Essa abordagem é uma modificação do meu outro envio do MATLAB . (Eles usam, no entanto, exatamente o mesmo controlador.)

Nessa abordagem, o mouse segue um caminho possível até encontrar um beco sem saída. Em seguida, ele retorna ao cruzamento anterior, onde havia um caminho que ainda não havia sido explorado. No entanto, em cada etapa, o mouse verifica aqui se existem áreas inexploradas fechadas. Dentro destes, o queijo obviamente não pode estar (como sempre está na fronteira). Se uma área desse tipo for encontrada, ela será ignorada a partir de agora.

É determinístico. Dos caminhos disponíveis, ele sempre escolhe na ordem NESW.

Como não consigo compilar scripts do matlab, traduzi o controlador para o MATLAB. O "programa" agora é apenas uma função que acessa variáveis ​​globais para armazenamento intermediário.

function find_the_cheese_controller()
clc;clear;
    global State;
    clearvars -global State;
    %uncomment the maze you want to test
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'!O !                    !      !';'!. ! !!!!!!!!!!!!!!!!!! ! !!!!!!';'!. !                    ! !    !';'!. ! !!!!!!!!!!!!!!!!!!!! ! !! !';'!. !...........           ! !!.+';'!. !.!!!!!!!!!.!!!!!!!!!!!!!!!.!';'!.!..!        ...............!.!';'!.!.!! !!!!!!!!!!!!!!!!!!!!!.!.!';'!.!.!! !!!  !               .!.!';'!.!.!! !!!  !!!!!!!!!!!!!!!!.!.!';'!...!! !!!                  .!.!';'! ! !! !!!                  .!.!';'! ! !! !!!  !!!!!!!!! !!!!!!.!.!';'! ! !! !!!  !      !! !     .!.!';'! ! !! !!!  ! !!!!!!! !     .!.!';'! ! !! !!!  !      !! !     .!.!';'! ! !! !!!  !      !! !     .!.!';'! ! !!   !  !      !! !     .!.!';'! ! !! ! !  !!!!!! !! !     .!.!';'! ! !! ! !  !      !! !     ...!';'! ! !! ! !  !      !! !        !';'! ! !! ! !  !      !! !      ! !';'! ! !! ! !  !  !!!!!! !      ! !';'! ! !! ! !  !      !! !      ! !';'! !    !    !      !! !      ! !';'! !!!!!!  !!!!!!!! !! !      ! !';'!                ! !! !      ! !';'! !!!!!!!!!!! !!!! !! !      ! !';'!                     !      ! !';'! !!!!!!!! !!!!       !        !';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!';'!      .......!';'! !!! !.!!!! .!';'!   ! !.!!O!!.!';'!!!   !....! .!';'!   !!!!!!!!!.!';'! !!        ..!';'!  !!!!!!!!!.!!';'!           ..+';'!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'!                            !!!';'! !  !!!  !!!!!!!!!!!!!!!!!!   !';'! !  ! !!!              !!!  ! !';'! !  ! !!!!!!!!!!!!!!!!     !! !';'! !  !                  !!!!   !';'! !! !!!!!!!!!!        !!    ! !';'!  ! !        !!!! !!!!!   !!! !';'!! ! ! !!!!      !         !   !';'!! ! ! !!!!   !!!!!!!!!!!!!! ! !';'!! ! ! !!!! ! !              ! !';'!! ! ! !!!! ! ! !!!!       ! ! !';'!! ! ! !!!! ! ! !   !!!    ! ! !';'!  ! ! !!!! ! ! !     !!!  ! ! !';'!  ! ! !!!! ! ! !!!!!      !   !';'!  ! ! !!!! !!! !   !!     ! !!!';'!  ! !  !!!  !! !    !!!   ! !!!';'!  ! !     ! !! !!!!   !!  ! !!!';'!  ! !!    ! !! !  !!      ! !!!';'!  !  !   !! !!     !!!    ! !!!';'!  !! !!!!     !!!    !!   !   !';'!!  ! !! !       !!!   !!  !!! !';'!!  !    !    !    !           !';'!!  !!!!!!    !!   !!!!!!!!!!! !';'!             !!!! !!!!!!!!!!! !';'!  ..........O!!!! !!!!!!!!!!!.+';'!! .!!!!!!    !!   !!!!!!!!!!!.!';'!! .!    !    !    !          .!';'!!..! !! !       !!!   !!  !!!.!';'! .!! !!!!     !!!    !!   !...!';'! .!  !   !! !!     !!!    !.!!!';'! .! !!    ! !! !  !!      !.!!!';'! .! !     ! !! !!!!   !!  !.!!!';'! .! !  !!!  !! !    !!!   !.!!!';'! .! ! !!!! !!! !   !!     !.!!!';'! .! ! !!!! ! ! !!!!!      !...!';'! .! ! !!!! ! ! !     !!!  ! !.!';'!!.! ! !!!! ! ! !   !!!    ! !.!';'!!.! ! !!!! ! ! !!!!       ! !.!';'!!.! ! !!!! ! !              !.!';'!!.! ! !!!!   !!!!!!!!!!!!!! !.!';'!!.! ! !!!!      !         !  .!';'!..! !        !!!! !!!!!   !!!.!';'!.!! !!!!!!!!!!        !!    !.!';'!.!  !                  !!!!  .!';'!.!  ! !!!!!!!!!!!!!!!!     !!.!';'!.!  ! !!!              !!!  !.!';'!.!  !!!  !!!!!!!!!!!!!!!!!!...!';'!............................!!!';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!+!!!!!!!!!!!!!!';'!.................           !!!';'!.!  !!!  !!!!!!!!!!!!!!!!!!   !';'!.!  ! !!!              !!!  ! !';'!.!  ! !!!!!!!!!!!!!!!!     !! !';'!.!  !                  !!!!   !';'!.!! !!!!!!!!!!        !!    ! !';'!..! !        !!!! !!!!!   !!! !';'!!.! ! !!!!      !         !   !';'!!.! ! !!!!   !!!!!!!!!!!!!! ! !';'!!.! ! !!!! ! !              ! !';'!!.! ! !!!! ! ! !!!!       ! ! !';'!!.! ! !!!! ! ! !   !!!    ! ! !';'! .! ! !!!! ! ! !     !!!  ! ! !';'! .! ! !!!! ! ! !!!!!      !   !';'! .! ! !!!! !!! !   !!     ! !!!';'! .! !  !!!  !! !    !!!   ! !!!';'! .! !     ! !! !!!!   !!  ! !!!';'! .! !!    ! !! !  !!      ! !!!';'! .!  !   !! !!     !!!    ! !!!';'! .!! !!!!     !!!    !!   !   !';'!!. ! !! !       !!!   !!  !!! !';'!!. !    !    !    !           !';'!!. !!!!!!    !!   !!!!!!!!!!! !';'! ........... !!!! !!!!!!!!!!! !';'!           . !!!! !!!!!!!!!!! !';'!!  !!!!!!  . !!   !!!!!!!!!!! !';'!!  !    !  . !    !           !';'!!  ! !! !  .    !!!   !!  !!! !';'!  !! !!!!  .  !!!    !!   !   !';'!  !  !   !!.!!     !!!    ! !!!';'!  ! !!    !.!! !  !!      ! !!!';'!  ! !     !.!! !!!!   !!  ! !!!';'!  ! !  !!!..!! !    !!!   ! !!!';'!  ! ! !!!!.!!! !   !!     ! !!!';'!  ! ! !!!!.! ! !!!!!      !   !';'!  ! ! !!!!.! ! !     !!!  ! ! !';'!! ! ! !!!!.! ! !   !!!    ! ! !';'!! ! ! !!!!.! ! !!!!       ! ! !';'!! ! ! !!!!.! !              ! !';'!! ! ! !!!!.  !!!!!!!!!!!!!! ! !';'!! ! ! !!!!.....O!         !   !';'!  ! !        !!!! !!!!!   !!! !';'! !! !!!!!!!!!!        !!    ! !';'! !  !                  !!!!   !';'! !  ! !!!!!!!!!!!!!!!!     !! !';'! !  ! !!!              !!!  ! !';'! !  !!!  !!!!!!!!!!!!!!!!!!   !';'!                            !!!';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'+......!!!!       !!!        !!!       !!!!     !!';'!     .!       !!                            !!!!!';'!  !!!.! !!      !!!  !!!!  !!!!!!!!!      !!!   !';'! !!...!   !!!!!   !!    !          !!    !!     !';'!!!..!!         !    !!  !           !    !     !!';'!! .!!........        !! !!!     !    !   !  !  !!';'!!!. !.  !  !.   !      !!!!!    !!   !   ! !! !!!';'!!!. !.  !  !.   !       !!!!!    !   !!    !  !!!';'!!.. !.  !  !..  !        !  !    !!   !    !   !!';'!!.! !.!  ! ! ..  ! !!!!!!  !      !   !    !   !!';'!!.! !.!  ! !! .  ! !      !        !  !    !   !!';'!!.! !.!  !  ! .  ! !!   !!    !!!! !  !    !   !!';'!!.! !.!! !  ! .  !  !!!   !!!!     !  !    !!  !!';'!!.! !. ! !  ! .  !    !!        !  !   !    !  !!';'! .!!!. ! !  !!.   !    !        !  !   !    !   !';'! .!!!. ! !   !.   !     !       !   !  !    !   !';'! .! !. ! !   !.   !     !       !   !   !   !   !';'! .! !. ! !!  !....!!!   !      !!   !     ! !   !';'! .!  ..!  !  !   ...!!!!       !    !     ! ! ! !';'! .!   .!  !  !!!!!!.... !!!!!!!             ! ! !';'! .! !!.!  !! !  !!!!  .!                        !';'! .!!!!.!   !!!! !!!   .!   !!!!!   !!!!!!!!!!!  !';'! .. !!.!    !!!  !!  !.!!                       !';'!!!.. !. !   !!!      !..!        !!!   !   !    !';'!!! .... !  !!!!      ! .!        !             !!';'!!!!!!!!!!!!!!!!!!!!!!! .! !!!!!!!!!!!!!!!!!!!! !!';'!!!  !                  .!                     !!!';'!!   !   !!!  !!        .!                      !!';'!!   !  !     !!  !!!!!!.!  !!!!!!              !!';'!!   !  !    !!   !!!!!!.! !!!!!!!!          !  !!';'!!  !   !   !!   !!!!!!!.! !!!!!! !!   !  !     !!';'!!  !   !   !   !!!!!!!!.! !!!  !  !   !        !!';'!!  !   !   !  !!!!!!!!!.! !!!! !   !  !  !  !  !!';'!!  !   !   !           .!  !!  !   !  !     !  !!';'!! !!!  !   !   !!!!!!  .!      !    !!         !!';'!! ! !   !  !   !     !!. !    !!!    !    !    !!';'!! ! !   !  !   ! !     .  !   ! !!    !     !  !!';'!! ! !   !  !   ! !!  !!.   !!!   !!   !   ! !  !!';'!! ! !   !  !!  ! !!! ! .....     !!   !      ! !!';'!! ! !   !   !  ! !!!!!!!   .     !    !        !!';'!  ! !   !   !  !  !!!  !   .!!!!     !  !       !';'!  ! !   !   !! !       !   .!      !!.......... !';'! !! !   !    !  !!!!!!!!!  .!    !!  .!   !!!!. !';'! !  !   !    !!       !!!  .!!!!!   ..   !    . !';'! !  !    !!   !!!     !!!  .......... !!!!    . !';'! !  !     !!     !!!!      !!!!!!!!!!!!      !. !';'! !         !         !!!!!!                  O. !';'!           !                                    !';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'!      !!!!   ....!!!        !!!       !!!!     !!';'!      !      .!!..........                  !!!!!';'!  !!! ! !!   ...!!!  !!!!. !!!!!!!!!      !!!   !';'! !!   !   !!!!!.. !!    !.         !!    !!     !';'!!!  !!         !.   !!  !.....      !    !     !!';'!!  !!          ..    !! !!!  .  !    !   !  !  !!';'!!!  !   !  !   .!      !!!!! .  !!   !   ! !! !!!';'!!!  !   !  !   .!       !!!!!.   !   !!    !  !!!';'!!   !   !  !   .!        !  !.   !!   !    !   !!';'!! ! ! !  ! !   . ! !!!!!!  ! ..   !   !    !   !!';'!! ! ! !  ! !!  . ! !      !   .....!  !    !   !!';'!! ! ! !  !  !  . ! !!   !!    !!!!.!  !    !   !!';'!! ! ! !! !  !  ..!  !!!   !!!!    .!  !    !!  !!';'!! ! !  ! !  !   .!    !!        ! .!   !    !  !!';'!  !!!  ! !  !!  . !    !        ! .!   !    !   !';'!  !!!  ! !   !  ..!     !       ! . !  !    !   !';'!  ! !  ! !   !   .!     !       ! . !   !   !   !';'!  ! !  ! !!  !   .!!!   !      !! . !     ! !   !';'!  !    !  !  !   ...!!!!       !  . !     ! ! ! !';'!  !    !  !  !!!!!!.... !!!!!!!   .         ! ! !';'!  ! !! !  !! !  !!!!  .!          .             !';'!  !!!! !   !!!! !!!   .!   !!!!!  .!!!!!!!!!!!  !';'!    !! !    !!!  !!  !.!!..........             !';'!!!   !  !   !!!      !. !.       !!!   !   !    !';'!!!      !  !!!!      !. !.       !             !!';'!!!!!!!!!!!!!!!!!!!!!!!. !.!!!!!!!!!!!!!!!!!!!! !!';'!!!  !                 . !.....................!!!';'!!   !   !!!  !!  O..... !                    ..!!';'!!   !  !     !!  !!!!!! !  !!!!!!             .!!';'!!   !  !    !!   !!!!!! ! !!!!!!!!          ! .!!';'!!  !   !   !!   !!!!!!! ! !!!!!! !!   !  !    .!!';'!!  !   !   !   !!!!!!!! ! !!!  !  !   !       .!!';'!!  !   !   !  !!!!!!!!! ! !!!! !   !  !  !  ! .!!';'!!  !   !   !            !  !!  !   !  !     ! .!!';'!! !!!  !   !   !!!!!!   !      !    !!        .!!';'!! ! !   !  !   !     !!  !    !!!    !    !   .!!';'!! ! !   !  !   ! !        !   ! !!    !     ! .!!';'!! ! !   !  !   ! !!  !!    !!!   !!   !   ! ! .!!';'!! ! !   !  !!  ! !!! !           !!   !      !.!!';'!! ! !   !   !  ! !!!!!!!         !    !       .!!';'!  ! !   !   !  !  !!!  !    !!!!     !  !     . !';'!  ! !   !   !! !       !    !      !!         . !';'! !! !   !    !  !!!!!!!!!   !    !!   !   !!!!. !';'! !  !   !    !!       !!!   !!!!!        !    . !';'! !  !    !!   !!!     !!!   !         !!!!    . !';'! !  !     !!     !!!!      !!!!!!!!!!!!      !..+';'! !         !         !!!!!!                     !';'!           !              !                     !';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!']



    %replace dot with space
    maze(maze=='.')=' ';
    %position of mouse
    [u,v]=find(maze=='O'); 
    maze(maze=='O') = ' ';
    step_counter = 0;
    while true; %game loop
        %test if mouse found cheese
        if maze(u,v) == '+';
            disp(['mouse found cheese after ', num2str(step_counter), ' steps']);
            break;
        end

        %extract NESW tiles
        nesw = [maze(u-1,v),maze(u,v+1),maze(u+1,v),maze(u,v-1)];

        %get result and move accordingly
        answer = find_the_cheese(nesw);
        switch answer;
            case 'n';
                u = u-1;
            case 'e';
                v = v+1;
            case 's';
                u = u+1;
            otherwise;
                v = v-1;
        end

        %make sure, mouse did not run into wall
        assert(maze(u,v) ~= '!','mouse ran into wall!');
        step_counter = step_counter + 1;
    end
end


function step = find_the_cheese(nesw)
    global State;
    NESW = 'nesw';
    NESW_REVERSE = 'swne';

    if all(nesw == '0000');
        return;
    elseif ~isfield(State,'maze');
        State = struct('maze', zeros(140)+' ','u',75,'v',75,'state','E');
        State.maze(State.u,State.v) = 'S';
    end    
    if State.maze(State.u-1,State.v) == ' '
        State.maze(State.u-1,State.v) = nesw(1);
    end
    if State.maze(State.u,State.v+1) == ' '
        State.maze(State.u,State.v+1) = nesw(2);
    end
    if State.maze(State.u+1,State.v) == ' '
        State.maze(State.u+1,State.v) = nesw(3);
    end
    if State.maze(State.u,State.v-1) == ' '
        State.maze(State.u,State.v-1) = nesw(4);
    end

    current_nesw = [State.maze(State.u-1,State.v),State.maze(State.u,State.v+1),State.maze(State.u+1,State.v),State.maze(State.u,State.v-1)];

    if any(current_nesw == '+'); % if there is cheese, go there
        nesw_index = find(current_nesw == '+',1);

    elseif any(current_nesw == ' '); % if there is a path that we did not walk, go there
        nesw_index = find(current_nesw == ' ',1);
        State.state = 'E';

    else % return to previous crossing
        nesw_index = find(NESW == State.maze(State.u,State.v),1);
        assert(numel(nesw_index)>0,'not enough indices')

        State.state = 'R';
    end

    %execute the step
    if State.state == 'E';
        step = NESW(nesw_index);
    else %State.state = 'R'
        step = State.maze(State.u, State.v);
    end

    switch step;
        case 'n';
            State.u = State.u-1;
        case 'e';
            State.v = State.v+1;
        case 's';
            State.u = State.u+1;
        otherwise;
            State.v = State.v-1;
    end

    if State.maze(State.u,State.v) == ' '; %if we do not have a reverse poniter yet
        State.maze(State.u,State.v) = NESW_REVERSE(nesw_index); %reverse pointer
    end

    %check whether we have any enclosed areas, where the cheese obviously cannot be
    M = imfill(State.maze ~= ' ','holes'); 
    %fill those areas with walls
    State.maze(M & State.maze == ' ') = '!';


    %disp_important(State.maze); %uncomment for display
end


function disp_important(m) %just show the important stuff of the maze
    if any(m(:) ~= ' ');
        for k=1:4
            m = rot90(m);
            while all(m(:,1) == ' ');
                m = m(:,2:end);
            end
        end
    end
    if numel(m) == 0;
        m = 'X';
    end
    m = padarray(m,[1,1],35,'both');
    disp([m,'']);
end

Para sua informação, esses labirintos não são os labirintos em que você está pontuado. "Provavelmente haverá 10 labirintos no total e cada envio provavelmente tentará cada labirinto várias vezes, de várias posições iniciais e posições de queijo".
mbomb007

Eu sei, mas não há mais nada que eu possa escrever no título: D Não, de verdade, eu apenas pensei que esses dois casos de teste pelo menos desse alguma impressão sobre o desempenho das submissões.
flawr

A bateria foi lançado agora pela maneira
Liam

Legal, obrigado! Vou atualização assim que eu sou feito com o trabalho =)
flawr

@Liam eu atualizei-os!
flawr

1

Python 3, 156 bytes, 37692 + 715 + 50626 + 27806 + 148596 + 172675 = 438110 etapas

Isso não é , mas o golfe é divertido de qualquer maneira. Isso segue o caminho do queijo ou segue o caminho de saída menos percorrido, semelhante à idéia de mbomb007 (não totalmente implementada) , mas com os vínculos quebrados ao ir para o nome da direção alfabeticamente mais recente.

Determinístico. Execute com python3 SCRIPT(testado em 3.5).

x=y=0
f={}
for l in iter(input,'0000'):c,d,x,y=p=max((f.setdefault(p,0),p)for p in zip(l,'nesw',[x,x+1,x,x-1],[y+1,y,y-1,y])if'!'!=p[0])[1];print(d);f[p]-=1

O @ mbomb007 fcontrola quais etapas entre os espaços foram usadas e com que frequência. Por exemplo, -f[' ', 'n', 3, 6]é o número de vezes que fomos para o norte de (3, 5) para (3, 6).
Anders Kaseorg

Então também rastreia a direção?
mbomb007

@ mbomb007 Sim, mas apenas porque isso economiza alguns bytes - lembrar a direção faz com que sejam necessárias muito mais etapas.
Anders Kaseorg

1

PHP 362 + 37 + 1638 + 1508 + 6696 + 1613 = 11854 etapas

Ran benchmark no código corrigido por bug:

<?php

class Maze {
    public $map, $pos;
    public $prevPos = FALSE;
    public $intersections = [];

    public $n = 75, $e = 75, $w = 75, $s = 75;

    public function __construct() {
        // since we don't know where we start, build a 150x150 map and position ourselves at the middle
        $this->map = array_pad([], 150, array_pad([], 150, 0)); // 0 is unknown
        $this->pos = ['x'=> 75, 'y'=> 75];
    }

    public function play($input){
        $this->updateMap($input);
        $this->move();
    }

    private function updateField($x, $y, $inData) {
        if ($inData == '!' || $this->map[$x][$y] >= 1000) {                 // avoid overwriting our observations
            $this->map[$x][$y] = 1000;
            return;
        }

        // update our known borders
        if ($x <= $this->w) {
            $this->w = $x - 1;
        }
        elseif ($x >= $this->e) {
            $this->e = $x + 1;
        }
        elseif ($y <= $this->n) {
            $this->n = $y - 1;
        }
        elseif ($y >= $this->s) {
            $this->s = $y + 1;
        }

        if (!$this->map[$x][$y]) {
            $this->map[$x][$y] = $inData == '+' ? -1 : 1;
        }
    }

    private function checkForIntersection($input) {
        if (array_key_exists('x' . $this->pos['x'] . 'y' . $this->pos['y'], $this->intersections)) {
            if ($this->intersections['x' . $this->pos['x'] . 'y' . $this->pos['y']] > 0) {
                $this->intersections['x' . $this->pos['x'] . 'y' . $this->pos['y']] --;
                return TRUE;                                        // intersection already crossed
            }
        }
        elseif ($c = substr_count($input, ' ') > 2) {
            $this->intersections['x' . $this->pos['x'] . 'y' . $this->pos['y']] = $c - 1;
        }

        return FALSE;
    }

    private function updateMap($input) {
        if ($this->checkForIntersection($input)) {
            // if we're at a known intersection, we know that the path we come from lead nowhere
            $this->updateField($this->prevPos['x'], $this->prevPos['y'], '!');
        }

        // update discovered information
        $this->updateField($this->pos['x'], $this->pos['y'] - 1, $input[0]);
        $this->updateField($this->pos['x'] + 1, $this->pos['y'], $input[1]);
        $this->updateField($this->pos['x'], $this->pos['y'] + 1, $input[2]);
        $this->updateField($this->pos['x'] - 1, $this->pos['y'], $input[3]);
    }

    private function move() {
        if ($this->prevPos) {

            $this->map[$this->prevPos['x']][$this->prevPos['y']] ++;    // count times stepped on   
        }

        $best = ['w' => 1000];

        foreach ([
            ['x' => $this->pos['x'], 'y' => $this->pos['y'] - 1, 'w' => $this->map[$this->pos['x']][$this->pos['y'] - 1], 'd' => 'n'],
            ['x' => $this->pos['x'] + 1, 'y' => $this->pos['y'], 'w' => $this->map[$this->pos['x'] + 1][$this->pos['y']], 'd' => 'e'],
            ['x' => $this->pos['x'], 'y' => $this->pos['y'] + 1, 'w' => $this->map[$this->pos['x']][$this->pos['y'] + 1], 'd' => 's'],
            ['x' => $this->pos['x'] - 1, 'y' => $this->pos['y'], 'w' => $this->map[$this->pos['x'] - 1][$this->pos['y']], 'd' => 'w']]
        as $direction) {
            if ($direction['w'] < $best['w'] || ($direction['w'] == $best['w'] && $best['w'] < 1000 && max($this->e - $direction['x'],  $direction['x'] - $this->w, $direction['y'] - $this->n, $this->s - $direction['y']) > max($best['x'] - $this->e, $this->w - $best['x'], $best['y'] - $this->n, $this->s - $best['y']))) { 
            // encourage searching for borders which will later allow to block certain dead end paths without walking them
            // testing with middle search instead
                $best = $direction;
            }
        }

        echo $best['d'] . "\n";

        $this->prevPos = $this->pos;
        $this->pos = $best;
    }
}

$maze = new Maze();

while (strncmp(($input = fgets(STDIN)), '0000', 4)) {
    $len = strlen($input);
    if (($len > 6) || $len < 3) { continue; }

    $maze->play($input);
}

1

MATLAB, 212 + 23 + 416 + 300 + 1806 + 757 = 3514 etapas

Nesta abordagem, o mouse segue um caminho possível até encontrar um beco sem saída. Em seguida, ele retorna ao cruzamento anterior, onde havia um caminho que ainda não havia sido explorado. É determinístico. Dos caminhos disponíveis, ele sempre escolhe na ordem NESW(não NSFW, como eu sempre tentava escrever =)

Como não consigo compilar scripts do matlab, traduzi o controlador para o MATLAB. O "programa" agora é apenas uma função que acessa variáveis ​​globais para armazenamento intermediário.

function find_the_cheese_controller()
clc;clear;
    global State;
    clearvars -global State;
    %uncomment the maze you want to test
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'!O !                    !      !';'!. ! !!!!!!!!!!!!!!!!!! ! !!!!!!';'!. !                    ! !    !';'!. ! !!!!!!!!!!!!!!!!!!!! ! !! !';'!. !...........           ! !!.+';'!. !.!!!!!!!!!.!!!!!!!!!!!!!!!.!';'!.!..!        ...............!.!';'!.!.!! !!!!!!!!!!!!!!!!!!!!!.!.!';'!.!.!! !!!  !               .!.!';'!.!.!! !!!  !!!!!!!!!!!!!!!!.!.!';'!...!! !!!                  .!.!';'! ! !! !!!                  .!.!';'! ! !! !!!  !!!!!!!!! !!!!!!.!.!';'! ! !! !!!  !      !! !     .!.!';'! ! !! !!!  ! !!!!!!! !     .!.!';'! ! !! !!!  !      !! !     .!.!';'! ! !! !!!  !      !! !     .!.!';'! ! !!   !  !      !! !     .!.!';'! ! !! ! !  !!!!!! !! !     .!.!';'! ! !! ! !  !      !! !     ...!';'! ! !! ! !  !      !! !        !';'! ! !! ! !  !      !! !      ! !';'! ! !! ! !  !  !!!!!! !      ! !';'! ! !! ! !  !      !! !      ! !';'! !    !    !      !! !      ! !';'! !!!!!!  !!!!!!!! !! !      ! !';'!                ! !! !      ! !';'! !!!!!!!!!!! !!!! !! !      ! !';'!                     !      ! !';'! !!!!!!!! !!!!       !        !';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!';'!      .......!';'! !!! !.!!!! .!';'!   ! !.!!O!!.!';'!!!   !....! .!';'!   !!!!!!!!!.!';'! !!        ..!';'!  !!!!!!!!!.!!';'!           ..+';'!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'!                            !!!';'! !  !!!  !!!!!!!!!!!!!!!!!!   !';'! !  ! !!!              !!!  ! !';'! !  ! !!!!!!!!!!!!!!!!     !! !';'! !  !                  !!!!   !';'! !! !!!!!!!!!!        !!    ! !';'!  ! !        !!!! !!!!!   !!! !';'!! ! ! !!!!      !         !   !';'!! ! ! !!!!   !!!!!!!!!!!!!! ! !';'!! ! ! !!!! ! !              ! !';'!! ! ! !!!! ! ! !!!!       ! ! !';'!! ! ! !!!! ! ! !   !!!    ! ! !';'!  ! ! !!!! ! ! !     !!!  ! ! !';'!  ! ! !!!! ! ! !!!!!      !   !';'!  ! ! !!!! !!! !   !!     ! !!!';'!  ! !  !!!  !! !    !!!   ! !!!';'!  ! !     ! !! !!!!   !!  ! !!!';'!  ! !!    ! !! !  !!      ! !!!';'!  !  !   !! !!     !!!    ! !!!';'!  !! !!!!     !!!    !!   !   !';'!!  ! !! !       !!!   !!  !!! !';'!!  !    !    !    !           !';'!!  !!!!!!    !!   !!!!!!!!!!! !';'!             !!!! !!!!!!!!!!! !';'!  ..........O!!!! !!!!!!!!!!!.+';'!! .!!!!!!    !!   !!!!!!!!!!!.!';'!! .!    !    !    !          .!';'!!..! !! !       !!!   !!  !!!.!';'! .!! !!!!     !!!    !!   !...!';'! .!  !   !! !!     !!!    !.!!!';'! .! !!    ! !! !  !!      !.!!!';'! .! !     ! !! !!!!   !!  !.!!!';'! .! !  !!!  !! !    !!!   !.!!!';'! .! ! !!!! !!! !   !!     !.!!!';'! .! ! !!!! ! ! !!!!!      !...!';'! .! ! !!!! ! ! !     !!!  ! !.!';'!!.! ! !!!! ! ! !   !!!    ! !.!';'!!.! ! !!!! ! ! !!!!       ! !.!';'!!.! ! !!!! ! !              !.!';'!!.! ! !!!!   !!!!!!!!!!!!!! !.!';'!!.! ! !!!!      !         !  .!';'!..! !        !!!! !!!!!   !!!.!';'!.!! !!!!!!!!!!        !!    !.!';'!.!  !                  !!!!  .!';'!.!  ! !!!!!!!!!!!!!!!!     !!.!';'!.!  ! !!!              !!!  !.!';'!.!  !!!  !!!!!!!!!!!!!!!!!!...!';'!............................!!!';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!+!!!!!!!!!!!!!!';'!.................           !!!';'!.!  !!!  !!!!!!!!!!!!!!!!!!   !';'!.!  ! !!!              !!!  ! !';'!.!  ! !!!!!!!!!!!!!!!!     !! !';'!.!  !                  !!!!   !';'!.!! !!!!!!!!!!        !!    ! !';'!..! !        !!!! !!!!!   !!! !';'!!.! ! !!!!      !         !   !';'!!.! ! !!!!   !!!!!!!!!!!!!! ! !';'!!.! ! !!!! ! !              ! !';'!!.! ! !!!! ! ! !!!!       ! ! !';'!!.! ! !!!! ! ! !   !!!    ! ! !';'! .! ! !!!! ! ! !     !!!  ! ! !';'! .! ! !!!! ! ! !!!!!      !   !';'! .! ! !!!! !!! !   !!     ! !!!';'! .! !  !!!  !! !    !!!   ! !!!';'! .! !     ! !! !!!!   !!  ! !!!';'! .! !!    ! !! !  !!      ! !!!';'! .!  !   !! !!     !!!    ! !!!';'! .!! !!!!     !!!    !!   !   !';'!!. ! !! !       !!!   !!  !!! !';'!!. !    !    !    !           !';'!!. !!!!!!    !!   !!!!!!!!!!! !';'! ........... !!!! !!!!!!!!!!! !';'!           . !!!! !!!!!!!!!!! !';'!!  !!!!!!  . !!   !!!!!!!!!!! !';'!!  !    !  . !    !           !';'!!  ! !! !  .    !!!   !!  !!! !';'!  !! !!!!  .  !!!    !!   !   !';'!  !  !   !!.!!     !!!    ! !!!';'!  ! !!    !.!! !  !!      ! !!!';'!  ! !     !.!! !!!!   !!  ! !!!';'!  ! !  !!!..!! !    !!!   ! !!!';'!  ! ! !!!!.!!! !   !!     ! !!!';'!  ! ! !!!!.! ! !!!!!      !   !';'!  ! ! !!!!.! ! !     !!!  ! ! !';'!! ! ! !!!!.! ! !   !!!    ! ! !';'!! ! ! !!!!.! ! !!!!       ! ! !';'!! ! ! !!!!.! !              ! !';'!! ! ! !!!!.  !!!!!!!!!!!!!! ! !';'!! ! ! !!!!.....O!         !   !';'!  ! !        !!!! !!!!!   !!! !';'! !! !!!!!!!!!!        !!    ! !';'! !  !                  !!!!   !';'! !  ! !!!!!!!!!!!!!!!!     !! !';'! !  ! !!!              !!!  ! !';'! !  !!!  !!!!!!!!!!!!!!!!!!   !';'!                            !!!';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'+......!!!!       !!!        !!!       !!!!     !!';'!     .!       !!                            !!!!!';'!  !!!.! !!      !!!  !!!!  !!!!!!!!!      !!!   !';'! !!...!   !!!!!   !!    !          !!    !!     !';'!!!..!!         !    !!  !           !    !     !!';'!! .!!........        !! !!!     !    !   !  !  !!';'!!!. !.  !  !.   !      !!!!!    !!   !   ! !! !!!';'!!!. !.  !  !.   !       !!!!!    !   !!    !  !!!';'!!.. !.  !  !..  !        !  !    !!   !    !   !!';'!!.! !.!  ! ! ..  ! !!!!!!  !      !   !    !   !!';'!!.! !.!  ! !! .  ! !      !        !  !    !   !!';'!!.! !.!  !  ! .  ! !!   !!    !!!! !  !    !   !!';'!!.! !.!! !  ! .  !  !!!   !!!!     !  !    !!  !!';'!!.! !. ! !  ! .  !    !!        !  !   !    !  !!';'! .!!!. ! !  !!.   !    !        !  !   !    !   !';'! .!!!. ! !   !.   !     !       !   !  !    !   !';'! .! !. ! !   !.   !     !       !   !   !   !   !';'! .! !. ! !!  !....!!!   !      !!   !     ! !   !';'! .!  ..!  !  !   ...!!!!       !    !     ! ! ! !';'! .!   .!  !  !!!!!!.... !!!!!!!             ! ! !';'! .! !!.!  !! !  !!!!  .!                        !';'! .!!!!.!   !!!! !!!   .!   !!!!!   !!!!!!!!!!!  !';'! .. !!.!    !!!  !!  !.!!                       !';'!!!.. !. !   !!!      !..!        !!!   !   !    !';'!!! .... !  !!!!      ! .!        !             !!';'!!!!!!!!!!!!!!!!!!!!!!! .! !!!!!!!!!!!!!!!!!!!! !!';'!!!  !                  .!                     !!!';'!!   !   !!!  !!        .!                      !!';'!!   !  !     !!  !!!!!!.!  !!!!!!              !!';'!!   !  !    !!   !!!!!!.! !!!!!!!!          !  !!';'!!  !   !   !!   !!!!!!!.! !!!!!! !!   !  !     !!';'!!  !   !   !   !!!!!!!!.! !!!  !  !   !        !!';'!!  !   !   !  !!!!!!!!!.! !!!! !   !  !  !  !  !!';'!!  !   !   !           .!  !!  !   !  !     !  !!';'!! !!!  !   !   !!!!!!  .!      !    !!         !!';'!! ! !   !  !   !     !!. !    !!!    !    !    !!';'!! ! !   !  !   ! !     .  !   ! !!    !     !  !!';'!! ! !   !  !   ! !!  !!.   !!!   !!   !   ! !  !!';'!! ! !   !  !!  ! !!! ! .....     !!   !      ! !!';'!! ! !   !   !  ! !!!!!!!   .     !    !        !!';'!  ! !   !   !  !  !!!  !   .!!!!     !  !       !';'!  ! !   !   !! !       !   .!      !!.......... !';'! !! !   !    !  !!!!!!!!!  .!    !!  .!   !!!!. !';'! !  !   !    !!       !!!  .!!!!!   ..   !    . !';'! !  !    !!   !!!     !!!  .......... !!!!    . !';'! !  !     !!     !!!!      !!!!!!!!!!!!      !. !';'! !         !         !!!!!!                  O. !';'!           !                                    !';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'];
    %maze=['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';'!      !!!!   ....!!!        !!!       !!!!     !!';'!      !      .!!..........                  !!!!!';'!  !!! ! !!   ...!!!  !!!!. !!!!!!!!!      !!!   !';'! !!   !   !!!!!.. !!    !.         !!    !!     !';'!!!  !!         !.   !!  !.....      !    !     !!';'!!  !!          ..    !! !!!  .  !    !   !  !  !!';'!!!  !   !  !   .!      !!!!! .  !!   !   ! !! !!!';'!!!  !   !  !   .!       !!!!!.   !   !!    !  !!!';'!!   !   !  !   .!        !  !.   !!   !    !   !!';'!! ! ! !  ! !   . ! !!!!!!  ! ..   !   !    !   !!';'!! ! ! !  ! !!  . ! !      !   .....!  !    !   !!';'!! ! ! !  !  !  . ! !!   !!    !!!!.!  !    !   !!';'!! ! ! !! !  !  ..!  !!!   !!!!    .!  !    !!  !!';'!! ! !  ! !  !   .!    !!        ! .!   !    !  !!';'!  !!!  ! !  !!  . !    !        ! .!   !    !   !';'!  !!!  ! !   !  ..!     !       ! . !  !    !   !';'!  ! !  ! !   !   .!     !       ! . !   !   !   !';'!  ! !  ! !!  !   .!!!   !      !! . !     ! !   !';'!  !    !  !  !   ...!!!!       !  . !     ! ! ! !';'!  !    !  !  !!!!!!.... !!!!!!!   .         ! ! !';'!  ! !! !  !! !  !!!!  .!          .             !';'!  !!!! !   !!!! !!!   .!   !!!!!  .!!!!!!!!!!!  !';'!    !! !    !!!  !!  !.!!..........             !';'!!!   !  !   !!!      !. !.       !!!   !   !    !';'!!!      !  !!!!      !. !.       !             !!';'!!!!!!!!!!!!!!!!!!!!!!!. !.!!!!!!!!!!!!!!!!!!!! !!';'!!!  !                 . !.....................!!!';'!!   !   !!!  !!  O..... !                    ..!!';'!!   !  !     !!  !!!!!! !  !!!!!!             .!!';'!!   !  !    !!   !!!!!! ! !!!!!!!!          ! .!!';'!!  !   !   !!   !!!!!!! ! !!!!!! !!   !  !    .!!';'!!  !   !   !   !!!!!!!! ! !!!  !  !   !       .!!';'!!  !   !   !  !!!!!!!!! ! !!!! !   !  !  !  ! .!!';'!!  !   !   !            !  !!  !   !  !     ! .!!';'!! !!!  !   !   !!!!!!   !      !    !!        .!!';'!! ! !   !  !   !     !!  !    !!!    !    !   .!!';'!! ! !   !  !   ! !        !   ! !!    !     ! .!!';'!! ! !   !  !   ! !!  !!    !!!   !!   !   ! ! .!!';'!! ! !   !  !!  ! !!! !           !!   !      !.!!';'!! ! !   !   !  ! !!!!!!!         !    !       .!!';'!  ! !   !   !  !  !!!  !    !!!!     !  !     . !';'!  ! !   !   !! !       !    !      !!         . !';'! !! !   !    !  !!!!!!!!!   !    !!   !   !!!!. !';'! !  !   !    !!       !!!   !!!!!        !    . !';'! !  !    !!   !!!     !!!   !         !!!!    . !';'! !  !     !!     !!!!      !!!!!!!!!!!!      !..+';'! !         !         !!!!!!                     !';'!           !              !                     !';'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!']

;

    %replace dot with space
    maze(maze=='.')=' ';
    %position of mouse
    [u,v]=find(maze=='O'); 
    maze(maze=='O') = ' ';
    step_counter = 0;
    while true; %game loop
        %test if mouse found cheese
        if maze(u,v) == '+';
            disp(['mouse found cheese after ', num2str(step_counter), ' steps']);
            break;
        end

        %extract NESW tiles
        nesw = [maze(u-1,v),maze(u,v+1),maze(u+1,v),maze(u,v-1)];

        %get result and move accordingly
        answer = find_the_cheese(nesw);
        switch answer;
            case 'n';
                u = u-1;
            case 'e';
                v = v+1;
            case 's';
                u = u+1;
            otherwise;
                v = v-1;
        end

        %make sure, mouse did not run into wall
        assert(maze(u,v) ~= '!','mouse ran into wall!');
        step_counter = step_counter + 1;
    end
end


function step = find_the_cheese(nesw)
    global State;
    NESW = 'nesw';
    NESW_REVERSE = 'swne';

    if all(nesw == '0000');
        return;
    elseif ~isfield(State,'maze');
        State = struct('maze', zeros(140)+' ','u',75,'v',75,'state','E');
        State.maze(State.u,State.v) = 'S';
    end    
    if State.maze(State.u-1,State.v) == ' '
        State.maze(State.u-1,State.v) = nesw(1);
    end
    if State.maze(State.u,State.v+1) == ' '
        State.maze(State.u,State.v+1) = nesw(2);
    end
    if State.maze(State.u+1,State.v) == ' '
        State.maze(State.u+1,State.v) = nesw(3);
    end
    if State.maze(State.u,State.v-1) == ' '
        State.maze(State.u,State.v-1) = nesw(4);
    end

    current_nesw = [State.maze(State.u-1,State.v),State.maze(State.u,State.v+1),State.maze(State.u+1,State.v),State.maze(State.u,State.v-1)];

    if any(current_nesw == '+'); % if there is cheese, go there
        nesw_index = find(current_nesw == '+',1);

    elseif any(current_nesw == ' '); % if there is a path that we did not walk, go there
        nesw_index = find(current_nesw == ' ',1);
        State.state = 'E';

    else % return to previous crossing
        nesw_index = find(NESW == State.maze(State.u,State.v),1);
        assert(numel(nesw_index)>0,'not enough indices')

        State.state = 'R';
    end

    %execute the step
    if State.state == 'E';
        step = NESW(nesw_index);
    else %State.state = 'R'
        step = State.maze(State.u, State.v);
    end

    switch step;
        case 'n';
            State.u = State.u-1;
        case 'e';
            State.v = State.v+1;
        case 's';
            State.u = State.u+1;
        otherwise;
            State.v = State.v-1;
    end

    if State.maze(State.u,State.v) == ' '; %if we do not have a reverse poniter yet
        State.maze(State.u,State.v) = NESW_REVERSE(nesw_index); %reverse pointer
    end

    %disp_important(State.maze); %uncomment for display
end


function disp_important(m) %just show the important stuff of the maze
    if any(m(:) ~= ' ');
        for k=1:4
            m = rot90(m);
            while all(m(:,1) == ' ');
                m = m(:,2:end);
            end
        end
    end
    if numel(m) == 0;
        m = 'X';
    end
    m = padarray(m,[1,1],35,'both');
    disp([m,'']);
end

1

Bot Simples, Java 1.4+, 176 + 25 + 1118 + 486 + 10944 + 1847 = 14596 etapas

Esse bot conta e registra o número de etapas executadas para alcançar cada célula visitada e, ao decidir qual direção mover, escolhe a direção que possui a menor contagem de etapas. Em caso de empate, escolhe a direção na ordem N, E, S, W.

Como não tenho ferrugem instalada, tive que implementar o controlador em java e esse foi o bot que usei para testá-lo. Em breve, tentarei um solucionador mais inteligente.

Determinístico. Correr comjava SimpleBot

import java.io.IOException;
import java.io.InputStream;

public class SimpleBot 
{
    private static final char[] DIRECTION = {'n','e','s','w'};
    public static void main(String[] args) throws Exception
    {
        int[][] stepMap = new int[100][100];
        int mx=49, my=49;
        int[][] offsets = new int[][]{{0,-1},{1,0},{0,1},{-1,0}};

        String line=readLine(System.in);
        int step=0;
        while (line!=null && !"0000".equals(line))
        {
            stepMap[mx][my]=step++;

            int minStep = Integer.MAX_VALUE;
            int minIndex = -1;
            for (int i=0;i<4;i++)
            {
                if (line.charAt(i) == '+')
                {
                    minIndex=i;
                    break;
                }
                else if (line.charAt(i) == ' ')
                {
                    if (stepMap[mx+offsets[i][0]][my+offsets[i][1]]<minStep)
                    {
                        minStep = stepMap[mx+offsets[i][0]][my+offsets[i][1]];
                        minIndex=i;
                    }
                }
            }
            mx +=offsets[minIndex][0];
            my +=offsets[minIndex][1];

            System.out.println(DIRECTION[minIndex]);
            line=readLine(System.in);
        }
    }

    /**
     * Reads a line of text from the input stream. Blocks until a new line character is read.
     * NOTE: This method is used in favor of BufferedReader.readLine(...) as BufferedReader buffers data before performing
     * text line tokenization. This means that BufferedReader.readLine() will block until sufficient input have been received. 
     * @param in a InputStream, nominally System.in
     * @return a line of text or null if end of stream.
     * @throws IOException
     */
    private static String readLine(InputStream in) throws IOException
    {
       StringBuilder sb = new StringBuilder();
       int readByte = in.read();
       while (readByte>-1 && readByte!= '\n')
       {
          sb.append((char) readByte);
          readByte = in.read();
       }
       return readByte==-1?null:sb.toString();
    }

}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.