N-битное изменение в сумме подмножеств

14

Для другой задачи, которую я пишу, мне нужно проверить, что тестовые случаи разрешимы с ограниченными целыми числами. В частности, мне нужно проверить следующее для непустого массива целых Aи целочисленной битовой ширины n:

  1. Все числа aв Aудовлетворяют условию -2**(n-1) <= a < 2**(n-1)(представимых с nбитовых дополнением до двух целых чисел).
  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))

Попробуйте онлайн!

Mego
источник
Должны ли мы обрабатывать пустой список?
г-н Xcoder
@ Mr.Xcoder Нет, я уточню.
Мего

Ответы:

7

Wolfram Language (Mathematica) , 40 байт

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

Попробуйте онлайн!

Условие 1 подразумевается проверкой условия 3 для всех подмножеств, включая одноэлементные. Итак, мы берем максимум

  • двойная сумма каждого подмножества,
  • один менее чем в два раза отрицательнее суммы каждого подмножества, и
  • длина всего набора

и проверьте, если это меньше, чем 2^#2(где#2 ввод битовой ширины).

Цена всего-более байт, мы можем заменить Subsets@#с GatherBy[#,Arg], который является гораздо более эффективным , поскольку он вычисляет только два наихудших подмножества: подмножество всех неотрицательных значений, а подмножество всех значений отрицательных. (Это работает, потому что Argимеет значение для 0первого и πвторого.)

Миша лавров
источник
3

Желе , 19 байт

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

Попробуйте онлайн!

Достаточно проверить, что mapped sum of powerset + length of setнаходится в требуемом диапазоне.

Дрянная Монахиня
источник
1
Я думаю (хотя я не уверен), что вы можете использовать ÆẸвместо 2*$(не проверено)
г-н Xcoder
@ Mr.Xcoder Это работает.
user202729
3

05AB1E , 13 12 11 байтов

Сохранено 1 байт благодаря Mr. Xcoder

æ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
Emigna
источник
@ 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. Редактирование: Сохранено 12 17 байт благодаря @Arnauld.

Нил
источник
Гораздо лучше, чем мой наивный подход. :-) Это может быть сокращено до 61 байта
Арно
На самом деле, мы можем просто обработать тест в цикле для 56 байтов .
Арно
Взломан ([-2, -1, -2]) (3)
l4m2
@ l4m2 Хороший улов. Предлагаемое исправление (57 байт)
Арно
@ Arnauld Проблема в том, что это [-2, -2], 3должно быть правдой, нет?
Нил
1

Желе , 21 20 байт

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

Попробуйте онлайн!

Решение по линейной временной сложности. Оказывается, я переоценил сложность времени

в девятнадцатом байте, 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())

user202729
источник
Кажется что ~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)

Контрольные примеры

Arnauld
источник
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) , как списки растут из головы. Я не мог найти способ использовать consвместо concatдвух списков, consчтобы. : /

NikoNyrh
источник
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)?

Сохранено 1 байт благодаря совместному использованию caird (чтение второго ввода из STDIN вместо CLA).

Мистер Xcoder
источник
@ user202729 Я спросил OP, и нам не нужно обрабатывать пустой список
Mr. 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
Zgarb
источник