Force gravitationnelle entre les nombres


52

La force de gravitation est une force qui attire deux objets quelconques avec une masse. Dans ce défi, nos objets seront des nombres et leur masse sera leur valeur. Pour ce faire, nous ne nous soucions pas de la force de la force mais de sa direction.

Imaginez cet ensemble de chiffres

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

Chacun d'eux crée une force entre lui-même et ses nombres adjacents. Dans certaines conditions, cela entraînera un autre nombre attiré (déplacé) vers un nombre. Quand le nombre est plus grand que le nombre adjacent, il l'attire. Jetons un coup d'oeil à notre exemple précédent:

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

Le nombre 1n’est pas assez grand pour être déplacé 6, mais le nombre 6est, etc. En gros, les nombres sont déplacés vers le plus grand nombre adjacent (également plus grand que le nombre lui-même). Si les deux nombres adjacents sont égaux, il n'est pas attiré alors. Cela se produit également lorsque le nombre et le nombre adjacent sont égaux.

Ce n'est que pour montrer l'attraction, mais que se passe-t-il après? Les nombres qui entrent en collision par attraction sont résumés:

[20 32 28]

En gros, le défi consiste à, à partir d’un ensemble de chiffres, produire le résultat de l’ensemble de nombres attiré.


Exemple 1

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

Exemple 2

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

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

Exemple 4

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

Exemple 5

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

Exemple 6

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

Exemple 7

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

Remarques

  • L'attraction ne se produit qu'une fois
  • Les nombres ne sont pas attirés par des nombres non adjacents
  • L'ensemble des nombres ne contiendra que des entiers positifs

1
Suggérez l'ajout d'un scénario de test qui se réduit à un seul entier.
Shaggy

2
[1 3 5 4 2]= 15?
Urne magique Octopus

@MagicOctopusUrn Oui
Luis Felipe De Jesus Munoz

14
1 n'est pas assez gros pour attirer le chiffre 6 Cette formulation dérange le physicien en moi. (Eh bien, certaines autres règles le sont aussi, mais celle-ci pourrait être corrigée en modifiant le libellé sans modifier la définition du problème). La force d'attraction entre deux corps G*M*m / r^2, est égale pour les deux corps. Le plus léger bouge plus que le plus lourd à cause de son élan, pas à cause d'un manque d'attraction. Peut-être dire "1 n'est pas assez grand pour déplacer 6".
Peter Cordes

4
Mais en réalité, vous définissez "attirer" comme "tiré vers", plutôt que "crée une force", ce qui est en contradiction avec la phrase précédente " Chacun d'eux crée une force d'attraction sur ses nombres adjacents ". Alors retravaillez peut-être cette ouverture en disant "chacune d’elles crée une force entre elle-même et ses nombres adjacents. Dans certaines conditions, cela entraînera l’attironnement (le déplacement) d’un autre nombre vers un nombre". Je sais que ce n’est qu’un nitpick de terminologie, et ce modèle de gravitation n’est que vaguement similaire à la physique réelle, mais cela m’ennuyait assez de vouloir écrire ce commentaire.
Peter Cordes

Réponses:


15

JavaScript (ES6),  106 104  100 octets

2 octets sauvés grâce à @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))

Essayez-le en ligne!

Commenté

a[]0

aiai+1

456[0,9,6][0,0,15]

aiakk<iai1

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

0

a.filter(n => n)

D'après votre explication, il semblerait que votre code échoue pour la [1,3,5,3,1,2,1]sortie [14,2], mais il fonctionne correctement et affiche en sortie [13,3].
Erik l'Outgolfer

@EriktheOutgolfer J'ai reformulé la partie qui, je pense, était trompeuse. Est-ce mieux?
Arnauld

2
Maintenant, il mentionne le "premier attracteur" au lieu de la "valeur précédente la plus élevée", afin que je puisse comprendre ce que vous voulez dire.
Erik l'Outgolfer

9

Stax , 27 25 23 18 octets

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

Exécuter et déboguer

La sortie est séparée par des nouvelles lignes.

Ce programme fonctionne sur des paires adjacentes dans la matrice et détermine s'il doit y avoir une séparation entre elles en utilisant cette procédure.

Considérons une entrée arbitraire [... w x y z ...]. Voici comment déterminer s’il devrait y avoir une séparation entre xet y.

  • Si x == y, alors oui.
  • Si x > y, alors si et si z >= x.
  • Si y > x, alors si et si w >= y.

La sommation est laissée comme un exercice.


8

Retina 0.8.2 , 64 octets

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

1+
$.&

Essayez-le en ligne! Le lien inclut la suite de tests. Explication:

\d+
$*

Convertir en unaire.

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

Supprimez les séparateurs entre les numéros attirés. (?<=(1+))définit \1le nombre avant le séparateur. Après le séparateur, il y a alors deux cas:

  • Le nombre après le séparateur est supérieur aux deux chiffres avant le séparateur
  • Le nombre avant le séparateur est supérieur aux deux nombres après le séparateur

Dans ces cas, il y a une attraction entre les deux nombres et la suppression du séparateur provoque la collision des nombres, en les additionnant.

1+
$.&

Convertir en décimal.


6

Gelée , 23 octets

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

Essayez-le en ligne!

Un lien monadique qui prend comme argument une liste d'entiers et renvoie une liste d'entiers.

Explication

Ø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

Quelques inspirations tirées de la réponse Stax de @ récursive .


4

C (gcc) , 111 octets

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;}

Essayez-le en ligne!

Prend un tableau d'entiers à zéro terminal.

Explication

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
}



3

R , 222 196 173 octets

Voici une solution avec l'aide 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]

Essayez-le en ligne!

Une courte série de commentaires

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

1
-4 octets avec sign(e)au lieu de(e>0)-(e<0)
Robin Ryder

1
de plus, la {}boucle for n'est pas nécessaire puisqu'il n'y a qu'une instruction dans la boucle.
Robin Ryder

1
189 octets avec les 2 commentaires ci-dessus + déplacement de la définition de y.
Robin Ryder

1
179 octets utilisant le fait qu’il ms’agit d’un booléen
Robin Ryder

3

Python, 114 112 octets

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]))+']')

Ceci utilise le fait que la direction de la flèche n'a pas vraiment d'importance, et que la présence d'une flèche entre un [i] et un [i + 1] peut être déterminée en regardant la plage de quatre éléments a [i- 1: i + 3].

Edit: Merci à Jo King pour la clarification de la règle


2

Perl 5 , 156 147 octets

$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}{

Essayez-le en ligne!


2

K (ngn / k) , 46 octets

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

Essayez-le en ligne!

0,x,0 entourer la dispute avec des 0

3' triplets d'objets consécutifs

{ }' pour chaque faire

x 2 0obtenir le dernier et le premier du triplet actuel - x[2]et x[0]. ils sont les voisins de x[1], sur lesquels le triplet est centré

x<\: comparer en utilisant moins que contre chacun des triplets actuels

+/somme. le résultat est une paire correspondant à x[2]etx[0]

2=vérifie si l'un des voisins est supérieur aux 2 autres éléments de x, retourne une paire de booléens 0 ou 1

-/soustrayez-les. un résultat de -1 signifie que x[1]c'est attiré à gauche, 1 à droite et 0 signifie qu'il reste en place

(!#x)+ ajoute 0 au premier élément, 1 au second, etc. Ceci calcule les indices vers lesquels les éléments sont attirés

{x x}/index avec lui-même jusqu'à la convergence. le résultat est l'indice effectif auquel chaque élément est finalement attiré

x@.=groupe x(l'argument initial) par ceux. le résultat est une liste de listes

+/' somme chaque


2

Clojure , 299 252 octets

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

Essayez-le en ligne!


Explication:

(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


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.