Forza gravitazionale tra i numeri


52

La forza gravitazionale è una forza che attira due oggetti con massa. In questa sfida i nostri oggetti saranno i Numeri e la loro massa sarà il loro valore. Per fare ciò, non ci importa della forza della forza ma della sua direzione.

Immagina questo insieme di numeri

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

Ognuno di essi crea una forza tra sé e i suoi numeri adiacenti. In alcune condizioni, ciò provocherà l'attrazione (spostamento) di un altro numero verso un numero. Quando il numero è maggiore di quello adiacente, lo attrae. Diamo un'occhiata al nostro esempio precedente:

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

Il numero 1non è abbastanza grande da spostarsi 6, ma il numero 6è, ecc ... Fondamentalmente, i numeri vengono spostati nel numero adiacente più grande (anche più grande del numero stesso). Se entrambi i numeri adiacenti sono uguali, allora non è attratto. Succede anche quando il numero e quello adiacente sono uguali.

Questo serve solo a mostrare l'attrazione, ma cosa succede dopo? I numeri che si scontrano a causa dell'attrazione sono riassunti:

[20 32 28]

Quindi sostanzialmente la sfida è, dato un insieme di numeri, produrre il risultato dell'insieme di numeri attratto.


Esempio 1

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

Esempio 2

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

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

Esempio 4

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

Esempio 5

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

Esempio 6

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

Esempio 7

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

Appunti

  • L'attrazione avviene solo una volta
  • I numeri non sono attratti da numeri non adiacenti
  • L'insieme di numeri conterrà solo numeri interi positivi

1
Suggerisci di aggiungere un caso di test che si comprime in un unico numero intero.
Shaggy,

2
[1 3 5 4 2]= 15?
Magic Octopus Urn

@MagicOctopusUrn Sì
Luis felipe De jesus Munoz

14
1 non è abbastanza grande per attirare il numero 6 Questa formulazione disturba il fisico in me. (Bene, anche alcune delle altre regole, ma questa potrebbe essere risolvibile cambiando il testo senza cambiare la definizione del problema). La forza di attrazione tra due corpi G*M*m / r^2è uguale per entrambi i corpi. Quello più leggero si muove più di quello più pesante a causa della quantità di moto, non a causa della mancanza di attrazione. Forse dire "1 non è abbastanza grande per spostare 6".
Peter Cordes,

4
Ma in realtà stai definendo "attrarre" come "tirato verso", piuttosto che "crea una forza", che è in conflitto con la frase precedente " Ognuno di loro crea una forza di attrazione per i suoi numeri adiacenti ". Quindi forse rielaborare quell'apertura per dire "ognuno di essi crea una forza tra se stesso e i suoi numeri adiacenti. In alcune condizioni, questo farà sì che un altro numero venga attratto (spostato) verso un numero". So che questo è solo un pignolo terminologico, e questo modello di gravitazione è solo vagamente simile alla fisica reale, ma mi ha infastidito abbastanza da voler scrivere questo commento.
Peter Cordes,

Risposte:


15

JavaScript (ES6),  106 104  100 byte

Salvato 2 byte grazie 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))

Provalo online!

Commentate

Aggiorniamo innanzitutto l'array di input originale a[]ripetendo una copia di esso. Durante questo passaggio, tutti i valori "attratti" da altri sono impostati su .0

Poiché l'array viene analizzato da sinistra a destra, possiamo semplicemente aggiungere a a ogni volta che un valore viene attratto dal suo vicino destro.aiai+1

Esempio: viene trasformato in e quindi .456[0,9,6][0,0,15]

Ma quando diversi valori di una riga sono attratti dal loro vicino sinistro, dobbiamo aggiungere al primo attrattore di questa sequenza (con ) anziché semplicemente .aiakk<iai1

Esempio: viene trasformato in e quindi .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()

Quindi filtriamo tutte le voci pari a .0

a.filter(n => n)

Dalla tua spiegazione, sembra che il tuo codice fallirebbe [1,3,5,3,1,2,1]e sarebbe output [14,2], ma in realtà funziona correttamente e output [13,3].
Erik the Outgolfer,

@EriktheOutgolfer Ho riformulato la parte che - penso - era fuorviante. Va meglio?
Arnauld

2
Ora menziona il "primo attrattore" anziché solo il "valore precedente più alto", quindi posso capire cosa intendi.
Erik the Outgolfer,

9

Stax , 27 25 23 18 byte

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

Esegui ed esegui il debug

L'output è separato da newline.

Questo programma opera su coppie adiacenti nell'array e determina se si debba dividere tra loro usando questa procedura.

Considera alcuni input arbitrari [... w x y z ...]. Ecco come determinare se ci dovrebbe essere una divisione tra xe y.

  • Se x == ysì, allora sì.
  • If x > y, then iff z >= x.
  • If y > x, then iff w >= y.

La somma è lasciata come un esercizio.


8

Retina 0.8.2 , 64 byte

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

1+
$.&

Provalo online! Il link include la suite di test. Spiegazione:

\d+
$*

Converti in unario.

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

Rimuovi i separatori tra i numeri attratti. (?<=(1+))imposta \1il numero prima del separatore. Dopo il separatore, ci sono quindi due casi:

  • Il numero dopo il separatore è maggiore di entrambi i numeri prima del separatore
  • Il numero prima del separatore è maggiore di entrambi i numeri dopo il separatore

In questi casi c'è un'attrazione tra i due numeri e l'eliminazione del separatore provoca la collisione dei numeri, sommandoli insieme.

1+
$.&

Converti in decimale.


6

Gelatina , 23 byte

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

Provalo online!

Un collegamento monadico che accetta un elenco di numeri interi come argomento e restituisce un elenco di numeri interi.

Spiegazione

Ø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

Qualche ispirazione presa dalla risposta Stax di @ recursive .


4

C (gcc) , 111 byte

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

Provalo online!

Accetta un array di numeri interi con terminazione zero.

Spiegazione

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

J , 45 byte

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

Provalo online!

Ispirato dalla risposta Stax originale ricorsiva


3

R , 222 196 173 byte

Ecco una soluzione con l'aiuto di 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]

Provalo online!

Una breve serie di commenti

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 byte con sign(e)invece di(e>0)-(e<0)
Robin Ryder

1
anche il {}ciclo in-for non è necessario poiché nel loop è presente solo un'istruzione.
Robin Ryder,

1
189 byte con i 2 commenti sopra + spostando la definizione di y.
Robin Ryder,

1
179 byte usando il fatto che mè un valore booleano
Robin Ryder

3

Python, 114 112 byte

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

Questo utilizza il fatto che la direzione della freccia in realtà non ha importanza e che la presenza di una freccia tra un [i] e un [i + 1] può essere determinata osservando l'intervallo di quattro elementi a [i- 1: i + 3].

Modifica: grazie a Jo King per il chiarimento delle regole


2

Perl 5 , 156 147 byte

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

Provalo online!


2

K (ngn / k) , 46 byte

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

Provalo online!

0,x,0 circonda l'argomento con 0s

3' terzine di elementi consecutivi

{ }' per ogni do

x 2 0ottenere l'ultimo e il primo della tripletta attuale - x[2]e x[0]. sono i vicini di x[1], su cui è centrata la tripletta

x<\: confrontare usando meno di rispetto a ciascuna della tripletta corrente

+/somma. il risultato è una coppia corrispondente a x[2]ex[0]

2=controlla se uno dei due vicini è maggiore degli altri 2 elementi da x, restituisce una coppia di booleani 0 o 1

-/sottrarli. un risultato di -1 significa che x[1]è attratto a sinistra, 1 a destra e 0 indica che rimane in posizione

(!#x)+ aggiungi 0 al primo oggetto, 1 al secondo, ecc. questo calcola gli indici verso i quali gli oggetti sono attratti

{x x}/indice con se stesso fino alla convergenza. il risultato sono gli indici effettivi verso i quali ogni elemento è in definitiva attratto

x@.=gruppo x(l'argomento originale) di quelli. il risultato è un elenco di elenchi

+/' sommare ciascuno


2

Clojure , 299 252 byte

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

Provalo online!


Spiegazione:

(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


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.