Gaya Gravitasi Antar Bilangan


52

Gaya gravitasi adalah gaya yang menarik dua benda dengan massa. Dalam tantangan ini objek kita akan menjadi Bilangan dan massa mereka akan menjadi nilainya. Untuk melakukannya, kita tidak peduli tentang kekuatan gaya tetapi arahnya.

Bayangkan serangkaian angka ini

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

Masing-masing dari mereka menciptakan kekuatan antara dirinya dan angka-angka yang berdekatan. Dalam beberapa kondisi, ini akan menyebabkan nomor lain tertarik (dipindahkan) ke suatu nomor. Ketika jumlahnya lebih besar dari yang berdekatan, itu menariknya. Mari kita lihat contoh kita sebelumnya:

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

Jumlahnya 1tidak cukup besar untuk bergerak 6, tetapi jumlahnya 6, dll ... Pada dasarnya, nomor dipindahkan ke nomor terdekat terbesar (juga lebih besar dari angka itu sendiri). Jika kedua angka yang berdekatan sama maka tidak tertarik. Ini juga terjadi ketika jumlah dan berdekatannya sama.

Ini hanya untuk menunjukkan daya tarik, tetapi apa yang terjadi setelahnya? Jumlah yang bertabrakan karena tarik-menarik dirangkum:

[20 32 28]

Jadi pada dasarnya tantangannya adalah, Mengingat satu set angka, output hasil dari set angka yang menarik.


Contoh 1

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

Contoh 2

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

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

Contoh 4

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

Contoh 5

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

Contoh 6

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

Contoh 7

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

Catatan

  • Ketertarikan hanya terjadi sekali
  • Angka tidak tertarik ke Angka yang tidak berdekatan
  • Himpunan angka hanya akan berisi bilangan bulat positif

1
Sarankan menambahkan test case yang runtuh ke satu integer.
Shaggy

2
[1 3 5 4 2]= 15?
Magic Gurita Guci

@MagicOctopusUrn Ya
Luis felipe De jesus Munoz

14
1 tidak cukup besar untuk menarik nomor 6. Kata-kata ini mengganggu fisikawan dalam diri saya. (Ya, begitu juga beberapa aturan lainnya, tetapi yang ini mungkin bisa diperbaiki dengan mengubah kata-kata tanpa mengubah definisi masalah). Gaya tarik-menarik antara dua benda,, G*M*m / r^2sama untuk kedua benda. Yang lebih ringan bergerak lebih dari yang lebih berat karena momentum, bukan karena kurangnya daya tarik. Mungkin mengatakan "1 tidak cukup besar untuk bergerak 6".
Peter Cordes

4
Tapi sebenarnya Anda mendefinisikan "menarik" sebagai "menarik ke arah", daripada "menciptakan kekuatan", yang bertentangan dengan kalimat sebelumnya " Masing-masing dari mereka menciptakan kekuatan tarik-menarik ke nomor yang berdekatan ". Jadi mungkin ulang celah itu untuk mengatakan "masing-masing dari mereka menciptakan kekuatan antara itu sendiri dan nomor yang berdekatan. Dalam beberapa kondisi, ini akan menyebabkan nomor lain tertarik (dipindahkan) ke suatu angka." Saya tahu ini hanyalah terminologi nitpick, dan model gravitasi ini hanya sedikit mirip dengan fisika nyata, tetapi cukup mengganggu saya untuk ingin menulis komentar ini.
Peter Cordes

Jawaban:


15

JavaScript (ES6),  106 104  100 byte

Disimpan 2 byte berkat @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))

Cobalah online!

Berkomentar

Kami pertama-tama memperbarui array input asli a[]dengan mengulanginya pada salinannya. Selama langkah ini, semua nilai 'tertarik' oleh yang lain diatur ke .0

Karena array diuraikan dari kiri ke kanan, kita bisa menambahkan ke setiap kali nilai tertarik oleh tetangga kanannya.aiai+1

Contoh: diubah menjadi dan kemudian .456[0,9,6][0,0,15]

Tetapi ketika beberapa nilai berturut-turut tertarik oleh tetangga kiri mereka, kita perlu menambahkan ke penarik pertama dari urutan ini (dengan ) daripada hanya .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)

Dari penjelasan Anda, sepertinya kode Anda akan gagal untuk [1,3,5,3,1,2,1]dan keluaran [14,2], tetapi sebenarnya berfungsi dengan benar dan keluaran [13,3].
Erik the Outgolfer

@EriktheOutgolfer Saya telah mengulangi bagian yang - saya pikir - menyesatkan. Apakah itu lebih baik?
Arnauld

2
Sekarang disebutkan "penarik pertama", bukan hanya "nilai sebelumnya tertinggi", jadi saya bisa mengerti apa yang Anda maksud.
Erik the Outgolfer

9

Stax , 27 25 23 18 byte

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

Jalankan dan debug itu

Output dipisahkan oleh baris baru.

Program ini beroperasi pada pasangan yang berdekatan dalam array, dan menentukan apakah harus ada pemisahan di antara mereka menggunakan prosedur ini.

Pertimbangkan beberapa input sewenang-wenang [... w x y z ...]. Berikut adalah cara menentukan apakah harus ada pemisahan antara xdan y.

  • Jika x == yya.
  • Jika x > y, maka iff z >= x.
  • Jika y > x, maka iff w >= y.

Penjumlahan dibiarkan sebagai latihan.


8

Retina 0.8.2 , 64 byte

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

1+
$.&

Cobalah online! Tautan termasuk test suite. Penjelasan:

\d+
$*

Konversikan ke unary.

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

Hapus pemisah antara nomor yang ditarik. (?<=(1+))mengatur \1ke nomor sebelum pemisah. Setelah pemisah, maka ada dua kasus:

  • Angka setelah pemisah lebih besar dari kedua angka sebelum pemisah
  • Angka sebelum pemisah lebih besar dari kedua angka setelah pemisah

Dalam kasus ini ada ketertarikan antara dua angka dan menghapus pemisah menyebabkan angka bertabrakan, menambahkannya bersama-sama.

1+
$.&

Konversikan ke desimal.


6

Jelly , 23 byte

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

Cobalah online!

Tautan monadik yang menggunakan daftar bilangan bulat sebagai argumennya dan mengembalikan daftar bilangan bulat.

Penjelasan

Ø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

Beberapa inspirasi diambil dari jawaban Stax @ 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;}

Cobalah online!

Mengambil array bilangan nol yang diakhiri.

Penjelasan

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 byte

Ini adalah solusi dengan bantuan dari 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]

Cobalah online!

Satu set komentar pendek

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 dengan sign(e)bukannya(e>0)-(e<0)
Robin Ryder

1
juga {}di dalam for loop tidak perlu karena hanya ada satu instruksi di loop.
Robin Ryder

1
189 byte dengan 2 komentar di atas + memindahkan definisi y.
Robin Ryder

1
179 byte menggunakan fakta bahwa itu madalah boolean
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]))+']')

Ini menggunakan fakta bahwa arah panah sebenarnya tidak penting, dan bahwa keberadaan panah antara [i] dan [i + 1] dapat ditentukan dengan melihat kisaran empat elemen a [i- 1: i + 3].

Sunting: Terima kasih kepada Jo King untuk klarifikasi aturan


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

Cobalah online!


2

K (ngn / k) , 46 byte

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

Cobalah online!

0,x,0 mengelilingi argumen dengan 0s

3' kembar tiga item berturut-turut

{ }' untuk setiap lakukan

x 2 0dapatkan yang terakhir dan pertama dari triplet saat ini - x[2]dan x[0]. mereka adalah tetangga x[1], tempat si kembar tiga berpusat

x<\: bandingkan dengan menggunakan kurang dari masing-masing triplet saat ini

+/jumlah. hasilnya adalah pasangan yang sesuai dengan x[2]danx[0]

2=periksa apakah tetangga lebih besar dari 2 elemen lainnya x, kembalikan sepasang boolean 0-atau-1

-/kurangi mereka. hasil -1 berarti x[1]tertarik ke kiri, 1 ke kanan, dan 0 berarti tetap di tempatnya

(!#x)+ tambahkan 0 ke item pertama, 1 ke item kedua, dll. ini menghitung indeks ke arah mana item tertarik

{x x}/indeks dengan sendirinya sampai konvergensi. hasilnya adalah indeks efektif di mana setiap item akhirnya tertarik

x@.=kelompok x(argumen asli) oleh mereka. hasilnya adalah daftar daftar

+/' jumlah masing-masing


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

Cobalah online!


Penjelasan:

(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


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.