비밀번호 찾기


12

일반적인 N 자리 콤비네이션 자물쇠는 N 개의 회전 디스크로 구성됩니다. 각 디스크에는 순서대로 0-9의 숫자가 새겨 져 있으므로 올바른 암호로 바꿔야합니다. 암호를 모르면 잠금을 해제하기 전에 최대 10N 번 시도해야 합니다. 흥미롭지 않습니다.

조합 잠금

따라서 콤비네이션 자물쇠의 변형을 고려해보십시오.

거리 표시 잠금을 열지 못할 때마다 잠금 해제를위한 최소 이동 횟수에 응답합니다.

하나의 움직임은 한 위치에 의한 회전으로 정의됩니다. 예를 들어에서 890로 이동하려면 1에서 로 899이동하고에서에서 9로 이동 137해야 952합니다.

도전

암호를 알 수없는 거리 표시 잠금이 주어지면 프로그램이 너무 오래 걸리지 않도록 최소한의 시도 (움직이지 않음)로 잠금을 열어보십시오 .

규칙 및 점수

  • stdin에서 출력하여 stdout으로 출력하는 전체 프로그램을 작성해야합니다. 프로그램은 다음과 같이 입력 / 출력을 수행해야합니다.
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
  • 프로그램은 최대 N = 200을 처리해야하며 모든 입력에서 5 초 미만을 실행해야합니다.

  • 출력에서 선행 0은 생략하면 안됩니다.

  • 길이마다 5 개의 테스트 데이터가 있으므로 총 테스트 데이터 수는 1000입니다. 테스트 데이터는 임의로 생성됩니다.

  • 최종 점수는 (모든 테스트 데이터의 총 추측 횟수) * ln (코드 길이 (바이트) + 50)입니다. 최저 점수가 이깁니다. (ln은 자연 로그입니다)

  • 나는 당신을 위해 프로그램을 득점합니다. 프로그램 점수를 매기는 방법을 알고 싶거나 스스로 점수를 매기려면 이 게시물의 이전 수정 사항을 살펴보십시오 .

  • 이 과제는 2017/12/07 14:00 UTC에 종료됩니다. 그런 다음 솔루션을 게시합니다.

실행 예

로 시작하는 줄 >은 입력 을 나타내고 다른 줄은 프로그램 출력을 나타냅니다.

당신은 당신의 마음에 암호를 가지고 그것을 테스트하기 위해 프로그램과 상호 작용할 수 있습니다.

> 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

샘플 프로그램

편집 : 위의 입력 / 출력 형식이 명확하지 않을 수 있습니다. 다음은 Python의 샘플 프로그램입니다.

Python, 369 바이트, 총 시도 횟수 = 1005973, 점수 = 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

도전을 단순화 한 Jonah 에게 감사드립니다 .

답변:


3

C, 388 374 368 바이트, 총 시도 = 162751, 점수 = 982280

char s[999];i;G;H;t;n;h;e;R(x){scanf("%d",x);}W(i,x,a){printf((i-n?0:4)+"%0*d%0*d\n",i,x,n-i,0);R(a);}S(k,i){if(!(t=e=k>4?s[i]=48:k<1?s[i]=53:!G?H=k,G=i:0)){for(;t++<n;)putchar(48|t==i|t==G);puts("");R(&t);t==h?W(G,e=1,&t):0;s[G]=t>h?53+H:53-H,s[i]=t>h^e?53+k:53-k;G=0;}}main(){R(&n);for(W(n,0,&h);i++<n;S(t-h+5>>1,i))W(i,5,&t);s[G]=53+H,puts(s+1),s[G]=53-H,puts(s+1);}

PPCG에 오신 것을 환영합니다! 의 좋은 점수를 받았습니다 162751*ln(388+50)=989887.
Colera Su

3

C # (. NET 코어) , 617 바이트, 총 시도 = 182255, 점수 = 1185166

using System;namespace p{class C{static void Main(){var l=Console.ReadLine();int L=int.Parse(l);var g=new int[L];var p=n(g);for(int i=0;i<L;i++){g[i]=5;var d=n(g);var f=d-p;var s=f;switch(s){case 5:g[i]=0;d-=5;break;case-5:break;case 3:g[i]=1;d=n(g);f=d-p;if(f>0){g[i]=9;d-=2;}break;case 1:g[i]=2;d=n(g);f=d-p;if(f>0){g[i]=8;d-=4;}break;case-1:g[i]=3;d=n(g);f=d-p;if(f>0){g[i]=7;d-=4;}break;case-3:g[i]=4;d=n(g);f=d-p;if(f>-3){g[i]=6;d-=2;}break;}p=d;}n(g);}static int n(int[] g){foreach(var i in g){Console.Write(i);}Console.WriteLine();var s=Console.ReadLine();var d=int.Parse(s);if(d<1) Environment.Exit(0);return d;}}}

이 형식의 C #이 도움이 되길 바랍니다. 완전한 프로그램의 형태이므로 실행 파일로 컴파일하는 방법이 있어야합니다. 더 쉽게하기 위해 할 수있는 일이 있으면 알려주십시오. Code Golf 태그가 제거 되어도 바이트가 점수의 일부이므로 공식 제출시 불필요한 공백과 유용한 이름이 모두 제거됩니다. 아래의 설명은 ungolfed 코드의 조각을 사용합니다.

설명

이 프로그램은 단일 도우미 메소드 만 사용합니다.

static int newGuess(IEnumerable<int> guess)
        {
            foreach (var item in guess)
            {
                Console.Write(item);
            }
            Console.WriteLine();
            var distanceString = Console.ReadLine();
            var distance = int.Parse(distanceString);
            if (distance < 1) System.Environment.Exit(0);
            return distance;
        }

이것은 stdout에 추측을 쓴 다음 stdin으로부터의 거리를 읽습니다. 추측이 정확한 조합이면 즉시 프로그램을 종료합니다. 나는 그것을 많이 부른다. 다음으로 초기 설정 :

var lengthString = Console.ReadLine();
int length = int.Parse(l);
var guess = new int[length];
var prevDistance = newGuess(guess);

이것은 조합의 길이를 얻은 다음 모든 0으로 추측하기 시작합니다. 그런 다음 for루프 에서 각 숫자를 반복합니다.

guess[i] = 5;
var distance = newGuess(guess);
var difference = distance - prevDistance;
var switchVar = difference;
switch (switchVar)

각 숫자에 대해 5를 추측 한 다음 이전 추측 이후 (거리가 0 인) 이후 거리가 어떻게 변경되었는지에 따라 다음 단계를 결정합니다.

case 5:
    guess[i] = 0;
    distance -= 5;
    break;

거리가 5 증가하면 해당 거리에 대해 0이 올바른 것입니다. 해당 숫자를 다시 0으로 조정하십시오. 기록 된 거리를 수동으로 변경하면 추가 추측을 방지 할 수 있습니다.

case -5:
    break;

거리가 5만큼 줄어든 경우 5는 올바른 숫자이며 즉시 다음 숫자로 이동합니다.

그 후에는 까다 롭습니다. 초기 추측 5및 사용 에 0대한 나머지 차이 가능성은 3, 1, -1, -3각각에 대해 2 가지 가능성이 있으며, 구별하려면 1 가지 추가 추측이 필요합니다. 각각의 경우는 비슷한 형태를 취합니다

case 3:
    guess[i] = 1;
    distance = newGuess(guess);
    difference = distance - prevDistance;
    if (difference > 0)
    {
        guess[i] = 9;
        distance -= 2;
    }

일부 숫자는 변경되지만 본질적으로 두 가지 가능성 중 하나를 시도하고 해당 숫자에 대한 변경이 올바른지 확인합니다. 그렇지 않은 경우 다른 숫자가 정확하므로 해당 숫자를 설정 한 다음 차이를 수동으로 조정합니다.

이 방법은 초기 0에 대해 최대 1 개의 추측, 숫자 당 2 개의 추측, 그리고 마지막 숫자가 빠지지 않도록 1 개의 최종 추측이 필요하다는 것을 의미합니다.

그래도 버그가있을 수 있지만 수동으로 확인한 한 작동하지만 보장 할 수는 없습니다. Colera Su 덕분에 버그를 발견하고 말살했습니다.


나는 그것을 테스트했고 답변이 일 때 작동하지 않았다 37. 출력은 다음과 같습니다 00, 50, 30, 75, 75(예, 2 개의 75).
Colera Su

교체 <>모든에 if있는 것은 switch버그를 수정 보인다. 그것이 당신이 원하는 것이라면, 당신의 점수는 182255*ln(617+50)=1185166입니다.
Colera Su

@ColeraSu 참으로! 코드를 단축 할 때 찾기 / 바꾸기를 잘못 했어야합니다. 골프 코드에서 수정했습니다 (자세한 버전은 정확한 비교를했습니다).
카밀 드라 카리

2

Python 2 및 3 : 175 바이트, 총 시도 = 1005972, 점수 = 5448445

이 프로그램은 조합 당 ceil (log (n)) * 10 회 시도 또는 모든 한 자리수는 10 회 시도 (따라서 33330 회 시도)합니다.

N=int(input());o=0
def c(a):
 print("0"*(N-len(str(a)))+str(a))
 return int(input())
for j in range(N):m={c(i):i for i in reversed(range(0,10**(j+1),10**j))};o+=m[min(m)]
c(o)

입력 / 출력 기능을 도와 주신 Colera Su에게 감사드립니다.

챌린지의 파이썬 버전 ( OP에 의해 수정 됨 ).

파이썬 내부에 ​​잠금 코드 버전을 작성했습니다. 파이썬에서 이것을 해결하려고하면 나처럼 사용할 수 있습니다. 다음은 파이썬 2와 3에서 작동합니다. 테스트 할 수있는 클래스로 잠금을 구현하는 것이 훨씬 더 합리적이며 입력을 추측하기위한 생성기 함수를 만들기로 결정했습니다.

import sys

class Lock:
    def __init__(self, number):
        self.lock = str(number)
    def l(self): #lengthOfNumber
        return len(self.lock)
    def c(self, guess): #check a guess
        guess = str(guess)
        guess = "0" * (len(self.lock) - len(guess)) + guess
        difference = 0
        for i in range(len(self.lock)):
            d1 = abs(int(self.lock[i]) - int(guess[i]))
            d2 = 10 - d1
            difference += d1 if d1 < d2 else d2
        return difference

def masterLock():
    testdata = ["000","555","755","735","744","746"]
    for answer in testdata:
        yield Lock(answer)

class LockIO:
    def __init__(self):
        self.lock = int(input())
    def l(self):
        return self.lock
    def c(self, guess):
        guess = str(guess)
        guess = "0" * (self.lock - len(guess)) + guess
        print(guess)
        sys.stdout.flush()
        return int(input())

for l in masterLock():
    # Write your code here that tries to guess it
    #   When you're done testing you can unindent your code,
    #   replace "for l in masterLock():" with "l = LockIO()"
    #   and submit the code.
    # 
    # Examples:
    #  l.l()      # returns the length of the lock
    #  l.c("952") # returns the distance to the lock
    #  l.c(952)   #  number also works
    pass

먼저 LockIO수업을 잘못 썼다는 점에 대해 죄송합니다 . 수정 요청을 보냈습니다. 둘째, 점수 기준을 잘못 읽은 것 같습니다. 점수는 예제가 아닌 생성기에 의해 생성 된 테스트 데이터로 계산됩니다 (프로그램을 실행했으며 총 수는 1005972입니다). 자연 로그도 없습니다. 셋째, 전체 프로그램을 제공해야한다고 지정 했으므로 LockIO바이트 수에도 해당 부분을 포함시켜야합니다 . 또한 최종 결과를 출력해야하며 점수에도 계산됩니다.
Colera Su

@ColeraSu "클래스 LockIO"는 어떻게 관련되어 있습니까? 또한 파이썬 코드의 두 번째 블록은 무엇입니까?
user202729

@ user202729 LockmasterLock단지 테스트의 편의를위한 것입니다. LockIO필수 I / O 형식을 사용하므로 실제로 제출해야합니다.
Colera Su

@nfnneil 메인 포스트에 샘플 프로그램을 추가했습니다. 또한 귀하의 참조를 위해 수정 요청을 보냈습니다.
Colera Su

@ColeraSu 내가 잠들 때 나는 당신이 의미하는 것을 깨달았고 사람에게 감사합니다. 좋은 도전이었습니다.
Neil

2

R , 277 바이트 (점수 = 1175356) 258 바이트, 총 시도 = 202999, 점수 = 1163205

f=file("stdin","r")
w=function(b=1,A=X){cat(A,"\n",sep="");if(b){b=scan(f,n=1)};b}
M=0:9
s1=c(-5,-3,-1,1,3,5,3,1,-1,-3)
s2=s1+rep(c(1,-1),,,5)
L=w(1,"")
X=S=rep(0,L)
v0=w()
for(i in 1:L){X[i]=5
v1=v0-w()
X[i]=4
v2=v0-w()
S[i]=M[s1==v1&s2==v2]
X=0*S}
b=w(0,S)

온라인으로 사용해보십시오!

OP가 요청한대로 상용구가없는 표준형 stdout 버전. 초기 버그를 수정 한 Colera Su에게 감사드립니다. 이것은 주석의 것보다 약간 짧은 버전입니다.


여기 TIO 내에서 일괄 테스트를 실행하기위한 TIO 제출 아래

R , 189 바이트

M=0:9
s1=c(-5,-3,-1,1,3,5,3,1,-1,-3)
s2=c(-4,-2,0,2,4,4,2,0,-2,-4)
f=function(L){S=rep(0,L)
v0=v(S)
X=S
for(i in c(1:L)){X[i]=5
v1=v0-v(X)
X[i]=4
v2=v0-v(X)
S[i]=M[s1==v1&s2==v2]
X[i]=0}
S}

온라인으로 사용해보십시오!

초기 추측으로 0으로 구성된 벡터를 고려하십시오. 현재 추측과 솔루션 사이의 거리를 V라고합시다. 각 위치에 대해 0을 5로 바꾸고 4로 바꿀 때 V의 변화 만 확인하면됩니다. 실제로, 0을 5로 바꾸는 것의 차이점은 내 벡터 s1에 나열되어 있습니다. 0에서 4로 변경하는 것의 차이점은 내 벡터 s2에 나열되어 있습니다. 보시다시피이 두 벡터는 솔루션의 숫자를 고유하게 매핑합니다.

따라서 총 테스트 수는 3 * L 2 * L + 1입니다. 여기서 L은 코드의 길이입니다. 모든 0에 대한 초기 검사, 각 숫자에 대한 2 개의 검사, 하나는 5에 대해, 하나는 4에 대해.

요소 3에서 요소 2 로의 개선은 Kamil Drakari의 제출에서 영감을 얻었습니다.

나머지 TIO 제출은 R의 상용구입니다. TIO 제출은 실행 시간과 L = 1 ... 200, L의 각 값에 대해 5 회 반복으로 1000 회 실행에 대한 총 작업 수를 보여줍니다.


나는 Error in scan(n = 1) : scan() expected 'a real', got 'S=rep(0,L)'실행할 때 얻는다 .
Colera Su

1
scan(file=file("stdin"),n=1)작동하는 것 같습니다 . 이 프로그램 (귀하의 것과 동일, 방금 수정 한 I / O)은 점수를 얻습니다 202999*ln(277+50)=1175356.
Colera Su

@ColeraSu, 나는 뭔가를 놓쳤을지도 모르지만, 나는 그렇게 생각했다.202999*ln(258+50) != 202999*ln(277+50)
NofP

@ user202729가 오타를 만든 것 같습니다. 결정된.
Colera Su
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.