열두 동전 문제


14

배경

열두 동전 문제는 면접에서 일반적으로 사용되는 고전적인 균형 퍼즐 입니다. 퍼즐은 1945 년에 처음 나타 났으며 할아버지가 어머니와 결혼 해달라고 부탁했을 때 아버지 께 제기되었습니다! 퍼즐에는 12 개의 동전이 있으며 그중 하나는 다른 것보다 무겁거나 가볍습니다 (당신은 어느 것을 모릅니다). 문제는 고유 동전을 결정하기 위해 저울을 세 번 사용하는 것입니다. 어떤 변형에서, 동전이 더 무거운 지 또는 더 가벼운지를 식별 할 필요가있다.

여기서 과제 는 최악의 경우 가능한 가장 적은 무게를 사용하여 n 개의 동전 과 관련된 일반적인 문제 를 해결하는 것 입니다. 동전이 더 무겁거나 더 가벼운 지 식별 할 필요는 없으며 어느 동전인지 알 수 있습니다. 또한, 주어진 세트 이외의 추가 동전에 액세스 할 수 없습니다 (흥미롭게도 차이가 있습니다).

k 계량은 최대 (3 ^ k-1) / 2 동전에 충분하다는 것이 밝혀졌습니다 (따라서이 변형에서 4 계량은 실제로 13 동전을 처리 할 수 ​​있음). 더욱이 (그리고 놀랍게도) 미래의 계량이 과거 결과에 의존하지 않고 전체 계량 세트를 미리 선택할 수 있습니다 (여기서는 필수는 아님). 가능한 두 가지 솔루션에 대한 설명은 이 백서Quora 답변을 참조하십시오 .

직무

STDIN, 명령 행 인수 또는 함수 인수를 통해 입력으로 정수 n 을 사용 하여 함수 또는 프로그램을 작성 하면 최악의 경우 가능한 최소 계량을 사용하여 n 코인 의 문제를 해결할 수 있습니다. 프로그램은 :

  • 저울의 1,2,3-4,5,6각면에 동전 목록을 표시하기 위해 형식으로 STDOUT에 계량을 인쇄 합니다. 무게가 측정되지 않은 동전은 언급하지 않아야합니다. 코인은 암시 적으로 1에서 n 까지 번호가 매겨지며 숫자 순서로 인쇄 할 필요가 없습니다 ( 2,1-3,4와 동일 1,2-3,4).
  • 되어야 STDIN 통해 입력 기다려야 프로그램 각각 계량 한 후에 <, =또는 >스케일의 좌측이 우측보다 가벼운 동일한 또는 중질인지를 나타낸다.
  • 마지막 계량 결과 후에 프로그램은 고유 동전의 번호를 인쇄하거나 반환해야합니다.
  • 프로그램은 사용자의 일관성없는 결과 입력을 처리 할 필요가 없습니다.
  • 프로그램은 n 보다 작은 n을 처리 할 필요가 없습니다 .

출력 예

>> 3
1-2
>> =
1-3
>> <
3

# using Quora algorithm
>> 13
1,2,3,4-5,6,7,8
>> <
1,2,5-3,4,6
>> >
3-4
>> <
3

# using paper algorithm
>> 13
1,2,3,4-5,6,7,8
>> <
2,6,7,9-3,8,10,11
>> >
6,8,10,12-4,5,7,11
>> =
3

채점

가장 짧은 코드가 승리합니다. 표준 규칙이 적용됩니다.

답변:


2

파이썬 3 : 497 바이트

I=lambda a,b:input(",".join(a)+"-"+",".join(b)+"\n>> ")
def A(a,b):
 l,L=len(a),len(b)
 if l+L==1:return(a or b)[0]
 m=(2*l+1-L)//3;M=m+L-l;x,y,X,Y=a[:m],a[m:2*m],b[:M],b[M:2*M];r=I(x+X,y+Y);return A(a[2*m:],b[2*M:])if r=="="else A(x,Y)if r=="<"else A(y,X)
def B(a,n=[]):
 if len(a)==1:return a[0]
 m=len(n);l=(len(a)+1+m)//3;x,y,z=a[:l],a[l:2*l-m],a[2*l-m:];r=I(x,y+n);return B(z,a[:1])if r=="="else A(x+z[:1-m],y)if r=="<"else A(y+z[:1-m],x)
print(B(list(map(str,range(1,int(input("N= "))+1)))))

나는 이것이 조금 더 줄어들 수 있다고 생각하지만 더 이상 명확한 장소는 보이지 않습니다 (각 기능의 약 5 가지 버전 이후).

이 코드는 세 가지 기능을 사용 하여이 페이지 에서 약간 수정 된 알고리즘 버전을 구현 합니다. 이 I기능은 IO를 수행합니다 (옵션 인쇄 및 사용자 응답 반환). AB기능은 알고리즘의 주요 구현합니다. A(리스트 중 큰 하나가 될 수 있지만) 정확하게 하나 개의 요소에 의해 크기가 상이한 두 목록 취 한 동전은 a정상보다 가벼운 수 있거나, 하나 개의 동전 b무거운 수있다. B이중 의무를 수행합니다. 하나의 동전 목록 a과 선택적으로 올바른 무게로 알려진 단일 동전이있는 두 번째 목록이 필요합니다. 두 경우 사이에 길이 반올림 동작이 달라야하므로 두통이 발생하지 않습니다.

두 알고리즘 함수는 k최대 다음과 같은 크기의 입력이 주어지면 계량 에서 비정상적으로 가중치가 부여 된 동전을 찾을 수 있습니다 .

  • A: 3^k두 가지 목록으로 나누어 총 동전, (3^k-1)/2(3^k+1)/2.
  • B: (3^k + 1)/2잘 알려진 동전이 공급되면 동전, (3^k - 1)/2 그렇지 않으면 동전 .

문제는 우리가 세트에 나쁜 동전을 찾아 해결할 수 있도록 우리가 처음에 알려진 - 좋은 동전이 없어 여기에 지정을 제기 (3^k - 1)/2k무게를 측정합니다.

다음은 코드에서 가짜 계량을 요청하지 않았거나 예정된 개수보다 많은 계량을 사용하지 않도록하기 위해 작성한 테스트 기능입니다.

def test(n):
    global I
    orig_I = I
    try:
        for x in range(3,n+1):
            max_count = 0
            for y in range(x*2):
                count = 0
                def I(a, b):
                    assert len(a) == len(b), "{} not the same length as {}".format(a,b)
                    nonlocal count
                    count += 1
                    if y//2 in a: return "<"if y%2 else ">"
                    if y//2 in b: return ">"if y%2 else "<"
                    return "="
                assert B(list(range(x)))==y//2, "{} {} not found in size {}".format(['heavy','light'][y%2], y//2+1, x)
                if count > max_count:
                    max_count = count
            print(x, max_count)
    finally:
        I = orig_I

이것은 동전과 무게가 나쁜 (무겁거나 가벼운) 각 조합으로 테스트 한 후 주어진 세트에 대해 최악의 계량 수를 인쇄합니다.

최대 125 세트의 테스트 출력은 다음과 같습니다.

>>> test(150)
3 2
4 2
5 3
6 3
7 3
8 3
9 3
10 3
11 3
12 3
13 3
14 4
15 4
16 4
17 4
18 4
19 4
20 4
21 4
22 4
23 4
24 4
25 4
26 4
27 4
28 4
29 4
30 4
31 4
32 4
33 4
34 4
35 4
36 4
37 4
38 4
39 4
40 4
41 5
42 5
43 5
44 5
45 5
46 5
47 5
48 5
49 5
50 5
51 5
52 5
53 5
54 5
55 5
56 5
57 5
58 5
59 5
60 5
61 5
62 5
63 5
64 5
65 5
66 5
67 5
68 5
69 5
70 5
71 5
72 5
73 5
74 5
75 5
76 5
77 5
78 5
79 5
80 5
81 5
82 5
83 5
84 5
85 5
86 5
87 5
88 5
89 5
90 5
91 5
92 5
93 5
94 5
95 5
96 5
97 5
98 5
99 5
100 5
101 5
102 5
103 5
104 5
105 5
106 5
107 5
108 5
109 5
110 5
111 5
112 5
113 5
114 5
115 5
116 5
117 5
118 5
119 5
120 5
121 5
122 6
123 6
124 6
125 6

당신이 기대하는 사이에 할 위치를 중단 점은 정확히 (3^k - 1)/2하고 (3^k + 1)/2.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.