Um bloqueio comum de combinação de dígitos N consiste em N discos rotativos. Cada disco tem dígitos de 0 a 9 inscritos em ordem e é necessário transformá-los na senha correta para abri-lo. Obviamente, se você não souber a senha, precisará tentar no máximo 10 N vezes antes de desbloqueá-la. Isso não é interessante.
Então, vamos considerar uma variante do bloqueio de combinação, nomeá-lo como bloqueio revelador de distância.
Em todas as tentativas frustradas de abrir um bloqueio revelador de distância, ele responderá ao número mínimo de movimentos a serem desbloqueados.
Um movimento é definido como uma rotação por uma posição; por exemplo, ele precisa de 1 movimento de 890
para 899
e 9 movimentos de 137
para 952
.
O desafio
Dado um bloqueio revelador de distância com sua senha desconhecida, tente abri-lo com um número mínimo de tentativas (não movimentos), mantendo o programa muito longo.
Regras e Pontuações
- Você deve escrever um programa completo com entradas de stdin e saídas para stdout. O programa deve fazer entrada / saída da seguinte maneira:
Start
Input an integer N (number of digits) from stdin
Do
Output a line containing decimal string of length N (your attempt) to stdout
Input an integer K (response of the lock) from stdin
While K not equal 0
End
Seu programa deve processar até N = 200 e deve executar menos de 5 segundos em qualquer entrada.
Zeros à esquerda na saída não devem ser omitidos.
São 5 dados de teste para cada comprimento, portanto, o número total de dados de teste é 1000. Os dados de teste são gerados aleatoriamente.
A pontuação final será (número total de tentativas em todos os dados do teste) * ln (comprimento do código em bytes + 50). Menor pontuação ganha. (ln é log natural)
Vou marcar o programa para você. Se você deseja saber como eu classificarei seu programa, ou se você deseja classificá-lo, verifique as edições anteriores deste post .
Este desafio será encerrado em 07/12/2017 às 14:00 UTC. Vou postar minha solução então.
Exemplo de execução
Linhas começando com >
representam entrada e outras representam saída do programa.
Você pode ter uma senha em mente e interagir com seu programa para testá-la.
> 3 # 3-digit lock. The hidden password is 746
000 # 1st guess (by program)
> 11 # response to the 1st guess
555 # 2nd guess
> 4 # ...
755
> 2
735
> 2
744
> 2
746 # finally the correct answer! The program attempts 6 times.
> 0 # this is not necessary
Programa de amostra
EDIT: Talvez o formato de entrada / saída acima não esteja claro. Aqui está um exemplo de programa em Python.
Python, 369 bytes, número total de tentativas = 1005973, pontuação = 6073935
import sys
N = int(input()) # get the lock size
ans = ''
for i in range(N): # for each digit
lst = []
for j in range(10): # try all numbers
print('0' * i + str(j) + '0' * (N - i - 1)) # make a guess
result = int(input()) # receive the response
lst.append(result)
ans += str(lst.index(min(lst)))
print(ans) # output the final answer
Agradecemos a Jonah por simplificar o desafio.
fonte
162751*ln(388+50)=989887
.C # (.NET Core) , 617 bytes, total de tentativas = 182255, pontuação = 1185166
Espero que o C # nesse formato funcione para você. É na forma de um programa completo, portanto, deve haver uma maneira de compilar em um executável. Deixe-me saber se há algo que eu possa fazer para facilitar. Os bytes fazem parte da pontuação, mesmo que a tag Code Golf tenha sido removida. Portanto, meu envio oficial remove todo o espaço em branco desnecessário e nomes úteis. Minha explicação abaixo usará fragmentos do código não destruído:
Explicação
Este programa usa apenas um único método auxiliar:
Isso escreve o palpite para stdout e depois lê a distância de stdin. Ele também encerra imediatamente o programa se um palpite é a combinação exata. Eu chamo muito isso. Em seguida, a configuração inicial:
Isso obtém o comprimento da combinação e começa a adivinhar com todos os 0s. Depois, itera através de cada dígito em um
for
loop.Para cada dígito, ele adivinha 5, e decide o próximo passo com base em como a distância mudou desde a estimativa anterior (onde esse dígito era 0).
Se a distância aumentasse em 5, 0 estava correto para essa distância. Ajuste esse dígito de volta para 0. Alterar a distância gravada manualmente evita um palpite extra.
Se a distância diminuiu em 5, 5 é o dígito correto e passamos para o próximo dígito imediatamente.
Depois disso, as coisas são complicadas. Usar
5
e0
para minhas suposições iniciais significa que as possibilidades de diferença restantes estão3, 1, -1, -3
com 2 possibilidades para cada uma, as quais precisam de um palpite adicional para distinguir. Cada um desses casos assume uma forma semelhanteAlguns dos números mudam, mas essencialmente tentamos uma das duas possibilidades e verificamos se a alteração foi a correta para esse dígito. Caso contrário, o outro dígito está correto, portanto, definimos esse dígito e ajustamos a diferença manualmente.
Esse método significa que devemos exigir, no máximo, 1 palpite para os 0s iniciais, 2 palpites por dígito e, em seguida, 1 palpite final para garantir que o último dígito não caia.
Pode ser um bug, porém, funciona até onde eu verifiquei manualmente, mas isso não é garantia.Bug encontrado e esmagado graças a Colera Sufonte
37
. A saída é:00, 50, 30, 75, 75
(sim, dois 75s).<
com>
em cadaif
naswitch
parece corrigir o erro. Se é isso que você quer, sua pontuação é182255*ln(617+50)=1185166
.Python 2 e 3: 175 bytes, total de tentativas = 1005972, pontuação = 5448445
Este programa leva o teto (log (n)) * 10 tentativas por combinação ou cada dígito leva 10 tentativas (portanto,
333
leva 30 tentativas).Muito obrigado a Colera Su por me ajudar com a funcionalidade de entrada / saída.
Versão Python do Desafio ( Modificado pelo OP ).
Eu escrevi uma versão do código de bloqueio dentro do Python. Você pode prosseguir e usar se estiver tentando resolver isso em Python (como eu). O seguinte funciona no Python 2 e 3. Fazia muito mais sentido implementar o bloqueio como uma classe com a qual você pode testar e eu decidi criar uma função geradora para adivinhar as entradas.
fonte
LockIO
classe errado. Enviei uma solicitação de edição. Segundo, acho que você interpretou mal o critério de pontuação. A pontuação é calculada pelos dados de teste gerados pelo gerador, não por exemplo (eu executei o seu programa e o número total é 1005972). O log natural também está ausente. Terceiro, especifiquei que você precisa fornecer um programa completo; portanto, inclua aLockIO
parte na sua contagem de bytes. Além disso, você precisa produzir o resultado final, e isso também é contado na pontuação.Lock
emasterLock
é apenas para conveniência dos testes.LockIO
é o que você realmente precisa enviar, pois ele usa o formato de E / S necessário.R ,
277 bytes (pontuação = 1175356)258 bytes, total de tentativas = 202999, pontuação = 1163205Experimente online!
A versão Stdin-stdout, conforme solicitado pelo OP, não possui clichês. Agradecemos a Colera Su por corrigir um erro inicial. Esta é uma versão ligeiramente mais curta que a dos comentários.
Aqui abaixo do envio do TIO para executar um lote de testes no TIO
R , 189 bytes
Experimente online!
Vamos considerar um vetor de zeros como o palpite inicial. Vamos chamar de V a distância entre o palpite atual e a solução. Para cada posição, você só precisa verificar as alterações em V ao substituir 0 por 5 e por 4. De fato, as diferenças entre alterar 0 e 5 estão listadas no meu vetor s1. As diferenças entre alterar 0 e 4 estão listadas no meu vetor s2. Como você vê esses dois vetores, mapeie exclusivamente os dígitos da solução.
O número total de testes é, portanto,
3 * L2 * L + 1, onde L é o comprimento do código: uma verificação inicial contra todos os zeros, depois duas verificações para cada dígito, uma contra 5 e uma contra 4.A melhoria de um fator 3 para um fator 2 foi inspirada na submissão de Kamil Drakari.
O restante do envio do TIO é padrão para R. O envio do TIO mostra o tempo de execução e o número total de operações para 1000 execuções com L = 1 ... 200, 5 repetições para cada valor de L.
fonte
Error in scan(n = 1) : scan() expected 'a real', got 'S=rep(0,L)'
ao executar.scan(file=file("stdin"),n=1)
funciona. Este programa (igual ao seu, apenas E / S corrigida) recebe uma pontuação de202999*ln(277+50)=1175356
.202999*ln(258+50) != 202999*ln(277+50)