Знайдіть бінарний!


24

Ми визначаємо бінарний масив як масив, що задовольняє наступним властивостям:

  • це не порожньо
  • перше значення - a 1
  • останнє значення - a 1
  • всі інші значення є 0або1

Наприклад, масив [ 1, 1, 0, 1 ]є допустимим бінарним набором .

Завдання

Враховуючи не порожній масив A невід’ємних цілих чисел і додатне ціле число N , ваше завдання - знайти бінарний масив B довжиною N, який дозволяє генерувати А шляхом підсумовування необмеженої кількості копій B , зміщених на необмежену кількість позиції.

Приклад

A = [ 1, 1, 2, 4, 1, 2, 2, 1, 0, 1, 0, 1, 1, 0, 1 ]
N = 4

Для цього вводу бінарний масив B = [ 1, 1, 0, 1 ] буде коректною відповіддю, оскільки ми можемо зробити:

  [ 1, 1, 0, 1 ]
+       [ 1, 1, 0, 1 ]
+       [ 1, 1, 0, 1 ]
+          [ 1, 1, 0, 1 ]
+                   [ 1, 1, 0, 1 ]
+                                  [ 1, 1, 0, 1 ]
  -----------------------------------------------
= [ 1, 1, 2, 4, 1, 2, 2, 1, 0, 1, 0, 1, 1, 0, 1 ]

Правила

  • Введення даних може бути здійснено у будь-якому розумному форматі.
  • Вихідним може бути власний масив (наприклад [1, 1, 0, 1]) або двійковий рядок з роздільником або без нього (наприклад, "1,1,0,1"або "1101")
  • Вам потрібно роздрукувати або повернути один дійсний бінарний набір . Крім того, ви можете вибрати, щоб надрукувати або повернути їх усі, коли існує декілька рішень.
  • Вам не потрібно підтримувати входи, які не призводять до жодного рішення.
  • Сума може включати в себе неявні нулі , які не перетинаються з будь-копією B . Другий нуль у наведеній вище сумі - це такий неявний нуль.
  • Можна припустити, що максимальний розмір A становить 100, а максимальний розмір B - 30.
  • Це код-гольф, тому найкоротша відповідь у байтах виграє. Стандартні лазівки заборонені.

Тестові справи

Input : N = 1 / A = [ 1, 2, 3, 4, 5 ]
Output: [ 1 ]

Input : N = 2 / A = [ 1, 2, 100, 99 ]
Output: [ 1, 1 ]

Input : N = 3 / A = [ 1, 1, 1 ]
Output: [ 1, 1, 1 ]

Input : N = 3 / A = [ 1, 1, 3, 2, 2 ]
Output: [ 1, 1, 1 ]

Input : N = 3 / A = [ 1, 0, 2, 1, 1, 1, 0, 0, 1, 0, 1 ]
Output: [ 1, 0, 1 ]

Input : N = 4 / A = [ 1, 2, 2, 2, 1 ]
Output: [ 1, 1, 1, 1 ]

Input : N = 4 / A = [ 1, 1, 2, 4, 1, 2, 2, 1, 0, 1, 0, 1, 1, 0, 1 ]
Output: [ 1, 1, 0, 1 ]

Input : N = 4 / A = [ 1, 1, 0, 2, 1, 0, 1 ]
Output: [ 1, 0, 0, 1 ] or [ 1, 1, 0, 1 ]

Input : N = 5 / A = [ 1, 3, 6, 9, 8, 6, 3, 4 ]
Output: [ 1, 1, 1, 0, 1 ]

Input : N = 8 / A = [ 2, 1, 0, 2, 3, 3, 1, 2, 1 ]
Output: [ 1, 0, 0, 1, 1, 1, 0, 1 ]

Input : N = 10 / A = [ 1, 2, 1, 2, 2, 1, 3, 3, 3, 2, 3, 0, 2, 1, 1, 0, 1 ]
Output: [ 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 ]

Input : N = 13 / A = [ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 ]
Output: [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ]

Input : N = 5 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 1, 1, 1, 1 ]

Input : N = 6 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 0, 0, 0, 0, 1 ]

Input : N = 7 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 1, 0, 0, 0, 1, 1 ]

Input : N = 9 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 0, 1, 0, 1, 0, 1, 0, 1 ]

Яке найбільше значення Nмає розумно підтримувати?
Ніл

@Neil Я додав обмеження розміру як на А, так і на Б.
Арнольд

1
@ fəˈnɛtɪk Можливо, але для цього N=4, A = [ 1, 1, 2, 4, 1, 2, 2, 2, 1, 2, 2, 1, 2, 0, 1 ]ви отримаєте 30459, що ділиться як на 11, так і на 13, але лише один із них [ 1, 1, 0, 1 ]і [ 1, 0, 1, 1 ]є правильною відповіддю.
Ніл

1
@ fəˈnɛtɪk Ці числа не записані у базі 2, тому правила арифметики не застосовуються. Наприклад, ви явно не можете перенести додавання.
BallpointBen

2
Будь ласка, додайте ці тестові випадки, які, здається, порушують майже всі опубліковані відповіді: N = 3, A = [1, 0, 2, 0, 2, 0, 1], вихід = [1, 0, 1]; N = 3, A = [1, 1, 1, 0, 0, 0, 1, 1, 1], вихід = [1, 1, 1].
Anders Kaseorg

Відповіді:


8

PHP, 105 92 90 86 байт

Рішення Йорга зафіксовано та гольф:

for($b=1+2**$argv[1];;)--$argc>1?$s+=$argv[$argc]*2**$i++:$s%($b-=2)||die(decbin($b));

бере Nз першого аргументу командного рядка значення після цього; запустити -rабо випробувати його в Інтернеті .
друкує двійкове число (формат 10001); друкує недійсне рішення або закінчується мертвим, якщо немає дійсного рішення.

перша версія (зараз 97 байт), яка нічого не друкує за недійсний ввід: протестуйте її в Інтернеті

for($b=1+$m=2**$argv[1];$m/2<=$b;)--$argc>1?$s+=$argv[$argc]*2**$i++:$s%($b-=2)||die(decbin($b));

зламатися

for($b=1+$m=2**$argv[1];$m/2<=$b;)  # second loop: loop $b from 2^N-1 by -2 to 2^(N-1)
--$argc>1                           # first loop: decrease $argc ...
    ?$s+=$argv[$argc]*2**$i++           # while $argc>1: binary sum from last to 2nd argument
    :$s%($b-=2)||die(decbin($b));       # later: if $b divides $s, print in binary and exit

Приємно, ви не могли досягти кількості байтів до 100?
Йорг Гюльсерманн

1
@ JörgHülsermann Я міг.
Тит

Важка думка. Я до цього знаю, що ти кращий. Я сподіваюсь, що ви зможете утримувати найнижчий байт
Йорг Гюльсерманн,

1
На N = 3, A = [1, 0, 2, 0, 2, 0, 1], це неправильно повертається111 там, де єдино правильний результат [1, 0, 1].
Андерс Касеорг

8

PHP , 219 байт

<?for(list($g,$z)=$_GET,$d=~-$l=2**$z;$d>=$l/2;max(array_diff_assoc($r,$g)?:[0])?:$o[]=$b,$d-=2)for($r=[],$b=decbin($d),$k=0;$k<count($g);$k++)for($u=$g[$k]-$r[$k],$i=0;$i<$z;$i++)$u<1?:$r[$k+$i]+=$u*$b[$i];print_r($o);

Спробуйте в Інтернеті!

-4 байти, використовуючи [$g,$z]=$_GETPHP 7.1 замістьlist($g,$z)=$_GET


Схоже, він видає і дійсну ( [1,0,1,0,1,0,1,0,1]), і недійсну відповідь ( [1,0,0,0,1,0,1,1,1]) для останнього тестового випадку.
Арнольд

-8 байт: while($_GET[0])$s+=2**$i++*array_pop($_GET[0]);. -5 байт: range(1|.5*$m=2**$_GET[1],$m,2).
Тит

@Arnauld Так, я повинен надати як результат лише найвищий бінарний набір, щоб зробити це рішення дійсним
Jörg Hülsermann

2
@ fəˈnɛtɪk Я згоден з вашою математикою, але завдання полягає в тому, щоб знайти шаблон, який можна точно підсунути А, а не еквівалентному розташуванню. Ось ми б дісталися [ 1,0,1,1,1,0,2,2,2,2,2,1 ].
Арнольд

1
-1 байт с for($g=$_GET[0];$g;).
Тит

3

Пітон, 166 байт

def f(a,n):
 for i in range(1<<n-1,1<<n):
  b=bin(i)[2:];u,v=(int(('0{:0>%d}'%sum(a)*len(s)).format(*s))for s in[a,b])
  if u%v<1>int(str(u//v*10)[::~sum(a)]):yield b

Спробуйте в Інтернеті!

Як це працює

Розглянемо A і B як цифри базових k чисел u і v . Наприклад ( для ілюстрації ми будемо використовувати k = 1000):

A = [1, 2, 1, 3, 2, 1, 2]
B = [1, 0, 0, 1]
u = 1 002 001 003 002 001 002
v = 1 000 000 001

Як зауважили багато інших відповідників, якщо B - правильна відповідь, то u ділиться на v . В цьому випадку,

u = 1 002 001 002 ⋅ v

Цей коефіцієнт, перекладений назад до масиву [1, 2, 1, 2], точно говорить нам, скільки копій B нам потрібно перенести на кожну позицію.

  [1, 0, 0, 1]
+    [1, 0, 0, 1]
+    [1, 0, 0, 1]
+       [1, 0, 0, 1]
+          [1, 0, 0, 1]
+          [1, 0, 0, 1]
-----------------------
  [1, 2, 1, 3, 2, 1, 2]

(Чому? Тому що саме так триває множення в базі k .)

Що інші відповіді не помітили, це те, що вищезазначена умова недостатня . Наприклад:

A = [1, 2, 1, 3, 2, 1, 2]
B = [1, 1, 1, 1]
u = 1 002 001 003 002 001 002
v = 1 001 001 001
u = 1 000 999 002 ⋅ v

Математично кажучи, ми все ще можемо перенести цей коефіцієнт назад у масив [1, 1, -1, 2], який добре працює, якщо нам дозволяють використовувати негативні копії B:

  [1, 1, 1, 1]
+    [1, 1, 1, 1]
       [1, 1, 1, 1]
+          [1, 1, 1, 1]
+          [1, 1, 1, 1]
-----------------------
  [1, 2, 1, 3, 2, 1, 2]

але звичайно виклик не дозволяє негативні копії. Тож нам потрібна додаткова перевірка.

З цією метою ми вибираємо основу k = 10 e, де k > 10 ⋅ сума (A), і перевіряємо, що жоден з цифр базового k не переливається в наступний базовий k, коли множимо коефіцієнт на десять. Тобто, кожен е й база десять цифри, починаючи з кінцем, в десятковому поданні раз фактормодулей десять, повинно бути 0. Це гарантує , що фактор переводить назад в масив з невід'ємними елементами.


1
Мені подобається твій фокус використання великої потужності 10 в якості основи для полегшення перетворення бази.
Ніл

2

PHP, 213 байт

Точно так само трохи гольфували

<?for($b=2**~-$l=$_GET[1];$b<2**$l;array_filter($t[$b++])?:$d[]=$o)for($g=count($t[$b]=$_GET[$i=0]);min($t[$b])>-1&$i<=$g-$l;$i++)for($e=$t[$b][$i],$k=0,$o=decbin($b);$k<$l;)$t[$b][$k+$i]-=$o[$k++]*$e;print_r($d);

Спробуйте в Інтернеті!

PHP, 344 байтів, що працюють вперше

Після своєї першої відповіді я вирішив зробити більш довгу спробу, щоб повернути всі дійсні рішення.

<?foreach(range(2**($l=$_GET[1])-1,2**($l-1))as$b){$t[$b]=($g=$_GET[0]);for($i=0;$t[$b]&&$i<=count($g)-$l;$i++){$e=reset($y=array_slice($t[$b],$i,$l));foreach(str_split(decbin($b))as$k=>$v)$t[$b][$k+$i]=$y[$k]-$e*$v;if(min($t[$b])<0)unset($t[$b]);}}foreach($t as$k=>$v)if(max($v)>0)unset($t[$k]);echo join(",",array_map(decbin,array_keys($t)));

Інтернет-версія

Зламатися

foreach(
    range(2**($l=$_GET[1])-1
    ,2**($l-1)
    ) # make decimal range of a binarray with given length
    as$b){
$t[$b]=($g=$_GET[0]); # make a copy for each possible solution pattern
    for($i=0;$t[$b]&&$i<=count($g)-$l;$i++){ # Loop till solution is valid or reach last digit
        $e=reset($y=array_slice($t[$b],$i,$l)); # take first value of a sequence with the length
        foreach(str_split(decbin($b))as$k=>$v)
            $t[$b][$k+$i]=$y[$k]-$e*$v; # replace values in copy
        if(min($t[$b])<0)unset($t[$b]); # kill solution if a minimum <0 exists
    }
}
foreach($t as$k=>$v)if(max($v)>0)unset($t[$k]); # drop all solutions where the sum is not zero 


echo join(",",array_map(decbin,array_keys($t))); #Output all solutions

Здається, це працює для N ≥ 2, але не вдається для N = 1 випадків, таких як перший тестовий випадок у виклику.
Anders Kaseorg

@AndersKaseorg Тепер він підтримує N = 1 Випадки, йому потрібно лише встановити a =в першому циклі для коротшої версії. У більшій версії йому потрібно видалити чотири байти
Jörg Hülsermann

1

Пітон, 205 байт

def f(a,l):
 b=lambda s:b(s[:-1])*sum(a)*8+int(s[-1])if s else 0
 c=lambda n:n and(n/sum(a)/4%2 or c(n/sum(a)/8))
 for i in range(2**~-l,2**l):
  j=bin(i)[2:]
  if b(a)%b(j)<1 and not c(b(a)/b(j)):return j

Повертає двійковий рядок без роздільника. Як зазначає @AndersKaseorg, є вхідні дані, для яких рішення @ fəˈnɛtɪk не працює, оскільки поділ представляє негативний коефіцієнт, який заборонено. Щоб вирішити це, я використовую дуже велику базу і перевіряю, що в підрозділі немає позики.


Гаразд, я думаю, що це фактичний контрприклад: f([1, 1, 1, 0, 0, 0, 1, 1, 1], 3)неправильно повертається 101.
Anders Kaseorg

@AndersKaseorg Хм, чи допомагає змінити порядок циклу, чи алгоритм все ще принципово порушений?
Ніл

Я думаю, що це принципово порушено без додаткових перевірок. Зворотний варіант не працює f([1, 0, 2, 0, 2, 0, 1], 3), і передній і зворотний варіанти вимикаються f([1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0], 5).
Anders Kaseorg

І навіть якщо ви перевірите, що iце непарно, і передній, і зворотний варіанти не вмикаються f([1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]*10, 5).
Anders Kaseorg

1
@AndersKaseorg Ага так, коли gcd (k, n) = 1, (x^kn-1)/(x^k-1)завжди є (x^n-1)/(x-1)фактором, який дурить рішення @ fəˈnɛtɪk у будь-якій базі.
Ніл

1

Pyth, 32 байти

f!|%FKiRJysQ,QT>#sQj/FKJ+L1^U2tE

Спробуйте в Інтернеті

Як це працює

                           ^U2tE   Cartesian power [0, 1]^(N - 1)
                        +L1        prepend 1 to every list
f                                  filter for lists T such that:
          sQ                         sum(A)
         y                           double
        J                            assign to J
      iR    ,QT                      convert [A, T] from base J
     K                               assign to K
   %F                                fold modulo
  |                                  logical OR with
                    /FK                fold integer division over K
                   j   J               convert to base J
               >#sQ                    filter for digits greater than sum(A)
 !                                   logical NOT

Стратегія схожа на мою відповідь Python , за винятком того, що оскільки Pyth має вбудовані для базової конверсії, ми можемо використовувати більш ефективну базу k = 2 ⋅ (A) і безпосередньо перевіряти, що кожна цифра коефіцієнта становить максимум суму (A ).


1

Парі / ГП , 77 74 96 80 байт

n->a->[v|d<-divisors(b=Pol(a)),(v=Vec(d))%2==v&&vecmin(Vec(b/d))>=0&&d%x&&#d==n]

Повертає всі рішення.

Спочатку перетворює масив aу многочлен b. Потім вибирає з дільників bмногочлени dтакі, що коефіцієнти dвсіх 1і 0, і коефіцієнти b / dвсіх невід'ємні, і d(0) = 1, і deg(d) = n + 1. Нарешті, перетворює їх назад у масиви.

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.