Sommes d'échange de signes


24

Étant donné une liste non vide d'entiers positifs , votre travail consiste à déterminer le nombre de valeurs uniques de± x ± y ± z ± (X,y,z,)±x±y±z±

Par exemple, considérez la liste . Il existe huit façons possibles de créer des sommes:(1,2,2)

  • +1+2+2+5
  • +1+22+1
  • +12+2+1
  • +1223
  • 1+2+2+3
  • -1+2-2-1
  • -1-2+2-1
  • -1-2-2-5

Il y a six sommes uniques , donc la réponse est .6{5,-5,1,-1,3,-3}6

Cas de 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

Solution de référence (optimise la vitesse et non la taille).

Si vous ne pouvez pas gérer le dernier cas parce que vous utilisez une méthode de force brute ou similaire, ça va.

Notation

Il s'agit de , donc la solution valide la plus courte (mesurée en octets) l'emporte.


Faut-il gérer le cas où l'entrée est le tableau vide?
Chas Brown

@ChasBrown, l'entrée n'est pas vide, selon le message.
JungHwan Min

Hm, je ne comprends pas comment fonctionne le troisième cas de test, veuillez expliquer s'il vous plaît?
Erik the Outgolfer

@EriktheOutgolfer C'est effectivement dire que si votre tableau est tous des nombres identiques (par exemple [2,2,2,2,...]) la réponse doit être la longueur du tableau + 1. C'est parce que dans ce cas, la position des signes n'est pas pertinente et que le nombre de chaque matière
reffu

@reffu C'est plus une blague, on dirait qu'elle a été incluse là par erreur.
Erik the Outgolfer

Réponses:


13

Wolfram Language (Mathematica) , 27 octets

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

Essayez-le en ligne!

Trouver le nombre de sommes d'échange de signes uniques équivaut à trouver le nombre de sommes de sous-ensembles uniques.

Une preuve impliquerait d'ajouter la somme de l'entrée à chacune des sommes d'échange de signes et de la diviser par deux. Ensuite, il y a une bijection évidente.

Explication

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

Parcourez l'entrée, la valeur initiale étant {0}: prenez l'union entre <current value>et <current value> + input element(mappe sur des listes).

Tr[1^ ... ]

Version Golfy de la Lengthfonction.


8

Gelée , 6 octets

ŒPS€QL

Essayez-le en ligne!

Contexte

Soit L la liste d'entrée et {P, N} une partition en sommets algébriques avec des signes positifs et négatifs. La spécification de défi nécessite de calculer s {P, N} = somme (P) - somme (N) .

Cependant, puisque somme (P) + somme (N) = somme (L) et somme (L) ne dépend pas de la partition, nous avons s {P, N} = somme (P) - somme (N) = somme ( P) - (somme (L) - somme (P)) = 2 somme (P) - somme (L) .

Ainsi, chaque valeur unique de somme (P) correspond à une valeur unique de s {P, N} .

Comment ça marche

Œ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 octets

nW:qBGY*un

Essayez-le en ligne! Ceci est un portage de la réponse Octave / MATLAB de Luis Mendo . J'essaie toujours d'apprendre MATL, et j'ai pensé que je le posterais, avec une explication, puisque MATL est la langue du mois.

Explication:

Voici une lecture pour tous ceux qui ne connaissent pas la programmation basée sur la pile en général, et MATL en particulier.

Le vecteur d'entrée est implicitement placé sur la pile. Notez que lorsqu'une opération est effectuée sur un élément de la pile, cet élément est supprimé de la pile.

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

Et puis il renvoie implicitement le dernier élément de la pile.


1
Belle explication!
Luis Mendo


6

Python 2 , 52 octets

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

Essayez-le en ligne!

Utilise la représentation binaire d'un nombre pour stocker les sommes des sous-ensembles accessibles.


1
Pourriez-vous expliquer comment cela fonctionne? L'avez-vous inventé vous-même ou s'agit-il d'un résultat connu?
sundar

1
@sundar Ce n'est pas si compliqué. Cette réponse calcule les sommes uniques (pas l'échange de signes) comme beaucoup d'autres réponses. Chaque bit en k correspond à une somme. k<<najoute n à chaque somme. Oring avec kstocke ces nouvelles sommes ktout en conservant toutes les précédentes, et les Sims dupliqués ne sont pas enregistrés
H.PWiz

Ah, la piste des miettes de pain nous ramène à l'idée de bijection de JungHwan Min , qui était la principale idée qui me manquait. Ici, chaque somme de sous-ensemble est représentée par un 1 à cette position dans la chaîne binaire (avec le 1 initial dans le LSB représentant la somme 0 pour le sous-ensemble vide). Ce n'est pas quelque chose que j'appellerais "pas si compliqué", mais c'est peut-être simplement mon inexpérience à parler. :)
sundar


5

Haskell, 46 octets

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

Essayez-le en ligne!

Au lieu de sommer les sous-ensembles de la liste d'entrée, nous faisons toutes les combinaisons soit en conservant un nombre, soit en le remplaçant par 0, par exemple

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

C'est deux octets de moins que subsequences.


Bonne réponse! J'espérais que quelque chose comme ça f x=sum[1|i<-[0..sum x],elem i$sum<$>mapM(:[0])x]serait plus court que l'importation, mais apparemment, ce n'est pas le cas.
Lynn

Sympa, encore plus court que la traduction de Mathematica, bien que je pense que c'est plus joli:import Data.List;length.foldr((<*>)union.map.(+))[0]
Jon Purdy

5

R, 83 75 octets

-8 octets grâce à JayCe et Giuseppe

Crée une matrice de toutes les combinaisons possibles de (1, -1) pour la taille du vecteur d'entrée, multiplie cela par le vecteur d'origine pour obtenir les sommes. Ensuite, unique et trouvez la longueur du résultat.

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


la version précédente:

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

Non golfé avec des commentaires:

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
  }

Économisez quelques octets avec t: TIO
JayCe

et sum(v|1)est un octet plus court quelength(v)
Giuseppe

4

Octave / MATLAB, 45 41 40 octets

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

L'entrée est un vecteur de colonne (utilisé ;comme séparateur).

Les erreurs de code pour le dernier cas de test en raison de restrictions de mémoire.

Cela utilise une idée de la réponse de JungHwan Min (sous-ensembles au lieu de signes alternés) pour économiser quelques octets.

Essayez-le en ligne!



3

Python 3 , 61 octets

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

Essayez-le en ligne!

Approche récursive, gardant une trace des sommes de sous-ensembles uniques.

Le vrai plaisir est que cela bat itertoolspar une grande marge:

76 octets

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

Essayez-le en ligne!



3

Attaché , 29 octets

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

Essayez-le en ligne!

Cela fonctionne en repliant l' ±opérateur sur la liste d'entrée, puis en prenant ±cette liste, puis en comptant les atomes uniques du tableau.

Voici quelques exemples du fonctionnement du pliage:

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]

Ensuite, nous générons toutes les permutations du signe final en appliquant à nouveau PlusMinus.

Une version plus efficace, 31 octets

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

Essayez-le en ligne! Cela n'expire pas sur le cas de test final, car il ne génère pas de combinaisons inutiles.


3

R , 62 octets

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

Essayez-le en ligne!

Algorithme de Ports Dennis. Il est le plus proche des réponses Octave / MATL car il utilise un produit bitmap et matrice similaire pour l'inclusion / exclusion de termes.







2

Utilitaires Bash + GNU, 49 octets

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

Essayez-le en ligne!

Entrée donnée sous forme de liste séparée par des virgules sur la ligne de commande.

Explication

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

Langage machine x86_64 pour Linux, 31 29 octets

 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

Essayez-le en ligne!

Inspiré par la réponse de @ xnor. Nécessite une machine avec l' POPCNTinstruction.




1

Nettoyer , 82 octets

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

Essayez-le en ligne!

Définit la fonction en ? :: [Int] -> Intutilisant f :: [Int] -> ([Int] -> Int)comme aide pour réduire chaque somme possible après un ajout ou une soustraction.


Voici une version golfée de la solution de référence à Haskell; Je ne sais pas combien il peut être transféré à Clean, mais vous pourriez en retirer quelque chose.
Esolanging Fruit

@EsolangingFruit Merci, mais il utilise déjà la même approche et je ne trouve pas de moyen de le raccourcir même avec la solution de référence golfée.
ousurous

1

APL (Dyalog Classic) , 21 octets

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

Essayez-le en ligne!

Explication

2(⍴⍨⊤∘⍳*)⍴

Un train de fonctions équivalent à {((⍴⍵)⍴2)⊤⍳(⍴⍵)}, qui génère une matrice qui a les représentations binaires de 0 à la longueur de l'entrée sous forme de colonnes

1-2×

Mappe 1s à -1s et 0s à 1s

⊢+.×

Multiplication matricielle avec l'entrée, qui donne un tableau de toutes les sommes possibles

⍴∘∪

Supprimer les doublons, puis compter


1

Java 8, 207 83 44 octets

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

Port de @ xnor réponse Python 2 .
-39 octets grâce à @Jakob .

Essayez-le en ligne .

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 octets, c'est tout ce dont nous avons besoin! Prendre un flux de Long: s->Long.bitCount(s.reduce(1l,(a,e)->a|a<<e)).
Jakob

@Jakob Merci! J'oublie toujours .reduce(et .bitCountaussi je pourrais ajouter ..>.>) -39 octets juste là! :)
Kevin Cruijssen

1
De plus, je viens de faire une version à précision arbitraire . Il semble que la façon la moins chère de le faire soit toujours avec un bitmap plutôt qu'avec des ensembles.
Jakob

1

Java 8, 85 octets

Un autre port Java de xnor réponse de . Comme la réponse d'origine, cela utilise un bitmap de précision arbitraire afin qu'il n'y ait pas de limite supérieure sur la taille d'une somme de sous-ensemble.

C'est un lambda d'un séquentiel java.util.stream.Stream<Integer>à int.

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

Essayez-le en ligne

Notez que le combineur (le troisième argument de reduce) n'est pas utilisé car le flux est séquentiel. La fonction que j'ai choisie est arbitraire.


1

Julia 0,6 , 54 52 octets

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

Essayez-le en ligne!

( -2 octets en remplaçant ¬par ~, merci à Jo King )

Fonctionne pour tous les cas de test. Utilise la diffusion pour collecter toutes les sommes possibles, puis les compte.

Explication:

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

Solution plus ancienne:

Julia 0,6 , 64 octets

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

Essayez-le en ligne!

Fonctionne pour les tableaux d'entrée avec une longueur jusqu'à 63 (donc ne fonctionne pas pour le dernier cas de test, ce qui est bien selon OP).

Explication:

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 (nœud Babel) , 64 octets

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

Essayez-le en ligne!

Cela ne fonctionnera pas pour le dernier test.


Solution plus efficace (fonctionne sur le dernier testcase):

JavaScript (Babel Node) , 71 octets

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

Essayez-le en ligne!


Cela ne fonctionnera pas dans un vrai navigateur à cause de Array#smoosh.

Merci à Bubbler, [x+f,x-f]-> [x+f,x]enregistre 2 octets.


Vous pouvez utiliser [x+f,x]à la place de [x+f,x-f]( preuve par JungHwan Min ).
Bubbler

+2 octets pour la version ES6:F=([f,...r],s=[0])=>f?F(r,[...s,...s.map(x=>x+f)]):new Set(s).size
Neil

@Neil, et ... [...s,...s.map(x=>x+f)], s.concat(s.map(x=>x+f))et, s,s.map(x=>s.push(x+f))part même longueur ...
tsh

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.