Atracción magnética en una matriz

20

Antecedentes

Tengo una fila de imanes poderosos y un montón de objetos metálicos entre ellos. ¿Dónde los atraerán los imanes?

Entrada

Su entrada es una matriz de enteros no negativos, que contendrá al menos uno 1. Puedes usar cualquier formato razonable.

Las 0s de la matriz representan espacios vacíos y las 1s representan imanes fijos. Todos los demás números son objetos metálicos, que son arrastrados por los imanes. Cada objeto se tira hacia el imán más cercano (si hay un lazo, el objeto se tira hacia la derecha), y viaja en esa dirección hasta que golpea el imán u otro objeto. Al final, todos los objetos se han agrupado alrededor de los imanes. Se conserva el orden de los objetos.

Salida

Su salida es la matriz donde cada objeto ha sido arrastrado lo más cerca posible del imán más cercano. Debe tener el mismo formato que la entrada.

Ejemplo

Considera la matriz

[0,0,2,0,1,1,0,2,0,3,0,5,0,1,0]

El extremo izquierdo 2se tira hacia el primer par de imanes, al igual que el segundo 2. El 3tiene un imán cuatro pasos en ambas direcciones, por lo que es atraída hacia la derecha. El 5también se tira hacia la derecha, y va entre el 3y el imán. La salida correcta es

[0,0,0,2,1,1,2,0,0,0,0,3,5,1,0]

Reglas y puntaje

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana, y las lagunas estándar no se permiten.

Casos de prueba

[0,1,0] -> [0,1,0]
[1,0,2,0,0,1,0] -> [1,2,0,0,0,1,0]
[7,0,5,0,0,1,0] -> [0,0,0,7,5,1,0]
[1,0,3,0,1,0,3,0,1] -> [1,0,0,3,1,0,0,3,1]
[1,0,0,0,0,0,0,7,3] -> [1,7,3,0,0,0,0,0,0]
[1,2,3,4,5,6,7,8,9,10,11,0,0,0,1] -> [1,2,3,4,5,6,7,0,0,0,8,9,10,11,1]
[12,3,0,0,1,0,1,3,0,0,6,12,0,0,0,1] -> [0,0,12,3,1,0,1,3,6,0,0,0,0,0,12,1]
Zgarb
fuente

Respuestas:

7

Pyth 28 20

[email protected]?bhaDk_x1QkQ~hZQ

¡Gracias @ThomasKwa por jugar 6 bytes!

Esto abusa de la ordenación estable asignando a todos los valores 1 o mayores en la lista el índice del 1 más cercano (lazos rotos al 1 más a la derecha) y luego ordenando la lista por estos valores. Los ceros reciben su propio índice como su valor de clasificación.

Banco de pruebas

Suite de Verificación

Explicación:

[email protected]?bhaDk_x1QkQ~hZQ  ##  implicit: Q = eval(input())
o                  Q  ##  Sort Q using the values of the lambda below
 @              ~hZ   ##  select the value from the matching index of the enumerate
  .e           Q      ##  enumerate with b = value, k = index
    ?b                ##  ternary on b
      haDk_x1Q        ##  if true, this thing
              k       ##  otherwise use the index as the sort weight
          _x1Q        ##  the indices of 1 in Q, given in reverse order 
                      ##  (the reverse makes it sort to the right because of stable sorts)
       aDk            ##  sort those indices by |index - k|
      h               ##  take the first value

Ejemplo:

Tome el caso de prueba [1,0,3,0,1,0,3,0,1], por ejemplo. Cuando apliquemos la enumeración, todos los ceros obtendrán su propio índice como un valor de clasificación, por lo que los omitiré y haré un uno y un tres.

Para el primero, se obtienen los índices de los: [0, 4, 8]. Luego inviértalo y ordene por el valor absoluto de los índices menos el índice del uno, que aquí es cero. Entonces volvemos de [0, 4, 8]nuevo. El primer valor es 0que usamos eso.

Para los tres, obtenemos los índices invertidos y hacemos la misma clasificación pero usando dos como el índice de los tres, por lo que tanto el 0y el 4dan el mismo valor para la diferencia absoluta, por lo que obtenemos: [4, 0, 8]y tomamos el 4.

Entonces será la matriz final de "valores de clasificación" [0, 1, 4, 3, 4, 5, 8, 7, 8]. Gracias a la ordenación estable, los lazos se rompen por el orden en que aparecieron originalmente los valores, por lo que obtenemos la matriz final que queremos.

FryAmTheEggman
fuente
¡Ordenar por el índice más cercano 1es una buena idea!
Zgarb
4

Retina , 97 72 bytes

+`(?<=\b1(,1*)*?)(\B,(11+)|,(11+))\b(?!(?<-1>,1*)*,1\b)|(11+),\B
$3,$4$5

Se espera que la entrada sea una lista separada por comas de enteros unarios (los delimitadores iniciales y finales, como el [...]trabajo, están bien).

Ejecute todos los casos de prueba aquí. (Por conveniencia, esto se encarga de la conversión de y a decimal automáticamente).

Aquí hay una idea completamente diferente que evita los costosos grupos de equilibrio mediante el uso de múltiples etapas. Actualmente tiene 6 bytes más, pero podría ser más fácil de jugar:

,1\b
>1
\b1,
1<
(T`,`<`<1*,
)T`,`>`,1*>
+`(1+>)>
>$1
+`<(<1+\b)(?!>)
$1<
<|>
,
Martin Ender
fuente
Tan pronto como vi este desafío, pensé que Retina encajaría bien (+1)
Michael Klein
@MichaelKlein Gracias, pero realmente no creo que sea así. Me sorprende que incluso supere a JavaScript, pero estoy bastante seguro de que no tendrá ninguna posibilidad contra ninguno de los idiomas de golf.
Martin Ender
Encaja bien ya que inmediatamente comencé a pensar cómo resolver en Retina
Michael Klein
3

JavaScript (ES6), 108 bytes

a=>a.map(_=>a.map((x,i)=>x>1?a[j=(n=a.indexOf(1,i))<0|n-i>i-p?i-1:i+1]?0:a[a[i]=0,j]=x:x<1?0:p=i,p=-1/0))&&a

Explicación

Itera sobre cada celda y si contiene metal, verifica si la siguiente celda en la dirección del imán más cercano está vacía y, si lo está, la mueve allí. Este proceso se repite muchas veces hasta que todo el metal se haya movido lo más lejos posible.

var solution =

a=>
  a.map(_=>                  // loop a.length times to ensure completeness
    a.map((x,i)=>            // for each cell item x at index i
      x>1?                   // if the cell contains metal
        a[j=                 // j = index of cell to move to
          (n=a.indexOf(1,i)) // n = index of next magnet
          <0|n-i>i-p?i-1:i+1 // set j to previous or next cell based on closest magnet
        ]?0:                 // if cell j is empty
          a[a[i]=0,j]=x      // set it to x and set cell i to 0
      :x<1?0:                // else if the cell contains a magnet
        p=i,                 // set p to the index of this magnet
      p=-1/0                 // p = index of previous magnet, initialise to -Infinity
    )
  )
  &&a                        // return a
<input type="text" id="input" value="1,2,3,4,5,6,7,8,9,10,11,0,0,0,1" />
<button onclick="result.textContent=solution(input.value.split(',').map(n=>+n))">Go</button>
<pre id="result"></pre>

usuario81655
fuente
2

PHP, 337 caracteres

<?$i=explode(",",$argv[1]);$m=$n=[];foreach($i as$k=>$v)if($v>0)eval("array_push(\$".($v<2?"m":"n").",$k);");for($p=0;$p<count($i);$p++)foreach($i as$k=>$v)if($v>1){$i[$k]=0;$r=-1;foreach($m as$_)if($r<0||abs($k-$r)>abs($_-$k))$r=$_;while($i[$r]>0)$r+=($r<$k?1:-1);$i[$r]=$v;}$s="";foreach($i as$v)$s.=$v.",";echo substr($s,0,-1)."\n";?>

Sí, esto es muy largo, porque PHP no es realmente un lenguaje para jugar al golf, pero funciona y me divertí haciéndolo, así que está bien para mí. Por supuesto que estoy abierto a posibles cortocircuitos.

También hay una pequeña característica de error que piensa, así que, por ejemplo, aquí:

root@raspberrypi:~/stack# php magnet.php 12,3,0,0,1,0,1,3,0,0,6,12,0,0,0,1
0,0,3,12,1,0,1,3,6,0,0,0,0,0,12,1

Parece que los 12 se pusieron mágicamente frente a los 3, ¡pero eso no es cierto!

¡El 3 respeta el número más grande y lo deja más cerca del maget!

timmyRS
fuente