R, 83 76 67 bytes
Acabei de perceber que posso salvar vários bytes, sem me preocupar em verificar se os mictórios candidatos estão vazios. Mictórios não vazios sempre retornam um Inf
valor de desconforto, portanto são excluídos no decorrer do cálculo. Além disso, basta usar a indexação direta em vez de replace
, portanto, é mais curto, mas menos elegante.
x=scan()
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x
Explicação
x=scan()
Lemos o estado atual de stdin e o chamamos x
. Nós assumimos que a entrada é uma sequência de 1
s e 0
s separados por espaços ou novas linhas. Para os fins da explicação, digamos que inserimos 1 0 0 0 0 0 1
.
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
Substituímos um valor de x
um índice específico por 1. Tudo entre o [ ]
é descobrir qual é o melhor índice.
Como os mictórios existentes são imutáveis, não precisamos considerar as distâncias entre eles. Só precisamos considerar as distâncias entre os mictórios ocupados e o possível novo. Então, determinamos os índices dos mictórios ocupados. Usamos which
uma função para retornar os índices de um vetor lógico que são TRUE
. Todos os números em R, quando forçados a digitar logical
, são TRUE
diferentes de zero e FALSE
zero. Simplesmente which(x)
resultará em um erro de tipo argument to 'which' is not logical
, como x
é um vetor numérico. Portanto, temos que coagi-lo à lógica. !
é a função de negação lógica de R, que obriga automaticamente a lógica. A aplicação duas vezes, !!x
produz um vetor de TRUE
eFALSE
indicando quais mictórios estão ocupados. (Coerções alternativas equivalentes a bytes para lógicas envolvem os operadores lógicos&
e |
e os builtins T
e F
, por exemplo, F|x
ou T&x
e assim por diante. !!x
Aparência mais exclamatory por isso vamos usar isso.)
which(!!x)
Isso é emparelhado com seq(x)
, que retorna a sequência inteira 1
do comprimento de x
, ou seja, todos os locais do mictório (e, portanto, todos os locais possíveis a serem considerados).
seq(x)
Agora temos os índices de nossos mictórios ocupados: 1 7
e nossos mictórios vazios 1 2 3 4 5 6 7
. Passamos `-`
, a função de subtração, para a outer
função de obter a "subtração externa", que é a seguinte matriz de distâncias entre todos os urinóis e os urinóis ocupados:
[, 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),`-`)
Nós elevamos isso ao -2
poder th. (Para aqueles que estão um pouco perdidos, no OP, "desconforto" é definido como 1 / (distance(x, y) * distance(x, y))
, o que simplifica para 1/d(x,y)^2
, ie d(x,y)^-2
.)
outer(seq(x),which(!!x),`-`)^-2
Pegue a soma de cada linha na matriz.
rowSums(outer(seq(x),which(!!x),`-`)^-2)
Obtenha o índice do menor valor, ou seja, o urinol ideal. No caso de vários valores menores, o primeiro (ou seja, mais à esquerda) é retornado.
which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))
E, voilà, temos o índice do mictório ideal. Substituímos o valor nesse índice x
por 1
. No caso de 1111
como entrada, não importa qual substituímos, ainda teremos uma saída válida.
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
Retorne a entrada modificada.
x