Послідовність збільшення набору


11

Фон

Зростаюча множинна послідовність порядку визначається як послідовність цілих наборів яка задовольняє наступному:S 1 , S 2 , , S nNS1,S2,,Sn

  • Кожен - це порожній підмножина . { 1 , 2 , , N }Si{1,2,,N}
  • Для , , тобто будь-які два послідовних набори не мають спільних елементів.S iS i + 1 = 1i<nSiSi+1=
  • Для середнє значення (середнє значення) суворо менше, ніж значення .S i S i + 11i<nSiSi+1

Виклик

Враховуючи додатне ціле число N, виведіть довжину найдовшої послідовної збільшеної послідовності порядку N.

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

Вони ґрунтуються на результатах проекту користувача Euler thunderre .

1 => 1 // {1}
2 => 2 // {1} {2}
3 => 3 // {1} {2} {3}
4 => 5 // {1} {2} {1,4} {3} {4}
5 => 7 // {1} {2} {1,4} {3} {2,5} {4} {5}
6 => 10 // {1} {2} {1,4} {3} {1,4,5} {2,3,6} {4} {3,6} {5} {6}
7 => 15 // {1} {2} {1,4} {3} {1,2,7} {3,4} {1,2,5,7} {4} {1,3,6,7} {4,5} {1,6,7} {5} {4,7} {6} {7}
8 => 21
9 => 29
10 => 39
11 => 49
12 => 63
13 => 79
14 => 99
15 => 121
16 => 145
17 => 171
18 => 203
19 => 237
20 => 277
21 => 321
22 => 369
23 => 419
24 => 477
25 => 537

Правила

Діють стандартні правила . Виграє найкоротше дійсне подання в байтах.

Баунті

Ця проблема обговорювалася тут на форумі Project Euler близько 4 років тому, але нам не вдалося розробити доцільний алгоритм поліноміального часу (з точки зору N). Тому я присуджую +200 баунті за перше подання, яке цього домагається, або доводжу його неможливість.


Я витратив більше тижня, намагаючись придумати алгоритм поліноміального часу або доказ твердості NP, використовуючи скорочення. Хтось тут просунувся в цьому?
Енріко Борба

Відповіді:


4

Брахілог , 28 байт

⟦₁⊇ᶠk⊇pSs₂ᶠ{c≠&⟨+/l⟩ᵐ<ᵈ}ᵐ∧Sl

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

Це справді чорт повільно. Триває близько 30 секунд N = 3, і не закінчилося через 12 хвилин N = 4.

Пояснення

⟦₁                             Take the range [1, …, Input]
  ⊇ᶠk                          Find all ordered subsets of that range, minus the empty set
     ⊇                         Take an ordered subset of these subsets
      pS                       Take a permutation of that subset and call it S
       Ss₂ᶠ                    Find all substrings of 2 consecutive elements in S
           {           }ᵐ      Map for each of these substrings:
            c≠                   All elements from both sets must be different
              &⟨+/l⟩ᵐ            And the average of both sets (⟨xyz⟩ is a fork like in APL)
                     <ᵈ          Must be in strictly increasing order
                         ∧Sl   If all of this succeeds, the output is the length of L.

Швидша версія, 39 байт

⟦₁⊇ᶠk⊇{⟨+/l⟩/₁/₁}ᵒSs₂ᶠ{c≠&⟨+/l⟩ᵐ<₁}ᵐ∧Sl

На моєму комп’ютері це займає близько 50 секунд N = 4.

Це та сама програма, за винятком того, що ми сортуємо підмножину підмножини за середнім рівнем замість того, щоб робити випадкову перестановку. Тому ми використовуємо {⟨+/l⟩/₁/₁}ᵒзамість цього p.

{         }ᵒ     Order by:
 ⟨+/l⟩             Average (fork of sum-divide-length)
      /₁/₁         Invert the average twice; this is used to get a float average

Нам потрібно отримати середнє плаваюче значення, тому що я щойно виявив смішну помилку, у якій плавці та цілі числа не порівнюються за значенням, а за типом із упорядкуванням предикатів (це також чому я використовую <ᵈі не <₁порівнюю обидва середні показники; останній вимагатиме, щоб подвійна інверсійна хитрість до роботи).


Я планував повільно пропрацювати свій шлях до вирішення цього (оскільки @JonathanAllan згадував це в іншому коментарі), але я, мабуть, тижнів позаду, щоб придумати щось подібне! Мені подобається, як (як і більшість відповідей Брахілога), врешті-решт, це виглядає як акуратне перетворення самого питання.
sundar

@sundar, ти завжди можеш повернутися до нього пізніше і спробувати знову знайти рішення!
Фаталізувати

3

CJam (81 байт)

{YY@#(#{{2bW%ee{)*~}%}:Z~{)Z__1b\,d/\a+}%$}%{_,1>{2ew{z~~&!\~=>}%0&!}{,}?},:,:e>}

Інтернет демо . Він повинен виконати для введення 4в розумний час, але я б не намагався це зробити з більш високими входами.

Розсічення

{                 e# Declare a block (anonymous function)
  YY@#(#          e# There are 2^N subsets of [0, N), but the empty subset is problematic
                  e# so we calculate 2^(2^N - 1) subsets of the non-empty subsets
  {               e# Map integer to subset of non-empty subsets:
    {             e#   Define a block to map an bitset to its set indices; e.g. 9 => [0 3]
      2bW%ee      e#     Convert to base 2, reverse, and index
      {)*~}%      e#     If the bit was set, keep the index
    }:Z           e#   Assign the block to variable Z
    ~             e#   Evaluate it
    {             e#   Map those indices to non-empty subsets of [0, N):
      )Z          e#     Increment (to skip the empty set) and apply Z
      __1b\,d/    e#     Sum one copy, take length of another, divide for average
      \a+         e#     Wrap the subset and prepend its average value
    }%
    $             e#   Sort (lexicographically, so by average value)
  }%
  {               e# Filter out subsets of subsets with conflicts:
    _,1>{         e#   If the length is greater than 1
      2ew         e#     Take each consecutive pair of subsets
      {           e#     Map:
        z~        e#       Zip and expand to get [score1 score2] [subset1 subset2]
        ~&!\      e#       No element in common => 1
        ~=        e#       Different scores => 0
        >         e#       1 iff both constraints are met
      }%
      0&!         e#     1 iff no consecutive pair failed the test
    }{
      ,           e#   Otherwise filter to those of length 1
    }?
  },
  :,:e>           e# Map to size of subset and take the greatest
}

1

JavaScript (ES6), 175 байт

Наївний і досить повільний рекурсивний пошук. На обчислення 7 перших термінів TIO потрібно 15 секунд.

n=>(a=[...Array(n)].reduce(a=>[...a,...a.map(y=>[x,...y],x=n--)],[[]]),g=(p,b=a,n)=>a.map(a=>(m=a.map(n=>s+=++k*b.includes(n)?g:n,s=k=0)&&s/k)>p&&g(m,a,-~n),r=r>n?r:n))(r=0)|r

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

або протестуйте цю модифіковану версію, яка виводить найдовшу послідовність збільшення набору.

Як?

Спочатку обчислюється Powerset з і зберігати його в :a{1,2,,n}a

a = [...Array(n)].reduce(a =>
  [...a, ...a.map(y => [x, ...y], x = n--)],
  [[]]
)

Рекурсивна частина:

g = (                         // g = recursive function taking:
  p,                          //   p = previous mean average
  b = a,                      //   b = previous set
  n                           //   n = sequence length
) =>                          //
  a.map(a =>                  // for each set a[] in a[]:
    (m = a.map(n =>           //   for each value n in a[]:
      s +=                    //     update s:
        ++k * b.includes(n) ? //       increment k; if n exists in b[]:
          g                   //         invalidate the result (string / integer --> NaN)
        :                     //       else:
          n,                  //         add n to s
      s = k = 0)              //     start with s = k = 0; end of inner map()
      && s / k                //   m = s / k = new mean average
    ) > p                     //   if it's greater than the previous one,
    && g(m, a, -~n),          //   do a recursive call with (m, a, n + 1)
    r = r > n ? r : n         //   keep track of the greatest length in r = max(r, n)
  )                           // end of outer map()

1

Python 3 , 205 197 184 182 байт

f=lambda N,c=[[1]]:max([len(c)]+[f(N,c+[n])for k in range(N)for n in combinations(range(1,N+1),k+1)if not{*c[-1]}&{*n}and sum(c[-1])/len(c[-1])<sum(n)/len(n)]);from itertools import*

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


197 байт, використовуючи sumзамість chain.from_iterable.
ов

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