给我一个最小的魔法总和


27

保持简短的挑战。

您会得到4个数字:p1,p2,p3和p4。

数字的魔术总和定义如下:

magic_sum = |p1 - p2| + |p2 - p3| + |p3 - p4| + |p4 - p1|

仅允许更改以上整数值之一(p1,p2,p3或p4)。您需要更改该值,以使这些值的神奇总和达到最小值。

例如:

p1,p2,p3,p4 = 17,-6、15、33。在这种情况下,魔法总和的值为78。

您可以在此处将-6更改为16,魔法总和的值将变为36,这是可达到的最小值。

请记住,数字可以是正整数或负整数。

这是代码高尔夫球,因此代码胜利中最少的字节。布朗尼指出在娱乐语言上使用实用语言。愿4日与您同在。

重申:

样品1

输入1

17 -6 15 33

输出1

36

说明1

-6可以替换为16,这使我们可以达到的最小魔术总和。

样品2

输入2

10 10 10 10

输出2

0 or 2

两者都可以接受

说明2

由于4个正整数的最小和为0,因此最小可达到的魔法总和为0。如果必须更改数字,则可以将10的整数之一更改为9,从而产生输出2。

样品3

输入3

1 2 3 4

输出3

4

说明3

输入本身产生6作为其魔术总和。将4更改为1,可以达到最小魔术总和,即4。


10
+1,但可以使用更多示例。
乔纳森·艾伦

2
一个完全有效的示例和两个更多的测试用例,这是+1我的。
毛茸茸的

@蓬松的完成。我的+1在哪里?:P
Koishore Roy

1
@KoishoreRoy如果没有更改,就不会测试用例3是6?
wizzwizz4

@ wizzwizz4 | 1-2 | + | 2-3-| + | 3 -4 | + | 4-1-| = 1 + 1 + 1 + 3 = 6。你是对的。进行编辑。
Koishore Roy

Answers:



20

Python 2,44字节

a,b,c,d=sorted(input())
print min(c-a,d-b)*2

在线尝试!

a,b,c,d,按升序对输入进行排序,取较小的c-ad-b,并且加倍了。为什么这样做?

首先,请注意,当我们更改一个元素以使其最大为距离的总循环总和时,将其更改为等于某个邻居是最优的(或并列为最优),例如 17, -6, 15, 33 -> 17, 17, 15, 33。那是因为它到它的左右循环邻居的新总距离至少是这些邻居之间的距离,因此使它们相等是我们能做的最好的事情。

现在,删除一个数字的两个相邻副本之一会得到相同的距离间隔。在示例中,这是17, 15, 33给定distances 2 + 18 + 16。因此,与其替换四个数字之一,不如将其删除就剩下三个数字,并使用它们的循环距离之和。

请注意,对于3个数字,最大距离是两个较小的数字之和。这是因为如果我们对数字进行排序a ≤ b ≤ c,则|a - c| = |a - b| + |b - c|。换句话说,我们在最大号和最小号之间旅行两次,使用中等号作为进站次数之一。因此,这三个距离的总和仅为最小与最大距离之间的两倍(c-a)*2

因此,问题是我们删除哪个数字以使剩下的三个数字的最大值和最小值之间的距离最小。显然,我们删除了最小或最大的数字。a, b, c, d按排序顺序调用它们,删除aleaves d - b和delete dleaves c - a,最终结果是double,以较小者为准。


在这里为我提供一个测试用例。如果魔术总和已经是0,即可达到的最低数字,该怎么办。在这种情况下,答案应该为0吗?或下一个可能的最低数字。如果输入为[10,10,10,10],则魔术总和为0。第二低的可能是2。让我知道您的想法。
Koishore Roy

我听到您说的是,您可以忽略给定的四个数字的顺序(第一步是对它们进行排序)。但是,如果我们通过要求了五个数字又仍然只允许更改一个数字该怎么办?四位数的情况似乎太简单了(仅在看到答案后)。p1p5
杰普·斯蒂格·尼尔森

@KoishoreRoy我喜欢您允许任何一个的解决方案。
xnor

@JeppeStigNielsen是的,顺序无关紧要的事实对于4个数字来说是特殊的,它的发生是因为删除一个数字成为3个数字之后,所有数字对都循环相邻。如果有五个数字,这是行不通的(您肯定可以找到一个例子),而挑战将大不相同。
xnor

希望我能投票两次。美丽的观察,很好的解释。
约拿

9

R66 33字节

function(x)2*min(diff(sort(x),2))

在线尝试!

短得多 xnor的算法要(请阅读他们的解释并赞成他们的帖子!)。

旧版:

R,66字节

function(x,m=matrix(x,3,4))min(colSums(abs(diff(rbind(m,m[1,])))))

在线尝试!

将输入作为4个整数的向量。

p2p2p1p2p3|p1p2|+|p2p3|p2=p1

有4种方法可以选择我们要更改的号码;对于每一个,我们只需要计算3个绝对差之和。

3×4rbind


4

果冻11 10字节

I;SASƲ$-ƤṂ

在线尝试!

如果整数作为输入,则采用列表的单子链接。应该适用于任意列表大小。根据可以通过测试从列表中删除每个数字,计算魔术和取最小值来获得最小和的方式工作。


3

果冻,8 字节

ṁ-Ƥ⁸IA§Ṃ

一个接受整数列表*的单子链接,该列表产生一个整数

*可以是任何数字,只要大于1;使用相同样式的魔术公式总结邻居的差异。

在线尝试!

怎么样?

ṁ-Ƥ⁸IA§Ṃ - Link: list of integers, X       e.g. [17,-6,15,33]
 -Ƥ      - for overlapping "outfixes" of length length(X)-1:
         -                                      [[-6,15,33],[17,15,33],[17,-6,33],[17,-6,15]]
ṁ  ⁸     -   mould like X                       [[-6,15,33,-6],[17,15,33,17],[17,-6,33,17],[17,-6,15,17]]
    I    - incremental differences              [[21,18,-39],[-2,18,-16],[-23,39,-16],[-23,21,2]]
     A   - absolute (vectorises)                [[21,18,39],[2,18,16],[23,39,16],[23,21,2]]
      §  - sums                                 [78,36,78,46]
       Ṃ - minimum                              36

3

Japt -Q,11个字节

ñÍó ®r- ÑÃn

使用@xnor的算法,为我节省了4个字节。

@Shaggy节省了5个字节

试试吧


似乎工作正常,但您能解释一下为什么行吗?
Koishore Roy

@KoishoreRoy添加了解释
无知的体现

29个字节(我认为
蓬松的

@Shaggy更新我的答案时,不小心用地图替换了sum,使某些高尔夫球无效,但其他高尔夫球很好
无知的体现

不错(进一步)打高尔夫球:)您可以通过替换再节省1个字节 ÃÃ用换行符。
毛茸茸的

3

J24 20 18 17字节

使用xnor算法的替代版本:

2*[:<./2 2-/@$\:~

怎么样

从通过对输入进行整形而形成的2x2矩阵的第一行减去第二行2 *的最小值的两倍[:<./[:-/2 2$\:~

在线尝试!

原始答案:J,24个字节

[:<./1(1#.2|@-/\],{.)\.]

在线尝试!

使用尼克·肯尼迪的想法。

  • 1(...)\.] 将动词中的动词应用于所有长度为1的后缀(长度为n的后缀是一个列表,其中删除了n个连续元素,因此将生成所有可能的列表,其中删除了1个榆树)
  • (1 #. 2 |@-/\ ] , {.) 这通过将第一个榆木附加到输入来计算魔术总和 ] , {.,将绝对差值|@-/应用于长度为2的缀来2 ...\,并对结果求和1 #.
  • [:<./ 返回最小值

2

05AB1E11 7 字节

的港口 @xnor的Jelly答案
-4个字节,感谢 @Emigna @Grimy

{2ô`αß·

在线尝试。

7 字节的替代方法,仅在05AB1E的旧版本中有效(在新版本中,需要在之前添加¥):

{2ôø¥W·

在线尝试。

说明:

{        # Sort the (implicit) input-list
         #  i.e. [17,-6,15,33] → [-6,15,17,33]
 2ô      # Split this list into parts of size 2
         #  → [[-6,15],[17,33]]
   `     # Push both separated to the stack
    α    # And take their absolute differences
         #  → [23,18]
     ß   # Pop and push the minimum
         #  → 18
      ·  # Double it (and output implicitly as result)
         #  → 36

{        # Sort the (implicit) input-list
         #  i.e. [17,-6,15,33] → [-6,15,17,33]
 2ô      # Split this list into parts of size 2
         #  → [[-6,15],[17,33]]
   ø     # Zip/transpose, swapping rows/columns
         #  → [[-6,17],[15,33]]
    ¥    # Get the deltas/forward differences of the inner lists
         #  → [[23],[18]]
     W   # Get the flattened minimum (without popping)
         #  → 18
      ·  # Double it (and output implicitly as result)
         #  → 36

1
旧有7个字节:{2ôø¥W·在重写中包含8 个字节。
Emigna

2
非旧版7个字节:{2ô`αW·
肮脏的

@Emigna Smart,谢谢!
凯文·克鲁伊森

@肮脏的谢谢!
凯文·克鲁伊森

1

C ++(gcc)

完整程式:138位元组

#include<iostream>
#include<regex>
using namespace std;int main(){int a[4];for(int&b:a)cin>>b;sort(a,a+4);cout<<min(a[2]-*a,a[3]-a[1])*2;}

在线尝试!

核心功能:84字节

#include<regex>
int m(int*a){std::sort(a,a+4);return std::min(a[2]-*a,a[3]-a[1])*2;}

在线尝试!

还使用xnor算法在他的Python 2帖子中进行了解释。


0

木炭,20字节

I⌊EEθΦθ⁻κμΣEι↔⁻λ§ι⊕μ

在线尝试!链接是详细版本的代码。原来我正在使用@NickKennedy的想法。说明:

   Eθ                   Map over input array
     Φθ                 Filter over input array where
       ⁻κμ              Outer and inner indices differ
  E                     Map over resulting list of lists
           Eι           Map over remaining values in list
                §ι⊕μ    Get the next value in the list
             ↔⁻λ        Compute the absolute difference with the current value
          Σ             Take the sum of absolute differences
 ⌊                      Take the minimum sum
I                       Cast to string and implicitly print

0

JavaScript(ES6),51个字节

使用xnor更聪明的方法

a=>([a,b,c,d]=a.sort((a,b)=>a-b),b+c<a+d?c-a:d-b)*2

在线尝试!


原始答案,96个字节

将输入作为4个整数的数组。也许绝对不是最短的方法。

a=>a.map(m=x=>a.map((y,i)=>a[m=a.map(v=>s+=Math.abs(p-(p=v)),a[i]=x,p=a[3],s=0)|m<s?m:s,i]=y))|m

在线尝试!



0

Java 8 8,235字节

@xnor的Python答案和算法的端口

import java.util.*;interface M{static void main(String[]A){Scanner I=new Scanner(System.in);int a[]={0,0,0,0};for(int i=0;i<4;a[i++]=I.nextInt());java.util.Arrays.sort(a);System.out.print(2*(a[2]-a[0]>a[3]-a[1]?a[3]-a[1]:a[2]-a[0]));}}

在线尝试!

Java 10,未经验证,222字节

使用Java 10,我应该能够将Scanner声明的左侧替换为var,尽管我无法在线进行编译,因此只能将其添加为琐事。抱歉。

interface M{static void main(String[]A){var I=new java.util.Scanner(System.in);int a[]={0,0,0,0};for(int i=3;i<4;a[i++]=I.nextInt());java.util.Arrays.sort(a);System.out.print(2*(a[2]-a[0]>a[3]-a[1]?a[3]-a[1]:a[2]-a[0]));}}

1
相信您可以像提交其他答案一样,具有提交功能。无需包括周围的类,接口,等等
牛头
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.