交换符号和


24

给定一个非空的正整数,您的工作是确定的唯一值数量± x ± y ± z ± (x,y,z,)±x±y±z±

例如,考虑列表。有八种创建总和的可能方法:(1,2,2)

  • +1+2+2+5
  • +1+22+1
  • +12+2+1
  • +1223
  • 1+2+2+3
  • 1+221
  • 12+21
  • 1225

有六个唯一的和,所以答案是。6{5,5,1,1,3,3}6

测试用例

[1, 2] => 4
[1, 2, 2] => 6
[s]*n => n+1
[1, 2, 27] => 8
[1, 2, 3, 4, 5, 6, 7] => 29
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5] => 45
[1, 7, 2, 8, 3, 1, 6, 8, 10, 9] => 56
[93, 28, 92, 100, 43, 66, 2, 98, 2, 52, 57, 75, 39, 77, 45, 15, 13, 82, 81, 20, 68, 14, 5, 3, 72, 56, 57, 1, 23, 25, 76, 59, 60, 71, 71, 24, 1, 3, 72, 84, 72, 28, 83, 62, 66, 45, 21, 28, 49, 57, 70, 3, 44, 47, 1, 54, 53, 56, 36, 20, 99, 9, 89, 74, 1, 14, 68, 47, 99, 61, 46, 26, 69, 21, 20, 82, 23, 39, 50, 58, 24, 22, 48, 32, 30, 11, 11, 48, 90, 44, 47, 90, 61, 86, 72, 20, 56, 6, 55, 59] => 4728

参考解决方案(针对速度而非大小进行了优化)。

如果由于使用暴力破解方法或类似方法而无法处理最后一种情况,那很好。

计分

这是,因此最短的有效解决方案(以字节为单位)获胜。


我们是否必须处理输入为空数组的情况?
布朗

根据帖子,@ ChasBrown输入为非空。
郑焕敏

嗯,我不明白第三个测试用例的工作原理,请解释一下吗?
暴民埃里克(Erik the Outgolfer)'18年

@EriktheOutgolfer这实际上是在说如果您的数组都是相同的数字(例如[2,2,2,2,...]),答案应该是数组的长度+1。这是因为在这种情况下,符号的位置无关紧要,而每个问题的数量都是唯一的
reffu

@reffu更像是个玩笑,看起来确实有点像被错误地包含在其中。
暴民埃里克(Erik the Outgolfer)'18年

Answers:


13

Wolfram语言(Mathematica),27个字节

Tr[1^Fold[#⋃+##&,{0},#]]&

在线尝试!

找到唯一的符号交换和的数量等同于找​​到唯一的子集和的数量。

证明将涉及将输入总和与每个符号交换总和相加并除以2。然后,有一个明显的双射。

说明

Fold[#⋃+##&,{0},#]

遍历输入,初始值为{0}<current value>和之间的并集<current value> + input element(映射到列表)。

Tr[1^ ... ]

Golfy版本的Length功能。


8

果冻,6个字节

ŒPS€QL

在线尝试!

背景

L为输入列表,{P,N}为带正负符号的代数求和式的分区。挑战规范要求计算s {P,N} = sum(P)-sum(N)

但是,由于sum(P)+ sum(N)= sum(L),并且sum(L)不依赖于分区,因此我们有s {P,N} = sum(P)-sum(N)= sum( P)-(sum(L)-sum(P))= 2sum(P)-sum(L)

因此,sum(P)的每个唯一值对应于s {P,N}的一个唯一值。

怎么运行的

ŒPS€QL  Main link. Argument: A (array)

ŒP      Powerset; generate all subarrays of A.
  S€    Take the sum of each.
    Q   Unique; deduplicate the sums.
     L  Take the length.

7

MATL11个10字节

nW:qBGY*un

在线尝试! 这是Luis Mendo的Octave / MATLAB答案的端口。我仍在尝试学习MATL,我想我会把它和说明一起发布,因为MATL是当月的语言。

说明:

对于那些不熟悉基于堆栈的编程(尤其是MATL)的读者,这里是通读。

输入向量隐式放置在堆栈上。请注意,对堆栈中的元素执行操作时,该元素将从堆栈中删除。

                % Stack:
                % [1, 2, 2]
n               % Counts the number of elements of the vector on the top of the stack.
                % Stack:
                % [3]
 W              % Raise 2^x, where x is the number above it in the stack
                % Stack:
                % [8]
  :             % Range from 1...x, where x is the number above it in the stack.                    % Stack:
                % [1, 2, 3, 4, 5, 6, 7, 8]
   q            % Decrement. Stack:
                % [0, 1, 2, 3, 4, 5, 6, 7]
    B           % Convert to binary. Stack:
                % [0,0,0; 0,0,1; 0,1,0; 0,1,1; 1,0,0; 1,0,1; 1,1,0; 1,1,1] 
     G          % Push input again. Stack:           
                % [0,0,0; 0,0,1; 0,1,0; 0,1,1; 1,0,0; 1,0,1; 1,1,0; 1,1,1], [1; 2; 2]
      Y*        % Matrix multiplication of the two elements on the stack.
                % Stack:
                % [0; 2; 2; 4; 1; 3; 3; 5]
        u       % Keep only unique elements. Stack:
                % [0; 2; 4; 1; 3; 5]
         n      % Number of elements in the vector. Stack:
                % [6]

然后,它在堆栈上隐式输出最终元素。


1
很好的解释!
路易斯·门多


6

Python 2,52字节

k=1
for n in input():k|=k<<n
print bin(k).count('1')

在线尝试!

使用数字的二进制表示形式来存储可达子集和。


1
您能解释一下这是如何工作的吗?您是自己想出来的还是已知结果?
sundar-恢复莫妮卡

1
@sundar没那么复杂。像许多其他答案一样,该答案将计算唯一和(不进行符号交换)。k中的每个位对应于一个和。k<<n将n加到每个和。Oring with k将这些新的总和存储在其中,k同时保留所有先前的总和,并且不会记录重复的Sims
H.PWiz

嗯,脚的痕迹可以追溯到郑焕敏的双射想法,那是我所缺少的主要见解。此处,每个子集总和在位串中的该位置由1表示(LSB中的初始1表示空子集的总和0)。我仍然不称其为“没那么复杂”,但这可能只是我的经验不足。:)
sundar-恢复莫妮卡


5

Haskell,46个字节

import Data.List
length.nub.map sum.mapM(:[0])

在线尝试!

而不是对输入列表的子集求和,我们进行了保留数字或将其替换为的所有组合0,例如

mapM(:[0])[1,2,3] -> [[1,2,3],[1,2,0],[1,0,3],[1,0,0],[0,2,3],[0,2,0],[0,0,3],[0,0,0]]

比短两个字节subsequences


好答案!我希望类似的东西f x=sum[1|i<-[0..sum x],elem i$sum<$>mapM(:[0])x]比导入的要短,但显然不是。
林恩

不错,甚至比Mathematica的翻译要短,尽管我认为它更漂亮:import Data.List;length.foldr((<*>)union.map.(+))[0]
乔恩·普迪

5

R,83 75字节

-8字节,感谢JayCe和Giuseppe

为输入向量的大小创建一个矩阵,其中包含所有可能的(1,-1)组合,将其乘以原始向量即可得到总和。然后唯一,并找到结果的长度。

function(v)nrow(unique(t(t(expand.grid(rep(list(c(1,-1)),sum(v|1)))))%*%v))


先前版本:

f=function(v)nrow(unique(as.matrix(expand.grid(rep(list(c(1,-1)),length(v))))%*%v))

取消评论:

f=function(vector){

  List=rep(list(c(1,-1)),length(vector))   ## Create a list with length(vector) elements, all (1,-1)

  Combinations=expand.grid(Length)    ## get all combinations of the elements of the list, e.g, 1,-1,1,1,-1,1

  Matrix=as.matrix(Combinations)   ## convert to matrix

  Results=Matrix%*%vector   ## multiply the matrix original vector to get a Nx1 matrix

  Unique_results=unique(Results)   ## unique the results

  nrow(Unique_results)   ## length = number of rows of unique values
  }

使用以下方法保存一些字节tTIO
JayCe

并且sum(v|1)length(v)
Giuseppe



3

Python 3,61字节

f=lambda a,s={0}:a and f(a[1:],s|{u+a[0]for u in s})or len(s)

在线尝试!

递归方法,跟踪唯一的子集和。

真正的乐趣是,这itertools大大超过了:

76字节

lambda a:len({*map(sum,product(*([0,x]for x in a)))})
from itertools import*

在线尝试!



3

附件,29个字节

{#Unique[Flat!±_]}@Fold[`±]

在线尝试!

通过将±运算符折叠到输入列表上,然后获取±该列表,然后对数组的唯一原子进行计数,可以实现此目的。

以下是有关折叠方式的一些示例:

Fold[`±][ [1,2] ] == 1 ± 2
                  == [1 + 2, 1 - 2]
                  == [3, -1]
Fold[`±][ [1,2,2] ] == (1 ± 2) ± 2
                    == [3, -1] ± 2
                    == [[3 + 2, 3 - 2], [-1 + 2, -1 - 2]]
                    == [[5, 1], [1, -3]]
                    == [5, 1, 1, -3]
Fold[`±][ [4,4,4,4] ] == (4 ± 4) ± 4 ± 4
                      == [8, 0] ± 4 ± 4
                      == [[12, 4], [4, -4]] ± 4
                      == [[[16, 8], [8, 0]], [[8, 0], [0, -8]]]
                      == [16, 8, 8, 0, 8, 0, 0, -8]
                      == [16, 8, 0, -8]

然后,通过再次应用PlusMinus来生成最终符号的所有排列。

效率更高的版本,31字节

`#@(q:=Unique@Flat@`±)@Fold[q]

在线尝试!这不会在最终测试用例上超时,因为它不会生成不必要的组合。


3

R,62个字节

function(V)sum(unique(c(V%*%combn(rep(0:1,L),L<-sum(V|1))))|1)

在线尝试!

Ports Dennis的算法。它最接近Octave / MATL答案,因为它使用相似的位图和矩阵乘积来包含/排除术语。







2

Bash + GNU实用程序,49字节

eval echo "{,-}${@//,/{+,-\}}\;"|bc|sort -u|wc -l

在线尝试!

在命令行中输入以逗号分隔的列表形式给出。

说明

               ${@//,/{+,-\}}                      # Replace commas with {+,-}
          "{,-}${@//,/{+,-\}}\;"                   # Build a brace expansion with {+,-} before every number and ; at the end
eval echo "{,-}${@//,/{+,-\}}\;"                   # Expand to give every combination expression, separated by ;
                                |bc                # Arithmetically evaluate each line
                                   |sort -u        # Remove duplicates
                                            wc -l  # Count

2

用于Linux的x86_64机器语言,31个 29字节

 0:   31 d2                   xor    %edx,%edx
 2:   6a 01                   pushq  $0x1
 4:   58                      pop    %rax
 5:   8b 0c 97                mov    (%rdi,%rdx,4),%ecx
 8:   48 89 c3                mov    %rax,%rbx
 b:   ff c2                   inc    %edx
 d:   48 d3 e3                shl    %cl,%rbx
10:   48 09 d8                or     %rbx,%rax
13:   39 d6                   cmp    %ese,%edx
15:   7c ee                   jle    5 <+0x5>
17:   f3 48 0f b8 c0          popcnt %rax,%rax
1c:   c3                      retq

在线尝试!

受到@xnor答案的启发。需要带有POPCNT说明的机器。




1

干净,82字节

import StdEnv
f[]=length
f[h:t]=f t o foldr(\e l=removeDup[e+h,e-h:l])[]
?l=f l[0]

在线尝试!

定义函数? :: [Int] -> Int使用f :: [Int] -> ([Int] -> Int)作为辅助加法或减法运算后,以减少在每一个可能的总和。


是Haskell中参考解决方案的高级版本。不知道有多少可以带入Clean,但您可能可以从中得到一些好处。
硕果累累'18年

@EsolangingFruit谢谢,但是它已经使用了相同的方法,即使使用参考解决方案,我也找不到缩短它的方法。
世纪

1

APL(Dyalog Classic),21字节

⍴∘∪⊢+.×1-2×2(⍴⍨⊤∘⍳*)⍴

在线尝试!

说明

2(⍴⍨⊤∘⍳*)⍴

等效于的函数列{((⍴⍵)⍴2)⊤⍳(⍴⍵)},生成一个矩阵,该矩阵具有0到输入长度的二进制表示形式作为列

1-2×

1-1s 映射到s并将0s 映射到1s

⊢+.×

矩阵与输入相乘,得到所有可能的和的数组

⍴∘∪

删除重复项,然后计数


1

Java 8,207 83 44字节

s->Long.bitCount(s.reduce(1L,(r,c)->r|r<<c))

@xnor的Python 2 Answer的端口。
-39个字节,感谢@Jakob

在线尝试

s->               // Method with Long-Stream parameter and long return-type
  Long.bitCount(  //  Return the amount of 1s in the binary representation of:
    s.reduce(1L,  //   Result-Long, starting at 1
     (r,c)->      //   Loop pair-wise (result,current):
      r|          //    Bitwise-OR the result `r` with:
        r<<c))    //    result `r` bitwise left-shifted by the current `c`

2
我们只需要44字节!流Longs->Long.bitCount(s.reduce(1l,(a,e)->a|a<<e))
Jakob

@Jakob谢谢!我总是忘记.reduce.bitCount也可能会添加..>>)-39字节!:)
Kevin Cruijssen

1
我还制作了一个任意精度的版本。看起来最便宜的方法仍然是使用位图而不是集合。
Jakob

1

Java 8,85字节

xnor的答案的另一个Java端口。像原始答案一样,它使用任意精度的位图,因此子集总和的大小没有上限。

从顺序java.util.stream.Stream<Integer>到都是lambda int

s->s.reduce(java.math.BigInteger.ONE,(a,e)->a.or(a.shiftLeft(e)),(u,v)->u).bitCount()

在线试用

请注意,reduce由于流是顺序的,因此未使用组合器(的第三个参数)。我选择的功能是任意的。


1

朱0.654 52个字节

V->(~W=W==[]?0:∪([n=W[] -n].+~W[2:end]))(V)|>endof

在线尝试!

-2通过替换字节¬~,这要归功于乔景

适用于所有测试用例。利用广播收集所有可能的金额,然后对它们进行计数。

说明:

function g_(V)
  function inner(W)  #named ~ in golf version to save bytes
    W == [] ? 0 :    #return 0 when input empty (base case)
    ∪(               #unique elements of
      [n=W[] -n]     #take the first element and its negation
      .+             #broadcast-add that to each element of
      inner([2:end]) #sign-swapping sums of the rest of the array
     )
  end                #returns the list of unique elements out of those sums
  return endof(inner(V)) #return the length of that list
end

较旧的解决方案:

朱莉娅0.6,64字节

N->endof(∪([2(i&2^~-j>0)-1 for i=0:~-2^(l=endof(N)),j=1:l]*N))

在线尝试!

适用于长度最大为63的输入数组(因此不适用于最后一个测试用例,根据OP可以使用)。

说明:

function f_(N)
  endof(                            #length of
        ∪(                          #unique elements of
          [
           (i & 2^(j-1) > 0)        #check j'th bit (from right) of i
           * 2 - 1                  #convert bit value from (0,1)=>(-1,1)
           for i = 0:2^endof(N)-1,  #where i is numbers 0 to 2^length(N)-1
           j = 1:endof(N)           #and j is 1 to length(N) (i.e. the bits in i)
          ]                         #so we have a matrix [-1 -1 -1;1 -1 -1;1 -1 1;...]
          *                         #matrix multiply that with the input array, 
          N                         #thus calculating different combinations of 
         ))                         #sign-swapping sums
end

0

JavaScript(Babel节点),64字节

F=([f,...r],s=[0])=>f?F(r,s.flatMap(x=>[x+f,x])):new Set(s).size

在线尝试!

这不适用于最后一个测试用例。


更有效的解决方案(适用于最后一个测试用例):

JavaScript(Babel Node),71个字节

F=([f,...r],s=[0])=>f?F(r,[...new Set(s.flatMap(x=>[x+f,x]))]):s.length

在线尝试!


由于导致此功能在实际的浏览器中不起作用Array#smoosh

多亏了Bubbler,[x+f,x-f]-> [x+f,x]节省了2个字节。


您可以使用[x+f,x]替代[x+f,x-f]由JungHwan闵证明)。
冒泡者

ES2版本的+2个字节:F=([f,...r],s=[0])=>f?F(r,[...s,...s.map(x=>x+f)]):new Set(s).size
尼尔

@Neil,以及... [...s,...s.map(x=>x+f)]s.concat(s.map(x=>x+f))s,s.map(x=>s.push(x+f))共享相同的长度...
tsh

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.