R、83 76 67バイト
候補小便器が空かどうかを確認する手間を省くことで、数バイトを節約できることに気付きました。空でない小便器は常にInf不快値を返すため、計算の過程で除外されます。また、ではなく直接インデックスを使用するだけなreplaceので、短くなりますがエレガントではありません。
x=scan()
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x
説明
x=scan()
stdinから現在の状態を読み取り、呼び出しますx。入力は、スペースまたは改行で区切られた1sと0sのシーケンスであると想定しています。説明のために、を入力し1 0 0 0 0 0 1たとしましょう。
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x特定のインデックスの値を1に置き換えます。その間のすべてが[ ]、最適なインデックスが何であるかを判断しています。
既存の小便器は不変であるため、それらの間の距離を考慮する必要はありません。占有されている小便器と可能性のある小便器との間の距離のみを考慮する必要があります。したがって、占有された小便器のインデックスを決定します。which論理ベクトルのインデックスを返す関数を使用しますTRUE。型に強制するとき、Rのすべての数字は、logicalあるTRUE非ゼロの場合にFALSEゼロならば。単純に実行which(x)すると、数値ベクトルargument to 'which' is not logicalと同様に型エラーが発生xします。したがって、論理的に強制する必要があります。!は、Rの論理否定関数であり、自動的に論理に強制されます。それを2回適用すると、!!xのベクトルを生成TRUEし、FALSEどの小便器が使用されているかを示します。(論理に対する代替のバイト相当の強制は、論理演算子含み&and |and builtins Tand F、eg F|xor T&xなどなど。!!xより感嘆するように見えるので、それを使用します。)
which(!!x)
これはとの組み合わせでseq(x)、1からの長さまでの整数シーケンスを返しますx。つまり、すべての小便器の位置(および考慮すべきすべての可能な位置)を返します。
seq(x)
これで、占有された小便器のインデックス1 7と、空の小便器ができました1 2 3 4 5 6 7。`-`減算関数を関数に渡し、outer「外部減算」を取得します。これは、すべての小便器と使用済み小便器間の距離の次のマトリックスです。
[、1] [、2]
[1、] 0 -6
[2、] 1 -5
[3、] 2 -4
[4、] 3 -3
[5、] 4 -2
[6、] 5 -1
[7、] 6 0
outer(seq(x),which(!!x),`-`)
これを-2累乗します。(と少し失われている人のために、OPで、「不快感」は定義されている1 / (distance(x, y) * distance(x, y))ように単純化され、1/d(x,y)^2すなわちd(x,y)^-2。)
outer(seq(x),which(!!x),`-`)^-2
マトリックスの各行の合計を取得します。
rowSums(outer(seq(x),which(!!x),`-`)^-2)
最小値のインデックス、つまり最適な小便器を取得します。複数の最小値の場合、最初の(つまり左端の)値が返されます。
which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))
ほら、最適な小便器のインデックスがあります。私たちは、このインデックスの値を置き換えるxと1。1111入力としての場合、どちらを置換するかは問題ではなく、有効な出力が引き続き得られます。
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
変更された入力を返します。
x