Gravitationskraft zwischen Zahlen

52

Die Gravitationskraft ist eine Kraft, die zwei beliebige Objekte mit Masse anzieht. In dieser Herausforderung werden unsere Objekte Zahlen sein und ihre Masse wird ihr Wert sein. Dabei geht es uns nicht um die Stärke der Kraft, sondern um die Richtung.

Stellen Sie sich diese Zahlenreihe vor

[1 6 9 4 6 9 7 6 4 4 9 8 7]

Jeder von ihnen schafft eine Kraft zwischen sich und seinen Nachbarn. Unter bestimmten Umständen wird dadurch eine andere Nummer angezogen (verschoben). Wenn die Zahl größer als die benachbarte ist, wird sie angezogen. Schauen wir uns unser vorheriges Beispiel an:

[1 → 6 → 9 ← 4 6 → 9 ← 7 ← 6 ← 4 4 → 9 ← 8 ← 7]

Die Zahl 1ist nicht groß genug, um sich zu bewegen 6, aber die Zahl 6ist usw. Grundsätzlich werden Zahlen zur größten benachbarten Zahl verschoben (auch größer als die Zahl selbst). Wenn beide benachbarten Zahlen gleich sind, wird es nicht angezogen. Es kommt auch vor, wenn die Zahl und die benachbarte Zahl gleich sind.

Dies soll nur die Attraktion zeigen, aber was passiert danach? Zahlen, die durch Anziehung kollidieren, sind zusammengefasst:

[20 32 28]

Die Herausforderung besteht also im Grunde darin, bei einer gegebenen Anzahl von Zahlen das Ergebnis der angezogenen Anzahl auszugeben.


Beispiel 1

Input  => [10 15 20 10 20 10 10]
          [10 → 15 → 20 10 20 ← 10 10]
Output => [45 10 30 10]

Beispiel 2

Input  => [9 9 9 9 8 1 8]
          [9 9 9 9 ← 8 1 8]
Output => [9 9 9 17 1 8]

Beispiel 3

Input  => [1 6 9 4 6 9 7 6 4 4 9 8 7]
          [1 → 6 → 9 ← 4 6 → 9 ← 7 ← 6 ← 4 4 → 9 ← 8 ← 7]
Output => [20 32 28]

Beispiel 4

Input  => [1 2 3 2 1]
          [1 → 2 → 3 ← 2 ← 1]
Output => [9]

Beispiel 5

Input  => [1]
Output => [1]

Beispiel 6

Input  => [1 1]
Output => [1 1]

Beispiel 7

Input  => [2 1 4]
Output => [2 5]

Anmerkungen

  • Anziehung geschieht nur einmal
  • Zahlen werden nicht von nicht benachbarten Zahlen angezogen
  • Die Menge der Zahlen enthält nur positive ganze Zahlen
Luis Felipe De Jesus Munoz
quelle
1
Schlagen Sie vor, einen Testfall hinzuzufügen, der zu einer einzelnen Ganzzahl zusammenfällt.
Shaggy
2
[1 3 5 4 2]= 15 & le;
Magic Octopus Urn
@MagicOctopusUrn Ja
Luis Felipe De Jesus Munoz
14
1 ist nicht groß genug, um die Nummer 6 anzuziehen. Diese Formulierung stört den Physiker in mir. (Nun, tun Sie dies auch für einige andere Regeln, aber diese können durch Ändern des Wortlauts behoben werden, ohne die Problemdefinition zu ändern.) Die Anziehungskraft zwischen zwei Körpern G*M*m / r^2ist für beide Körper gleich. Das leichtere bewegt sich mehr als das schwerere, nicht wegen mangelnder Anziehungskraft. Sagen Sie vielleicht "1 ist nicht groß genug, um 6 zu bewegen".
Peter Cordes
4
Aber in Wirklichkeit definieren Sie "anziehen" als "angezogen", anstatt "eine Kraft zu erzeugen", was im Widerspruch zum früheren Satz " Jede von ihnen erzeugt eine Anziehungskraft auf ihre benachbarten Zahlen " steht. Also überarbeiten Sie diese Öffnung vielleicht, um zu sagen: "Jeder von ihnen erzeugt eine Kraft zwischen sich und seinen benachbarten Zahlen. Unter bestimmten Umständen wird dadurch eine andere Zahl zu einer Zahl hingezogen (verschoben)." Ich weiß, das ist nur ein Trottel in der Terminologie, und dieses Gravitationsmodell ist der realen Physik nur vage ähnlich, aber es hat mich genug gestört, diesen Kommentar schreiben zu wollen.
Peter Cordes

Antworten:

15

JavaScript (ES6),  106 104  100 Bytes

2 Bytes dank @Shaggy gespart

a=>a.filter(n=>n,[...a].map((v,i)=>a[a[p>v&(n=~~a[i+1])<p?k:i+(k=i,n>v&p<n)]+=x=a[i],p=v,i]-=x,p=0))

Probieren Sie es online!

Kommentiert

Wir aktualisieren zuerst das ursprüngliche Eingabearray, a[]indem wir eine Kopie davon iterieren. Während dieses Schritts werden alle von anderen 'angezogenen' Werte auf .0

Da das Array von links nach rechts analysiert wird, können wir einfach zu hinzufügen , wenn ein Wert von seinem rechten Nachbarn angezogen wird.aiai+1

Beispiel: Aus wird und dann .456[0,9,6][0,0,15]

Wenn jedoch mehrere Werte in einer Reihe von ihrem linken Nachbarn angezogen werden, müssen wir zum ersten Attraktor dieser Sequenz (mit ) hinzufügen und nicht einfach .aiakk<iai1

Beispiel: wird in und dann in .654[11,0,4][15,0,0]

[...a]                 // create a copy of a[]
.map((v, i) =>         // for each value v in a[] at position i:
  a[                   //   this statement updates a[i]:
    a[                 //     this statement updates either a[i] or an adjacent value:
      p > v &          //       if the previous value p is greater than v
      (n = ~~a[i + 1]) //       and the next value n
      < p ?            //       is less than p (attraction to the left):
        k              //         use k (k is initially undefined, but this code cannot
                       //         be triggered during the first iteration)
      :                //       else:
        i + (          //         use either i or i + 1:
          k = i,       //           set k to i
          n > v &      //           use i + 1 if n is greater than v
          p < n        //           and p is less than n (attraction to the right)
        )              //
    ] += x = a[i],     //     add x = a[i] to the entry defined above
    p = v,             //     update the previous value to v
    i                  //     actual index to update a[i]
  ] -= x,              //   subtract x from a[i]
  p = 0                //   start with p = 0
)                      // end of map()

Wir filtern dann alle Einträge gleich .0

a.filter(n => n)
Arnauld
quelle
Nach Ihrer Erklärung klingt es so, als würde Ihr Code fehlschlagen [1,3,5,3,1,2,1]und ausgegeben [14,2], aber es funktioniert tatsächlich richtig und wird ausgegeben [13,3].
Erik der Outgolfer
@EriktheOutgolfer Ich habe den Teil umformuliert, der - glaube ich - irreführend war. Ist das besser?
Arnauld
2
Jetzt wird der "erste Attraktor" anstelle des "höchsten vorherigen Werts" erwähnt, damit ich verstehen kann, was Sie meinen.
Erik der Outgolfer
9

Stax , 27 25 23 18 Bytes

«╥╦.ê§┘h!@ÆEÿ☺╜╫♥B

Führen Sie es aus und debuggen Sie es

Die Ausgabe wird durch Zeilenumbrüche getrennt.

Dieses Programm bearbeitet benachbarte Paare im Array und bestimmt anhand dieser Prozedur, ob eine Aufteilung zwischen ihnen erfolgen soll.

Betrachten Sie eine willkürliche Eingabe [... w x y z ...]. Hier erfahren Sie, ob eine Aufteilung zwischen xund erfolgen soll y.

  • Wenn x == yja, dann ja.
  • Wenn x > y, dann iff z >= x.
  • Wenn y > x, dann iff w >= y.

Die Summierung bleibt als Übung.

rekursiv
quelle
8

Retina 0.8.2 , 64 Bytes

\d+
$*
(?<=(1+)) ((?=(1+\1))(?<!\3 \1 )|(?!\1)(?!1+ \1))

1+
$.&

Probieren Sie es online! Link enthält Testsuite. Erläuterung:

\d+
$*

In Unary konvertieren.

(?<=(1+)) ((?=(1+\1))(?<!\3 \1 )|(?!\1)(?!1+ \1))

Entfernen Sie die Trennzeichen zwischen den angezogenen Zahlen. (?<=(1+))wird \1auf die Zahl vor dem Trennzeichen gesetzt. Nach dem Trennzeichen gibt es dann zwei Fälle:

  • Die Zahl nach dem Trennzeichen ist größer als die beiden Zahlen vor dem Trennzeichen
  • Die Zahl vor dem Trennzeichen ist größer als die beiden Zahlen nach dem Trennzeichen

In diesen Fällen besteht eine Anziehungskraft zwischen den beiden Zahlen, und das Löschen des Trennzeichens führt dazu, dass die Zahlen kollidieren und sie addieren.

1+
$.&

In Dezimalzahl konvertieren.

Neil
quelle
6

Jelly , 23 Bytes

Ø0jMÆmær0Ʋ3Ƥ×=4$o<ʋƝk⁸§

Probieren Sie es online!

Ein monadischer Link, der eine Liste von Ganzzahlen als Argument verwendet und eine Liste von Ganzzahlen zurückgibt.

Erläuterung

Ø0j                     | Join [0, 0] with input list
         Ʋ3Ƥ            | For each length 3 infix, do the following as a monad:
   M                    | - Indices of maximum
    Æm                  | - Mean
      ær0               | - Round to even (so the means of [1, 2, 3], [1, 2], [2, 3] and [1, 3] will all round to 2
                  ʋƝ    | For each neighbouring pair, do the following as a dyad:
            ×           | - Multiply
             =4$        | - Check if equal to 4
                o       | - Or
                 <      | - First number less than second
                    k⁸  | Split input after truthy values of the above
                      § | Sum, vectorised

Einige Inspirationen stammen aus der Stax-Antwort von @ recursive .

Nick Kennedy
quelle
4

C (gcc) , 111 Bytes

a,b,c,s;P(){s=!printf("%d ",s);}f(int*v){for(b=s=0,c=*v;a=b,b=c;a<b|b<a&c<a||P(),s+=b,b<c&c<=a|!c&&P())c=*++v;}

Probieren Sie es online!

Nimmt ein nullterminiertes Array von Ganzzahlen.

Erläuterung

a,b,c,  // Three consecutive elements of input array
s;      // Accumulator for sum
P(){s=!printf("%d ",s);}  // Print and clear s
f(int*v){
    for(
        // Init
        b=s=0,
        c=*v;
        // Loop test
        a=b,  // Shift b into a
        b=c;  // Shift c into b, exit if zero
        // Post loop
        a<b|b<a&c<a||P(),  // Print if a==b || (b<a && a<=c)
        s+=b,  // Accumulate
        b<c&c<=a|!c&&P()   // Print if c==0 || (b<c && c<=a)
    )
        // Loop body
        c=*++v;  // Read next number into c
}
nwellnhof
quelle
3

Python 2 , 162 Bytes

l=input()
a=[(L<R>C)-(R<L>C)for L,C,R in zip([0]+l,l,l[1:]+[0])]
while any(a):
 i=0
 while a[i]==0:i+=1
 m=a.pop(i);x,y=[i,i+m][::m];l[x:y+1]=l[i]+l[i+m],
print l

Probieren Sie es online!

Erik der Outgolfer
quelle
3

J , 45 Bytes

+//.~0,[:+/\2(<+.1=*)/\3(>./1:/@I.@E.])\0,,&0

Probieren Sie es online!

Inspiriert von der ursprünglichen Stax-Antwort von recursive

Jona
quelle
3

R , 222 196 173 Bytes

Hier ist eine Lösung mit etwas Hilfe von Robin Ryder

n=length(d<-diff(y<-x<-scan()));l=c(1,sign(d[-n]+d[-1]),-1);m=!!l*n&c(d[1]>0,d[-1]>0|d[-n]<0,d[n]<0);for(t in 1:n){for(i in which(m))y[a]=y[a<-i+l[i]]+x[i];y=x=y-x*m};x[!m]

Probieren Sie es online!

Eine kurze Reihe von Kommentaren

n=length(d<-diff(y<-x<-scan()));  #read input and compute pairwise differences
                    #d[-n]+d[-1]: compare left and right differences
l=c(1,sign(d[-n]+d[-1]),-1)                 #direction of attraction
m=!!l*n&                          #indices of attracted numbers
  c(d[1]>0,d[-1]>0|d[-n]<0,d[n]<0)  
                                   #!!l*n eliminates zeroes in l & the case n==0
for(t in 1:n){                   #excessive loop on transfers
 for(i in which(m))
   y[a]=y[a<-i+l[i]]+x[i]         #transfer right vs. left
 y=x=y-m*x}                        #complete transfer
x[!m]                             #output
Xi'an
quelle
1
-4 Bytes mit sign(e)statt(e>0)-(e<0)
Robin Ryder
1
Auch die {}in der for-Schleife sind nicht erforderlich, da sich nur ein Befehl in der Schleife befindet.
Robin Ryder
1
189 Bytes mit den obigen 2 Kommentaren + Verschieben der Definition von y.
Robin Ryder
1
179 Bytes unter Verwendung der Tatsache, dass mes sich um einen Booleschen handelt
Robin Ryder
3

Python, 114 112 Bytes

lambda a:eval('['+'+'.join(str(c)+',0'*((e<c>d)==(c<d>b))for b,c,d,e in zip([0]+a,a,a[1:]+[0],a[2:]+[0,0]))+']')

Dies nutzt die Tatsache, dass die Richtung des Pfeils eigentlich keine Rolle spielt und dass das Vorhandensein eines Pfeils zwischen a [i] und a [i + 1] durch Betrachten des Bereichs von vier Elementen bestimmt werden kann. 1: i + 3].

Edit: Danke an Jo King für die Regelklärung

Rikhavshah
quelle
2

Perl 5 , 156 147 Bytes

$q='$F[$i';map{eval"\$i++while$q]$_"}"<$q+1]",">$q+1]&&$q]>$q+2]&&\$i<\@F"if eval"$q-1]-$q+1]||$q]>$q+1]";$\.=$".sum@F[$p..$i];($p=++$i)<@F&&redo}{

Probieren Sie es online!

Xcali
quelle
2

K (ngn / k) , 46 Bytes

{+/'x@.={x x}/(!#x)+{-/2=+/x<\:x 2 0}'3'0,x,0}

Probieren Sie es online!

0,x,0 Umgeben Sie das Argument mit 0s

3' Drillinge aufeinanderfolgender Gegenstände

{ }' für jeden tun

x 2 0Holen Sie sich das letzte und erste der aktuellen Drillinge - x[2]und x[0]. Sie sind die Nachbarn von x[1], auf denen das Triplett zentriert ist

x<\: Vergleichen Sie mit weniger als gegen jedes der aktuellen Tripletts

+/Summe. das Ergebnis ist ein Paar, das x[2]und entsprichtx[0]

2=Überprüfen Sie, ob einer der Nachbarn größer ist als die beiden anderen Elemente von. xGeben Sie ein Paar 0- oder 1-Boolescher Werte zurück

-/subtrahieren sie. Ein Ergebnis von -1 bedeutet, dass x[1]es nach links gezogen wird, 1 nach rechts und 0 bedeutet, dass es an Ort und Stelle bleibt

(!#x)+ Addiere 0 zu dem ersten Element, 1 zu dem zweiten usw. Dies berechnet die Indizes, zu denen Elemente angezogen werden

{x x}/Index mit sich selbst bis zur Konvergenz. das ergebnis sind die effektiven indizes, zu denen jeder artikel letztendlich hingezogen wird

x@.=Gruppe x(das ursprüngliche Argument) von denen. Das Ergebnis ist eine Liste von Listen

+/' summiere jeden

ngn
quelle
2

Clojure , 299 252 Bytes

(fn[l](loop[o[0]m(vec(map-indexed(fn[i v](def f #(max(nth l(+ % i)0)v))(-(f -1)(f 1)))l))i 0](defn f[x](update o(-(count o)x)#(+(l i)%)))(cond(<=(count m)i)(pop o)(>(m i)0)(recur(f 2)m(inc i))(<(m i)0)(recur(f 1)m(inc i))1(recur(conj(f 1)0)m(inc i)))))

Probieren Sie es online!


Erläuterung:

(fn [l]
  (loop [o [0]
         m (vec(map-indexed (fn [i v] ; This maps each element l[i] of l to max(l[i-1], l[i]) - max(l[i+1], l[i])
                              (def f #(max (nth l (+ % i) 0) v))
                              (- (f -1) (f 1)))
                            l))       ; l[x] is zero when l[x] is out of bounds of the input vector l
         i 0]
    (defn f [x] (update o (- (count o) x) #(+ (l i) %)))
    ; Defines a function f(x) that returns the result of mapping the (x-1)th to last element of o over the function g(y) = l[i] + y

    (cond
      (<= (count m) i) (pop o) ; If the length of m is less than or equal to i, there are no more elements in m, so return all but the last element of o
      (> (m i) 0) (recur (f 2) m (inc i)) ; If m[i] is positive, l[i] is pulled toward to the previous element, so add l[i] to the 2nd to last element of o
      (< (m i) 0) (recur (f 1) m (inc i)) ; If m[i] is negative, l[i] is pulled toward the next element, so add l[i] to the last element of o
      1 (recur (conj (f 1) 0) m (inc i))))) ; 1 is truthy
      ; If the length of l is less than or equal to i, and m[i] is not positive or negative, we have m[i] = 0, so l[i] is not pulled toward any other element
TheGreatGeek
quelle