橋とトーチの問題


17

このコードのゴルフパズルのインスピレーションは、ブリッジとトーチの問題です。この問題では、ブリッジの開始時にd人がすべて最短時間で橋を渡らなければなりません。

キャッチは、最大2人が一度に横断できることです。さもないと、橋は自重でつぶれ、グループは橋を渡るために運ばなければならない1つのトーチにしかアクセスできません。

パズル全体の各人には、橋を渡るのにかかる時間が指定されています。2人が一緒に交差する場合、ペアは最も遅い人と同じくらい遅くなります。

橋を渡らなければならない人数は決まっていない。あなたのソリューションは、dの任意の値に対して機能しなければなりません。

この問題に標準入力を使用する必要はありませんが、問題を説明するために、以下の入力および出力形式を使用して説明します。最初の数dは、橋の始点にいる人の数です。次に、コードはd個の数字をスキャンし、それぞれが人の速度を表します。

コード出力は、前述の基準を満たしながら、ブリッジの開始から終了までのすべてのユーザーを横断するのに必要な最短時間になります。

以下に、いくつかの入力ケースと出力ケース、および最初の入力ケースの説明を示します。この情報からアルゴリズムを導き出し、可能な限り少ないバイトのコードで問題を解決するのはあなた次第です。

入力

4
1 2 5 8

出力

15

この出力に到達するには、人々は次の方法で交差する必要があります。

A and B cross forward (2 minutes)
A returns (1 minute)
C and D cross forward (8 minutes)
B returns (2 minutes)
A and B cross forward (2 minutes)

道に沿ってガイドする別のテストケースを次に示します。

入力

5
3 1 6 8 12

出力

29

ルール:

  1. 入力がソートされないと仮定し、自分でソートする必要があります(必要な場合)
  2. パズルの人数は4人に固定されていません(N> = 1)
  3. すべてのグループと個々の交差点にはトーチが必要です。トーチは1つだけです。
  4. 各グループは最大2人で構成する必要があります!
  5. いいえ、橋から飛び降りて反対側に泳ぐことはできません。このような他のトリックはありません;)。

XNORで見られるように、下記のようなテストケースに必ず1 3 4 514ない15.返すべき、
gladed

1 4 5 6 7同様の問題があります。25対26
Sherlock9

1
これは奇妙な質問のように思えますが、パズルの最小人数と最大人数はどのくらいですか?私のソリューションに取り組んでいる間、私は彼らがN >= 2人だけを扱うことに気づきました(つまり、奇妙なことに、「1人が交差する必要がある」という些細なケースを扱うのに余分な仕事です)、この点に関するいくつかの明確化は素晴らしいでしょう。前もって感謝します。
Sherlock9

@ Sherlock9ソリューションはN> = 1で動作する必要があると仮定します
-baseman101

テストケースは、長さをパラメーターとして使用できることを示していますが、ルールでそれをより明確にすることはできますか?入力は時間の配列と人数に許可されていますか、それとも時間だけに許可されていますか?
Sherlock9

回答:


8

Pythonの3、100の 99バイト

再帰的な解決策

f=lambda s:s[0]+s[-1]+min(2*s[1],s[0]+s[-2])+f(s[:-2])if s.sort()or 3<len(s)else sum(s[len(s)==2:])

この論文を作成してくれた@xnorに感謝

@lirtosiastが2バイトを節約し、@ movaticaが1バイトを節約し、@ gladedが私の以前のソリューションが機能しないことを指摘しているおかげで

次のトリックを使用してラムダ関数の何かを評価し、s.sort() or s ここでソートを計算し、テストの結果を返しますs.sort()or len(s)>3

非ゴルフ

def f(s):
    s.sort()                                   # sort input in place
    if len(s)>3:                               # loop until len(s) < 3
        a = s[0]+s[-1]+min(2*s[1],s[0]+s[-2])  # minimum time according to xnor paper
        return  a + f(s[:-2])                  # recursion on remaining people
    else:
        return sum(s[len(s)==2:])              # add last times when len(s) < 3

結果

>>> f([3, 1, 6, 8, 12])
29
>>> f([1, 2, 5, 8])
15
>>> f([5])
5
>>> f([1])
1
>>> f([1, 3, 4, 5])
14

あなたは1バイトと変更保存することができますlen(s)==2len(s)<3
ミスター公共

あなたがバグを見つけ@MrPublic、私はそれがだソリューション変わっs[0]*(len(s)==2)ていない(s[0]*len(s)==2) バグをf([1]) -> 0なぜ我々はによって置き換えることができないことを<3感謝
エルワン・

この論文では、複数の可能性の最小値である最適な時間を表現しています。ソリューションはすべての場合に最適であると確信していますか?
-xnor

@xnorうわー、私が補題3で式を最適なソリューションを使用しているようだA5:22
エルワン・

1
@movaticaの最新情報の提案
Erwan

4

パイソン2、119の 114 112 119 110 100 95バイト

私は自分の答えを分けることを勧められました。

Theorem 1, A2:09 このペーパーを使用したソリューションxnor linked。論文を引用するには(ゼロインデックスに変更):The difference between C_{k-1} and C_k is 2*t_1 - t_0 - t_{N-2k}.

lambda n,t:t.sort()or(n-3)*t[0]*(n>1)+sum(t)+sum(min(0,2*t[1]-t[0]-t[~k*2])for k in range(n/2))

アンゴルフ:

def b(n, t): # using length as an argument
    t.sort()
    z = sum(t) + (n-3) * t[0] * (n>1) # just sum(t) == t[0] if len(t) == 1
    for k in range(n/2):
        z += min(0, 2*t[1] - t[0] - t[-(k+1)*2]) # ~k == -(k+1)
    return z

lengthが引数になり得ると仮定できるか?
エルワン

@Erwanサンプルテストケースではそれが許可されているようです。私は頼むよ
Sherlock9

2

ルビー、94 133 97 96 101 96 99バイト

私は自分の答えを分けることを勧められました。

これは、で説明されているアルゴリズムに基づくソリューションA6:06-10です橋とトーチの問題で、この論文

編集:が ifの最後に呼び出されたa=s[0]ときにまだ定義されていないバグを修正します。as.size <= 3

->s{r=0;(a,b,*c,d,e=s;r+=a+e+[b*2,a+d].min;*s,y,z=s)while s.sort![3];r+s.reduce(:+)-~s.size%2*s[0]}

アンゴルフ:

def g(s)
  r = 0
  while s.sort![3]      # while s.size > 3
    a, b, *c, d, e = s  # lots of array unpacking here
    r += a + e + [b*2, a+d].min
    *s, y, z = s        # same as s=s[:-2] in Python, but using array unpacking
  end
  # returns the correct result if s.size is in [1,2,3]
  return r + s.reduce(:+) - (s.size+1)%2 * s[0]
end

1

Scala、113 135(darnit)

def f(a:Seq[Int]):Int={val(s,b)=a.size->a.sorted;if(s<4)a.sum-(s+1)%2*b(0)else b(0)+Math.min(2*b(1),b(0)+b(s-2))+b(s-1)+f(b.take(s-2))}

ややアンゴルフ:

def f(a:Seq[Int]):Int = {
    val(s,b)=a.size->a.sorted      // Sort and size
    if (s<4) a.sum-(s+1)%2*b(0)    // Send the rest for cases 1-3
    else Math.min(b(0)+2*b(1)+b(s-1),2*b(0)+b(s-2)+b(s-1)) + // Yeah.
        f(b.take(s-2))             // Repeat w/o 2 worst
}

テスター:

val tests = Seq(Seq(9)->9, Seq(1,2,5,8)->15, Seq(1,3,4,5)->14, Seq(3,1,6,8,12)->29, Seq(1,5,1,1)->9, Seq(1,2,3,4,5,6)->22, Seq(1,2,3)->6, Seq(1,2,3,4,5,6,7)->28)
println("Failures: " + tests.filterNot(t=>f(t._1)==t._2).map(t=>t._1.toString + " returns " + f(t._1) + " not " + t._2).mkString(", "))

一般的には素晴らしいことではありませんが、強く型付けされた言語にとっては悪くないかもしれません。そして、私が見つけられなかったケースを見つけてくれたxnorに感謝します。


この論文では、複数の可能性の最小値である最適な時間を表現しています。ソリューションはすべての場合に最適であると確信していますか?
-xnor

1

ルビー、104 95 93バイト

私は自分の答えを分けることを勧められました。

これは、上ベースのソリューションです私はPython 2溶液Theorem 1, A2:09ブリッジとトーチ問題で、この論文

->n,t{z=t.sort!.reduce(:+)+t[0]*(n>1?n-3:0);(n/2).times{|k|z+=[0,2*t[1]-t[0]-t[~k*2]].min};z}

アンゴルフ:

def b(n, t) # using length as an argument
  z = t.sort!.reduce(:+) + t[0] * (n>1 ? n-3 : 0)
  (n/2).times do each |k|
    a = t[1]*2 - t[0] - t[-(k+1)*2] # ~k == -(k+1)
    z += [0, a].min
  end
  return z
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.