N-Bit-Variation der Teilmengen-Summe


14

Für eine weitere Herausforderung, die ich schreibe, muss ich überprüfen, ob Testfälle mit begrenzten ganzen Zahlen lösbar sind. Insbesondere muss ich Folgendes für ein nicht leeres Array von Ganzzahlen Aund eine ganzzahlige Bitbreite überprüfen n:

  1. Alle Ganzzahlen ain Aerfüllen -2**(n-1) <= a < 2**(n-1)(darstellbar mit n-bit zwei Komplement-Ganzzahlen).
  2. Die Länge von Aist weniger als 2**n.
  3. Die Summe von Aerfüllt -2**(n-1) <= sum(A) < 2**(n-1).
  4. Alle Kombinationen von Elementen Aerfüllen alle obigen Bedingungen.

Natürlich habe ich beschlossen, dieses Problem an Sie auszulagern!

Vergewissern Sie sich bei einem gegebenen Array von Ganzzahlen Aund einer positiven Ganzzahlbitbreite n, dass Adie obigen Bedingungen erfüllt sind.

Testfälle

[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

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

Probieren Sie es online!



Müssen wir mit der leeren Liste umgehen?
Mr. Xcoder

@ Mr.Xcoder Nein, das werde ich klären.
Mego

Antworten:


7

Wolfram Language (Mathematica) , 40 Byte

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

Probieren Sie es online!

Bedingung 1 wird impliziert, indem Bedingung 3 für alle Teilmengen, einschließlich der Ein-Element-Teilmengen, überprüft wird. Also nehmen wir das Maximum aus

  • die doppelte Summe jeder Teilmenge,
  • eins weniger als das Doppelte des Negativs der Summe jeder Teilmenge und
  • die Länge des ganzen Sets

und überprüfe, ob das weniger ist als 2^#2(wo #2ist die Bitbreiteneingabe).

Auf Kosten von nur 6 mehr Bytes, können wir ersetzen Subsets@#mit GatherBy[#,Arg], was viel effizienter ist , weil es nur die beiden schlimmsten Fall Teilmengen berechnet: die Teilmenge aller nicht - negative Werte und die Teilmenge aller negativen Werte. (Das funktioniert, weil Arges einen Wert für 0das erstere und πdas letztere hat.)



3

05AB1E , 13 12 11 Bytes

1 Byte gespart dank Mr. Xcoder

æO·D±¹gMIo‹

Probieren Sie es online!

Erläuterung

æ             # 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

@ Mr.Xcoder: Oh ja, danke! (Ich vergesse immer wieder ±)
Emigna

2

JavaScript (ES6), 75 63 58 Byte

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

Die Summe aller Teilmengen aliegt zwischen den Summen der negativen und der nichtnegativen Elemente. Die Überprüfung der beiden Summen ist also für alle Elemente mit Ausnahme von Fall 2 ausreichend. Bearbeiten: Dank @Arnauld 12 bis 17 Byte gespeichert.


Weitaus besser als meine naive Herangehensweise. :-) Dies könnte auf 61 Bytes
Arnauld

Tatsächlich können wir den Test nur innerhalb der Schleife für 56 Bytes verarbeiten .
Arnauld

Gehackt am ([-2, -1, -2]) (3)
14m2

@ l4m2 Guter Fang. Vorgeschlagener Fix (57 Bytes)
Arnauld

@Arnauld Das Problem hier ist, dass [-2, -2], 3das wahr sein sollte, nein?
Neil

1

Jelly , 21 bis 20 Bytes

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

Probieren Sie es online!

Lineare Zeitkomplexitätslösung. Es stellte sich heraus, dass ich die zeitliche Komplexität überschätzt habe

im neunzehnten Byte, 2017-12-11 13-15-03Z, von user202729

@NewSandboxedPosts "Echte" Teilmengenprobleme sind viel schwerer. Dies kann in linearithmischer Zeit erfolgen ...

denn jetzt ist mir klar, dass das Sortieren des Arrays völlig unnötig ist.


Erläuterung:

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


Scheint ~2¦so ;~. EDIT: Fertig.
user202729

@ user202729 Falsch. Trotzdem ;~$wird es funktionieren.
user202729

1

JavaScript (ES6), 114 Byte

Übernimmt Eingaben in der Currying-Syntax (A)(n). Gibt einen Booleschen Wert zurück.

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)

Testfälle



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

Nun, das war ein bisschen doof. Das Aufteilen in positive und negative Werte ist viel besser als das Sortieren. Originell, aber überraschenderweise nicht mehr lange:

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

Dies funktioniert, indem die Präfixsummen der Sequenz in aufsteigender und absteigender Reihenfolge überprüft werden. Ich denke, es ist nicht erforderlich, alle Kombinationen von Elementen in zu generieren A.

(into () S)ist in der Tat dasselbe wie (reverse S), wenn Listen aus dem Kopf wachsen. Ich konnte keinen Weg finden, consstatt concatzwei Listen conszu verwenden. : /


1

Gelee , 15 Bytes

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

Probieren Sie es online!

Erläuterung

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

1 Byte gespart dank Caird Coinheringaahing (Lesen der zweiten Eingabe von STDIN anstelle von CLA).


@ user202729 Ich habe das OP gefragt, und wir müssen die leere Liste nicht bearbeiten
Mr. Xcoder

0

Schale , 14 Bytes

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

Gehen Sie mit brachialer Gewalt vor, indem Sie alle Unterlisten durchlaufen, da die Aufteilung in positive und negative Teile mehr Bytes erfordert. Probieren Sie es online!

Erläuterung

≥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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.