Самый короткий самый длинный увеличивающийся код подпоследовательности

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)

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

Табло

  1. Деннис CJam - 22
  2. Исаакг Пиф - 26
  3. Говард Гольфск - 35
  4. гордый haskeller Haskell - 56
  5. Рэй Питон 3 - 66
  6. гистократ рубин - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. фаубигуй питон 3 - 113
Мостафа 36а2
источник
1
«У нас есть 1 подпоследовательность длины 0 [будет считать, что она увеличивается]», технически у вас есть бесконечное количество подпоследовательностей 0 длины :)
Cruncher
На самом деле, я должен изменить утверждение так, чтобы все «Наборы» должны были удалить дубликаты, например, {1,5,7,1,8,4,3,5} должно быть {1,5,7,8,4 , 3} и тогда мы можем сказать, что в «множестве» есть подпоследовательность длиной 1 0. спасибо
Мостафа 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 (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).
Говард
@ Ховард Это O(1000 n)и 1000 постоянная. Вы также можете думать об этом как O(m n).
Рэй
3
С таким аргументом вся дискуссия бесполезна, потому что при ограниченном вводе сложность всегда O(1);-)
Говард
@ Как я родом из мира ACM-ICPC, и это в какой-то степени конвенция. Вы можете думать это как O (мн). Это все еще отличается от O (n ^ 2). В любом случае, это будет меньше, чем время запуска переводчика, поэтому я думаю, что это достаточно быстро.
Рэй
Впечатляюще короткий алгоритм! Я могу определить только один символ (по крайней мере, при переходе на Python 2): вы можете напечатать результат. printкороче чем return.
Фалько
3

Python - 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))
faubi
источник
Принято решение. Ваш код был протестирован здесь и здесь .
Мостафа 36a2
@ Mostafa36a2 Слово «принято» имеет другое значение на этом сайте. Я думаю, что вы имеете в виду "приемлемо".
Рэй
Извините, да, я имел в виду приемлемый, слишком рано, чтобы выбрать принятый.
Мостафа 36a2
С помощью строки 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.

isaacg
источник
Ваш код не выполняется своевременно для случая с большим списком (скажем, 100 элементов)
Mostafa 36a2
3
@ Mostafa36a2 Если вы хотите сделать требование времени выполнения обязательным, укажите это в вопросе и добавьте один или два тестовых примера. Если это просто комментарий, то я согласен, это довольно медленно.
Исаак
Извините, но я упомянул, что это не время выполнения, а, по крайней мере, [своевременно], нет проблем, если код занимает 10-20 минут или даже час, но решения O (2 ^ n) никогда не дадут результата во время наша долгая жизнь
Мостафа 36a2
@ Mostafa36a2 Понял, я только что заметил эту строку. Я буду работать над улучшением.
Исаак
1
Извините, я вижу обновление сейчас, пожалуйста, попробуйте этот случай и скажите мне, если оно работает.
Мостафа 36a2
3

Clojure, 94 символа

Используя подход @ Ray для обновления результатов в векторе из 1000 элементов:

(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))))
YosemiteMark
источник
Вы можете добавить оператор печати, чтобы сделать его тестируемым? Он не будет засчитан в счет.
Мостафа 36a2
1
Обновлено. Я запустил его на обоих ваших больших примерах и получил 58 и 57, как и ожидалось.
YosemiteMark
Я думаю, что вам все еще нужно вызвать функцию: p, но если вы проверили ее, этого достаточно.
Мостафа 36a2
3

Haskell, 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 Для 1000 номеров на моем компьютере требуется около 5 секунд. Предполагая, $что O (n log n), алгоритм O (n ^ 2 log n).
Говард
пожалуйста, попробуйте ввод по этой ссылке
Мостафа 36a2
@ 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 секунд на большом входе, это считается своевременным способом? :п

Это грубая рекурсия, но с некоторыми воспоминаниями.

histocrat
источник
1
Да, это своевременно :)
Мостафа 36a2
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;}

Спасибо Армин и Боб за их улучшения!

DLeh
источник
1
вы можете изменить свой параметр на int [], и тогда у вас будет меньше символов, потому что вам не нужно
Armin
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

Stax , 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;}

Попробуйте онлайн!

jrivor
источник
0

Wolfram Language (Mathematica) , 38 байт

Length@LongestOrderedSequence[#,Less]&

Попробуйте онлайн!

Конечно, есть встроенный Mathematica для поиска самых длинных упорядоченных последовательностей. Его название очень длинное: оно составляет более половины решения, и я не удивлюсь, если кто-то превзойдет это решение.

Роман
источник