Magnetisches Ziehen in einem Array

20

Hintergrund

Ich habe eine Reihe mächtiger Magnete und ein paar Metallgegenstände dazwischen. Wohin ziehen die Magnete sie?

Eingang

Ihre Eingabe besteht aus einem Array nicht negativer Ganzzahlen, die mindestens eine enthalten 1. Sie können jedes vernünftige Format verwenden.

Das 0s des Arrays steht für leeren Raum und das 1s für feste Magnete. Alle anderen Zahlen sind Metallgegenstände, die von den Magneten gezogen werden. Jedes Objekt wird in Richtung des nächsten Magneten gezogen (bei einem Gleichstand wird das Objekt nach rechts gezogen) und bewegt sich in diese Richtung, bis es auf den Magneten oder ein anderes Objekt trifft. Am Ende haben sich alle Objekte um die Magnete gruppiert. Die Reihenfolge der Objekte bleibt erhalten.

Ausgabe

Ihr Ausgang ist das Array, in dem jedes Objekt so nah wie möglich an den nächsten Magneten gezogen wurde. Es sollte dasselbe Format wie die Eingabe haben.

Beispiel

Betrachten Sie das Array

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

Das linke 2wird ebenso wie das zweite zum ersten Magnetpaar gezogen 2. Der 3hat einen Magneten, der vier Schritte in beide Richtungen entfernt ist, sodass er nach rechts gezogen wird. Das wird 5auch nach rechts gezogen, und es geht zwischen dem 3und dem Magneten. Die korrekte Ausgabe ist

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

Regeln und Wertung

Sie können ein vollständiges Programm oder eine Funktion schreiben. Die niedrigste Byteanzahl gewinnt, und Standardlücken sind nicht zulässig.

Testfälle

[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
quelle

Antworten:

7

Pyth, 28 20

[email protected]?bhaDk_x1QkQ~hZQ

Danke @ThomasKwa für das Golfen mit 6 Bytes!

Dies missbraucht eine stabile Sortierung, indem allen Werten 1 oder mehr in der Liste der Index der nächsten 1 zugewiesen wird (Gleichstand mit der am weitesten rechts stehenden 1) und die Liste dann nach diesen Werten sortiert wird. Nullen erhalten einen eigenen Index als Sortierwert.

Test Suite

Verification Suite

Erläuterung:

[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

Beispiel:

Nehmen Sie [1,0,3,0,1,0,3,0,1]zum Beispiel den Testfall . Wenn wir die Aufzählung anwenden, erhalten alle Nullen einen eigenen Index als Sortierwert. Daher überspringe ich diese und führe eine Eins und eine Drei aus.

Für die ersten, bekommen wir die Indizes von Einsen: [0, 4, 8]. Kehren Sie es dann um und sortieren Sie nach dem absoluten Wert der Indizes minus dem Index der Eins, der hier zufällig Null ist. Also kommen wir wieder [0, 4, 8]zurück. Der erste Wert ist, 0dass wir das verwenden.

Für die drei erhalten wir die umgekehrten Indizes und führen dieselbe Sortierung durch, verwenden jedoch zwei als Index der drei, sodass sowohl der 0als auch der 4den gleichen Wert für die absolute Differenz [4, 0, 8]angeben 4.

Dann wird das letzte Array "Sorting Values" sein [0, 1, 4, 3, 4, 5, 8, 7, 8]. Dank der stabilen Sortierung werden die Bindungen in der Reihenfolge unterbrochen, in der die Werte ursprünglich angezeigt wurden, sodass wir das endgültige Array erhalten, das wir möchten.

FryAmTheEggman
quelle
Das Sortieren nach dem nächstgelegenen Index 1ist eine gute Idee!
Zgarb
4

Retina , 97-72 Bytes

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

Es wird erwartet, dass es sich bei der Eingabe um eine durch Kommas getrennte Liste von unären Ganzzahlen handelt (führende und nachfolgende Trennzeichen wie [...]work sind in Ordnung).

Führen Sie hier alle Testfälle aus. (Dies übernimmt der Einfachheit halber die automatische Konvertierung von und nach Dezimalstellen.)

Hier ist eine ganz andere Idee, die die teuren Bilanzkreise durch die Verwendung von mehreren Stufen vermeidet. Es ist derzeit 6 Bytes länger, könnte aber besser zum Golfen sein:

,1\b
>1
\b1,
1<
(T`,`<`<1*,
)T`,`>`,1*>
+`(1+>)>
>$1
+`<(<1+\b)(?!>)
$1<
<|>
,
Martin Ender
quelle
Sobald ich diese Herausforderung sah, dachte ich, Retina würde gut passen (+1)
Michael Klein
@MichaelKlein Danke, aber ich glaube nicht wirklich, dass es so ist. Ich bin überrascht, dass es sogar JavaScript schlägt, aber ich bin mir ziemlich sicher, dass es gegen keine der Golfsprachen eine Chance hat.
Martin Ender
Gute Passform wie in Ich begann sofort zu überlegen, wie in Retina zu lösen
Michael Klein
3

JavaScript (ES6), 108 Byte

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

Erläuterung

Durchläuft jede Zelle und überprüft, ob die nächste Zelle in Richtung des nächstgelegenen Magneten leer ist, und verschiebt sie dorthin, wenn dies der Fall ist. Dieser Vorgang wird so oft wiederholt, bis sich das gesamte Metall so weit wie möglich bewegt hat.

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>

user81655
quelle
2

PHP, 337 Zeichen

<?$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";?>

Ja, das ist sehr lang, weil PHP nicht wirklich eine Sprache zum Golfen ist, aber es funktioniert und ich hatte Spaß daran, es so zu gestalten, dass es für mich in Ordnung ist. Natürlich bin ich offen für mögliche Kurzschlüsse.

Es gibt auch ein kleines Bug- Feature, das denkt, also zum Beispiel hier:

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

es sieht so aus, als wären die 12 magisch vor die 3 gekommen, aber das stimmt nicht!

Die 3 respektiert die größere Zahl und lässt sie näher an das Maget heranrücken!

timmyRS
quelle