Codice di conseguenza crescente più breve più lungo


11

La sfida è scrivere l' implementazione più breve per trovare la sottosequenza crescente più lunga .

Esempio : Sia S la sequenza 1 5 7 1 8 4 3 5 [lunghezza di S = 8]

  • Abbiamo 1 sotto-sequenza di lunghezza 0 [la considereremo in aumento]
  • 6 sotto-sequenze di lunghezza 1 {1,5,7,8,4,3} [sono considerate tutte in aumento]
  • (7 * 8) / 2 sotto-sequenze di lunghezza 2 [ma rimuoveremo i duplicati], i sotto-seq crescenti sono in nero forte.
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[nota che ci interessa solo sub-sequenze in costante aumento]

[non è possibile modificare l'ordine degli elementi all'interno della sequenza, quindi non vi è alcuna sottosequenza [37] nella sequenza di esempio]

  • Abbiamo sub-sequenze crescenti di lunghezza 4 che è 1578, ma non ci sono sotto-sequenze di lunghezza 5, quindi consideriamo la lunghezza della sub-sequenza crescente più lunga = 4.

Input :

a 1 a 2 ... a N (La sequenza)

tutti i numeri sono numeri interi positivi inferiori a 10 3
N <= 1000

Uscita :

Un numero intero che indica la lunghezza della sotto-sequenza crescente più lunga della sequenza di input.

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

Il tuo codice dovrebbe essere eseguito in modo tempestivo, prova il tuo codice su questo caso prima di inviarlo qui (anche il link contiene la mia soluzione c ++ 11 da 290 byte)

Puoi prendere l'input da un file / stdin o come parametro di funzione e puoi stampare l'output in un file / stdout o semplicemente restituire il valore se scrivi una funzione

Tabellone dei punteggi

  1. Dennis CJam - 22
  2. isaacg Pyth - 26
  3. Howard GolfScript - 35
  4. orgoglioso haskeller Haskell - 56
  5. Ray Python 3 - 66
  6. istocratico Ruby - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. faubiguy Python 3 - 113

1
"Abbiamo 1 sotto-sequenza di lunghezza 0 [la considereremo in aumento]", Beh, tecnicamente hai un numero infinito di sotto-sequenze di lunghezza 0 :)
Cruncher,

In realtà, devo cambiare l'affermazione in modo che tutti i "Set" debbano rimuovere i duplicati, ad esempio {1,5,7,1,8,4,3,5} dovrebbe essere {1,5,7,8,4 , 3} e quindi possiamo dire che esiste una sottosequenza di lunghezza 0 nel "Set". grazie
Mostafa 36a2,

1
Per le funzioni, dovremmo contare i byte della funzione esterna ( function f(){...}) o della funzione interna (solo ...)? Se contiamo le funzioni esterne, sono consentite le funzioni anonime?
Dennis,

Contiamo la funzione esterna e sono consentite funzioni anonime, ma non mancate di fornire una versione verificabile (versione completa con gestione input / output)
Mostafa 36a2,

Risposte:


2

CJam, 22 byte

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

Provalo online.

Esempio

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

Il programma stampa 57per questo caso di prova dopo 0,25 secondi.

Come funziona

Ho preso l'idea generale dalla risposta di @ 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

Python 3, 66

Si noti che tutti i numeri sono nell'intervallo [1, 999], è possibile utilizzare un array bper mantenere la lunghezza di sottosequenza più lunga che termina con ciascun numero. b[x] = dsignifica che la sottosequenza più lunga che termina con xha lunghezza d. Per ogni numero dall'input, aggiorniamo l'array usando b[x] = max(b[:x]) + 1e poi abbiamo completato il lavoro prendendo max(b)finalmente.

La complessità temporale è Su) O (mn) , dove mè sempre 1000 ed nè il numero di elementi di input.

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

Wow, sembra già non golfato :) Puoi provarlo usando stdin / stdout aggiungendo una riga:

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

for x in a: max(b)sembra praticamente O (n ^ 2).
Howard,

@Howard It's O(1000 n)e 1000 è una costante. Puoi anche pensarlo come O(m n).
Ray

3
Con tale argomento l'intera discussione è inutile perché su input limitati la complessità è sempre O(1);-)
Howard

@Howard Vengo dal mondo ACM-ICPC e questa è in qualche modo una convenzione lì. Puoi pensarlo come O (mn). È ancora diverso da O (n ^ 2). Ad ogni modo, il tempo che costerà sarà inferiore al tempo di avvio dell'interprete, quindi penso che sia abbastanza veloce.
Ray

Algoritmo straordinariamente breve! Posso individuare solo un personaggio (almeno quando si passa a Python 2): è possibile stampare il risultato. printè più corto di return.
Falko,

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))

Soluzione accettata Il tuo codice è stato testato qui e qui .
Mostafa 36a2,

@ Mostafa36a2 La parola "accettato" ha un altro significato su questo sito. Penso che ciò che intendi sia "accettabile".
Ray

Scusa, sì, intendevo accettabile, troppo presto per scegliere quello accettato.
Mostafa 36a2,

Con la linea a+=[i]*(a==[]or i>a[-1]);z=0e la stampa len(a)(senza parentesi) è possibile salvare 4 caratteri.
Falko,

3

Pyth , 26 29 33 39

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

La soluzione Port of @ ray. Supera i test ufficiali. Ora utilizza input STDIN separato da spazi, non chiamata di funzione.

Esegui come segue:

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

Spiegazione:

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)

Tempo illimitato:

Pyth , 18 anni

L?eS,ytbhyf>Thbbb0

Nota tecnica: ho notato un errore nel mio compositore Pyth mentre scrivevo questo golf. Lnon funzionava. Ecco perché c'è un recente commit nel repository git sopra.


il tuo codice non viene eseguito in modo tempestivo per un caso con un ampio elenco (diciamo 100 elementi)
Mostafa 36a2

3
@ Mostafa36a2 Se desideri rendere il runtime un requisito, ti preghiamo di comunicarlo nella domanda e aggiungere uno o due casi di test. Se è solo un commento, sono d'accordo, è piuttosto lento.
isaacg,

Scusate ma ho detto che non è il runtime ma almeno una [modalità tempestiva], nessun problema se il codice impiega 10-20 minuti o anche un'ora, ma le soluzioni O (2 ^ n) non daranno mai il risultato durante la nostra lunga vita.
Mostafa 36a2,

@ Mostafa36a2 Capito, ho appena notato quella linea. Lavorerò su un miglioramento.
isaacg,

1
Spiacenti, ora vedo l'aggiornamento, prova questo caso e dimmi se funziona.
Mostafa 36a2,

3

Clojure, 94 caratteri

Utilizzando l'approccio di @ Ray per l'aggiornamento risulta in un vettore di 1000 elementi:

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

Per richiesta, con dichiarazione di stampa (stampa la risposta e restituisce zero). L'input deve essere un vettore (g [1 2 3]) o un elenco (g '(1 2 3)):

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

puoi aggiungere la dichiarazione di stampa per renderla testabile? Non verrà conteggiato nel punteggio.
Mostafa 36a2,

1
Aggiornato. L'ho eseguito su entrambi i tuoi grandi esempi e ho ottenuto 58 e 57 come previsto.
YosemiteMark,

Penso che devi ancora chiamare la funzione: p, ma se l'hai testato allora è abbastanza.
Mostafa 36a2,

3

Haskell, 58 57 56 caratteri

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

Questo utilizza un algoritmo che ho visto una volta su Internet, ma non riesco a trovarlo. Ci vuole un tempo impercettibile sul caso test dato sul mio computer con GHCi (probabilmente sarebbe ancora più veloce se fosse compilato).


L'algoritmo che hai citato è lo stesso usato da @faubiguy.
Ray

@Ray hai ragione
orgoglioso haskeller il

2

GolfScript, 35 caratteri

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

Un'implementazione che funziona come un programma completo con input su STDIN (senza il numero di lunghezza indicato). L'implementazione è abbastanza veloce, anche per input più lunghi (prova qui ).

Esempi:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2

1
@ MartinBüttner Ci vogliono circa 5 secondi per 1000 numeri sul mio computer. Supponendo che $O (n log n) l'algoritmo sia O (n ^ 2 log n).
Howard,

si prega di provare l'ingresso in questo link
Mostafa 36a2

@ Mostafa36a2 l'ho già fatto (vedi commento prima). Dopo 5 secondi restituisce 58.
Howard

questo è un altro, dovrebbe restituire 57, quindi se il tuo codice ha restituito 57, allora è accettato :) Congratulazioni
Mostafa 36a2

@ Mostafa36a2 Ah, ora vedo che sono due casi di test distinti. Sì, il tuo secondo link restituisce 57 così come la mia soluzione su questo input.
Howard,

2

Ruby, 67

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

Funziona in 30 secondi sull'input di grandi dimensioni, conta come un modo tempestivo? : p

È una ricorsione bruta, ma con un po 'di memoization.


1
Sì, questo è un modo tempestivo :)
Mostafa 36a2

2

C #, 172 92 caratteri

Niente di speciale, ma l'ho fatto, quindi ho pensato di poterlo presentare.

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

Grazie Armin e Bob per i loro miglioramenti!


1
puoi cambiare il tuo parametro in int [] e quindi avresti meno caratteri perché non avresti bisogno di lanciare la stringa in int
Armin

2
Gli spazi intorno =>non sono necessari. È inoltre possibile spostare la i=0dichiarazione all'esterno del forciclo in int c=2,m=2,i=0;for(;. Puoi anche rilasciare le parentesi graffe attorno al forcorpo, poiché hai solo una singola istruzione.
Bob

E c++;if(c>m)m=c;può esserlo m=c++>m?m:c;, e puoi ancora far cadere le parentesi graffe attorno a quello.
Bob

1
In effetti, puoi anche scartare il if(i>0)controllo facendo foriniziare il ciclo da 1. Puoi accorciare ulteriormente il int c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0)suggerito in precedenza int c=2,m=2,i=0;for(;i++<j.Length;). L'intera sezione potrebbe essere convertita in 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;}(usando un altro ternario per sostituire l'ultimo rimanente if- la regola empirica è che i ternari sono più brevi se il tuo ifcorpo è semplicemente un incarico.
Bob

2
Ci dispiace - errore di battitura nel mio commento precedente, m=c>m?m:cdovrebbe essere m=c>m?c:m. E se aggiungi il suggerimento di @Armin, ottieni 92 byte, quasi dimezzando le dimensioni! 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;}
Bob

2

J , 19 byte

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

Provalo online!

Viene eseguito in O (n log n) , utilizzando un ordinamento di pazienza modificato poiché è necessaria solo la lunghezza, non la sottosequenza effettiva.

Spiegazione

[:#]`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 byte

Questa soluzione fallisce orribilmente sul requisito della tempestività e non è nemmeno particolarmente breve, ma mi è piaciuto che questo genere di cose sia almeno teoricamente possibile nello script di shell, quindi sto postando comunque. Questo corre con una complessità temporale inducente l'eternità di 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

L'input è un elenco separato da virgole passato come singolo argomento della riga di comando:

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

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

L'espansione del controvento viene utilizzata per creare l'elenco di tutte le sottosequenze possibili.

  • La prima riga sostituisce le virgole con ,:},{, che produce una stringa simile1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • La seconda riga completa questa stringa con parentesi graffe, virgole e punti e virgola per dare questo {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}. Questa è un'espansione bash brace valida, che quando viene modificata evalcon un echoproduce questo elenco separato da spazi1,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,:,: ...
  • per impostazione predefinita, bash divide le stringhe con spazi bianchi, quindi passiamo sopra ogni elemento di questo elenco:
    • le virgole vengono sostituite con newline, quindi le righe contenenti due punti vengono rimosse, fornendo elenchi separati da newline per ogni possibile sottosequenza
    • dobbiamo quindi sort -Cverificare l'ordine crescente e, in tal caso, utilizzare wc -wper stampare la lunghezza dell'elenco
  • l'elenco risultante delle lunghezze dell'elenco è ordinato al contrario e il primo valore viene stampato per fornire la lunghezza di sottosequenza crescente più lunga.

1

Stax , 21 byte

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

Esegui ed esegui il debug

Questo ha due casi di test, uno dei quali è il caso di 1000 elementi. Funziona quello in 24 secondi sulla mia macchina. Utilizza il classico approccio di programmazione dinamica per questo tipo di problema.


0

J 34

Nota che ho letto anche l'input standard.

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

Senza leggere l'input standard, la carne è di 26 caratteri.

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

Ho appena notato che il mio funziona lentamente per input di grandi dimensioni, vabbè.



0

C # (.NET Core) , 155 byte

Ha usato un array per calcolare la fine di sottosequenza crescente più lunga in corrispondenza di ciascuna posizione dell'array di input (programmazione dinamica), quindi ha restituito il valore più grande. Ad esempio, [1,5,7,1,8,4,3,5]sarebbe l' array calcolato per l'input [1,2,3,1,4,2,2,3]e 4verrà restituito il valore più grande .

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

Provalo online!


0

Wolfram Language (Mathematica) , 38 byte

Length@LongestOrderedSequence[#,Less]&

Provalo online!

Esiste ovviamente un Mathematica integrato per trovare sequenze ordinate più lunghe. Il suo nome è molto lungo: costituisce più della metà della soluzione e non mi sorprenderò se qualcuno supererà questa soluzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.