Soma de troca de sinal

24

Dada uma lista não vazia de números inteiros positivos , seu trabalho é determinar o número de valores exclusivos de ± x ± y ± z ± (x,y,z,)±x±y±z±

Por exemplo, considere a lista . Existem oito maneiras possíveis de criar somas:(1,2,2)

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

Existem seis somas únicas , então a resposta é 6 .{5,5,1,1,3,3}6

Casos de teste

[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

Solução de referência (otimiza a velocidade e não o tamanho).

Se você não consegue lidar com o último caso porque usa um método de força bruta ou similar, tudo bem.

Pontuação

Isso é , então a solução válida mais curta (medida em bytes) vence.

Esolanging Fruit
fonte
Temos que lidar com o caso em que a entrada é a matriz vazia?
Chas Brown
@ChasBrown, a entrada não está vazia, de acordo com a publicação.
JungHwan Min
Hum, não consigo entender como funciona o terceiro caso de teste, gostaria de explicar por favor?
Erik the Outgolfer
@EriktheOutgolfer É efetivamente dizer que se sua matriz possui todos os números idênticos (por exemplo [2,2,2,2,...]) a resposta deve ser o comprimento da matriz + 1. Isso ocorre porque, neste caso, a posição dos sinais é irrelevante e apenas o número de cada questão
repffu
@reffu É mais uma piada, parece que foi incluída por engano.
Erik the Outgolfer

Respostas:

13

Wolfram Language (Mathematica) , 27 bytes

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

Experimente online!

Encontrar o número de somas exclusivas de troca de sinal é equivalente a encontrar o número de somas de subconjuntos exclusivos.

Uma prova envolveria adicionar a soma da entrada a cada uma das somas de troca de sinal e dividir por duas. Então, há uma biografia óbvia.

Explicação

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

Itere através da entrada, com o valor inicial sendo {0}: faça a união entre<current value> e <current value> + input element(mapeia em listas).

Tr[1^ ... ]

Versão Golfy da Lengthfunção.

JungHwan Min
fonte
8

Gelatina , 6 bytes

ŒPS€QL

Experimente online!

fundo

Seja L a lista de entrada e {P, N} uma partição em somas algébricas com sinais positivos e negativos. A especificação de desafio requer o cálculo de s {P, N} = soma (P) - soma (N) .

No entanto, como soma (P) + soma (N) = soma (L) e soma (L) não depende da partição, temos s {P, N} = soma (P) - soma (N) = soma ( P) - (soma (L) - soma (P)) = 2 soma (P) - soma (L) .

Assim, cada valor único da soma (P) corresponde a um valor único de s {P, N} .

Como funciona

Œ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.
Dennis
fonte
7

MATL , 11 10 bytes

nW:qBGY*un

Experimente online! Este é um porto da oitava de Luis Mendo / MATLAB resposta . Ainda estou tentando aprender o MATL e achei que o postaria, juntamente com uma explicação, já que o MATL é o idioma do mês.

Explicação:

Aqui está uma leitura para qualquer pessoa que não esteja familiarizada com a programação baseada em pilha em geral e o MATL em particular.

O vetor de entrada é implicitamente colocado na pilha. Observe que quando uma operação é executada em um elemento da pilha, esse elemento é removido da pilha.

                % 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]

E, em seguida, gera o elemento final na pilha implicitamente.

Stewie Griffin
fonte
11
Boa explicação!
Luis Mendo
6

Python 2 , 55 bytes

s={0}
for n in input():s|={t+n for t in s}
print len(s)

Experimente online!

Dennis
fonte
6

Python 2 , 52 bytes

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

Experimente online!

Usa a representação binária de um número para armazenar as somas do subconjunto alcançável.

xnor
fonte
11
Você poderia explicar como isso funciona? Você inventou você mesmo ou é algum resultado conhecido?
sundar - Restabelece Monica
11
@ Sundar Não é tão complicado. Esta resposta calcula as somas exclusivas (sem troca de sinal) como muitas outras respostas. Cada bit em k corresponde a uma soma. k<<nadiciona n a cada soma. ORING com klojas estas novas somas em kmantendo todos os anteriores, e duplicados Sims não são registrados
H.PWiz
Ah, o rastro de brechas nos leva de volta à ideia de bijeção de JungHwan Min , que era o principal insight que eu estava perdendo. Aqui cada soma de subconjunto é representada por um 1 nessa posição na cadeia de bits (com o 1 inicial no LSB representando a soma 0 para o subconjunto vazio). Ainda não é algo que eu chamaria de "não tão complicado", mas isso pode ser apenas a minha inexperiência falando. :)
sundar - Reinstate Monica
5

Haskell, 46 bytes

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

Experimente online!

Em vez de somar os subconjuntos da lista de entrada, fazemos todas as combinações de manter um número ou substituí-lo 0, por exemplo

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]]

Isso é dois bytes menor que subsequences.

nimi
fonte
Boa resposta! Eu esperava que algo como f x=sum[1|i<-[0..sum x],elem i$sum<$>mapM(:[0])x]fosse mais curto que a importação, mas aparentemente não é.
Lynn
Bom, ainda mais curto do que a translação do Mathematica, embora eu acho que é mais bonita:import Data.List;length.foldr((<*>)union.map.(+))[0]
Jon Purdy
5

R, 83 75 bytes

-8 bytes graças a JayCe e Giuseppe

Cria uma matriz de todas as combinações possíveis de (1, -1) para o tamanho do vetor de entrada, multiplica isso pelo vetor original para obter as somas. Então único e encontre a duração do resultado.

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


versão anterior:

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

Ungolfed com comentários:

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
  }
Andrew Haynes
fonte
Salve alguns bytes com t: TIO
JayCe
e sum(v|1)é um byte menor quelength(v)
Giuseppe
4

Oitava / MATLAB, 45 41 40 bytes

@(x)nnz(unique(dec2bin(0:2^nnz(x)-1)*x))

Input é um vetor de coluna (usando ; como separador).

Os erros de código para o último caso de teste devido a restrições de memória.

Isso usa uma idéia da resposta de JungHwan Min (subconjuntos em vez de sinais alternados) para salvar alguns bytes.

Experimente online!

Luis Mendo
fonte
4

Pari / GP , 39 bytes

a->#[1|n<-Vec(prod(i=1,#a,1+x^a[i])),n]

Euuma(1 1+xEu)uma

Experimente online!

alefalpha
fonte
Essa é uma maneira legal de fazer isso!
JungHwan Min
3

Python 3 , 61 bytes

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

Experimente online!

Abordagem recursiva, acompanhando somas de subconjuntos exclusivos.

A verdadeira diversão é que isso supera itertoolsuma grande margem:

76 bytes

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

Experimente online!

Bubbler
fonte
3

Anexo , 29 bytes

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

Experimente online!

Isso funciona dobrando o ±operador sobre a lista de entrada e, em seguida,± a lista e contando os átomos exclusivos da matriz.

Aqui estão alguns exemplos de como a dobra funciona:

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]

Em seguida, geramos todas as permutações do sinal final aplicando o PlusMinus mais uma vez.

Uma versão mais eficiente, 31 bytes

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

Experimente online! Isso não atinge o tempo limite no caso de teste final, pois não gera combinações desnecessárias.

Conor O'Brien
fonte
3

R , 62 bytes

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

Experimente online!

Portos algoritmo de Dennis. É o mais próximo das respostas do Octave / MATL, pois usa um produto de bitmap e matriz semelhante para inclusão / exclusão de termos.

Giuseppe
fonte
2

JavaScript (ES6), 63 bytes

f=([c,...a],s=n=!(o={}))=>c?f(a,s-c)|f(a,s+c)&&n:o[s]=o[s]||++n

Experimente online!

Arnauld
fonte
2

Casca , 5 bytes

LumΣṖ

Experimente online!

Resposta da geléia do Porto de Dennis.

Explicação

LumΣṖ                     [1,2,2]
    Ṗ  Powerset           [[],[1],[2],[1,2],[2],[1,2],[2,2],[1,2,2]]
  mΣ   Sum each           [0,1,2,3,2,3,4,5]
 u     Remove duplicates  [0,1,2,3,4,5]
L      Length             6
Fyr
fonte
Equivalente à resposta Pyth , essencialmente caracter por caracter.
Isaacg
2

Utilitários Bash + GNU, 49 bytes

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

Experimente online!

Entrada fornecida como uma lista separada por vírgula na linha de comando.

Explicação

               ${@//,/{+,-\}}                      # 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
Trauma Digital
fonte
2

linguagem de máquina x86_64 para Linux, 31 29 bytes

 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

Experimente online!

Inspirado pela resposta de @ xnor. Requer uma máquina com as POPCNTinstruções.

teto
fonte
2

C (gcc) , 74 69 bytes

f(a,b)int*a;{long k=1;for(;b--;k|=k<<a[b]);a=__builtin_popcountl(k);}

Experimente online!

Porta C da resposta do @ xnor

teto
fonte
1

APL (Dyalog Classic) , 34 33 32 bytes

{≢∪⍵+.×⍨↑{,⍵∘.,U}⍣(≢1↓⍵)⊢U←¯1 1}

Experimente online!

Obrigado a @ngn por -1 byte!

Zacharý
fonte
1-⍨≢⍵->≢1↓⍵
ngn
+.×⍨->+.×
ngn
O último não funciona, receio.
Zacharý
oops, eu não sei porque eu pensei que você está aplicando + × em vetores ... desculpe.
NGN
1

Limpo , 82 bytes

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

Experimente online!

Define a função ? :: [Int] -> Intusando f :: [Int] -> ([Int] -> Int)como auxiliar para reduzir cada soma possível após uma adição ou subtração.

Furioso
fonte
Aqui está uma versão em golf da solução de referência em Haskell; não tenho certeza do quanto ele pode ser transferido para o Clean, mas você poderá obter algo com isso.
Esolanging Fruit
@EsolangingFruit Obrigado, mas já está usando a mesma abordagem e não consigo encontrar uma maneira de reduzi-la, mesmo com a solução de referência em uso.
Οurous
1

APL (Dyalog Classic) , 21 bytes

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

Experimente online!

Explicação

2(⍴⍨⊤∘⍳*)⍴

Um trem de função equivalente a {((⍴⍵)⍴2)⊤⍳(⍴⍵)}, que gera uma matriz que tem as representações binárias de 0 ao comprimento da entrada como colunas

1-2×

Mapas 1s para -1s e 0s a 1s

⊢+.×

Multiplicação de matrizes com a entrada, que fornece uma matriz de todas as somas possíveis

⍴∘∪

Remova duplicatas e conte

TwiNight
fonte
1

Java 8, 207 83 44 bytes

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

Porta da resposta Python 2 do @ xnor .
-39 bytes graças a @Jakob .

Experimente online .

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`
Kevin Cruijssen
fonte
2
44 bytes é tudo o que precisamos! Tomando um fluxo de Long: s->Long.bitCount(s.reduce(1l,(a,e)->a|a<<e)).
22418 Jakob
@Jakob Thanks! Eu sempre esqueço .reduce(e .bitCounttambém devo adicionar ..>.>) -39 bytes ali! :)
Kevin Cruijssen
11
Também acabei de criar uma versão de precisão arbitrária . Parece que a maneira mais barata de fazer isso ainda é com um bitmap em vez de conjuntos.
22418 Jakob
1

Java 8, 85 bytes

Outra porta Java da resposta do xnor . Como a resposta original, isso usa um bitmap de precisão arbitrária para que não haja limite superior no tamanho de uma soma de subconjunto.

É um lambda de um seqüencial java.util.stream.Stream<Integer>para int.

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

Experimente Online

Observe que o combinador (o terceiro argumento para reduce) não é utilizado, pois o fluxo é seqüencial. A função que eu escolhi é arbitrária.

Jakob
fonte
1

Julia 0.6 , 54 52 bytes

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

Experimente online!

( -2 bytes substituindo ¬por ~, graças a Jo King )

Funciona para todos os casos de teste. Faz uso da transmissão para coletar todas as somas possíveis e as conta.

Explicação:

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

Solução mais antiga:

Julia 0,6 , 64 bytes

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

Experimente online!

Funciona para matrizes de entrada com comprimento até 63 (portanto, não funciona para o último caso de teste, o que é bom de acordo com o OP).

Explicação:

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
sundar - Restabelecer Monica
fonte
0

JavaScript (Nó Babel) , 64 bytes

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

Experimente online!

Isso não funcionará no último caso de teste.


Solução mais eficaz (funciona no último caso de teste):

JavaScript (Nó Babel) , 71 bytes

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

Experimente online!


Isso não funcionará em um navegador real devido a Array#smoosh .

Graças ao Bubbler, [x+f,x-f]-> [x+f,x]economiza 2 bytes.

tsh
fonte
Você pode usar [x+f,x]no lugar de [x+f,x-f]( prova de JungHwan Min ).
Bubbler
+2 bytes para a versão ES6:F=([f,...r],s=[0])=>f?F(r,[...s,...s.map(x=>x+f)]):new Set(s).size
Neil
@Neil, e ... [...s,...s.map(x=>x+f)], s.concat(s.map(x=>x+f))e, s,s.map(x=>s.push(x+f))share mesmo comprimento ...
TSH
0

Vermelho , 73 bytes

func[b][s:[0]foreach n b[foreach m s[s: union s reduce[m + n]]]length? s]

Resposta do Python 2 do porto de Dennis. Não lida com o último caso de teste.

Experimente online!

Galen Ivanov
fonte