Etiqueta de baño posicional

24

Fondo

La etiqueta del baño, cuando se trata de los urinarios disponibles, establece que el próximo urinario que se debe llenar debe ser el que minimice la incomodidad total. La ecuación de incomodidad total viene dada por el siguiente conjunto de ecuaciones:

dist (x, y) = distancia lineal entre la persona xy la persona y en unidades urinarias
 malestar (x) = sum (1 / (dist (x, y) * dist (x, y))) para todas las personas y excluyendo a la persona x
 Total_Discomfort = sum (malestar (x)) para todos los x

Aquí puede encontrar un documento más detallado sobre un problema similar (no exactamente el mismo): (¡Gracias a @Lembik por alertarme sobre este increíble documento técnico!)


De entrada y salida

Dada la entrada de un urinario vacío y lleno, genera el conjunto resultante de urinarios con la adición de una persona. Si hay un empate para una posición, los urinarios deben llenarse de izquierda a derecha. La salida debe estar en el mismo formato que la entrada.

  • Si se le da un caso con urinarios llenos, devuelva la entrada.
  • La entrada siempre tendrá al menos un urinario definido.


Casos de prueba

ENTRADA -> SALIDA
1000001 -> 1001001
101010101 -> 111010101
100 -> 101
00000 -> 10000
1111111 -> 1111111
0100 -> 0101
101000 -> 101001


Reglas

Este es el , por lo que gana el código más corto en bytes. Los agujeros de bucle estándar están prohibidos.

Nick Frev
fuente
1
Se recomienda esperar aproximadamente una semana antes de aceptar una respuesta. Aceptar en menos de un día puede disminuir la cantidad de respuestas que recibe su desafío.
Emigna
1
Me gustaría sugerir la adición 0100y 101000en los casos de prueba (algunos basados en expresiones regulares enfoque de trabajo en los casos de prueba actuales, pero no funcionará en aquellos que todavía debe ser manejado)
Dada
@TheBitByte ¿Cómo es ofensivo? Es una descripción bastante precisa de cómo los hombres eligen los urinarios en el baño.
mbomb007

Respuestas:

3

Jalea , 13 12 bytes

J_þTݲSiṂ$Ṭo

Pruébalo en línea! o Verificar todos los casos de prueba.

Explicación

J_þTݲSiṂ$Ṭo  Input: boolean array A
J             Indices, returns [1, 2, ..., len(A)]
   T          Truthy indices, returns the indices which have a truthy value
 _þ           Form the subtraction (_) table (þ) between them
    İ         Inverse, find the reciprocal of each
     ²        Square each
      S       Sum the sublists column-wise
         $    Monadic chain
        Ṃ       Minimum
       i        Find the first index of that
          Ṭ   Untruth indices, returns a boolean array with 1's at those indices
           o  Logical OR between that and A, and return
millas
fuente
10

MATL , 19 18 17 bytes

lyf!Gn:-H_^Xs&X<(

Pruébalo en línea! O verifique todos los casos de prueba (código ligeramente modificado).

Explicación

Es suficiente calcular la distancia desde cada nueva posición potencial a las ya ocupadas. Las distancias restantes no dependen de la nueva posición potencial, por lo que constituyen un término constante que puede ignorarse.

Tomemos la entrada [1 0 0 0 0 0 1]como un ejemplo.

l      % Push 1
       % STACK: 1
y      % Take input implicitly. Duplicate from below
       % STACK: [1 0 0 0 0 0 1], 1, [1 0 0 0 0 0 1]
f!     % Indices of nonzero elements, as a column array
       % STACK: [1 0 0 0 0 0 1], 1, [1 7]
Gn:    % Push [1 2 ... n], where n is input size (array of possible positions)
       % STACK: [1 0 0 0 0 0 1], 1, [1; 7], [1 2 3 4 5 6 7]
-      % Matrix with all pairs of differences 
       % STACK: [1 0 0 0 0 0 1], 1, [1; 7], [0 -1 -2 -3 -4 -5 -6;
                                             6  5  4  3  2  1  0]
H_^    % Raise each entry to -2
       % STACK: [1 0 0 0 0 0 1], 1, [   Inf 1.0000 0.2500 0.1111 0.0625 0.0400 0.0278;
                                     0.0278 0.0400 0.0625 0.1111 0.2500 1.0000    Inf]
Xs     % Sum of each column
       % STACK: [1 0 0 0 0 0 1], 1, [Inf 1.04 0.3125 0.2222 0.3125 1.04 Inf]
&X<    % Index of minimum. Takes the first if there is a tie
       % STACK: [1 0 0 0 0 0 1], 1, 4
(      % Assign: write 1 at the position of the minimizer
       % STACK: [1 0 0 1 0 0 1]
       % Implicitly display
Luis Mendo
fuente
4

JavaScript (ES6), 89 bytes

a=>a[a.map((e,i)=>!e&&(t=0,a.map((e,j)=>t+=(j-=i)&&e/j/j),t<m&&(m=t,k=i)),k=0,m=1/0),k]=1

Salidas modificando la matriz de entrada.

Neil
fuente
4

R, 83 76 67 bytes

Me acabo de dar cuenta de que puedo guardar varios bytes sin molestarme en verificar si los urinarios candidatos están vacíos. Los urinarios no vacíos siempre devolverán un Infvalor de incomodidad, por lo que se excluyen en el curso del cálculo. Además, solo usa la indexación directa en lugar de hacerlo replace, por lo que es más corto pero menos elegante.

x=scan()
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x

Explicación

x=scan()

Leemos el estado actual de stdin y lo llamamos x. Suponemos que la entrada es una secuencia de 1s y 0s separados por espacios o saltos de línea. A los fines de la explicación, digamos que ingresamos 1 0 0 0 0 0 1.

x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1

Reemplazamos un valor de xen un índice particular con 1. Todo lo que hay entre ellos [ ]es averiguar cuál es el mejor índice.

Como los urinarios existentes son inmutables, no necesitamos considerar las distancias entre ellos. Solo necesitamos considerar las distancias entre los urinarios ocupados y el posible nuevo. Entonces determinamos los índices de los urinarios ocupados. Usamos which, una función para devolver los índices de un vector lógico que son TRUE. Todos los números en R, cuando están obligados a escribir logical, son TRUEdistintos de cero y FALSEsi son cero. Simplemente hacerlo which(x)dará como resultado un error de tipo argument to 'which' is not logical, como xes un vector numérico. Por lo tanto, tenemos que obligarlo a lógico. !es la función de negación lógica de R, que coacciona automáticamente a lógica. Aplicando dos veces, !!xproduce un vector de TRUEyFALSEindicando qué urinarios están ocupados. (Coacciones alternativos byte equivalente a lógica implican los operadores lógicos &y |y las órdenes internas Ty F, por ejemplo, F|xo T&xy así sucesivamente. !!xApariencia más exclamatoria por lo que vamos a utilizar.)

                                 which(!!x)

Esto se combina con seq(x), que devuelve la secuencia de enteros 1a la longitud de x, es decir, todas las ubicaciones de urinarios (y, por lo tanto, todas las ubicaciones posibles a considerar).

                          seq(x)

Ahora tenemos los índices de nuestros urinarios ocupados: 1 7y nuestros urinarios vacíos 1 2 3 4 5 6 7. Pasamos `-`, la función de resta, a la outerfunción para obtener la "resta externa", que es la siguiente matriz de distancias entre todos los urinarios y los urinarios 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),`-`)

Elevamos esto al -2poder th. (Para aquellos que están un poco perdidos, en el OP, "incomodidad" se define como 1 / (distance(x, y) * distance(x, y)), lo que se simplifica 1/d(x,y)^2, es decir d(x,y)^-2).

                    outer(seq(x),which(!!x),`-`)^-2

Tome la suma de cada fila en la matriz.

            rowSums(outer(seq(x),which(!!x),`-`)^-2)

Obtenga el índice del valor más pequeño, es decir, el urinario óptimo. En el caso de múltiples valores más pequeños, se devuelve el primero (es decir, el más a la izquierda).

  which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))

Y voilà, tenemos el índice del urinario óptimo. Reemplazamos el valor en este índice xcon 1. En el caso de 1111como entrada, no importa cuál reemplacemos, todavía tendremos una salida válida.

x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1

Devuelve la entrada modificada.

x
rturnbull
fuente
2

PHP, 135 bytes

$a=explode(1,$argv[1]);$b=0;foreach($a as$c=>$d){$l=strlen($d);if($l>$b){$b=$l;$e=$c;}}if($b)$a[$e][intval($b/2)]=1;echo implode(1,$a);

Estoy seguro de que hay una manera considerablemente más rápida de hacerlo, ¡pero tengo la cabeza confusa y no puedo pensar en una!

Código antiguo

El código sin minificación:

$a=explode(1,$argv[1]);
$b=0;
foreach($a as $c=>$d){
    $l=strlen($d);
    if($l>$b){
        $b=$l;
        $e=$c;
    }
}
if($b){
    $a[$e][intval($b/2)]=1;
}
echo implode(1,$a);
CT14.IT
fuente
2

Python 3 223 222 165 Bytes

Está bien, sé que esta no es la respuesta más bonita que existe, y estoy seguro de que se puede jugar un poco, pero estaba jugando y viendo lo que podía hacer.

Grite a mbomb007 por los consejos sobre espacios en blanco y comparadores Además, vi que mi contador de personajes en línea estaba tomando todas las pestañas y convirtiéndolas en espacios, por lo que el recuento es mucho menor de lo que originalmente tenía

def u(a):
 m,r,x=9,0,len(a)
 for i in range(x): 
    d=0
    if a[i]<'1':
     for j in range(x):
        if a[j]>'0':d+=float((j-i)**-2)
     if d<m:r=i;m=d
 return a[:r]+'1'+a[r+1:]

Mostrando espacios en blanco revisados:

def u(a):
<sp> m,r,x=9,0,len(a)
<sp> for i in range(x): 
<tab> d=0
<tab> if a[i]<'1':
<tab><sp> for j in range(x):
<tab><tab> if a[j]>'0':d+=float((j-i)**-2)
<tab><sp> if d<m:r=i;m=d
<sp> return a[:r]+'1'+a[r+1:]

Original:

def u(a):
    m,r,x=9,0,len(a)
    for i in range(x): 
        d=0
        if a[i]!='1':
            for j in range(x):
                if a[j]=='1':d+=float(1/(j-i)**2)
            if d<m:r=i;m=d
    return a[:r]+'1'+a[r+1:]

Esto espera que se le pase una cadena de 1 y 0 como "10001"y devuelve una cadena"10101"

Editar: cambiado 1/float((j-i)**2)afloat((j-i)**-2)

bioweasel
fuente
!='1'puede ser <'1'y =='1'puede ser >'0'. Además, considere este consejo
mbomb007
Gracias por ese consejo de espacio en blanco. Definitivamente no lo sabía. ¡Eso es genial!
bioweasel
Esa sugerencia de espacios en blanco solo funciona en Python 2, creo. Tal vez la versión anterior de Python 3, pero idk. Tendrás que restringir tu respuesta a Python 2 o alguna versión específica de 3 para que funcione.
mbomb007
Lo tengo funcionando en un shell 3.5.2 en IDLE y se está ejecutando sin problemas, así que creo que todavía está bien
bioweasel
2

Python 3, 574 471 347 bytes

Probablemente trabajaré en esto un poco más, considerando que la otra solución de Python es como una quinta parte de esta: [.

def a(I):
 D,l,r={},len(I),range
 for i in r(l):
  if I[i]<1:
   n,t,n[i]=I[:],[],1
   for j in r(l):
    if n[j]>0:
     q,Q=[],0
     for k in r(l):
      if k!=j and n[k]>0:q.append((k-j,j-k)[k<j])
     for i in q:Q+=1/(i**2)
    t.append(Q)
   T=sum(t)
   if T not in D.keys():D[T]=i
 if len(D)>0:I[D[min(D.keys())]]=1
 print(I)

Bueno, eso es mucho mejor ahora que he aprendido que puedes usar espacios individuales.

Yodle
fuente
1

Python, 165 163 158 147 141 140 139 bytes

def u(p):e=enumerate;a=[(sum((i-j)**-2for j,y in e(p)if"0"<y),i)for i,x in e(p)if"1">x];return a and p[:min(a)[1]]+"1"+p[min(a)[1]+1:] or p
Francisco Couzo
fuente
reescribir la segunda línea if"1"*len(p)==p:return ppara guardar un byte
FlipTack