数字之间的引力


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?
魔术章鱼缸

@MagicOctopusUrn是的
Luis

14
1不足以吸引数字6 这个措辞困扰着我的物理学家。(其他一些规则也是如此,但是可以通过更改措辞而不更改问题定义来解决此问题)。两个物体之间的吸引力G*M*m / r^2对于两个物体是相等的。较轻的人比重的人运动多是因为有动力,而不是因为缺乏吸引力。也许说“ 1不足以移动6”。
彼得·科德斯

4
但是实际上,您是在将“吸引力”定义为“向”拉动,而不是“产生力量”,这与前面的句子“ 它们各自对相邻数字产生吸引力 ”相抵触。因此,也许可以改写开场白,说“它们中的每一个都会在自身与相邻数字之间产生作用力。在某些情况下,这将导致另一个数字被吸引(移动)到一个数字上”。我知道这只是一个术语“ nitpick”,这种引力模型在某种程度上仅与真实物理学相似,但它足以打扰我,我想写这篇评论。
彼得·科德斯

Answers:


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我改写了我认为会引起误解的部分。那个更好吗?
Arnauld

2
现在,它的确提到了“第一个吸引子”,而不仅仅是“最高的先前价值”,因此我可以理解您的意思。
暴民埃里克

9

Stax27 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的Stax答案的一些启发。


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

Python 2,162字节

l=input()
a=[(L<R>C)-(R<L>C)for L,C,R in zip([0]+l,l,l[1:]+[0])]
while any(a):
 i=0
 while a[i]==0:i+=1
 m=a.pop(i);x,y=[i,i+m][::m];l[x:y+1]=l[i]+l[i+m],
print l

在线尝试!



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
-4个字节,sign(e)而不是(e>0)-(e<0)
Robin Ryder

1
也是{}在for循环是不必要的,因为仅存在一个在循环指令。
罗宾·赖德

1
带有上述2条注释的189个字节 +移动的定义y
罗宾·赖德

1
179个字节,使用的m是布尔值
Robin Ryder

3

Python,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- 1:i + 3]。

编辑:感谢Jo King澄清规则


2

Perl 5中156个 147字节

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

在线尝试!


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添加到第一个项目,将1添加到第二个,依此类推。这将计算吸引项目的索引

{x x}/索引自身直到收敛。结果是最终吸引每个项目的有效指标

x@.=x按那些分组(原始参数)。结果是列表列表

+/' 每个加起来


2

Clojure299252字节

(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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.