Бінарні огорожі


16

Вхід:

  • Ціле число nв діапазоні2 <= n <= 10
  • Список натуральних чисел

Вихід:

Перетворіть цілі числа у їх бінарне подання (без жодних провідних нулів) та з'єднайте їх усі разом.
Потім визначте всі бінарні підрядки, які утворюють "двійковий огорожу", використовуючи nкількість огорож. Пробіли (нулі) між кожним стовпом огорожі не мають значення (принаймні 1), але самі огорожі повинні бути однакової ширини.
Тут регулярні вирази двійкових підрядків повинні відповідати кожному n:

n   Regex to match to be a 'binary fence'   Some examples

2   ^(1+)0+\1$                              101; 1100011; 1110111;
3   ^(1+)0+\10+\1$                          10101; 1000101; 110011011;
4   ^(1+)0+\10+\10+\1$                      1010101; 110110011011; 11110111100001111001111;
etc. etc. You get the point

Дивлячись на n=4приклади:

1010101
^ ^ ^ ^    All fence posts have a width of one 1
 ^ ^ ^     with one or more 0s in between them

110110011011
^^ ^^  ^^ ^^    All fence posts have a width of two 1s
  ^  ^^  ^      with one or more 0s in between them

11110111100001111001111
^^^^ ^^^^    ^^^^  ^^^^    All fence posts have a width of four 1s
    ^    ^^^^    ^^        with one or more 0s in between them

Потім ми виводимо числа, що використовують двійкові цифри збігів 'бінарні огорожі'.

Приклад:

Вхідні дані : n=4,L=[85,77,71]

Двійкове представлення цих цілих чисел, об'єднаних разом:
1010101 1001101 1000111(ПРИМІТКА: Пробіли додаються лише як пояснення для прикладу).

Оскільки n=4ми шукаємо підрядки, що відповідають регексу (1+)0+\10+\10+\1, і в цьому випадку ми можемо знайти дві:
1010101(у положенні (1010101) 1001101 1000111); і 11001101100011(в положенні 101010(1 1001101 100011)1)

Перший бінарний паркан використовує лише двійкові цифри від 85, а другий бінарний паркан використовує двійкові цифри з усіх трьох цілих чисел. Отже, вихід у цьому випадку буде:
[[85],[85,77,71]]

Правила виклику:

  • Хоча це також згадується у наведеному вище прикладі, останнє речення є важливим: ми виводимо числа, для яких використовуються двійкові цифри у підрядку "двійковий паркан".
  • Введення / виведення гнучко. Введенням може бути список / масив / потік цілих чисел, пробіл / кома / рядок з обмеженим рядком і т.д. Все залежить від вас, але, будь ласка, вкажіть, що ви використали у своїй відповіді.
  • Порядок виведення списку сам по собі не має значення, але вихід кожного внутрішнього списку, звичайно, у тому ж порядку, що і список введення. Отже, з наведеного вище прикладу [[85,77,71],[85]]є і допустимим результатом, але [[85],[77,85,71]]це не так.
  • Як ви вже помітили з прикладу ( 85), двійкові цифри можуть використовуватися кілька разів.
  • Режекси повинні повністю відповідати підрядці. Так 110101чи 010101ніколи не є дійсними «бінарними огорожами» ( 10101проте, iff n=3).
  • Елементи у списку вихідних даних не є унікальними, лише бінарні позиції «бінарних огорож» є унікальними. Якщо кілька «двійкових огорож» можна створити з однаковими цілими числами, ми додаємо їх кілька разів до списку вихідних даних.
    Наприклад: n=2, L=[109, 45](двійковий 1101101 101101) може формувати ці підрядка «довічного забору»: 11011(в положенні (11011)01 101101); 101(в положенні 1(101)101 101101); 11011(в положенні 110(1101 1)01101); 101(в положенні 1101(101) 101101); 11011(в положенні 110110(1 1011)01); 101(в положенні 1101101 (101)101); 101(у положенні 1101101 101(101)), тож вихід був би [[109],[109],[109,45],[109],[109,45],[45],[45]].
    Інший приклад: n=2, L=[8127](двійковий 1111110111111) може формувати ці підрядка «довічного забору»: 1111110111111(в положенні (1111110111111));11111011111(в положенні 1(11111011111)1); 111101111(в положенні 11(111101111)11); 1110111(в положенні 111(1110111)111); 11011(в положенні 1111(11011)1111); 101(у положенні 11111(101)11111), тож вихід був би [[8127],[8127],[8127],[8127],[8127],[8127]].
  • Якщо дійсна вихід неможливо, ви можете повернути порожній список або який - або інший вид продукції falsey ( null, false, видає повідомлення про помилку і т.д. Знову ж , ваш виклик).

Загальні правила:

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам з кодовим гольфом відштовхувати вас від публікації відповідей з мов, що не кодують гольф. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Стандартні правила застосовуються до вашої відповіді, тому вам дозволяється використовувати STDIN / STDOUT, функції / метод із відповідними параметрами та повним програмами типу повернення. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду (тобто TIO ).
  • Також настійно рекомендується додавати пояснення до своєї відповіді.

Тестові приклади:

Input:                       Output
                             (the binary below the output are added as clarification,
                             where the parenthesis indicate the substring matching the regex):

4, [85,77,71]                [[85],[85,77,71]]
                             (1010101) 1001101 1000111; 101010(1 1001101 100011)1

2, [109,45]                  [[109],[109],[109,45],[109],[109,45],[45],[45]]
                             (11011)01 101101; 1(101)101 101101; 110(1101 1)01101; 1101(101) 101101; 110110(1 1011)01; 1101101 (101)101; 1101101 101(101)

3, [990,1,3,3023,15,21]      [[990,1,3,3023],[990,1,3,3023],[1,3,3023],[21]]
                             (1111011110 1 11 1)01111001111 1111 10101; 11110(11110 1 11 101111)001111 1111 10101; 1111011110 (1 11 101111001111) 1111 10101; 1111011110 1 11 101111001111 1111 (10101)

2, [1,2,3,4,5,6,7,8,9,10]    [[1,2,3],[2,3],[4,5],[5],[5,6,7],[6,7],[6,7],[8,9],[9],[10]]
                             (1 10 11) 100 101 110 111 1000 1001 1010; 1 (10 1)1 100 101 110 111 1000 1001 1010; 1 10 11 (100 1)01 110 111 1000 1001 1010; 1 10 11 100 (101) 110 111 1000 1001 1010; 1 10 11 100 10(1 110 111) 1000 1001 1010; 1 10 11 100 101 (110 11)1 1000 1001 1010; 1 10 11 100 101 1(10 1)11 1000 1001 1010; 1 10 11 100 101 110 111 (1000 1)001 1010; 1 10 11 100 101 110 111 1000 (1001) 1010; 1 10 11 100 101 110 111 1000 1001 (101)0

3, [1,2,3,4,5,6,7,8,9,10]    [[4,5],[8,9]]
                             1 10 11 (100 101 )110 111 1000 1001 1010; 1 10 11 100 101 110 111 (1000 1001) 1010

10, [1,2,3,4,5,6,7,8,9,10]   []
                             No binary fences are possible for this input

6, [445873,2075]             [[445873,2075],[445873,2075],[445873,2075]]
                             (1101100110110110001 1)00000011011; 110(1100110110110001 100000011)011; 1101100(110110110001 100000011011)

2, [8127]                    [[8127],[8127],[8127],[8127],[8127],[8127]]
                             (1111110111111); 1(11111011111)1; 11(111101111)11; 111(1110111)111; 1111(11011)1111; 11111(101)11111

2, [10,10]                   [[10],[10,10],[10]]
                             (101)0 1010; 10(10 1)010; 1010 (101)0

4, [10,10,10]                [[10,10],[10,10,10],[10,10]]
                             (1010 101)0 1010; 10(10 1010 1)010; 1010 (1010 101)0

Ах, шу, ти це опублікував так само, як почався клас!
Квінтек

Не [1,2,3]вірно для тестової вітрини 4? Я бачу паркан(1 10 11)
TFeld

1
Гаразд, я думаю, що цього разу зрозумів. Я не прочитав останнього речення прикладу досить уважно. (Оскільки це дуже важливо, можливо, його не слід згадувати в прикладі.)
Арнольд

1
@Arnauld Я додав останнє речення прикладу як перше правило зараз. Я сподіваюся, що це стане більш очевидним.
Кевін Кройсейсен

3
Я б запропонував додати тестовий випадок, коли одне ціле число відображається кілька разів у списку, наприклад, 2, [10, 10]який повинен призвести, [[10],[10,10],[10]]якщо я зрозумію виклик
truel.y

Відповіді:


5

Лушпиння , 33 байти

ṠṘmȯF-mȯ#öΛΛ=⁰Fzż+C2gQṁḋmëhohttIQ

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

Проходить усі тестові справи. Це було непростим викликом, і моє рішення відчуває дещо перекрученість.

Пояснення

Програма проходить цикл через фрагменти введення та повторюється кожен стільки разів, скільки містить відповідність регулярного вираження. Ми хочемо рахувати лише ті збіги, які перекривають двійкове розширення кожного числа в зрізі. Це здається важким, але простіше порахувати ті поєдинки, які не використовують перше число: просто видаліть це число і підрахуйте всі збіги. Щоб отримати хороші матчі, ми підраховуємо всі матчі, потім віднімаємо кількість збігів, які не використовують перше число, і ті, що не використовують останнє число. Матчі, які не використовують жодного, не рахуються двічі, тому ми повинні додати їх назад, щоб отримати правильний результат.

Підрахунок кількості збігів у фрагменті - це питання об'єднання бінарних розширень та перекидання на фрагменти результату. Оскільки у Husk немає підтримки для регулярних виразів, ми використовуємо маніпуляції зі списком для розпізнавання відповідності. Функція gрозбиває зріз на групи рівних сусідніх елементів. Тоді ми повинні перевірити наступне:

  1. Перша група - це 1-група.
  2. Кількість груп непарна.
  3. Кількість 1-х груп дорівнює першому вводу n.
  4. 1-групи мають однакову довжину.

Спочатку розрізаємо групи на пари. Якщо 1 і 2 утримуються, то перша група кожної пари - це 1-група, а остання пара - одиночна. Потім ми зменшуємо цей список пар, блискавично додаючи їх за допомогою складових компонентів. Це означає, що 1-групи та 0-групи додаються окремо. Додавання зберігає переливні елементи, тому додавання [1,1,1]і [1,1]дає [2,2,1]. Зіппінг цього не робить, тому якщо остання пара є однотонною, складова сума 0-груп випадає з результату. Нарешті ми перевіряємо, чи всі числа в результаті дорівнюють n.

ṠṘm(...)Q  First input is explicit, say 3, second is implicit.
        Q  List of slices.
  m(...)   Map this function (which counts good matches) over the slices
ṠṘ         and replicate each by the corresponding number.

F-m(...)mëhohttI  Count good matches. Argument is a slice, say [6,2,5].
         ë        Define a list of 4 functions:
          h        remove first element,
           oht     remove first and last element,
              t    remove last element,
               I   identity.
        m         Apply each: [[2,5],[2],[6,2],[6,2,5]]
  m(...)          Map function (which counts all matches): [0,0,1,2]
F-                Reduce by subtraction: 1
                  In Husk, - has reversed arguments, so this computes
                  M(x) - (M(tx) - (M(htx) - M(hx)))
                  where M means number of matches.

#(...)Qṁḋ  Count all matches. Argument is a slice.
       ṁ   Map and concatenate
        ḋ  binary expansions.
      Q    List of slices.
#(...)     Count number of truthy results of function (which recognizes a match).

ΛΛ=⁰Fzż+C2g  Recognize a match. Argument is list of bits, say [1,1,0,1,1,0,0,0,1,1].
          g  Group elements: [[1,1],[0],[1,1],[0,0,0],[1,1]]
        C2   Cut into pairs: [[[1,1],[0]],[[1,1],[0,0,0]],[[1,1]]]
    F        Reduce by
     z       zip (discarding extraneous elements) with
      ż      zip (preserving extraneous elements) with
       +     addition: [[3,3]]
Λ            For all lists
 Λ           all elements
  =⁰         are equal to first input.

7

Perl 6 , 114 112 110 107 106 104 байт

->\n,\L{L[map {[...] flat(^L Zxx(L>>.msb X+1))[.from,.to-1]},L.fmt('%b','')~~m:ov/(1+)<{"0+$0"x n-1}>/]}

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

Пояснення

->\n,\L{  # Anonymous block taking arguments n and L
 L[       # Return elements of L
   map {  # Map matches to ranges
    [...] # Create range from start/end pair
          # Map indices into binary string to indices into L
          flat(     # Flatten
               ^L   # indices into L
               Zxx  # repeated times
               (L>>.msb X+1)  # length of each binary representation
          )
          # Lookup start/end pair in map above
          [.from,.to-1]
   },
   L.fmt('%b','')  # Join binary representations
   ~~              # Regex match
   m:ov/(1+)<{"0+$0"x n-1}>/  # Find overlapping matches
 ]
}

4

JavaScript (ES6), 187 184 177 173 байт

Вводиться як " (n)(list). Повертає масив масивів.

n=>a=>(g=p=>(m=s.slice(p).match(`(1+)(0+\\1){${n-1}}`))?[a.filter((_,i)=>-~b[i-1]<p+m[0].length&b[i]>=p,p-=~m.index),...g(p)]:[])(s=[],b=a.map(n=>(s+=n.toString(2)).length))

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

Як?

Спочатку обчислюємо двійковий рядок с і список б що описує межі кожного числа в с.

s = [], b = a.map(n => (s += n.toString(2)).length)

Приклад:

                      (0)     7     13
                       v      v     v
a = [109, 45] --> s = "1101101101101" --> b = [7, 13]
                       \_____/\____/
                         109    45

Ми використовуємо наступний шаблон для створення регулярних виразів, що відповідають бінарним огорожам:

`(1+)(0+\\1){${n-1}}`

Цей регулярний вираз застосовується до с, починаючи з позиції p.

m = s.slice(p).match(`(1+)(0+\\1){${n-1}}`)

Почнемо з p=0 і оновлювати його на кожній ітерації відповідно до позиції попереднього матчу.

Кожен раз, коли матч м знайдено в с с: для кожного i-те число у вхідному масиві, ми перевіряємо, чи проходить інтервал його меж (зберігається в б) перекриває інтервал, зроблений з початкової та кінцевої позицій м в с.

a.filter((_, i) => -~b[i - 1] < p + m[0].length & b[i] >= p, p -= ~m.index)


1

Python 2 , 182 байт

lambda n,L,b='{:b}'.format:[zip(*set([t
for t in enumerate(L)for _ in b(t[1])][slice(*m.span(1))]))[1]for
m in re.finditer('(?=((1+)'+r'[0]+\2'*~-n+'))',''.join(map(b,L)))]
import re

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


Це, здається, дає помилку на будь-якому nвході, більший за 2. Крім того, навіть якщо n=2він дає неправильний результат для тестового випадку n=2, L=[10,10]. Інші тестові випадки з n=2роботою.
Кевін Кройсейсен

О, я бачу, чому це не вдається [10,10]; дозвольте мені побачити, як дорого це виправити…
Лінн

1
@KevinCruijssen Я виправив обидва питання (ціною 22 байти, добре!)
Лінн

0

05AB1E , 38 36 байт

Œvyy¨D¦y¦)bJεŒεγ0KDËsgIQyнyθP}}OÆFy,

Натхненний @Zgarb Husk .

Виведіть списки з обмеженим рядком

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

Π           # Get the sublists of the (implicit) input-list
 v           # Loop `y` over each sublist:
  y          #  Push `y`
  y¨         #  Push `y` with the last item removed
  D¦         #  Push `y` with the first and last items removed
  y¦         #  Push `y` with the first item removed
  )          #  Wrap all four into a list
   b         #  Get the binary-string of each integer
    J        #  Join each inner list together
     ε       #  Map each converted binary-string to:
      Π     #   Get all substrings of the binary-string
      ε      #   Map each binary substring to:
       γ     #    Split it into chunks of equal adjacent digits
       0K    #    Remove all chunks consisting of 0s
       DË    #    Check if all chunks consisting of 1s are the same
       sgIQ  #    Check if the amount of chunks of 1s is equal to the second input-integer
       yн    #    Check if the substring starts with a 1
       yθ    #    Check if the substring end with a 1
       P     #    Check if all four checks above are truthy for this substring
             #    (1 if truthy; 0 if falsey)
     }}      #  Close both maps
       O     #  Take the sum of each inner list
        Æ    #  Reduce the list of sums by subtraction
         F   #  Loop that many times:
          y, #   And print the current sublist `y` with a trailing newline
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.