Гравітаційна сила між числами


52

Гравітаційна сила - це сила, яка притягує будь-які два об’єкти масою. У цьому виклику нашими об'єктами будуть Числа, а їхня маса стане їхньою цінністю. Для цього нас не хвилює сила сили, а напрямок її.

Уявіть цей набір чисел

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

Кількість 1не є достатньо великою для переміщення 6, але число 6є і т.д. ... В основному, числа переміщуються до найбільшого суміжного числа (також більшого, ніж саме число). Якщо обидва сусідніх чисел рівні, то це не приваблює. Так само буває, коли число та суміжні з ним рівні.

Це лише для того, щоб показати потяг, але що буде після? Числа, які стикаються через притягання, підсумовуються:

[20 32 28]

Тому в основному завдання полягає в тому, що, враховуючи набір чисел, вивести результат залученого набору чисел.


Приклад 1

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

Приклад 2

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

Приклад 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]

Приклад 4

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

Приклад 5

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

Приклад 6

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

Приклад 7

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

Примітки

  • Залучення трапляється лише один раз
  • Числа не притягуються до сусідніх Чисел
  • Набір чисел буде містити лише додатні цілі числа

1
Запропонуйте додати тестовий випадок, який згортається на одне ціле число.
Кудлатий


@MagicOctopusUrn Так
Luis felipe De jesus Munoz

14
1 не є достатньо великим, щоб залучити число 6. Це формулювання турбує фізика в мені. (Ну, так і деякі інші правила, але це може бути виправлене, змінивши формулювання, не змінюючи визначення проблеми). Сила притягання між двома тілами G*M*m / r^2,, однакова для обох тіл. Легший рухається більше, ніж важчий через імпульс, а не через відсутність тяжіння. Можливо, скажіть, що "1 недостатньо великий, щоб рухатись 6".
Пітер Кордес

4
Але насправді ви визначаєте "притягування" як "потягнуту до", а не "створює силу", яка суперечить попередньому реченню " Кожен з них створює силу притягання до своїх сусідніх чисел ". Тому, можливо, перегляньте це відкриття, щоб сказати, "кожен з них створює силу між собою і суміжними числами. За деяких умов це призведе до залучення (переміщення) іншого числа до числа". Я знаю, що це лише термінологічна нітпік, і ця модель гравітації лише невиразно схожа на реальну фізику, але це мене досить непокоїло, щоб хотіти написати цей коментар.
Пітер Кордес

Відповіді:


15

JavaScript (ES6),  106 104  100 байт

Збережено 2 байти завдяки @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))

Спробуйте в Інтернеті!

Прокоментував

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)

З вашого пояснення, це здається, що ваш код не працює [1,3,5,3,1,2,1]і виводиться [14,2], але він насправді працює правильно і виводить [13,3].
Ерік Аутгольфер

@EriktheOutgolfer Я перефразував частину, яка - я думаю - вводила в оману. Це краще?
Арнольд

2
Тепер він згадує "перший атрактор" замість просто "найвищого попереднього значення", тому я можу зрозуміти, що ви маєте на увазі.
Ерік Аутгольфер

9

Стакс , 27 25 23 18 байт

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

Запустіть і налагоджуйте його

Вихідні дані розділені новими рядками.

Ця програма працює на суміжних парах у масиві і визначає, чи повинен бути розділений між ними за допомогою цієї процедури.

Розглянемо деякі довільні дані [... w x y z ...]. Ось як визначити, чи повинен бути розрив між xі y.

  • Якщо так x == y, то так.
  • Якщо x > y, то iff z >= x.
  • Якщо y > x, то iff w >= y.

Підведення підсумків залишається як вправа.


8

Сітківка 0,8.2 , 64 байти

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

1+
$.&

Спробуйте в Інтернеті! Посилання включає тестовий набір. Пояснення:

\d+
$*

Перетворити в одинарне.

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

Видаліть роздільники між залученими номерами. (?<=(1+))встановлює \1число перед роздільником. Після поділу є два випадки:

  • Число після роздільника більше, ніж обидва числа перед роздільником
  • Число перед роздільником більше, ніж обидва числа після роздільника

У цих випадках між двома числами є притягнення, а вилучення роздільника призводить до стикання чисел, додавання їх разом.

1+
$.&

Перетворити в десятковий.


6

Желе , 23 байти

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

Спробуйте в Інтернеті!

Монадічне посилання, яке бере аргумент списку цілих чисел і повертає список цілих чисел.

Пояснення

Ø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

Деякі натхнення взяли з відповіді Стакса @ recursive .


4

C (gcc) , 111 байт

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

Спробуйте в Інтернеті!

Бере нульовий завершений масив цілих чисел.

Пояснення

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 байт

Ось рішення з деякою допомогою Робіна Райдера

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]

Спробуйте в Інтернеті!

Короткий набір коментарів

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 байти з sign(e)замість(e>0)-(e<0)
Робін Райдер

1
також {}цикл for for є непотрібним, оскільки існує лише одна інструкція.
Робін Райдер

1
189 байт із зазначеними вище коментарями + переміщення визначення y.
Робін Райдер

1
179 байт, використовуючи той факт, що mє булевим,
Робін Райдер

3

Пітон, 114 112 байт

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

Для цього використовується той факт, що напрямок стрілки насправді не має значення і що наявність стрілки між [i] та a [i + 1] можна визначити, переглянувши діапазон чотирьох елементів a [i- 1: i + 3].

Редагувати: Дякую Джо Кінгу за уточнення правила



2

К (нг / к) , 46 байт

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

Спробуйте в Інтернеті!

0,x,0 оточіть аргумент 0

3' трійки підрядних предметів

{ }' для кожного робити

x 2 0отримати останнє і перше з поточного триплета - x[2]і x[0]. вони - сусіди x[1], на яких триплет зосереджений

x<\: порівняти, використовуючи менше ніж порівняно з кожним із поточних триплетів

+/сума. в результаті виходить пара, що відповідає x[2]іx[0]

2=перевірте, чи один із сусідів більший за інші 2 елементи від x, поверніть пару булевих 0 або 1

-/відняти їх. результат -1 означає x[1]притягується зліва, 1 праворуч, а 0 означає, що він залишається на місці

(!#x)+ додайте 0 до першого пункту, 1 до другого тощо. Це обчислює показники, до яких предмети залучені

{x x}/індексувати з собою до конвергенції. Результатом є ефективні показники, до яких в кінцевому підсумку притягується кожен предмет

x@.=група x(оригінальний аргумент) тими. результат - перелік списків

+/' суму кожного


2

Clojure , 299 252 байт

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

Спробуйте в Інтернеті!


Пояснення:

(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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.