Problema D - Buscas no aeroporto

Este é um problema de interação.
Ao contrário dos outros problemas em que deves fazer leitura de dados e escrita do output, neste problema deves interagir com o avaliador através da implementação de uma função e da interação com as funções fornecidas.

Mais um ano de olimpíadas e mais uma vez a comitiva portuguesa vai viajar para participar em mais uma olímpiada internacional. Depois de uma jornada cansativa num grande avião, já se encontram todos prontos para sair do aeroporto e juntar-se aos concorrentes dos outros países.

Parte I

Infelizmente parece haver um problema com o passaporte de um dos concorrentes, o Luís. O número de série não está a ser aceite pela máquina automática! Para ser aceite no país, é necessário introduzir o número de série na máquina automática para validar a identidade do Luís...

O número de série de um passaporte é uma sequência de N caracteres 0 ou 1 (ou seja, uma string binária), onde N é um número par positivo. A máquina automática lê um número de série e posteriormente reporta se está correto ou não. Para ajudar a corrigir potenciais erros, ao introduzir um número de série qualquer que esteja incorreto, a máquina retorna um inteiro que representa quão diferentes são os números. Se P for o número de série do passaporte e G o número de série introduzido, a máquina retorna k se existirem exatamente k caracteres diferentes entre os dois números de série.

Seja, por exemplo, P = 101101 e G = 100010, então (os caracteres '=' representam posições iguais e '!' diferentes):

P -> 101101
G -> 100010
     ==!!!!

Logo a máquina retorna 4, visto que os últimos 4 caracteres são diferentes.

A equipa portuguesa só poderá continuar quando conseguirem obter o número de série correto, para tal, decidiram tentar adivinhar o número correto usando a máquina automática para ir sabendo quão próximos da solução estão. Infelizmente, a máquina tem um limite de 2050 operações, mais que isso e a máquina bloqueará e o Luís não poderá entrar no país nem participar na IOI... Consegues ajudar o Luís adivinhando o seu número de série?

Parte II

Enquanto se tratava do problema do Luís, aparentemente o número de série de outro concorrente, o Vitor, também não está a ser aceite! Parece que vai ser preciso adivinhar o número de série do passaporte do Vitor. Infelizmente, a máquina automática parece estar avariada e o seu funcionamento está ligeiramente diferente.

Se P for o número de série do passaporte (com N dígitos) e G o número de série introduzido, a máquina retorna: 0 se o G for igual a P (o número foi adivinhado corretamente); N/2 se G e P forem diferentes em exatamente N/2 posições; N em qualquer outra situação.

Para este modelo, se N = 6 e P = 101101 o resultado:

Dada a condição da máquina automática a usar para o Vitor, consegues ajudá-lo também a saber o seu número de série?

O Problema

Dado o tamanho dos números de série de passaportes N e um dos concorrentes (o Luís ou o Vitor), adivinhar o número de série do seu passaporte em menos de 2050 tentativas.

Ficheiros para Download

Podes começar por descarregar os ficheiros correspondentes à tua linguagem (ou um arquivo zip contendo tudo):

Linguagem Ficheiro a implementar Ficheiro com avaliador exemplo Ficheiros auxiliares Input para avaliador exemplo
C resolver.c avaliador.c avaliador.h input.txt
C++ resolver.cpp avaliador.cpp
Java resolver.java avaliador.java ------
Pascal resolver.pas avaliador.pas avaliadorlib.pas

Nota que a implementação do avaliador a usar nos testes oficiais será diferente, mas podes esperar o mesmo comportamento. Além disso, é garantido que a máquina automática demora menos de 0.1 segundos a responder a 2050 adivinhas.

Implementação

Deves submeter um único ficheiro que implementa a função resolver(N, C), que recebe um inteiro N, que representa o número de dígitos do número de série (que será sempre par), e um carácter C, que representa o concorrente a ajudar (que será apenas ou 'L' para o Luís, ou 'V' para o Vitor). Para isso deves usar o ficheiro resolver.{c,cpp,java,pas} que descarregaste, colocando no interior da função o teu código. Podes acrescentar outras funções, mas devem ficar todas neste ficheiro que é o único que deves submeter.

Função a implementar:
C/C++/Java:void resolver(int N, char C);
Pascal:procedure resolver(N : Longint, C : char);

A tua função deve invocar a seguinte função:

adivinhar(g) implementada pelo avaliador, que recebe uma string g e devolve a resposta da máquina automática para esse número de série.

Nota que é importante que a string g tenha exatamente N caracteres e que todos eles sejam ou '0' ou '1', caso contrário as funções chamadas irão terminar o programa e a resposta será considerada incorreta. Também é importante notar que se excederes as 2050 perguntas o programa será interrompido e a resposta será considerada incorreta.

Funções do avaliador:
C:int adivinhar(char g[MAXN]);
C++/Java:int adivinhar(string g);
Pascal:function adivinhar(g : array of char): Longint;

O teu objetivo é descobrir o número de série correto para o Luís ou para o Vitor. Para tal, deves chamar a função adivinhar(g) com o número de série correto, ao qual esta irá retornar 0 não deverás chamar mais nenhuma vez a função adivinhar(g).

A vossa função não deve ler nem escrever para os canais de entrada/saída padrão.

Exemplo

Imagina que estás a ajudar o Luís que N = 6. A função resolver que deves implementar será chamada como resolver(6, 'L').

Uma possível execução seria a seguinte (com a ordem das chamadas a ser de cima para baixo):

InvocaçãoResultadoDescrição
adivinhar(000000)44 dos dígitos do que adivinhámos estão incorretos.
adivinhar(101000)22 dos dígitos do que adivinhámos estão incorretos.
adivinhar(101001)11 dos dígitos do que adivinhámos estão incorretos.
adivinhar(101101)0Acertámos!

Para este exemplo o número de série correto era 101101.

Restrições

São garantidos os seguintes limites em todos os casos de teste:
1 ≤ N ≤ 1 000Número de dígitos.

Avaliação e Casos de Teste

Os casos de teste deste problema estarão agrupados em conjuntos de testes. Ao contrário dos restantes problemas, para obter pontuação é necessário acertar todos os casos de teste de um grupo de casos, nesse caso terão a pontuação completa relativa a esse grupo. Se falharem um ou mais casos de um grupo, a pontuação atribuída relativa a esse grupo será nula.

Cada grupo tem um número de pontos associado e um conjunto de restrições adicionais. Os grupos são os seguintes:

Grupo Número de Pontos Restrições adicionais
1 25 N ≤ 10, C = 'L'
2 25 C = 'L'
3 25 N ≤ 50, C = 'V'
4 25 C = 'V'

Testes no vosso computador

É disponibilizado um avaliador exemplo em cada linguagem (avaliador.{c,cpp,java,pas}) que pode ser utilizado para testar a vossa submissão. Para C/C++/Pascal está ainda disponível um ficheiro auxiliar (para C/C++ o avaliador.h e para Pascal o avaliadorlib.pas). Este avaliador não corresponde ao utilizado pelo sistema de avaliação.

Este avaliador começa por receber como input um inteiro N e um carácter C correspondendo, respetivamente, ao número de dígitos do número de série, e ao concorrente a ajudar ('L' para o Luís e 'V' para o Vitor). Segue-se uma linha com N dígitos 0 ou 1, que representa o número de série a adivinhar.

O avaliador irá automaticamente invocar a função resolver(N,C) por vocês implementada e indicará se a resposta foi correta. Em caso afirmativo, também indicará o número de adivinhas que foram efetuadas.

Disponibilizamos um ficheiro input.txt que contém o caso de exemplo referido a cima.

Um exemplo de teste na tua máquina (supondo que tens os compiladores oficiais instalados) seria o seguinte:

LinguagemCompilarExecutar com o exemplo
Cgcc -Wall avaliador.c resolver.c./a.out < input.txt
C++g++ -Wall avaliador.cpp resolver.cpp./a.out < input.txt
Javajavac avaliador.java resolver.javajava avaliador < input.txt
Pascalfpc avaliador.pas./avaliador < input.txt

Qualificação para a final das ONI'2017
(30/03 a 01/04 de 2017)