Fuerza gravitacional entre números

52

La fuerza gravitacional es una fuerza que atrae dos objetos con masa. En este desafío, nuestros objetos serán Números y su masa será su valor. Para hacerlo, no nos importa la fuerza de la fuerza sino la dirección de la misma.

Imagina este conjunto de números

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

Cada uno de ellos crea una fuerza entre sí y sus números adyacentes. En algunas condiciones, esto provocará que otro número sea atraído (movido) hacia un número. Cuando el número es mayor que el adyacente, lo atrae. Echemos un vistazo a nuestro ejemplo anterior:

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

El número 1no es lo suficientemente grande como para moverse 6, pero el número 6es, etc. Básicamente, los números se mueven al número adyacente más grande (también más grande que el número mismo). Si los dos números adyacentes son iguales, entonces no se atrae. También ocurre cuando el número y el adyacente son iguales.

Esto es solo para mostrar la atracción, pero ¿qué sucede después? Los números que chocan debido a la atracción se resumen:

[20 32 28]

Básicamente, el desafío es, dado un conjunto de números, generar el resultado del conjunto atraído de números.


Ejemplo 1

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

Ejemplo 2

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

Ejemplo 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]

Ejemplo 4

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

Ejemplo 5

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

Ejemplo 6

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

Ejemplo 7

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

Notas

  • La atracción solo ocurre una vez
  • Los números no son atraídos por números no adyacentes
  • El conjunto de números solo contendrá enteros positivos
Luis felipe De jesus Munoz
fuente
1
Sugiera agregar un caso de prueba que se contraiga en un solo entero.
Shaggy
2
[1 3 5 4 2]= 15?
Urna mágica de pulpo
@MagicOctopusUrn Sí
Luis felipe De jesus Munoz
14
1 no es lo suficientemente grande como para atraer el número 6 Esta redacción molesta al físico en mí. (Bueno, también algunas de las otras reglas, pero esta podría ser reparable cambiando la redacción sin cambiar la definición del problema). La fuerza de atracción entre dos cuerpos G*M*m / r^2, es igual para ambos cuerpos. El más ligero se mueve más que el más pesado por el impulso, no por falta de atracción. Tal vez diga "1 no es lo suficientemente grande como para mover 6".
Peter Cordes
44
Pero realmente está definiendo "atraer" como "atraído hacia", en lugar de "crea una fuerza", lo que está en conflicto con la oración anterior " Cada uno de ellos crea una fuerza de atracción a sus números adyacentes ". Así que quizás vuelva a trabajar esa apertura para decir "cada uno de ellos crea una fuerza entre sí y sus números adyacentes. En algunas condiciones, esto hará que otro número sea atraído (movido) hacia un número". Sé que esto es solo una cuestión de terminología, y este modelo de gravitación solo es vagamente similar a la física real, pero me molestó lo suficiente como para querer escribir este comentario.
Peter Cordes

Respuestas:

15

JavaScript (ES6),  106 104  100 bytes

Guardado 2 bytes gracias a @Shaggy

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))

Pruébalo en línea!

Comentado

Primero actualizamos la matriz de entrada original a[]iterando en una copia de la misma. Durante este paso, todos los valores 'atraídos' por otros se establecen en .0

Debido a que la matriz se analiza de izquierda a derecha, podemos agregar a siempre que un valor sea atraído por su vecino derecho.aiai+1

Ejemplo: se convierte en y luego .456[0,9,6][0,0,15]

Pero cuando su vecino izquierdo atrae varios valores seguidos, necesitamos agregar al primer atractor de esta secuencia (con ) en lugar de simplemente .aiakk<iai1

Ejemplo: se convierte en y luego .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()

Luego filtramos todas las entradas iguales a .0

a.filter(n => n)
Arnauld
fuente
Según su explicación, parece que su código fallará [1,3,5,3,1,2,1]y se generará [14,2], pero en realidad funciona correctamente y genera resultados [13,3].
Erik the Outgolfer
@EriktheOutgolfer He reformulado la parte que, creo, fue engañosa. ¿Eso está mejor?
Arnauld
2
Ahora sí menciona el "primer atractor" en lugar de solo el "valor anterior más alto", por lo que puedo entender lo que quiere decir.
Erik the Outgolfer
9

Stax , 27 25 23 18 bytes

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

Ejecutar y depurarlo

La salida está separada por nuevas líneas.

Este programa opera en pares adyacentes en la matriz y determina si debe haber una división entre ellos mediante este procedimiento.

Considere alguna entrada arbitraria [... w x y z ...]. Aquí es cómo determinar si debería haber una división entre xy y.

  • Si x == y, entonces si.
  • Si x > y, entonces iff z >= x.
  • Si y > x, entonces iff w >= y.

La suma se deja como ejercicio.

recursivo
fuente
8

Retina 0.8.2 , 64 bytes

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

1+
$.&

Pruébalo en línea! El enlace incluye un conjunto de pruebas. Explicación:

\d+
$*

Convierte a unario.

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

Eliminar los separadores entre los números atraídos. (?<=(1+))establece \1el número antes del separador. Después del separador, hay dos casos:

  • El número después del separador es mayor que los dos números anteriores al separador.
  • El número antes del separador es mayor que ambos números después del separador.

En estos casos, hay una atracción entre los dos números y al eliminar el separador, los números colisionan y se suman.

1+
$.&

Convierte a decimal.

Neil
fuente
6

Jalea , 23 bytes

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

Pruébalo en línea!

Un enlace monádico que toma una lista de enteros como argumento y devuelve una lista de enteros.

Explicación

Ø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

Alguna inspiración tomada de la respuesta Stax de @ recursive .

Nick Kennedy
fuente
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;}

Pruébalo en línea!

Toma una matriz de enteros con terminación cero.

Explicación

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
fuente
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

Pruébalo en línea!

Erik el Outgolfer
fuente
3

J , 45 bytes

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

Pruébalo en línea!

Inspirado por la respuesta Stax original de recursive

Jonás
fuente
3

R , 222 196 173 bytes

Aquí hay una solución con ayuda de 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]

Pruébalo en línea!

Un breve conjunto de comentarios

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
fuente
1
-4 bytes con en sign(e)lugar de(e>0)-(e<0)
Robin Ryder
1
También {}en el bucle for son innecesarios ya que solo hay una instrucción en el bucle.
Robin Ryder
1
189 bytes con los 2 comentarios anteriores + moviendo la definición de y.
Robin Ryder
1
179 bytes usando el hecho de que mes un booleano
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]))+']')

Esto utiliza el hecho de que la dirección de la flecha en realidad no importa, y que la presencia de una flecha entre un [i] y un [i + 1] puede determinarse observando el rango de cuatro elementos a [i- 1: i + 3].

Editar: Gracias a Jo King por la aclaración de la regla.

rikhavshah
fuente
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}{

Pruébalo en línea!

Xcali
fuente
2

K (ngn / k) , 46 bytes

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

Pruébalo en línea!

0,x,0 rodear el argumento con 0s

3' trillizos de artículos consecutivos

{ }' para cada hacer

x 2 0obtener el último y el primer triplete actual - x[2]y x[0]. son vecinos de x[1], en los que se centra el triplete

x<\: compare usando menos que contra cada uno de los tresillos actuales

+/suma. el resultado es un par correspondiente a x[2]yx[0]

2=compruebe si cualquiera de los vecinos es mayor que los otros 2 elementos x, devuelva un par de booleanos 0 o 1

-/restarlos. un resultado de -1 significa x[1]atraído a la izquierda, 1 a la derecha y 0 significa que permanece en su lugar

(!#x)+ agregue 0 al primer elemento, 1 al segundo, etc. esto calcula los índices hacia los cuales los elementos son atraídos

{x x}/índice consigo mismo hasta la convergencia. el resultado son los índices efectivos a los que cada elemento se ve atraído

x@.=grupo x(el argumento original) por aquellos. el resultado es una lista de listas

+/' suma cada

ngn
fuente
2

Clojure , 299252 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)))))

Pruébalo en línea!


Explicación:

(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
fuente