Somma di scambio di segni


24

Dato un elenco non vuoto di numeri interi positivi , il tuo compito è determinare il numero di valori univoci di± x ± y ± z ± (X,y,z,...)±X±y±z±...

Ad esempio, considera l'elenco . Esistono otto modi possibili per creare somme:(1,2,2)

  • +1+2+2+5
  • +1+2-2+1
  • +1-2+2+1
  • +1-2-2-3
  • -1+2+2+3
  • -1+2-2-1
  • -1-2+2-1
  • -1-2-2-5

Ci sono sei somme uniche , quindi la risposta è .6{5,-5,1,-1,3,-3}6

Casi test

[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

Soluzione di riferimento (ottimizza per velocità e non dimensioni).

Se non riesci a gestire l'ultimo caso perché usi un metodo di forza bruta o simile, va bene.

punteggio

Questo è , quindi vince la soluzione valida più breve (misurata in byte).


Dobbiamo gestire il caso in cui l'input è l'array vuoto?
Chas Brown,

@ChasBrown l'input non è vuoto, secondo il post.
JungHwan Min,

Hm, non riesco a capire come funziona il terzo caso di test, ti va di spiegare per favore?
Erik the Outgolfer,

@EriktheOutgolfer In effetti sta dicendo che se il tuo array è composto da numeri identici (es. [2,2,2,2,...]) La risposta dovrebbe essere la lunghezza dell'array + 1. Questo perché in questo caso la posizione dei segni è irrilevante e solo il numero di ogni argomento
reffu

@reffu È più uno scherzo, sembra un po 'come se fosse stato incluso lì per errore.
Erik the Outgolfer,

Risposte:


13

Wolfram Language (Mathematica) , 27 byte

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

Provalo online!

Trovare il numero di somme univoche di scambio di segni equivale a trovare il numero di somme univoche del sottoinsieme.

Una prova implicherebbe l'aggiunta della somma dell'input a ciascuna delle somme di scambio di segni e la divisione per due. Quindi, c'è un'ovvia biiezione.

Spiegazione

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

Scorri attraverso l'input, con il valore iniziale che è {0}: prendi l'unione tra <current value>e <current value> + input element(mappa su liste).

Tr[1^ ... ]

Versione da golf della Lengthfunzione.


8

Gelatina , 6 byte

ŒPS€QL

Provalo online!

sfondo

Sia L un elenco di input e {P, N} una partizione in somme algebriche con segni positivi e negativi. La specifica della sfida richiede il calcolo di s {P, N} = sum (P) - sum (N) .

Tuttavia, poiché sum (P) + sum (N) = sum (L) e sum (L) non dipendono dalla partizione, abbiamo s {P, N} = sum (P) - sum (N) = sum ( P) - (somma (L) - somma (P)) = 2sum (P) - somma (L) .

Pertanto, ogni valore univoco di somma (P) corrisponde a un valore univoco di s {P, N} .

Come funziona

Œ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

MATL , 11 10 byte

nW:qBGY*un

Provalo online! Questa è una porta della risposta Octave / MATLAB di Luis Mendo . Sto ancora cercando di imparare MATL e ho pensato di pubblicarlo insieme a una spiegazione, poiché MATL è la lingua del mese.

Spiegazione:

Ecco un read-through per chiunque non abbia familiarità con la programmazione basata su stack in generale e MATL in particolare.

Il vettore di input viene implicitamente inserito nello stack. Si noti che quando viene eseguita un'operazione su un elemento nello stack, quell'elemento viene rimosso dallo stack.

                % 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 quindi restituisce implicitamente l'elemento finale sullo stack.


1
Bella spiegazione!
Luis Mendo,


6

Python 2 , 52 byte

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

Provalo online!

Utilizza la rappresentazione binaria di un numero per memorizzare le somme di sottoinsieme raggiungibili.


1
Potresti spiegare come funziona? L'hai inventato tu stesso o è un risultato noto?
Sundar - Ripristina Monica il

1
@sundar Non è così complicato. Questa risposta calcola le somme uniche (non lo scambio di segni) come molte altre risposte. Ogni bit in k corrisponde a una somma. k<<naggiunge n a ogni somma. Orando con i knegozi queste nuove somme, kpur mantenendo tutte le precedenti, e i Sim duplicati non vengono registrati
H.Pwiz

Ah, la scia di briciole mi riporta all'idea di bijection di JungHwan Min , quella era la visione principale che mi mancava. Qui ogni somma del sottoinsieme è rappresentata da un 1 in quella posizione nella stringa di bit (con 1 iniziale nell'LSB che rappresenta la somma 0 per il sottoinsieme vuoto). Ancora non qualcosa che definirei "non così complicato", ma potrebbe essere solo la mia inesperienza a parlare. :)
Sundar - Ripristina Monica il


5

Haskell, 46 byte

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

Provalo online!

Invece di sommare i sottoinsiemi dell'elenco di input, facciamo tutte le combinazioni di mantenere un numero o sostituirlo con 0, ad es

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

Questo è due byte più corto di subsequences.


Bella risposta! Speravo che qualcosa del genere f x=sum[1|i<-[0..sum x],elem i$sum<$>mapM(:[0])x]fosse più breve dell'importazione, ma a quanto pare non lo è.
Lynn,

Bello, anche più breve della traduzione di Mathematica, anche se penso che sia più bello:import Data.List;length.foldr((<*>)union.map.(+))[0]
Jon Purdy,

5

R, 83 75 byte

-8 byte grazie a JayCe e Giuseppe

Crea una matrice di tutte le possibili combinazioni di (1, -1) per la dimensione del vettore di input, moltiplica questa per il vettore originale per ottenere le somme. Quindi unico e trova la lunghezza del risultato.

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


versione precedente:

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

Ungolfed con commenti:

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
  }

Salva alcuni byte con t: TIO
JayCe,

ed sum(v|1)è un byte più corto dilength(v)
Giuseppe,

4

Octave / MATLAB, 45 41 40 byte

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

L'input è un vettore di colonna (che utilizza ;come separatore).

Gli errori di codice per l'ultimo caso di test a causa di restrizioni di memoria.

Questo utilizza un'idea della risposta di JungHwan Min (sottoinsiemi invece di segni alternati) per salvare alcuni byte.

Provalo online!



3

Python 3 , 61 byte

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

Provalo online!

Approccio ricorsivo, tenendo traccia di somme di sottogruppi uniche.

Il vero divertimento è che questo batte itertoolscon un grande margine:

76 byte

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

Provalo online!



3

Attache , 29 byte

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

Provalo online!

Funziona piegando l' ±operatore sull'elenco di input, quindi prendendo ±quell'elenco, quindi contando gli atomi univoci dell'array.

Ecco alcuni esempi di come funziona la piegatura:

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]

Quindi generiamo tutte le permutazioni del segno finale applicando nuovamente PlusMinus.

Una versione più efficiente, 31 byte

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

Provalo online! Ciò non scade sul caso di test finale, poiché non genera combinazioni non necessarie.


3

R , 62 byte

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

Provalo online!

Algoritmo di Ports Dennis. È il più vicino alle risposte Octave / MATL in quanto utilizza un prodotto bitmap e matrice simile per l'inclusione / esclusione dei termini.







2

Utilità Bash + GNU, 49 byte

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

Provalo online!

Input fornito come elenco separato da virgole nella riga di comando.

Spiegazione

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

linguaggio macchina x86_64 per Linux, 31 29 byte

 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

Provalo online!

Ispirato dalla risposta di @ xnor. Richiede una macchina con le POPCNTistruzioni.




1

Pulito , 82 byte

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

Provalo online!

Definisce la funzione ? :: [Int] -> Intusando f :: [Int] -> ([Int] -> Int)come aiuto per ridurre ogni somma possibile dopo un'aggiunta o sottrazione.


Ecco una versione giocata a golf della soluzione di riferimento in Haskell; non sei sicuro di quanto possa essere trasferito su Clean ma potresti riuscire a ricavarne qualcosa.
Esolanging Fruit

@EsolangingFruit Grazie, ma sta già utilizzando lo stesso approccio e non riesco a trovare un modo per accorciarlo anche con la soluzione di riferimento golfata.
Οuroso

1

APL (Dyalog Classic) , 21 byte

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

Provalo online!

Spiegazione

2(⍴⍨⊤∘⍳*)⍴

Un treno di funzioni equivalente a {((⍴⍵)⍴2)⊤⍳(⍴⍵)}, che genera una matrice che ha le rappresentazioni binarie di 0 alla lunghezza dell'input come colonne

1-2×

Mappe 1s per -1s e 0s per 1s

⊢+.×

Moltiplicazione della matrice con l'input, che fornisce una matrice di tutte le possibili somme

⍴∘∪

Rimuovi i duplicati, quindi conta


1

Java 8, 207 83 44 byte

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

Port of @ xnor's Python 2 answer .
-39 byte grazie a @Jakob .

Provalo 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`

2
44 byte è tutto ciò di cui abbiamo bisogno! Prendendo un flusso di Long: s->Long.bitCount(s.reduce(1l,(a,e)->a|a<<e)).
Jakob,

@Jakob Grazie! Mi dimentico sempre di .reduce(e .bitCountpotrei anche aggiungere ..>.>) -39 byte proprio lì! :)
Kevin Cruijssen il

1
Inoltre ho appena realizzato una versione di precisione arbitraria . Sembra che il modo più economico per farlo sia ancora con una bitmap piuttosto che con i set.
Jakob,

1

Java 8, 85 byte

Un altro porto Java di XNOR risposta s' . Come la risposta originale, utilizza una bitmap di precisione arbitraria in modo che non vi siano limiti massimi per la dimensione di una somma di sottoinsieme.

È un lambda da un sequenziale java.util.stream.Stream<Integer>a int.

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

Provalo online

Si noti che il combinatore (il terzo argomento di reduce) non è utilizzato poiché lo stream è sequenziale. La funzione che ho scelto è arbitraria.


1

Julia 0.6 , 54 52 byte

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

Provalo online!

( -2 byte sostituendo ¬con ~, grazie a Jo King )

Funziona con tutti i casi di test. Fa uso della trasmissione per raccogliere tutte le possibili somme, quindi conta.

Spiegazione:

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

Soluzione precedente:

Julia 0.6 , 64 byte

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

Provalo online!

Funziona con array di input con lunghezza fino a 63 (quindi non funziona per l'ultimo caso di test, che va bene secondo OP).

Spiegazione:

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 Node) , 64 byte

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

Provalo online!

Questo non funzionerà per l'ultimo testcase.


Soluzione più efficace (funziona sull'ultima testcase):

JavaScript (Babel Node) , 71 byte

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

Provalo online!


Questo non funzionerà in un vero browser a causa di Array#smoosh.

Grazie a Bubbler, [x+f,x-f]-> [x+f,x]salva 2 byte.


È possibile utilizzare [x+f,x]al posto di [x+f,x-f]( prova di JungHwan Min ).
Bubbler,

+2 byte per la versione 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))la quota stessa lunghezza ...
TSH

0

Rosso , 73 byte

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

Python 2 di Port of Dennis. Non gestisce l'ultimo caso di test.

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.