R 83 76 67 байт
Просто понял, что я могу сэкономить несколько байтов, не потрудившись проверить, пустые ли писсуары кандидата. Непустые писсуары всегда возвращают Inf
значение дискомфорта, поэтому они исключаются в ходе расчета. Кроме того, просто используется прямое индексирование, а не replace
, так что это короче, но не так элегантно.
x=scan()
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x
объяснение
x=scan()
Мы читаем текущее состояние из стандартного ввода и называем его x
. Мы предполагаем, что входные данные представляют собой последовательность 1
s и 0
s, разделенных пробелами или символами новой строки. Для целей объяснения, скажем, мы вводим 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, которая автоматически приводит к логическому. Применяя его дважды, !!x
получаем вектор TRUE
иFALSE
указывая, какие писсуары заняты. (Альтернативные побайтно-эквивалентные приведения к логическому включают в себя логические операторы &
и |
и встроенные функции T
и F
, например, F|x
или 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
власти. (Для тех, кто немного потерян, в ОП «дискомфорт» определяется как 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