Variación de N bits en suma de subconjuntos

14

Para otro desafío que estoy escribiendo, necesito verificar que los casos de prueba se puedan resolver con enteros acotados. Específicamente, necesito verificar lo siguiente, para una matriz no Aentera de enteros y un ancho de bit entero n:

  1. Todos los enteros aen Asatisf -2**(n-1) <= a < 2**(n-1)(representables con nlos enteros complementarios de dos bits).
  2. La longitud de Aes menor que 2**n.
  3. La suma de las Asatisfacciones -2**(n-1) <= sum(A) < 2**(n-1).
  4. Todas las combinaciones de elementos Asatisfacen todas las condiciones anteriores.

¡Naturalmente, he decidido externalizar este problema!

Dada una matriz de enteros Ay un ancho de bit entero positivo n, verifique que Acumpla con las condiciones anteriores.

Casos de prueba

[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

Implementación de referencia (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))

Pruébalo en línea!

Mego
fuente
Sandbox
Mego
¿Debemos manejar la lista vacía?
Sr. Xcoder
@ Mr.Xcoder No, lo aclararé.
Mego

Respuestas:

7

Wolfram Language (Mathematica) , 40 bytes

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

Pruébalo en línea!

La condición 1 está implícita al verificar la condición 3 para todos los subconjuntos, incluidos los de un elemento. Entonces tomamos el máximo de

  • dos veces la suma de cada subconjunto,
  • uno menos del doble del negativo de la suma de cada subconjunto, y
  • la longitud de todo el conjunto

y verifique si es menor que 2^#2(donde #2está la entrada de ancho de bits).

A costa de sólo 6 bytes más, podemos reemplazar Subsets@#con GatherBy[#,Arg], que es mucho más eficiente, ya que sólo computa los dos subconjuntos peor de los casos: el subconjunto de todos los valores no negativos, y el subconjunto de todos los valores negativos. (Esto funciona porque Argtiene un valor 0en el primero y πen el segundo).

Misha Lavrov
fuente
3

Jalea , 19 bytes

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

Pruébalo en línea!

Es suficiente verificar que mapped sum of powerset + length of setesté en el rango requerido.

Monja permeable
fuente
1
Yo creo (aunque no estoy seguro) se puede utilizar ÆẸen lugar de 2*$(no probado)
Sr. Xcoder
@ Mr.Xcoder funciona.
user202729
3

05AB1E , 13 12 11 bytes

Guardado 1 byte gracias al Sr. Xcoder

æO·D±¹gMIo‹

Pruébalo en línea!

Explicación

æ             # 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
fuente
@ Mr.Xcoder: ¡Oh sí, gracias! (Me sigo olvidando ±)
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)

La suma de cualquier subconjunto de amentiras entre las sumas de los elementos negativos y no negativos, por lo que verificar las dos sumas es suficiente para todo excepto el caso 2. Editar: Guardado 12 17 bytes gracias a @Arnauld.

Neil
fuente
Mucho mejor que mi enfoque ingenuo. :-) Esto podría acortarse a 61 bytes
Arnauld
En realidad, podemos procesar la prueba dentro del ciclo para 56 bytes .
Arnauld
Hackeado ([-2, -1, -2]) (3)
l4m2
@ l4m2 Buena captura. Arreglo sugerido (57 bytes)
Arnauld
@Arnauld El problema aquí es que [-2, -2], 3debería ser cierto, ¿no?
Neil
1

Jalea , 21 20 bytes

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

Pruébalo en línea!

Solución de complejidad de tiempo lineal. Resulta que sobreestimé la complejidad del tiempo

en El decimonoveno byte, 2017-12-11 13-15-03Z, por usuario202729

@NewSandboxedPosts El problema de suma de subconjuntos "real" es mucho más difícil. Este se puede hacer en tiempo linealitmico ...

porque ahora me doy cuenta de que ordenar la matriz es completamente innecesario.


Explicación:

»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())

usuario202729
fuente
Parece que ~2¦puede ser ;~. EDITAR: Listo.
user202729
@ user202729 Incorrecto. Aún así, ;~$funcionará.
usuario202729
1

JavaScript (ES6), 114 bytes

Toma entrada en la sintaxis de curry (A)(n). Devuelve un 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 prueba

Arnauld
fuente
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)))))

Bueno, eso fue un poco tonto, dividir en valores positivos y negativos es mucho mejor que ordenar. Original, pero sorprendentemente no mucho más:

#(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)))))

Esto funciona comprobando las sumas de prefijos de la secuencia en orden ascendente y descendente, creo que no es necesario generar todas las combinaciones de elementos A.

(into () S)es en efecto igual que (reverse S), a medida que las listas crecen desde la cabeza No pude encontrar una manera de usar en conslugar de concatcuando hay dos listas para conshacer. : /

NikoNyrh
fuente
1

Jalea , 15 bytes

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

Pruébalo en línea!

Explicación

Œ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)?

Guardado 1 byte gracias a caird coinheringaahing (leyendo la segunda entrada de STDIN en lugar de CLA).

Sr. Xcoder
fuente
@ user202729 He preguntado al OP, y nosotros no tenemos que manejar la lista vacía
Sr. Xcoder,
0

Casco , 14 bytes

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

Ir con fuerza bruta recorriendo todas las sublistas, ya que dividir en partes positivas y negativas requiere más bytes. Pruébalo en línea!

Explicación

≥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
fuente