秘書の問題を解決する


13

秘書の問題は、これと述べた有名な問題です。

  1. 新しい秘書が必要です
  2. N人の応募者がいて、一度に1人ずつ面接できます
  3. 面接後に各応募者を採点できます。あなたのスコアリングシステムは、2人の志願者に同じスコアを与えることはありません
  4. 応募者に面接した後、すぐに「はい」または「いいえ」を提出する必要があります
  5. 最高得点の応募者が欲しい

解決策は、最初のfloor(N/e)応募者にインタビューし、それまでの応募者全員よりも高いスコアを持つ最初の応募者を受け入れることです。申請者のいずれもより高い場合、最後の申請者を返します。おもしろいことに、これは1/e時間の上位の申請者にパーセントを与えます。 オイラーの番号をe指します。の値を取得するにはeは、組み込みのを使用するlogか、少なくとも5つの小数点にハードコードします。

入力:

以下の一意の非負整数の空でない配列 2^31-1

出力:

選択された候補を表す整数。アルゴリズムを明確にするために:

  1. 最初の最大要素を見つける floor(N/e)配列の要素で。
  2. 残りの要素を反復処理し、手順1で見つかった最大値よりも大きい最初の要素を返します。
  3. いずれの要素も高ければ、最後の要素を返します。

たとえば、配列が[2,7,4,3,9,20]であったN = 6としfloor(N/e) = 2ます。配列の最初の2つの要素は[2,7]です。の最大値は[2,7]です7。残りの要素は[4,3,9,20]です。大きい最初の要素7である9私たちが戻るので、9

テストケース:

[0]         => 0
[100]       => 100
[100, 45]   => 100
[0, 1]      => 0
[45, 100]   => 45
[1, 4, 5]   => 4
[1, 5, 4]   => 5
[5, 4, 1]   => 1
[5, 1, 4]   => 4
[4, 1, 5]   => 5
[56, 7, 37, 73, 90, 59, 65, 61, 29, 16, 47, 77, 60, 8, 1, 76, 36, 68, 34, 17, 23, 26, 12, 82, 52, 88, 45, 89, 94, 81, 3, 24, 43, 55, 38, 33, 15, 92, 79, 87, 14, 75, 41, 98, 31, 58, 53, 72, 39, 30, 2, 0, 49, 99, 28, 50, 80, 91, 83, 27, 64, 71, 93, 95, 11, 21, 6, 66, 51, 85, 48, 62, 22, 74, 69, 63, 86, 57, 97, 32, 84, 4, 18, 46, 20, 42, 25, 35, 9, 10, 19, 40, 54, 67, 70, 5, 44, 13, 78, 96]
=> 98
[10, 68, 52, 48, 81, 39, 85, 54, 3, 21, 31, 59, 28, 64, 42, 90, 79, 12, 63, 41, 58, 57, 13, 43, 74, 76, 94, 51, 99, 67, 49, 14, 6, 96, 18, 17, 32, 73, 56, 7, 16, 60, 61, 26, 86, 72, 20, 62, 4, 83, 15, 55, 70, 29, 23, 35, 77, 98, 92, 22, 38, 5, 50, 82, 1, 84, 93, 97, 65, 37, 45, 71, 25, 11, 19, 75, 78, 44, 46, 2, 53, 36, 0, 47, 88, 24, 80, 66, 87, 40, 69, 27, 9, 8, 91, 89, 34, 33, 95, 30]
=> 30

ソリューションはである必要がありますO(n)。ここnで、配列の長さです。言語に配列の最大値を検出する組み込み関数がある場合、関数はO(n)(できれば可能です)。

標準的な抜け穴が適用され、これはですので、あなたの好きな言語で最短の回答をしてください!


1
何をe使うべきですか?
激しい


1
ああ、これでアルゴリズムの仕組みがわかりました。2番目の段落では、floor(n / e)の後、候補者にまったくインタビューしないことを意味すると思いました。
ドアノブ

1
一部の言語では、それが実際に組み込みを使用するよりも精度の10進数5ポイントで変数を定義するために短いですので、私は特に尋ねたe(例えばPythonの、e=2.71828より短いimport math;math.E
MEGO

1
注:「時間の1 / eパーセント」は本当に悪いでしょう。それは時間の約37%であること、1 / Eのprobabiltyだ
edc65

回答:


4

ゼリー、13バイト

L:Øe³ḣȯ-Ṁ<i1ị

間違いなくO(n)アルゴリズム、できればO(n)実装。オンラインでお試しください!

使い方

L:Øe³ḣȯ-Ṁ<i1ị  Main link. Argument: A (list of scores)

L              Get the length of A.
 :Øe           Divide the length by e, flooring the result.
    ³ḣ         Retrieve the that many scores from the beginning of A.
      ȯ-       Logical OR; replace an empty list with -1.
        Ṁ      Compute the maximum of those scores.
         <     Compare each score in A with that maximum.
          i1   Find the first index of 1 (0 if not found).
            ị  Retrieve the element of A at that index (the last one if 0).

3

CJam、20バイト

q~___,1me/i<:e>f>1#=

デニスの提案と同様に機能します。

q~___                     Read array, duplicate three times
      ,                   Consume one to find the length
       1me/i              Push e then divide and take floor
            <             Take that many elements from the list
             :e>          Find maximum (Thanks to Dennis)
                f>        Label array elements larger than this as 1
                  1#      Find the first one (won't be in set of elements we've looked in)
                    =     Take that element from the final copy of the array. -1 gives us the last element as required

$W=線形時間で実行されません。
デニス

ええ、あなたは正しいです。あなたが知っているCJamの最大値を見つけるより良い方法はありますか?
シモンズ

1
:e>(最大削減)
デニス

@デニスありがとう!
シモンズ

2

Java、128 118バイト

a->{int c=(int)(a.length/Math.E),i=0,m=-1,t=0;for(;i<a.length;i++){t=a[i];if(i<c)m=t>m?t:m;if(t>m)return t;}return t;}

インデント:

static Function<Integer[], Integer> secretary2 = a -> {
    int c = (int) (a.length/Math.E),     // c = floor(N/E)
        i = 0, m = -1, t = 0;            // declare vars early to save bytes
    for (;i<a.length;i++) {              // for each element of input
        t = a[i];                        // cache element to save bytes
        if (i<c)                         // if before c
            m = t>m ? t : m;             // m = max(m, element)
        if (t>m)                         // if element > m
            return t;                    // return: we've found our best
    }                                    // if never found a good element
    return t;                            // return the last element
};


2

JavaScript(ES6)64

(a,l=a.length/Math.E,x)=>(a.every(v=>--l>0?x>v?1:x=v:(z=v)<x),z)

少ないゴルフ

(
 a, 
 l=a.length/Math.E, // limit for stage 1
 x // init at undefined
)=>(
  a.every(v => --l > 0 // checking for >0 no need to floor
          ? x>v?1:x=v // stage 1, find max in x, always return truthy
          : (z=v)<x ) // stage 2, set z to current value and exit early if z>x
  , z // at last z has the last seen value
)

テスト

f=(a,l=a.length/Math.E,x)=>(a.every(v=>--l>0?x>v?1:x=v:(z=v)<x),z)

console.log=x=>O.textContent+=x+'\n'

;[ 
 [0], [100], [0,1], [1,2,3],
 [100, 45],
 [45, 100],
 [1, 4, 5],
 [1, 5, 4],
 [5, 4, 1],
 [5, 1, 4],
 [4, 1, 5],   
 [10, 68, 52, 48, 81, 39, 85, 54, 3, 21, 31, 59, 28, 64, 42, 90, 79, 12, 63, 41, 58, 57, 13, 43, 74, 76, 94, 51, 99, 67, 49, 14, 6, 96, 18, 17, 32, 73, 56, 7, 16, 60, 61, 26, 86, 72, 20, 62, 4, 83, 15, 55, 70, 29, 23, 35, 77, 98, 92, 22, 38, 5, 50, 82, 1, 84, 93, 97, 65, 37, 45, 71, 25, 11, 19, 75, 78, 44, 46, 2, 53, 36, 0, 47, 88, 24, 80, 66, 87, 40, 69, 27, 9, 8, 91, 89, 34, 33, 95, 30],
[56, 7, 37, 73, 90, 59, 65, 61, 29, 16, 47, 77, 60, 8, 1, 76, 36, 68, 34, 17, 23, 26, 12, 82, 52, 88, 45, 89, 94, 81, 3, 24, 43, 55, 38, 33, 15, 92, 79, 87, 14, 75, 41, 98, 31, 58, 53, 72, 39, 30, 2, 0, 49, 99, 28, 50, 80, 91, 83, 27, 64, 71, 93, 95, 11, 21, 6, 66, 51, 85, 48, 62, 22, 74, 69, 63, 86, 57, 97, 32, 84, 4, 18, 46, 20, 42, 25, 35, 9, 10, 19, 40, 54, 67, 70, 5, 44, 13, 78, 96]
].forEach(t=>{
  var r=f(t)
  console.log(r+' : '+t)
})
<pre id=O></pre>


1

ルビー、64バイト

->a{m=a[0...c=a.size/Math::E].max
a[c..-1].find{|n|n>m}||a[-1]}

2
@Doorknob最初のfloor(N / e)要素を1回ループして最大値を検出し、最悪の場合はリストの残りをループして各要素を最大値と比較します。両方の部分の要素ごとに1つの比較のみがあります。
激しい

ああ、そうです。私は誤解し、あなたは各反復で最大値を見つけていると思った。
ドアノブ

1
実際、a.find2番目のステップで行っただけではまだO(n)であると思いますが、明らかに効率ははるかに劣ります。
histocrat

1
(0...c)cを除外する範囲に使用できます。
histocrat

@histocratはい、O(2n)はO(n)である必要があります
チャールズではない

1

PARI / GP、70バイト

これは、シングルトンを与えられた場合、gpの古いバージョンでは問題が発生する可能性がありますが、少なくともリビジョン18487以降は動作します。

v->m=vecmax(v[1..t=#v\exp(1)]);for(i=t+1,#v,v[i]>m&&return(v[i]));v[#v]

1

JavaScript(ES6)、79バイト

a=>(m=Math.max(...a.splice(0,a.length/Math.E)),a.slice(a.findIndex(x=>x>m))[0])

なぜなら作品findIndex戻り-1不良ではなく、a.slice(-1)[0]所望に応じて、配列の最後の要素を返します。


1

Python 2、87バイト

a=input()
t=int(len(a)/2.71828)
m=max(a[:t]+[-1])
for x in a[t:]:
 if x>m:break
print x

ユーザーは、角括弧とコンマを使用して配列をリストとして入力します。input()ここではPython 2のコマンドが便利です。

プロセスを早期に終了するかどうかにかかわらず、インタビューを受けた最後の人を雇います。



1

Python 3.5; 110バイト:

def Interview(h):k=max(h[0:int(len(h)/2.71828)-1]);n=max(h[int(len(h)/2.71828)-1:len(h)-1]);return max([k, n])

基本的に、上記のことは、5個以上の項目を含む限り(「...」)、最初に提供された配列「h」最初に取得し、最初の(配列の長さ(len(h ))/オイラーの番号(小数点以下5桁まで))その配列の項目、およびその値を「k」として返します。さらに、「n」は配列の残りの最大値です。最後に、関数から返される値は、「k」と「n」の両方を含む配列の最大値です。

注:max()Python の機能 O(n)の複雑さです。

以下は、上記のコードのより読みやすい非コード バージョンであり、ランダムで一意の10項目配列が提供されており、機能することを確認しています。

import random, math

def Interview():
    k = max(h[0:int(len(h)/math.e)-1])
    n = max(h[int(len(h)/math.e)-1:len(h)-1])
    return max([k, n])

h = random.sample(range((2*31)-1), 10)

print(Interview(h))

PPCGへようこそ!インポートをカンマで区切ることができます。また、自分で配列を生成する必要がないので、コードのその部分を削除することができます(単純に配列を関数のパラメーターとして使用できます)
Nathan Merrill

@NathanMerrillええ、そうすることを考えていましたが、あなたはそれが本当に好きではないと思っていましたが、今は本当に重要ではないことがわかったので、答えを編集します。また、インポートを区切るコンマに関するヒントをありがとう。私はそれを完全に忘れていました!
R.ガプス

その他のヒント:あなたは等号記号の間、カンマの後に(不要な空白がたくさんあるあなたはどちらかの終わりにprint文を必要としません。。
ネイサンメリル

@NathanMerrillヒントをありがとう!コードゴルフをもっとするので、それらを覚えておきましょう!:)
R. Kap
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.