Variação de N bits na soma de subconjuntos

14

Para outro desafio que estou escrevendo, preciso verificar se os casos de teste são solucionáveis ​​com números inteiros limitados. Especificamente, preciso verificar o seguinte, para uma matriz não vazia de números inteiros Ae uma largura de bit inteiro n:

  1. Todos os números inteiros aem Asatisfazíveis -2**(n-1) <= a < 2**(n-1)(representáveis ​​com nnúmeros inteiros de complemento de -bit two).
  2. O comprimento de Aé menor que 2**n.
  3. A soma de Asatisfaz -2**(n-1) <= sum(A) < 2**(n-1).
  4. Todas as combinações de elementos Aatendem a todas as condições acima.

Naturalmente, decidi terceirizar esse problema para você!

Dada uma matriz de números inteiros Ae uma largura de bits inteira positiva n, verifique se Asatisfaz as condições acima.

Casos de teste

[0, 0, 0], 2: True
[0, 0, 0, 0], 2: False (violates #2)
[1, 2, 3, 4, 5], 8: True
[1, 2, 3, 4, 5], 2: False (violates all conditions)
[1, 2, 3, 4, 5], 5: True
[-3, 4, 1], 4: True
[10, 0, -10], 4: False (violates #1 and #4)
[27, -59, 20, 6, 10, 53, -21, 16], 8: False (violates #4)
[-34, 56, 41, -4, -14, -54, 30, 38], 16: True
[-38, -1, -11, 127, -35, -47, 28, 89, -8, -12, 77, 55, 75, 75, -80, -22], 7: False (violates #4)
[-123, -85, 6, 121, -5, 12, 52, 31, 64, 0, 6, 101, 128, -72, -123, 12], 12: True

Implementação de referência (Python 3)

#!/usr/bin/env python3
from itertools import combinations
from ast import literal_eval


def check_sum(L, n):
  return -2**(n-1) <= sum(L) < 2**(n-1)


def check_len(L, n):
  return len(L) < 2**n


def check_elems(L, n):
  return all(-2**(n-1) <= a < 2**(n-1) for a in L)


A = literal_eval(input())
n = int(input())
OUTPUT_STR = "{}, {}: {}".format(A, n, "{}")

if not (check_elems(A, n) and check_len(A, n) and check_sum(A, n)):
  print(OUTPUT_STR.format(False))
  exit()

for k in range(1, len(A)):
  for b in combinations(A, k):
    if not check_sum(b, n):
      print(OUTPUT_STR.format(False))
      exit()

print(OUTPUT_STR.format(True))

Experimente online!

Mego
fonte
Sandbox
Mego
Devemos lidar com a lista vazia?
Xcoder
@ Mr.Xcoder Não, vou esclarecer.
Mego 14/12

Respostas:

7

Wolfram Language (Mathematica) , 40 bytes

Max[x=2Tr/@Subsets@#,-x-1,Tr[1^#]]<2^#2&

Experimente online!

A condição 1 é implícita verificando a condição 3 para todos os subconjuntos, incluindo os de um elemento. Então tomamos o máximo de

  • duas vezes a soma de cada subconjunto,
  • um menos que o dobro da soma negativa de cada subconjunto, e
  • o comprimento de todo o conjunto

e verifique se é menor que 2^#2(onde #2está a entrada de largura de bits).

Ao custo de apenas mais 6 bytes, podemos substituí-lo Subsets@#por GatherBy[#,Arg], o que é muito mais eficiente, porque calcula apenas os dois subconjuntos de pior caso: o subconjunto de todos os valores não negativos e o subconjunto de todos os valores negativos. (Isso funciona porque Argtem um valor de 0no primeiro e πno segundo.)

Misha Lavrov
fonte
3

Geléia , 19 bytes

ŒPS€;⁸L¤ḟ⁹’2*$ŒRṖ¤Ṇ

Experimente online!

Basta verificar se mapped sum of powerset + length of setestá no intervalo necessário.

Freira Furada
fonte
1
Eu acho que (embora eu não tenho certeza) que você pode usar ÆẸem vez de 2*$(não testado)
Mr. Xcoder
@ Mr.Xcoder Funciona.
user202729
3

05AB1E , 13 12 11 bytes

Economizou 1 byte graças ao Sr. Xcoder

æO·D±¹gMIo‹

Experimente online!

Explicação

æ             # powerset of first input
 O            # sum each subset
  ·           # multiply each element by 2
   D          # duplicate
    ±         # bitwise negation of each element in the copy
     ¹g       # push length of first input
       M      # get the maximum value on the stack
        Io    # push 2**<second input>
          ‹   # compare
Emigna
fonte
@ Mr.Xcoder: Ah, sim, obrigado! (Eu continuo esquecendo ±) #
1111 Emigna
2

JavaScript (ES6), 75 63 58 bytes

a=>n=>!a.some(e=>(a.length|2*(e<0?l-=e:u+=e))>>n,u=0,l=-1)

A soma de qualquer subconjunto de amentiras entre as somas dos elementos negativos e não-negativos, portanto, verificar as duas somas é suficiente para tudo, exceto o caso 2. Edit: Saved 12 17 bytes graças a @Arnauld.

Neil
fonte
Muito, muito melhor do que minha abordagem ingênua. :-) Isso pode ser encurtado para 61 bytes #
Arnauld
Na verdade, podemos apenas processar o teste dentro do loop por 56 bytes .
Arnauld
Hacked on ([-2, -1, -2]) (3)
l4m2
@ l4m2 Boa captura. Correção sugerida (57 bytes)
Arnauld
@ Arnauld O problema aqui é que [-2, -2], 3deveria ser verdade, não?
217 Neil
1

Geléia , 21 20 bytes

»0,«0$S€~2¦Ḥ;LṀ<2*Ɠ¤

Experimente online!

Solução linear de complexidade de tempo. Acontece que eu superestimei a complexidade do tempo

em O décimo nono byte, 11-12-2017 13-15-03Z, pelo usuário202729

@NewSandboxedPosts O problema de soma de subconjuntos "real" é muito mais difícil. Este pode ser feito em tempo linearitmico ...

porque agora percebo que classificar a matriz é completamente desnecessário.


Explicação:

»0,«0$S€~2¦Ḥ;LṀ<2*Ɠ¤    Main link. Example list: [-1, 0, 1]
»0                      Maximize with 0. Get [0, 0, 1]
  ,                     Pair with
   «0$                    minimize with 0. Get [-1, 0, 0]
      S€                Sum €ach. Get [1, -1]
        ~               Inverse
          ¦               at element
         2                2. (list[2] = ~list[2]) Get [-1, 2]
           Ḥ            Unhalve (double, ×2). Get [-2, 4]
            ;           Concatenate with
             L            Length (3). Get [-2, 4, 3]
              Ṁ         Maximum of the list (4).
               <   ¤    Still less than
                2         two
                 *        raise to the power of
                  Ɠ       eval(input())

user202729
fonte
Parece que ~2¦pode ser ;~. EDIT: Feito.
user202729
@ user202729 Errado. Ainda assim, ;~$vai funcionar.
user202729
1

JavaScript (ES6), 114 bytes

Recebe entrada na sintaxe de currying (A)(n). Retorna um booleano.

A=>n=>!(A.reduce((a,x)=>[...a,...a.map(y=>[x,...y])],[[]]).some(a=>(s=eval(a.join`+`),s<0?~s:s)>>n-1)|A.length>>n)

Casos de teste

Arnauld
fonte
1

Clojure, 121 117 bytes

#(let[l(int(Math/pow 2(dec %2)))](every?(set(range(- l)l))(cons(count %)(for[i(vals(group-by pos? %))](apply + i)))))

Bem, isso foi um pouco idiota, dividir em valores positivos e negativos é muito melhor do que classificar. Original, mas surpreendentemente não muito mais:

#(let[l(int(Math/pow 2(dec %2)))S(sort %)R reductions](every?(set(range(- l)l))(concat[(count S)](R + S)(R +(into()S)))))

Isso funciona verificando somas de prefixo da sequência em ordem crescente e decrescente, acho que não é necessário gerar todas as combinações de elementos em A .

(into () S)é efetivamente o mesmo que (reverse S), à medida que as listas crescem da cabeça. Não consegui descobrir uma maneira de usar em consvez de concatquando há duas listas conspara. : /

NikoNyrh
fonte
1

Gelatina , 15 bytes

ŒPS€Ḥ;~$;LṀl2<Ɠ

Experimente online!

Explicação

ŒPS€Ḥ;~$;LṀl2<Ɠ ~ Monadic full program.

ŒP              ~ Powerset.
  S€            ~ The sum of each subset.
    Ḥ           ~ Double (element-wise).
     ;~$        ~ Append the list of their bitwise complements.
        ;L      ~ Append the length of the first input.
          Ṁ     ~ And get the maximum.
           l2   ~ Base-2 logarithm.
             <Ɠ ~ Is smaller than the second input (from stdin)?

Economizou 1 byte graças a caird coinheringaahing (lendo a segunda entrada de STDIN em vez de CLA).

Mr. Xcoder
fonte
@ user202729 Eu perguntei ao OP e não precisamos lidar com a lista vazia
Sr. Xcoder
0

Casca , 14 bytes

≥Lḋ▲ṁ§eLöa→DΣṖ

Ir com força bruta fazendo um loop sobre todas as sublistas, pois a divisão em partes positivas e negativas leva mais bytes. Experimente online!

Explicação

≥Lḋ▲ṁ§eLöa→DΣṖ  Implicit inputs, say A=[1,2,3,4,5] and n=5
             Ṗ  Powerset of A: [[],[1],[2],[1,2],..,[1,2,3,4,5]]
    ṁ           Map and concatenate:
                  Argument: a sublist, say S=[1,3,4]
            Σ     Sum: 8
           D      Double: 16
          →       Increment: 17
        öa        Absolute value: 17
     §eL          Pair with length of S: [3,17]
                Result is [0,1,1,3,1,5,2,7,..,5,31]
   ▲            Maximum: 31
  ḋ             Convert to binary: [1,1,1,1,1]
 L              Length: 5
≥               Is it at most n: 1
Zgarb
fonte