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 Inf
rahatsı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ış 1
s ve 0
s 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
x
Belirli 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. which
Mantıksal bir vektörün indekslerini döndüren bir fonksiyon kullanıyoruz TRUE
. R Tüm sayılar, türüyle zaman logical
vardır TRUE
Sıfır dışındaki eğer FALSE
sıfır ise. Basitçe yapmak which(x)
, sayısal bir vektörde olduğu argument to 'which' is not logical
gibi 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 TRUE
veFALSE
hangi 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 T
ve F
örneğin F|x
veya T&x
diğerleri !!x
vb.
which(!!x)
Bu, seq(x)
tamsayı sırasını 1
uzunluğ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 7
boş pisuarlarımız 1 2 3 4 5 6 7
. Biz geçmesi `-`
için, toplama, çıkarma işlevi outer
tü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 -2
inci 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)^2
d(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 x
ile 1
. 1111
Girdi 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