Чарівні послідовності довжини n


11

Чарівна послідовність - це послідовність невід’ємних цілих чисел, x[0..n-1]така, що є саме x[i]випадкиi

Наприклад, 6,2,1,0,0,0,1,0,0,0 - це магічна послідовність, оскільки існує 6 0, 2 1 та ін.

Напишіть функцію, яка при заданні n видає всі магічні послідовності довжиною n


Виграє програма, яка може виробляти правильний вихід за найвище значення n протягом 10 секунд. (Хоча всі програми вітаються)

Наприклад, програма Аліси може вирішувати до n = 15 протягом 10 секунд, тоді як Боба може вирішити до n = 20 за той же час. Перемагає Боб.

Платформа: 2,7 ГГц @ 4 ЦП


5
Ласкаво просимо до PPCG! Це великий виклик, але вам потрібен критерій виграшу. Наприклад, можна сказати, що переможець - найкоротша програма.
Ypnypn

1
Відповідно: Номер
самопису

2
Будь ласка, не змінюйте критерій виграшу після опублікування відповідей. Крім того, це було набагато краще як кодовий гольф, ніж як найшвидший код, принаймні, на мою думку.
Олексій А.

2
@xnor ви можете почати, генеруючи цілі розділи n і перевіряючи, чи можуть вони бути самостійно описовими.
Мартін Ендер

2
Що найменшого n>5з розчином не форми [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]? Я подивився на нього n=20і не знайшов його, і цікаво, чи помиляюсь я.
xnor

Відповіді:


19

Пітон, n≈10 8

def magic_sequences(n):
    if n==4:
        return (1, 2, 1, 0),(2, 0, 2, 0) 
    elif n==5:
        return (2, 1, 2, 0, 0),
    elif n>=7:
        return (n-4,2,1)+(0,)*(n-7)+(1,0,0,0),
    else:
        return ()

Для цього використовується той факт, який я доведе, що єдиними магічними послідовностями довжини nє:

  • [1, 2, 1, 0]і [2, 0, 2, 0]дляn=4
  • [2, 1, 2, 0, 0] для n=5
  • [n-4, 2, 1, 0, 0, ..., 0, 0, 1, 0, 0, 0] для n>=7

Отож, для n>=7одного потрібно лише повернути величезний кортеж. Я можу це зробити приблизно n=10^8на своєму ноутбуці, що, ймовірно, обмежено пам'яттю; більше, і він замерзає. (Завдяки trichoplax за ідею використовувати кортежі, а не списки.) Або, якщо можна замість цього надрукувати словник ненульових записів, {0:n-4, 1:2, 2:1, (n-4):1}можна зробити це для ginormous n.

Я доводжу унікальність для n>=7; інші можна перевірити грубою силою чи справою.

Сума записів l- це загальна кількість всіх чисел списку, яка є його довжиною n. У списку є l[0]нулі і так n-l[0]ненульові записи. Але за визначенням l[0]має бути ненульовим або ми отримаємо протиріччя, і кожна з інших ненульових записів становить щонайменше 1. Це вже становить суму l[0] + (n-l[0]-1)*1 = n-1, що не відповідає загальній сумі n. Отже, не рахуючи l[0], може бути не більше одного 2 і жодного запису більше 2.

Але це означає, що єдиними ненульовими записами є l[0], l[1], l[2], and l[l[0]], значення яких максимум l[0]і перестановка 1,1,2, яка дає максимальну суму l[0]+4. Оскільки ця сума є n, яка становить щонайменше 7, ми маємо l[0]>=3і так l[l[0]]=1. Зараз є принаймні одне 1, що означає l[1]>=1, але якщо l[1]==1це інше 1, то l[1]>=2, що означає, що l[1]це одинокий 2. Це дає l[2]=1, і всі записи, що залишилися, є 0такими l[0]=n-4, що завершує рішення.


А мова - це ...?
edc65

@ edc65 Це схоже на python. Але я не впевнений.
Ісмаїл Мігель

4

Python 3, n≈40

def plausible_suffix(l,N):
    if sum(l)>N:
        return False

    pairs = [(N-1-i,l[i]) for i in range(len(l))]

    if sum(i*x for i,x in pairs)>N:
        return False

    num_remaining = N - len(l)

    for index, desired_count in pairs:
        count = l.count(index)
        more_needed = desired_count - count
        if more_needed<0: 
            return False
        num_remaining -= more_needed
        if num_remaining<0:
            return False
    return True

plausible_func = plausible_suffix

def generate_magic(N):
    l=[0]
    while l:
        extend = False
        if plausible_func(l,N):
            if len(l)==N:
                yield l[::-1]
            else:
                extend = True
        if extend:
            l.append(0)
        else:
            while l[-1]>=N-2:
                l.pop(-1)
                if not l:raise StopIteration
            l[-1]+=1

n=40 #test parameter

if n>0:
    for x in generate_magic(n):
        print(n,x)

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

  • Сума записів у суфіксі перевищує n(сума для всього списку повинна бути n)
  • Середньозважена сума i*l[i]суфікса перевищує n(сума для всього списку повинна бути n)
  • Будь-яке число з’являється в суфіксі більше разів, ніж суфікс говорить, що повинен
  • Кількість залишених незаповнених плям занадто мала, щоб враховувати всі номери, які повинні з’являтися більше разів.

У мене були оригінальні перевірені префікси зліва направо, але це йшло повільніше.

Виходи до n=30:

4 [1, 2, 1, 0]
4 [2, 0, 2, 0]
5 [2, 1, 2, 0, 0]
7 [3, 2, 1, 1, 0, 0, 0]
8 [4, 2, 1, 0, 1, 0, 0, 0]
9 [5, 2, 1, 0, 0, 1, 0, 0, 0]
10 [6, 2, 1, 0, 0, 0, 1, 0, 0, 0]
11 [7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0]
12 [8, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
13 [9, 2, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
14 [10, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
15 [11, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
16 [12, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
17 [13, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
18 [14, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
19 [15, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
20 [16, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
21 [17, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
22 [18, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
23 [19, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
24 [20, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
25 [21, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
26 [22, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
27 [23, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
28 [24, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
29 [25, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
30 [26, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

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


@Ypnypn У мене є спеціальна робота n=0. Я пропустив, що ми повертаємо результат за один n, не рахуючи їх n. Це мене змушує n=40.
xnor

0

Pyth - 15 байт

Застосовує грубу силу усіма можливими послідовностями лен nі потім фільтрує.

f.A.eq/TkYT^UQQ

Повне пояснення найближчим часом.

Спробуйте це онлайн .


2
FYI, ОП змінила критерій виграшу на найшвидший код.
Олексій А.

2
Незалежно від критерію виграшу, ось гольф на 3 байти: `fqm / TdQT ^ UQQ`
Jakube

0

К, 26 байт

{f@&{x~(+/x=)'!#x}'f:!x#x}

Як і підхід Мальтісена, груба сила. Серцем програми є присудок, який перевіряє, чи є даний вектор "магічним":

{x~(+/x=)'!#x}

Побудуйте вектор йоти до тих пір, як вхідний вектор ( !#x), порахуйте випадки кожної цифри ( (+/x=)') та порівняйте результат із вхідним вектором ( x~). Якщо є відповідність, у вас є магічна послідовність.

На жаль, цей перший удар здається досить повільним. Тестування за допомогою Kona на моєму ноутбуці займає близько 12 секунд, щоб обробити n = 7. Мені потрібно трохи більше подумати над цим.

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