高尔夫球的子总和问题


15

任务

给定以空格分隔的整数列表作为输入,请输出这些数字的所有唯一非空子集,每个子​​集的总和为0。


测试用例

输入: 8 −7 5 −3 −2
输出:-3 -2 5


获胜标准

这是,因此以字节为单位的最短代码胜出!


1
如果输入包含非唯一数字,我们是否需要担心唯一性?换句话说,我必须为输入打印多少个结果3 3 -3 -3
基思·兰德尔

@基思 按照惯例,集合由最多出现一次的不同元素组成。多重集可以包含多次出现的元素。en.wikipedia.org/wiki/Multiset
DavidC

4
@ DavidCarraher,OP通过谈论列表的子集来混合术语。
彼得·泰勒

@PeterTaylor谢谢。好点子。
DavidC 2012年

Answers:


4

GolfScript,41个字符

~][[]]\{`{1$+$}+%}%;(;.&{{+}*!},{" "*}%n*

如果您不关心特定的输出格式,则可以将代码缩短为33个字符。

~][[]]\{`{1$+$}+%}%;(;.&{{+}*!},`

示例(请参见在线):

> 8 -7 5 -3 -2 4
-3 -2 5
-7 -2 4 5
-7 -3 -2 4 8

6

Brachylog(2),9个字符

{⊇.+0∧}ᵘb

在线尝试!

{⊇.+0∧}ᵘb
 ⊇           subset
   +0        that sums to 0
  .  ∧       output the subset
{     }ᵘ     take all unique solutions
        b    except the first (which is the empty solution)

4

Python,119个字符

def S(C,L):
 if L:S(C,L[1:]);S(C+[L[0]],L[1:])
 elif sum(map(int,C))==0and C:print' '.join(C)
S([],raw_input().split())

递归枚举所有2 ^ n个子集,并检查每个子集。


太棒了!我进入一个角色...
12

3

Python,120

我的性格比Keith的解决方案差。但是...太接近了,无法发布。我最喜欢的代码高尔夫球功能之一是相似长度的解决方案有多不同。

l=raw_input().split()
print[c for c in[[int(j)for t,j in enumerate(l)if 2**t&i]for i in range(1,2**len(l))]if sum(c)==0]

2

蟒(128 137 136)

你该死的itertools.permutations,因为这么长的名字!

蛮力解决方案。我很惊讶这不是最短的:但是我猜想itertools解决方案毁了。

取消高尔夫:

import itertools
initial_set=map(int, input().split())
ans=[]
for length in range(1, len(x)+1):
    for subset in itertools.permutations(initial_set, length):
        if sum(subset)==0:
            ans+=str(sorted(subset))
print set(ans)

打高尔夫球(难看的输出):

from itertools import*
x=map(int,input().split())
print set(`sorted(j)`for a in range(1,len(x)+1)for j in permutations(x,a)if sum(j)==0)

打高尔夫球(漂亮的输出)(183):

from itertools import*
x=map(int,input().split())
print `set(`sorted(j)`[1:-1]for a in range(1,len(x)+1)for j in permutations(x,a)if sum(j)==0)`[5:-2].replace("'","\n").replace(",","")

import itertools as i:导入itertools模块并调用它 i

x=map(int,input().split()):用空格分隔输入,然后将结果列表的项目转换为整数(2 3 -5->[2, 3, -5]

set(sorted(j)for a in range(1,len(x)+1)for i in i.permutations(x,a)if sum(j)== 0):
返回x,排序的所有子集的列表,其中和为0,然后仅获取唯一项
set(...)

周围的坟墓(`)sorted(j)是Python的缩写repr(sorted(j))。之所以这样,是因为Python中的集合无法处理列表,因此,下一个最好的方法是使用带有列表的字符串作为文本。


我对如何获取整数而不是字符串感到困惑。 split()创建一个字符串列表,但是稍后您需要调用sum该拆分的子集。
基思·兰德尔

@KeithRandall:facepalm我很着急,所以我没有测试我的代码。感谢您指出这一点。
beary605

您可以这样做来保存角色from itertools import*
Matt

实际上坟墓是简写repr()
gnibbler

@gnibbler:在运行`'hello'`时会更有意义。谢谢!
beary605

2

C#– 384个字符

好的,用C#编写的函数式编程并不,但是我喜欢它!(仅使用强力枚举,没有什么比这更好的了。)

using System;using System.Linq;class C{static void Main(){var d=Console.ReadLine().Split(' ').Select(s=>Int32.Parse(s)).ToArray();foreach(var s in Enumerable.Range(1,(1<<d.Length)-1).Select(p=>Enumerable.Range(0,d.Length).Where(i=>(p&1<<i)!=0)).Where(p=>d.Where((x,i)=>p.Contains(i)).Sum()==0).Select(p=>String.Join(" ",p.Select(i=>d[i].ToString()).ToArray())))Console.WriteLine(s);}}

格式化和注释以提高可读性:

using System;
using System.Linq;

class C
{
    static void Main()
    {
        // read the data from stdin, split by spaces, and convert to integers, nothing fancy
        var d = Console.ReadLine().Split(' ').Select(s => Int32.Parse(s)).ToArray();
        // loop through all solutions generated by the following LINQ expression
        foreach (var s in
            // first, generate all possible subsets; well, first just their numbers
            Enumerable.Range(1, (1 << d.Length) - 1)
            // convert the numbers to the real subsets of the indices in the original data (using the number as a bit mask)
            .Select(p => Enumerable.Range(0, d.Length).Where(i => (p & 1 << i) != 0))
            // and now filter those subsets only to those which sum to zero
            .Where(p => d.Where((x, i) => p.Contains(i)).Sum() == 0)
            // we have the list of solutions here! just convert them to space-delimited strings
            .Select(p => String.Join(" ", p.Select(i => d[i].ToString()).ToArray()))
        )
            // and print them!
            Console.WriteLine(s);
    }
}

2

SWI-Prolog 84

此版本打印列表,而不是尝试为谓词中的术语找到适当的绑定。

s([],O):-O=[_|_],sum_list(O,0),print(O).
s([H|T],P):-s(T,[H|P]).
s([_|T],O):-s(T,O).

输入法

s([8,-7,5,-3,-2,4],[]).

作为记录,这是找到满足谓词的绑定的版本:

s(L,O):-s(L,0,O),O=[_|_].
s([],0,[]).
s([H|T],S,[H|P]):-R is H+S,s(T,R,P).
s([_|T],S,O):-s(T,S,O).

输入法

s([8,-7,5,-3,-2,4],O).

先前的版本包含一个不完整的解决方案,该解决方案无法删除空集。


2

Mathematica 62 57 38

在数组中以整数形式输入的输入x

x

输入

Grid@Select[Subsets@x[[1, 1]], Tr@# == 0 &]

输出量

输出


说明

x[[1, 1]] 将输入转换为整数列表。

Subsets 从整数生成所有子集。

Select....Tr@# == 0 给出所有总计等于0的子集。

Grid 将选定的子集格式化为以空格分隔的整数。


2

果冻,6个字节

ŒPḊSÐḟ

在线尝试!

只是为了完整性。与Brachylog相似,Jelly也推迟了挑战,但是到目前为止,较新的语言可以正常竞争。

ŒP       Power set.
  Ḋ      Dequeue, remove the first element (empty set).
    Ðḟ   Filter out the subsets with truthy (nonzero)...
   S       sum.


1

J,57 53 51 49个字符

>a:-.~(#:@i.@(2&^)@#<@":@(#~0=+/)@#"1 _])".1!:1[1

用法:

   >a:-.~(#:@i.@(2&^)@#<@":@(#~0=+/)@#"1 _])".1!:1[1
8 _7 5 _3 _2 4
5 _3 _2
_7 5 _2 4
8 _7 _3 _2 4

将火车改写为可(<@":@(#~0=+/)@#"1 _~2#:@i.@^#)节省4个字符。
algorithmhark

1

Stax,8 字节CP437

â±3╒yΣ╓à

在线运行和调试!

说明

使用解压后的版本(9个字节)进行解释。

LS{|+!fmJ
L            Convert to list
 S           Powerset
  {   f      Filter with block
   |+!       Sum is zero
       mJ    Print each subset, joined by spaces

Given a list of space-delimited integers as input; 您-但是-将列表作为输入。
乔纳森·弗雷希

将修复一个字节的开销。

1

J,34个字节

(a:-.~](<@#~0=+/)@#~[:#:@i.2^#)@".

在线尝试!

怎么样

".将输入转换为列表。然后:

a: -.~ ] (<@#~ (0 = +/))@#~ [: #:@i. 2 ^ #
                                  i.       NB. ints from 0 to...
                                     2 ^ # NB. 2 to the input len
                            [: #:@         NB. converted to binary masks
       ] (             ) #~                NB. filter the input using
                                           NB. using those masks, giving
                                           NB. us all subsets
         (             )@                  NB. and to each one...
         (  #~ (0 = +/))                   NB. return it if its sum is
                                           NB. 0, otherwise make it 
                                           NB. the empty list.
         (<@           )                   NB. and box the result.
                                           NB. now we have our answers
                                           NB. and a bunch of empty 
                                           NB. boxes, or aces (a:).
a: -.~                                     NB. remove the aces.

1

Perl 6,51个字节

*.words.combinations.skip.grep(!*.sum)>>.Bag.unique

在线尝试!

返回总计为0的唯一Bags的列表。Bag是加权Set。

说明:

*.words                 # Split by whitespace
 .combinations          # Get the powerset
 .skip                  # Skip the empty list
 .grep(!*.sum)          # Select the ones that sum to 0
 >>.Bag                 # Map each to a weighted Set
 .unique                # And get the unique sets

0

Ruby,110个字节

a=gets.split.map &:to_i;b=[];(1...a.length).each{|c|a.permutation(c){|d|d.sum==0?b<<d:0}};p b.map(&:sort).uniq

稍后将添加TIO链接。

将来自stdin的输入作为数字列表,例如 8 −7 5 −3 −2

工作原理:将输入转换为数字数组。获取从1到数组长度的所有长度排列。如果它们的总和为0,则将它们添加到输出数组。将输出不重复的数组。

样本输入的输出: [[-3, -2, 5]]

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.