숫자 사이의 중력


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
단일 정수로 축소되는 테스트 사례를 추가하도록 제안하십시오.
얽히고 설킨

2
[1 3 5 4 2]= 15?
매직 문어 Urn

@MagicOctopusUrn 예
Luis felipe De jesus Munoz

14
1은 숫자 6을 끌어 들이기에 충분하지 않습니다. 이 표현은 물리학자를 귀찮게합니다. (다른 규칙도 마찬가지이지만, 문제 정의를 변경하지 않고 문구를 변경하면이 규칙을 고칠 수 있습니다). 두 몸체 사이의 인력은 두 몸체에서 G*M*m / r^2동일합니다. 무게가 가벼울수록 운동량이 적기 때문에 무게가 가벼울수록 무게가 가벼워집니다. 아마도 "1은 6을 옮길만큼 크지 않다"고 말할 수 있습니다.
Peter Cordes

4
하지만 실제로 당신은 이전 문장 "과 충돌하는"힘을 생성합니다 "보다는"으로 뽑아 "로"유치 "정의하고 이 인접한 숫자의에 그들 각각의 흡인력을 생성합니다 ." "각각의 숫자는 자신과 인접한 숫자 사이에 힘을 생성합니다. 어떤 조건에서는 다른 숫자가 숫자쪽으로 끌어 당겨질 수 있습니다." 나는 이것이 용어 nitpick이라는 것을 알고 있으며,이 중력 모델은 실제 물리학과 모호하게 유사하지만이 의견을 쓰고 싶을 정도로 귀찮았습니다.
Peter Cordes

답변:


15

자바 스크립트 (ES6)  106 104  100 바이트

@Shaggy 덕분에 2 바이트 절약

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]됩니다.
Outgolfer Erik

@EriktheOutgolfer 나는 오해의 소지가 있다고 생각했던 부분을 표현했습니다. 더 낫습니까?
Arnauld

2
이제는 "가장 높은 이전 값"대신 "첫 번째 유인 자"에 대해 언급 했으므로 의미하는 바를 이해할 수 있습니다.
Outgolfer Erik

9

Stax , 27 25 23 18 바이트

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

실행 및 디버깅

출력은 개행으로 구분됩니다.

이 프로그램은 어레이의 인접한 쌍에서 작동하며이 절차를 사용하여 두 쌍 사이에 분할이 있는지 여부를 결정합니다.

임의의 입력을 고려하십시오 [... w x y z ...]. x와 사이에 분할이 있는지 확인하는 방법은 다음과 같습니다 y.

  • 그렇다면 x == y, 그렇습니다.
  • 인 경우 x > yiff z >= x.
  • 인 경우 y > xiff 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의 Stax answer 에서 영감을 얻었습니다 .


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

온라인으로 사용해보십시오!

0으로 끝나는 정수 배열을 취합니다.

설명

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 바이트

다음은 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]

온라인으로 사용해보십시오!

간단한 의견 모음

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
sign(e)대신 -4 바이트(e>0)-(e<0)
Robin Ryder

1
또한 {}루프에는 하나의 명령어 만 있기 때문에 for 루프는 불필요합니다.
로빈 라이더

1
위의 2 개의 주석이있는 189 바이트 +의 정의 이동 y.
로빈 라이더

1
m부울 이라는 사실을 사용하는 179 바이트
Robin Ryder

3

파이썬, 114112 바이트

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

이것은 화살표의 방향이 실제로 중요하지 않다는 사실과 a [i]와 a [i + 1] 사이의 화살표의 존재는 네 가지 요소 a [i- 1 : i + 3].

편집 : 규칙 설명을 해준 Jo King에게 감사합니다.



2

K (ngn / k) , 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=이웃이에서 다른 두 요소보다 큰지 확인하고 x0 또는 1 부울 쌍을 반환합니다.

-/빼기. -1의 결과는 x[1]왼쪽으로, 1은 오른쪽으로 끌리고 0은 결과가 그대로 유지됨을 의미합니다.

(!#x)+ 첫 번째 항목에 0을 추가하고 두 번째 항목에 1을 더합니다. 그러면 항목이 끌리는 인덱스가 계산됩니다.

{x x}/수렴까지 자체 색인. 결과는 각 항목이 궁극적으로 유인되는 유효 지수입니다

x@.=x그것들에 의해 그룹 (원래의 논쟁). 결과는 목록의 목록입니다

+/' 각각을 합하다


2

클로저 , 299252 바이트

(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


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.