12コイン問題


14

バックグラウンド

12コインの問題は、就職の面接で一般的に使用される古典的なバランスパズルです。このパズルは1945年に初めて登場し、祖父が母と結婚するように頼んだときに父に提示されました!パズルには12個のコインがあり、そのうちの1つは他のものよりも重いか軽い(どちらかはわかりません)。問題は、バランススケールを3回使用して一意のコインを決定することです。いくつかのバリエーションでは、コインが重いか軽いかを識別することも必要です。

ここでのタスクには、最悪の場合に可能な限り少ない計量を使用して、n個のコインを含む一般的な問題を解決することが含まれます。コインが重いか軽いかを識別する必要はなく、どちらかだけです。さらに、指定されたセット以外の追加のコインにはアクセスできません(奇妙なことに、違いが生じます)。

最大で(3 ^ k-1)/ 2個のコインに対してk個の計量で十分であることがわかります(したがって、このバリエーションでは4個の計量で実際に13個のコインを処理できます)。さらに(そして驚くべきことに)、将来の計量が過去の結果に依存するのではなく、計量の完全なセットを事前に選択することが可能です(ただし、ここでは必要ありません)。2つの可能なソリューションの説明については、このペーパーこのQuoraの回答を参照してください。

仕事

STDIN、コマンドライン引数、または関数引数を介して整数nを入力として関数またはプログラムを作成します。これにより、最悪の場合に可能な限り少ない計量を使用してnコインの問題を解決します。プログラムは:

  • 計量器の1,2,3-4,5,6両側にあるコインのリストを示す形式で計量を標準出力に印刷します。計量されていない硬貨については言及しないでください。コインには暗黙的に1からnまでの番号が付けられ、番号順に印刷する必要はありません(2,1-3,4と同じ1,2-3,4です)。
  • 各プログラムを秤量した後であるべき、STDINを介して入力を待つ必要があり<=または>、スケールの左側は、ライター同じ、または右側よりも重いかどうかを示します。
  • 最後の計量結果の後、プログラムは一意のコインの番号を印刷または返す必要があります。
  • プログラムは、ユーザーからの一貫性のない結果入力を処理する必要はありません。
  • プログラムは3未満の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

Python 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つの異なるバージョンの後では)明らかな場所はもうありません。

このコードは、3つの関数を使用して、このページのアルゴリズムをわずかに変更したバージョンを実装しています。このI関数はIOを実行します(オプションを出力し、ユーザーの応答を返します)。AおよびB機能は、アルゴリズムの主要な実装します。A(いずれかのリストは大きい方であってもよいが)正確に1つの要素によって、サイズが異なる2つのリストを取る:で1枚のコインがa通常よりも軽いこと、または内の1枚の硬貨できるb重くしてもよいです。Bダブルデューティを行います。コインの1つのリストとa、オプションで正しい重量であることがわかっている1つのコインの2番目のリストを受け取ります。長さを丸める動作は、2つのケースで異なる必要があり、頭痛の終わりはありませんでした。

2つのアルゴリズム関数はk、次のサイズまでの入力が与えられた計量で、異常に重くされたコインを見つけることができます。

  • A3^k合計コイン、(3^k-1)/2との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.