数字間の重力


52

重力は、質量を持つ任意の2つのオブジェクトを引き付ける力です。この課題では、オブジェクトが数字になり、その質量が値になります。そうするために、力の強さではなく、その方向を気にします。

この数字のセットを想像してください

[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?
マジックタコ


14
1は数字6を引き付けるのに十分な大きさ ではありません。これは私の物理学者を悩ませます。(他のルールも同様ですが、これは問題の定義を変更せずに文言を変更することで修正できるかもしれません)。2つのボディ間の引力G*M*m / r^2は、両方のボディで等しくなります。軽い方の方が重い方よりも動きますが、それは引力がないからではなく、運動量のためです。「1は6を動かすのに十分な大きさではない」と言うかもしれません。
ピーターコーデス

4
しかし実際には、「誘引力」は「力を生み出す」というよりも「引き寄せられる」と定義しています。これは、「それぞれが隣接する数に引力をつくる」という文と矛盾します。そのため、「それぞれがそれ自体と隣接する数字との間に力を生み出す。ある条件下では、これによって別の数字が数字に引き寄せられる(移動する)」という言い回しをやり直すかもしれません。これは単なる用語のつまらないものであり、この重力のモデルは実際の物理学に漠然と似ているだけですが、このコメントを書きたいと思うほど気になりました。
ピーターコーデス

回答:


15

JavaScriptの(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]
エリック・ザ・アウトゴルファー

@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

Retina 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します。セパレータの後に、次の2つのケースがあります。

  • 区切り記号の後の数字が区切り記号の前の両方の数字より大きい
  • 区切り記号の前の数字が区切り記号の後の両方の数字より大きい

これらの場合、2つの数値の間に引力があり、区切り文字を削除すると数値が衝突し、それらが加算されます。

1+
$.&

10進数に変換します。


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

オンラインでお試しください!

ゼロで終わる整数の配列を受け取ります。

説明

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

R222の 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
また、{}ループ内には命令が1つしかないため、forループ内も不要です。
ロビンライダー

1
上記の2つのコメントを含む189バイト +の定義を移動しますy
ロビンライダー

1
mブールであるという事実を使用して179バイト
ロビンライダー

3

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

これは、矢印の方向は実際には重要ではなく、a [i]とa [i + 1]の間の矢印の存在は、4つの要素a [i- 1:i + 3]。

編集:ルールの明確化のためにジョーキングに感謝



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=いずれかのネイバーがからの他の2つの要素よりも大きいかどうかをチェックしx、0または1のブール値のペアを返します

-/それらを引きます。結果が-1の場合はx[1]左に、1の場合は右に、0の場合は所定の位置にとどまることを意味します

(!#x)+ 最初のアイテムに0、2番目に1などを追加します。これにより、アイテムが引き付けられるインデックスが計算されます

{x x}/収束するまでそれ自体でインデックスを作成します。結果は、各アイテムが最終的に引き付けられる有効なインデックスです

x@.=xそれらによるグループ(元の引数)。結果はリストのリストです

+/' それぞれを合計する


2

Clojure299 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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.