R, 83 76 67 bayt
Aday pisuarların boş olup olmadığını kontrol etmek için canınızı sıkmadan birkaç byte tasarruf edebileceğimi farkettim. Boş olmayan pisuarlar her zaman bir Infrahatsızlık değeri döndürür , bu nedenle hesaplama sırasında dışlanırlar. Ayrıca, doğrudan değil doğrudan dizin kullanarak replace, bu yüzden daha kısa ama daha az zarif.
x=scan()
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x
açıklama
x=scan()
Şu anki durumu stdin'den okuyoruz ve diyoruz x. Girdilerin boşluk veya yeni satırlarla ayrılmış 1s ve 0s dizisi olduğunu varsayıyoruz . Açıklama amacıyla diyelim ki girelim 1 0 0 0 0 0 1.
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
xBelirli bir dizindeki değeri 1 ile değiştiririz. Arasındaki her şey [ ]en iyi dizinin ne olduğunu bulmaktır.
Mevcut pisuarlar değişmez olduğu için, aralarındaki mesafeleri düşünmemize gerek yoktur. Sadece işgal edilmiş pisuarlar ve olası yenileri arasındaki mesafeleri göz önünde bulundurmamız gerekir. Bu yüzden işgal altındaki pisuarların indekslerini belirliyoruz. whichMantıksal bir vektörün indekslerini döndüren bir fonksiyon kullanıyoruz TRUE. R Tüm sayılar, türüyle zaman logicalvardır TRUESıfır dışındaki eğer FALSEsıfır ise. Basitçe yapmak which(x), sayısal bir vektörde olduğu argument to 'which' is not logicalgibi bir tür hatayla sonuçlanır x. Bu nedenle mantıklı olmaya zorlamalıyız. !R'nin otomatik olarak mantığa zorlayan mantıksal olumsuzlama işlevidir. İki kez uygulayarak !!x, bir vektör verir TRUEveFALSEhangi pisuarların işgal edildiğini gösterir. (Mantıksal için alternatif bayt eşdeğer zorlamalar, mantıksal operatörleri &ve |ve yerleşikleri içerir Tve Förneğin F|xveya T&xdiğerleri !!xvb.
which(!!x)
Bu, seq(x)tamsayı sırasını 1uzunluğuna x, yani tüm pisuar konumlarına (ve dolayısıyla göz önünde bulundurulacak tüm olası konumlara) geri döndüren eşleştirilir .
seq(x)
Şimdi işgal edilmiş pisuvarlarımızın indeksleri var: 1 7boş pisuarlarımız 1 2 3 4 5 6 7. Biz geçmesi `-`için, toplama, çıkarma işlevi outertüm pisuar ve işgal pisuar arasındaki mesafeleri aşağıdaki matristir "dış çıkarma", almak için işlevi:
[, 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),`-`)
Bunu -2inci gücüne yükseltiriz . (Biraz kaybedilenler için OP'de "rahatsızlık" yani 1 / (distance(x, y) * distance(x, y))basitleştirici olarak tanımlanmaktadır .)1/d(x,y)^2d(x,y)^-2
outer(seq(x),which(!!x),`-`)^-2
Matristeki her satırın toplamını alın.
rowSums(outer(seq(x),which(!!x),`-`)^-2)
En küçük değerin dizinini alın, yani en uygun pisuar. En küçük değerlerin çoklu olması durumunda, ilk (yani en solda) bir geri döndürülür.
which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))
Ve voilà, en uygun pisuarın indeksine sahibiz. Biz bu endeksine değerini değiştirmek xile 1. 1111Girdi durumunda, hangisini değiştirdiğimiz önemli değil, yine de geçerli bir çıktı elde edeceğiz.
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
Değiştirilen girişi döndürün.
x