サブセット合計のNビットバリエーション


14

私が書いている別の課題については、テストケースが有界整数で解けることを検証する必要があります。具体的には、空ではない整数の配列Aと整数のビット幅について、以下を検証する必要がありますn

  1. すべての整数aA満たされます-2**(n-1) <= a < 2**(n-1)n-bit 2の補数整数で表現可能)。
  2. の長さAは未満です2**n
  3. の合計はをA満たし-2**(n-1) <= sum(A) < 2**(n-1)ます。
  4. 要素のすべての組み合わせはA、上記のすべての条件を満たす。

当然、この問題を外部に委託することにしました!

整数の配列Aと正の整数ビット幅nを指定するとA、上記の条件を満たすことを確認します。

テストケース

[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

リファレンス実装(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))

オンラインでお試しください!



空のリストを処理する必要がありますか?
ミスターXcoder

@ Mr.Xcoderいいえ、明確にします。
Mego

回答:


7

Wolfram言語(Mathematica)、40バイト

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

オンラインでお試しください!

条件1は、1要素のものを含むすべてのサブセットの条件3をチェックすることで暗示されます。だから私たちは

  • 各サブセットの合計の2倍、
  • 各サブセットの合計の負の2倍未満、および
  • セット全体の長さ

それがより小さいかどうかを確認します2^#2#2ビット幅の入力はどこですか)。

唯一の6バイト以上のコストで、我々は交換することが可能Subsets@#GatherBy[#,Arg]、すべての非負値のサブセット、およびすべての負の値のサブセットは:それは2つだけ最悪の場合のサブセットを計算しますので、はるかに効率的です。(前者と後者にArg価値があるため、これは機能します。)0π



3

05AB1E13 12 11バイト

Mr. Xcoderのおかげで1バイト節約

æO·D±¹gMIo‹

オンラインでお試しください!

説明

æ             # 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:そうそう、ありがとう!(私は忘れて±
しまいます

2

JavaScript(ES6)、75 63 58バイト

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

のサブセットのa合計は負の要素と非負の要素の合計の間にあるため、ケース2を除くすべてについて2つの合計をチェックするだけで十分です。編集:@Arnauldのおかげで12 17バイトを保存しました。


私の素朴なアプローチよりもはるかに優れています。:-)これまで短縮することができた61バイト
アルノー

実際、56バイトのループ内でテストを処理するだけです。
アーナルド

ハッキングされた([-2、-1、-2])(3)
l4m2

@ l4m2良いキャッチ。修正案(57バイト)
アーナルド

@Arnauldここでの問題は、[-2, -2], 3真実であるべきだということですよね?
ニール

1

ゼリー21 20バイト

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

オンラインでお試しください!

線形時間複雑性ソリューション。時間の複雑さを過大評価していたことが判明

The Nineteenth Byte、2017-12-11 13-15-03Z、 by user202729

@NewSandboxedPosts「実際の」サブセット合計問題ははるかに困難です。これは線形時間で行うことができます...

配列の並べ替えが完全に不要であることに気付いたからです。


説明:

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


それはそう~2¦することができ;~。編集:完了。
user202729

@ user202729間違っています。それでも、;~$動作します。
user202729

1

JavaScript(ES6)、114バイト

カリー化構文の入力を受け取ります(A)(n)。ブール値を返します。

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)

テストケース



1

Clojure、121 117バイト

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

まあそれは少し馬鹿げていた、正と負の値に分割することは、ソートよりもはるかに優れています。オリジナルですが、驚くほど長くはありません:

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

これは、昇順および降順でシーケンスのプレフィックス合計をチェックすることで機能しAます。の要素のすべての組み合わせを生成する必要はないと思います。

(into () S)(reverse S)リストは先頭から大きくなるため、実質的にはと同じです。to に2つのリストがconsあるconcat場合の代わりに使用する方法がわかりませんでしたcons。:/


1

ゼリー、15バイト

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

オンラインでお試しください!

説明

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

caird coinheringaahing(CLAの代わりにSTDINから2番目の入力を読み取る)のおかげで1バイト節約されました


@ user202729私はOPを求めている、と私たちは空のリストを処理する必要はありません
氏Xcoder

0

、14バイト

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

正の部分と負の部分に分割するにはより多くのバイトが必要になるため、すべてのサブリストをループして総当たり攻撃を行います。 オンラインでお試しください!

説明

≥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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.