Короткий найдовший збільшуючий наступний код


11

Завдання полягає в тому, щоб написати найкоротшу реалізацію, щоб знайти Найдовшу зростаючу послідовність .

Приклад : Нехай S - послідовність 1 5 7 1 8 4 3 5 [довжина S = 8]

  • У нас є 1 підпослідовність довжиною 0 [вважатимемо, що вона збільшується]
  • 6 підрядів довжиною 1 {1,5,7,8,4,3} [усі вони вважаються зростаючими]
  • (7 * 8) / 2 підрядки довжиною 2 [але ми видалимо дублікати], зростаючі підрядки знаходяться у сильному чорному кольорі.
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[зауважимо, що нас цікавлять лише суттєво зростаючі підрядки]

[ви не можете змінити порядок елементів всередині послідовності, тому в прикладі послідовності немає підрядів [37]

  • У нас збільшуються під послідовності довжиною 4, яка дорівнює 1578, але немає підпослідовності довжиною 5, тому ми вважаємо довжину найдовшої зростаючої під послідовності = 4.

Вхід :

a 1 a 2 ... a N (Послідовність)

всі числа є натуральними цілими числами, меншими ніж 10 3
N <= 1000

Вихід :

Одне ціле число, що позначає довжину найдовшої зростаючої підпослідовності вхідної послідовності.

sample input(1)
1 2 4 2 5
sample output(1)
4

sample input(2)
1 5 7 1 8 4 3 5
sample output(2)
4

Ваш код повинен працювати своєчасно, будь ласка, протестуйте свій код у цьому випадку, перш ніж надсилати його сюди (також посилання містить моє рішення 290 байтів c ++ 11)

Ви можете взяти вхід з файлу / stdin або як функціональний параметр, і ви можете або надрукувати вихід у файл / stdout, або просто повернути значення, якщо ви пишете функцію

Табло оцінки

  1. Dennis CJam - 22
  2. isaacg Pyth - 26
  3. Говард GolfScript - 35
  4. гордий haskeller Haskell - 56
  5. Рей Пітон 3 - 66
  6. гістократ Рубі - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. faubiguy Python 3 - 113

1
"У нас є 1 підпослідовність довжиною 0 [вважатимемо, що вона збільшується]". Ну, технічно у вас є нескінченна кількість підрядків 0-довжини :)
Cruncher

Насправді, я повинен змінити твердження, щоб усі "набори" повинні видалити дублікати, наприклад {1,5,7,1,8,4,3,5} має бути {1,5,7,8,4 , 3}, і тоді ми можемо сказати, що в "Наборі" є 1 0-довжина. спасибі
Mostafa 36a2

1
Чи слід для функцій рахувати байти зовнішньої функції ( function f(){...}) або внутрішньої функції (просто ...)? Якщо порахувати зовнішні функції, чи дозволяються анонімні функції?
Денніс

Ми рахуємо зовнішню функцію, а анонімні функції дозволені, але не пропустіть надати тестовану версію (повну версію з обробкою вводу / виводу)
Mostafa 36a2,

Відповіді:


2

CJam, 22 байти

1e3,q~{_2$<$0=(t}/$0=z

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

Приклад

$ cjam subsequence.cjam <<< '[2 1]'; echo
1
$ cjam subsequence.cjam <<< '[1 9 2 4 3 5]'; echo
4

Програма друкує 57для цього тестового випадку через 0,25 секунди.

Як це працює

Я взяв загальну думку з відповіді @ Ray .

1e3,    " Push the array [ 0 ... 999 ] (J).        ";
q~      " Read from STDIN and evaluate.            ";
{       " For each integer (I) of the input array: ";
  _2$<  " Push [ J[0] ... J[I - 1] ] (A).          ";
  $0=(  " Compute min(A) - 1.                      ";
  t     " Update J[I] with the value on the stack. ";
}/      "                                          ";
$0=     " Compute abs(min(J)).                     ";

5

Пітон 3, 66

Зауважимо, що всі числа знаходяться в діапазоні [1, 999], ми можемо використовувати масив, bщоб підтримувати найдовшу довжину послідовності, що закінчується кожним числом. b[x] = dозначає, що найдовша підрядність, що закінчується, xмає довжину d. На кожне число з вхідних даних ми оновлюємо масив за допомогою, b[x] = max(b[:x]) + 1і тоді ми закінчили роботу, прийнявши max(b)остаточно.

Часова складність є O (n) O (mn) , де mзавжди 1000 і nкількість вхідних елементів.

def f(a):
 b=[0]*1000
 for x in a:b[x]=max(b[:x])+1
 return max(b)

Нічого собі, схоже, що вже не прийнято :) Ви можете протестувати це за допомогою stdin / stdout, додавши рядок:

print(f(map(int,input().split())))

for x in a: max(b)виглядає досить O (n ^ 2).
Говард

@Howard Це O(1000 n)і 1000 - це константа. Ви також можете вважати це як O(m n).
Рей

3
З таким аргументом вся дискусія марна, тому що при обмеженому вкладі складність завжди O(1);-)
Говард

@Howard Я родом із світу ACM-ICPC, і це дещо умова. Ви можете думати це як O (mn). Він все ще відрізняється від O (n ^ 2). У будь-якому випадку, час, який це коштує, буде менше, ніж час запуску перекладача, тому я думаю, що це досить швидко.
Рей

Вражаючий короткий алгоритм! Я можу помітити лише один символ (принаймні при переході на Python 2): Ви можете надрукувати результат. printкоротше, ніж return.
Фалько

3

Пітон - 113

a=[]
for i in map(int,input().split()):
 if not a or i>a[-1]:a+=[i]
 z=0
 while a[z]<i:z+=1
 a[z]=i
print(len(a))

Прийнятий розчин. Ваш код перевірений тут і тут .
Мостафа 36а2

@ Mostafa36a2 Слово "прийнято" має інше значення на цьому веб-сайті. Я думаю, що ви маєте на увазі "прийнятне".
Рей

Вибачте, так, я мав на увазі прийнятне, занадто рано, щоб вибрати Прийняте.
Мостафа 36а2

За допомогою лінії a+=[i]*(a==[]or i>a[-1]);z=0та друку len(a)(без дужок) ви можете зберегти 4 символи.
Фалько

3

Піта , 26 29 33 39

J*]0^T3Fkyw=@JkheS:J0k)eSJ

Порт рішення @ ray. Проходить офіційні тести. Тепер використовується вхід STDIN, розділений пробілом, а не виклик функції.

Виконайте наступне:

./pyth.py -c "J*]0^T3Fkyw=@JkheS:J0k)eSJ" <<< "1 5 7 2 8 4 3 5"
4

Пояснення:

J*]0^T3                 J = [0]*10^3
Fkyw                    For k in space_sep(input()):
=@Jk                    J[k]=
heS:J0k                 max(J[0:k])+1
)                       end for
eSJ                     max(J)

Час необмежений:

Піт , 18

L?eS,ytbhyf>Thbbb0

Технічна примітка: Я помітив помилку в своєму компіляторі Pyth, коли писав цей гольф. Lне працював. Ось чому існує нещодавнє звернення до вищезгаданого сховища git.


ваш код не працює своєчасно для справи з великим списком (скажімо, 100 елемент)
Mostafa 36a2,

3
@ Mostafa36a2 Якщо ви хочете зробити вимогу часу виконання, будь ласка, скажіть це у запитанні та додайте тестовий чи два випадки. Якщо це просто коментар, то я згоден, це досить повільно.
isaacg

Вибачте, але я згадував, що це не час виконання, а принаймні [своєчасно], без проблем, якщо код займає 10-20 хвилин або навіть годину, але рішення O (2 ^ n) ніколи не дадуть результату протягом наше довге життя.
Мостафа 36а2

@ Mostafa36a2 Зрозумів, я щойно помітив цей рядок. Я буду працювати над удосконаленням.
isaacg

1
Вибачте, я зараз бачу оновлення, спробуйте цей випадок і скажіть, чи працює воно.
Мостафа 36а2

3

Clojure, 94 символи

Використовуючи підхід @ Ray до оновлення результатів у векторному елементі:

(defn g[s](apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s)))

За запитом, із заявою про друк (надрукує відповідь та поверне нуль). Вхід повинен бути вектором (g [1 2 3]) або списком (g '(1 2 3)):

(defn g[s](prn(apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s))))

чи можете ви додати твердження про друк, щоб зробити його тестуваним? Це не буде зараховано до рахунку.
Мостафа 36а2

1
Оновлено. Я запустив це на ваших великих прикладах, і отримав 58 і 57, як очікувалося.
YosemiteMark

Я думаю, вам все одно потрібно викликати функцію: p, але якщо ви її протестували, то цього достатньо.
Мостафа 36а2

3

Хаскелл, 58 57 56 символів

(x:s)%v|v>x=x:s%v|0<1=v:s
_%v=[v]
l s=length$foldl(%)[]s

Тут використовується алгоритм, який я бачив один раз в Інтернеті, але я не можу його знайти. На моєму комп’ютері з GHCi знадобиться непомітна кількість часу (можливо, це було б ще швидше, якби воно було складено).


Алгоритм, який ви згадали, такий же, як і у @faubiguy.
Рей

@Ray маєш рацію
гордий haskeller

2

GolfScript, 35 символів

~]]){1${~2$<*)}%1+$-1>[\+]+}/$-1=0=

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

Приклади:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2

1
@ MartinBüttner Це займає близько 5 секунд на 1000 номерів на моєму комп’ютері. Припустимо, що $це O (n log n), алгоритм - O (n ^ 2 log n).
Говард

будь ласка, спробуйте
ввійти

@ Mostafa36a2 я вже (див. Коментар раніше). Через 5 секунд він повертається на 58.
Говард

це ще один, він повинен повернути 57, тож якщо ваш код повернувся 57, то це прийнято :) Вітаємо
Mostafa 36a2

@ Mostafa36a2 Ага, тепер я бачу, що це два різних тестових випадки. Так, ваше друге посилання повертає 57, як і моє рішення на цьому вході.
Говард

2

Рубі, 67

s=Hash.new{|s,a|f,*r=a
s[a]=f ?[1+s[r.select{|x|x>f}],s[r]].max: 0}

Це працює за 30 секунд на великому вході, чи вважається це своєчасним? : с

Це груба рекурсія, але з певним запам'ятовуванням.


1
Так, це вчасно :)
Мостафа 36а2

2

C #, 172 92 символів

Нічого особливого, але я це зробив, і я зрозумів, що міг би також подати це.

int a(int[] j){int c=2,m=2,i=1;for(;++i<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?c:m;}return m;}

Дякуємо Арміну та Бобу за їх вдосконалення!


1
ви можете змінити параметр на int [], і тоді у вас буде менше символів, тому що вам не потрібно буде передавати рядок до int
Армін

2
Проміжки навколо =>не потрібні. Ви також можете перемістити i=0декларацію за межі forциклу, до int c=2,m=2,i=0;for(;. Ви також можете опустити брекети навколо forтіла, оскільки у вас є лише одна заява.
Боб

І c++;if(c>m)m=c;може бути m=c++>m?m:c;, і ви можете знову скинути брекети навколо цього.
Боб

1
Насправді ви також можете відмовитись від if(i>0)перевірки, зробивши forцикл починаючи з 1. Ви можете додатково скоротити int c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0)запропоновані раніше int c=2,m=2,i=0;for(;i++<j.Length;). Весь цей розділ можна перетворити на int c=2,m=2,i=0;for(;i++<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?m:c;}(використовуючи інший тернар для заміни останнього, що залишився if- правило великого пальця - це терени, які коротше, якщо ваше ifтіло просто завдання.
Боб

2
До жаль - помилка в моєму попередньому коментарі, m=c>m?m:cповинно бути m=c>m?c:m. А якщо додати в пропозицію @ Armin, ви отримаєте 92 байти, майже вдвічі зменшивши розмір! int a(int[] j){int c=2,m=2,i=0;for(;i++<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?c:m;}return m;}
Боб

2

J , 19 байт

[:#]`I.`[} ::,~/@|.

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

Працює в O (n log n) , використовуючи модифікований сорт терпіння, оскільки потрібна лише довжина, а не фактична послідовність.

Пояснення

[:#]`I.`[} ::,~/@|.  Input: array
                 |.  Reverse
               /     Reduce right-to-left
     I.                Find the index to insert while keeping it sorted
                       (uses binary search)
         }             Amend the current search array at that index with the next value
           ::          If error (when the index is not found)
             ,           Append the value at the end
 #                   Length of that array

1

Bash + coreutils, 131 байт

Це рішення страшенно не відповідає вимогам своєчасного способу , і навіть не особливо коротке, але мені сподобалося, що подібний варіант теоретично можливий у сценарії оболонки, тому я все-таки публікую повідомлення. Це працює з вічністю, що викликає вічність, часову складність O (2 ^ n).

s=${1//,/,:\},\{}
a=`eval echo "{$s,:}"`
for s in $a;{
b="$(tr , \\n<<<$s|grep -v :)"
sort -nC<<<"$b"&&wc -w<<<$b
}|sort -nr|sed 1q

Введення - це розділений комою список, переданий як єдиний аргумент командного рядка:

$ time ./slisc.sh 1,5,7,1,8,4,3,5
4

real    0m1.240s
user    0m0.518s
sys 0m0.689s
$ 

Розширення брекетів використовується для складання списку всіх можливих підрядів.

  • Перший рядок замінює коми на ,:},{, що створює подібний рядок1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • Другий рядок завершує цей рядок дужками, комами та крапками з комою, щоб надати це {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}. Це дійсне розширення bash brace, яке при evalредагуванні echoстворює цей розділений пробілом список1,5,7,1,8,4,3,5 1,5,7,1,8,4,3,: 1,5,7,1,8,4,:,5 1,5,7,1,8,4,:,: ...
  • за замовчуванням bash розбиває рядки з пробілом, тому ми переносимо цикл на кожен елемент цього списку:
    • коми замінюються новими рядками, потім видаляються рядки, що містять колонки, даючи списки, розділені новим рядком, для кожної можливої ​​послідовності
    • ми sort -Cперевіряємо на збільшення порядку, і якщо так, використовуємо wc -wдля друку довжини списку
  • отриманий список довжин списку сортується в зворотному порядку і друкується перше значення, щоб дати найбільшу збільшувальну довжину послідовності.

1

Стакс , 21 байт

ë/NS7Γ╥╚┌{1╤╒¬è¶²╢╦┌☼

Запустіть і налагоджуйте його

Це два тестові випадки, один з яких - це 1000-елементний випадок. Це працює на моїй машині за 24 секунди. Для цього типу проблем використовується класичний підхід до динамічного програмування.


0

J 34

Зауважте, що я читаю і стандартний ввід.

>./;+/@:*&.>(<*>.)/\&.><\.".1!:1]3

Не читаючи стандартного введення, м'ясо - 26 символів.

>./;+/@:*&.>(<*>.)/\&.><\.

Щойно помітив, міна працює повільно для великого вводу, о, добре.



0

C # (.NET Core) , 155 байт

Використовували масив для обчислення найбільш тривалої послідовності, що збільшується, що закінчується на кожній позиції вхідного масиву (динамічне програмування), а потім повертає найбільше значення. Наприклад, обчислюваний масив для введення [1,5,7,1,8,4,3,5]буде [1,2,3,1,4,2,2,3], і найбільше значення 4повертається.

int b(int[]x){int l=x.Length,r=1,i=0,j,c;var a=new int[l];a[0]=1;while(++i<l)for(j=0;j<i;j++){c=x[j]<x[i]?a[j]+1:1;a[i]=a[i]<c?c:a[i];r=r<c?c:r;}return r;}

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


0

Мова Вольфрама (Mathematica) , 38 байт

Length@LongestOrderedSequence[#,Less]&

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

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

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