It depends on both m and n in ?m#nAlso, note that it's better to move definition of the input outside the time
(and space) test.
Using ?. to fix the samples, and 1 ts to save waiting on longer arguments: ts each '#longascseq1 q';'#longascseq2 q'[q =: ?.~100000NB. set outside +------------------+------------------+ |0.475994 1.18106e6|0.675194 1.17299e6| +------------------+------------------+ ts each '#longascseq1 ?.~100000';'#longascseq2 ?.~100000' NB. set inside +------------------+------------------+ |0.493492 6.42419e6|0.629799 6.41613e6| +------------------+------------------+ 1 ts each '#longascseq1 q';'#longascseq2 q'[q =: ?.~1000000 +-----------------+-----------------+ |3.38978 8.74317e6|7.69395 8.72691e6| +-----------------+-----------------+ 1 ts each '#longascseq1 ?.~1000000';'#longascseq2 ?.~1000000' +-----------------+----------------+ |3.71289 5.06865e7|8.4527 5.06702e7| +-----------------+----------------+ It appears that the estimate of space used is more strongly influenced than time, here. I'm wondering why you tested equality in this way: (([: longascseq1 ]) *./ . = [: longascseq2 ])a Isn't it sufficient to test (longascseq1 -: longascseq2 )l 1 ? Thanks, Mike On 14/09/2016 09:30, Erling Hellenäs wrote:
I can't verify that. For some values it is faster, yes, but it seems measurements with 1 000 000 items shows your original assumption was correct. See below. /ErlingNB. Find the longest ascending subsequence in y NB. y is a list of numbersNB. Result is indexes of the values that form the largest ascending sequence in ylongascseq1 =: 3 : 0"1 NB. Initialize the arrays valueofminendvalue =. indexofminendvalue =. 0$0 predecessor =. (#y)$2 NB. process the input for_v. y do.NB. j{indexofminendvalue is the index in the original input of the smallestNB. input value that ends a sequence of length j+1. valueofminendvalue is NB. the corresponding value.NB. When a new value v comes in, we see how many previous values are smaller;NB. calling that value j, we see that the new value becomes the smallest valueNB. that ends a subsequence of length j+1 if. (#valueofminendvalue) = j =. valueofminendvalue I. v do.NB. New highest value (and therefore new greatest length): extend the arraysvalueofminendvalue =. valueofminendvalue , v indexofminendvalue =. indexofminendvalue , v_index else. NB. New low value for an existing length: update for that length valueofminendvalue =. v j} valueofminendvalue indexofminendvalue =. v_index j} indexofminendvalue end.NB. Get a snapshot of the predecessor to the added point at the time it wasNB. added. This predecessor is given by the end of the next-shorter subsequence.predecessor =. (indexofminendvalue {~ <: j) v_index} predecessor NB. wraps if j=0, but who cares?end. NB. Reconstruct the chain of predecessors from the end predecessor {~^:(i.-#indexofminendvalue) {: indexofminendvalue ) NB. Find the longest ascending subsequence in y NB. y is a list of numbersNB. Result is indexes of the values that form the largest ascending sequence in ylongascseq2 =: 3 : 0"1 NB. Initialize the arrays valueofminendvalue =. indexofminendvalue =. 0$0 predecessor =. (#y)$2 NB. process the input for_v. y do.NB. j{indexofminendvalue is the index in the original input of the smallestNB. input value that ends a sequence of length j+1. valueofminendvalue is NB. the corresponding value.NB. When a new value v comes in, we see how many previous values are smaller;NB. calling that value j, we see that the new value becomes the smallest valueNB. that ends a subsequence of length j+1 NB. if. (#valueofminendvalue) = j =. valueofminendvalue I. v do. if. (#indexofminendvalue) = j =. v I.~ indexofminendvalue{y do. NB. valueofminendvalue =. valueofminendvalue , v indexofminendvalue =. indexofminendvalue , v_index else. NB. valueofminendvalue =. v j} valueofminendvalue indexofminendvalue =. v_index j} indexofminendvalue end.NB. Get a snapshot of the predecessor to the added point at the time it wasNB. added. This predecessor is given by the end of the next-shorter subsequence.predecessor =. (indexofminendvalue {~ <: j) v_index} predecessor NB. wraps if j=0, but who cares?end. NB. Reconstruct the chain of predecessors from the end predecessor {~^:(i.-#indexofminendvalue) {: indexofminendvalue ) l 7 4 4 5 2 7 1 8 13 2 10 4 9 1 4 5 5 4 3 10 3 4 5 8 15 7 11 19 (longascseq1 { ])l 1 2 3 4 5 7 11 19 (longascseq2 { ])l 1 2 3 4 5 7 11 19 a=:10000?10000 (([: longascseq1 ]) *./ . = [: longascseq2 ])a 1 ts'(longascseq1 { ]) 10000?10000' 0.0439489 830592 ts'(longascseq2 { ]) 10000?10000' 0.0415926 830720 ts'(longascseq1 { ]) ?10000$10000' 0.044282 439424 ts'(longascseq2 { ]) ?10000$10000' 0.0410495 435840 ts'(longascseq1 { ]) 100000?100000' 0.446059 6.42803e6 ts'(longascseq2 { ]) 100000?100000' 0.468622 6.41946e6 ts'(longascseq1 { ]) ?100000$100000' 0.447244 3.28205e6 ts'(longascseq2 { ]) ?100000$100000' 0.458428 3.27373e6 ts'(longascseq1 { ]) 1000000?1000000' 4.55264 5.07078e7 ts'(longascseq2 { ]) 1000000?1000000' 5.98209 5.06932e7 ts'(longascseq1 { ]) ?1000000$1000000' 4.42172 2.55429e7 ts'(longascseq2 { ]) ?1000000$1000000' 5.83236 2.55252e7 On 2016-09-13 20:38, 'Mike Day' via Programming wrote:Actually, the hit on run time gets more significant as the length of thesequence and/or the optimal subsequence increase, so it's not negligible for, say, ?1000000#500000, but fine for ?10000#5000, and not too bad for ?100000#50000 Mike On 13/09/2016 19:22, 'Mike Day' via Programming wrote:Thanks. It might help to point out that the main loop in Henry Rich's version, as shown in the wiki page, can be simplified slightly with negligible effect on run time, some savings in space, and doing without the "sorted value" array. I'm rather surprised - I'd introduced the array which I'd called mx, more helpfully called valeofminendvalue by Henry, to avoid repeated indirect look-up into the raw input. Here's a copy of the relevant part of the loop with the removed or former code commented out: NB. if. (#valueofminendvalue) = j =. valueofminendvalue I. v do. if. (#indexofminendvalue) = j =. v I.~ indexofminendvalue{y do. NB. valueofminendvalue =. valueofminendvalue , v indexofminendvalue =. indexofminendvalue , v_index else. NB. valueofminendvalue =. v j} valueofminendvalue indexofminendvalue =. v_index j} indexofminendvalue end. I won't venture to suggest changes in your code, below! Mike On 13/09/2016 17:17, Erling Hellenäs wrote:Hi all !My first idea only took me down to 1 second for 10 000 numbers, 25 times longer than longscseq. I then made a tacit version of longascseq. It still takes about 4 times longer than longascseq.See these two versions below. I included the full project of the tacit version. Cheers, Erling NB. Find the longest stricty increasing subsequenceNB. Values are the lowest last values yet found for each subsequence length.NB. Indices are the indices of these values in the original sequence. NB. Predecessors are indices to the end of the next lower subsequence NB. for each value in the original sequence.NB. The longest sequence is found by index lookup in predecessors from the indexNB. of the highest found value. Amend=:([:>[:{.[)`([:>[:{:[)`] } PickPower=: {~^:([`([:>[:{.])`([:>[:{:]))ValuesIndicesPredecessorsIndexInitialState=: [: < a:"_ , a:"_ , (([: # ]) $2:) ;0:PackValues=: <@+ Values=: [: > 0 { ] Indices=: [: > 1 { ] Predecessors=: [: > 2 { ] Index=: [: > 3 { ] AdjustLength=: ((1 + [) >. [: # ]) {. ]AmendValues=: (([: {. [) ; [: {: [) Amend ([: {: [) AdjustLength ValuesAmendIndices=: (Index ; [: {: [) Amend ([: {: [) AdjustLength IndicesAmendPredecessors=: ((([: <: [: {: [){Indices);Index ) Amend PredecessorsDoBetweenElementsInFold=: ([,(Values I. [ )) ( [ (Values;Indices;AmendPredecessors;1+Index) AmendValues;AmendIndices;Predecessors;Index) ]Reconstruct=: [: (Predecessors PickPower ([: i. [: - [: # Indices);[: {: Indices) [: > ]LongestIncreasingSubsequenceIndices=: [: Reconstruct [: DoBetweenElementsInFold&.:>/ ([: |. PackValues) , ValuesIndicesPredecessorsIndexInitialStateLongestIncreasingSubsequence=: ([: LongestIncreasingSubsequenceIndices ]){ ]LongestIncreasingSubsequence=: LongestIncreasingSubsequence f.NB. This is a solution to the problem of finding the longest strictly increasing subsequence.NB. Draws numbers from the end of the sequence. Selects groups with its first element largerNB. than the drawn element. Selects one of the longest of these groups if one exists and prependsNB. the drawn number. If no such group exists create a new group containing the drawn number.NB. Removes groups which are both shorter than the new group or of equal length and which startsNB. with a number which is smaller or equal to the number which starts the new group.NB. Append the new group to the remaining groups.NB. When all numbers are drawn one of the longest remaining groups is selected.GroupOfEmptyGroupInitialState=: [: < a:"_ PackElements=: <@+ StartsWithLonger=: ([: {.@> [) < [: {.@> ] Longer=:([: #@> [) < [: #@> ] SelectLongerOrStartsWithLonger=: (Longer +. StartsWithLonger ) # ] SelectGroupsWithLeftLessThanFirstElement=: ([ < [: {.@> ]) # ]SelectFirstGroupOfMaxLength=: ((1 <. [: # ]) {. [: I. [: (] = [: >./ ]) #@>) { ]PrependLeftInGroups=: ([: < [) ,&.> ] AddGroupWithLeftIfNoGroups=: ((0 = [: # ]) {. [: < [) , ]DoBetweenElementsInFold=: ([: {. [ AddGroupWithLeftIfNoGroups [ PrependLeftInGroups [: SelectFirstGroupOfMaxLength SelectGroupsWithLeftLessThanFirstElement ) ([ , SelectLongerOrStartsWithLonger) ]LongestIncreasingSubsequence=: [: ; [: SelectFirstGroupOfMaxLength [: > [: DoBetweenElementsInFold&.:>/ PackElements , GroupOfEmptyGroupInitialStateLongestIncreasingSubsequence=: LongestIncreasingSubsequence f. Full project of tacit version ======================= NB. Find the longest stricty increasing subsequenceNB. Values are the lowest last values yet found for each subsequence length.NB. Indices are the indices of these values in the original sequence. NB. Predecessors are indices to the end of the next lower subsequence NB. for each value in the original sequence.NB. The longest sequence is found by index lookup in predecessors from the indexNB. of the highest found value. ts=: 6!:2 , 7!:2@] NB. Time and space Amend=:([:>[:{.[)`([:>[:{:[)`] } (1;0) Amend 3 4 5 PickPower=: {~^:([`([:>[:{.])`([:>[:{:])) 2 3 4 PickPower 1;1ValuesIndicesPredecessorsIndexInitialState=: [: < a:"_ , a:"_ , (([: # ]) $2:) ;0:ValuesIndicesPredecessorsIndexInitialState 7 1 2 3 PackValues=: <@+ PackValues 7 1 2 3 Values=: [: > 0 { ] Values 1 2 3;0 1 2;2 2 2;0 Indices=: [: > 1 { ] Indices 1 2 3;0 1 2;2 2 2;0 Predecessors=: [: > 2 { ] Predecessors 1 2 3;0 1 2;2 2 2;0 Index=: [: > 3 { ] Index 1 2 3;0 1 2;2 2 2;0 AdjustLength=: ((1 + [) >. [: # ]) {. ] 3 AdjustLength 1 2 3 2 AdjustLength 1 2 3AmendValues=: (([: {. [) ; [: {: [) Amend ([: {: [) AdjustLength Values(7,3) AmendValues 1 2 3;0 1 2;2 2 2;0 AmendIndices=: (Index ; [: {: [) Amend ([: {: [) AdjustLength Indices (7,3) AmendIndices 1 2 3;0 1 2;2 2 2;0AmendPredecessors=: ((([: <: [: {: [){Indices);Index ) Amend Predecessors(7,3) AmendPredecessors 1 2 3;0 1 2;2 2 2;0DoBetweenElementsInFold=: ([,(Values I. [ )) ( [ (Values;Indices;AmendPredecessors;1+Index) AmendValues;AmendIndices;Predecessors;Index) ]3 DoBetweenElementsInFold 1 2;1 2;0 1 1 2;3Reconstruct=: [: (Predecessors PickPower ([: i. [: - [: # Indices);[: {: Indices) [: > ]Reconstruct < 1 2 3;1 2 3;0 1 1 2;4LongestIncreasingSubsequenceIndices=: [: Reconstruct [: DoBetweenElementsInFold&.:>/ ([: |. PackValues) , ValuesIndicesPredecessorsIndexInitialState( 7 DoBetweenElementsInFold [: > ValuesIndicesPredecessorsIndexInitialState)7 1 2 3( 1 DoBetweenElementsInFold (7 DoBetweenElementsInFold [: > ValuesIndicesPredecessorsIndexInitialState))7 1 2 3( 2 DoBetweenElementsInFold (1 DoBetweenElementsInFold (7 DoBetweenElementsInFold [: > ValuesIndicesPredecessorsIndexInitialState)))7 1 2 3( 3 DoBetweenElementsInFold (2 DoBetweenElementsInFold (1 DoBetweenElementsInFold (7 DoBetweenElementsInFold [: > ValuesIndicesPredecessorsIndexInitialState))))7 1 2 3Reconstruct < (3 DoBetweenElementsInFold ( 2 DoBetweenElementsInFold ( 1 DoBetweenElementsInFold ( 7 DoBetweenElementsInFold [: > ValuesIndicesPredecessorsIndexInitialState))))7 1 2 3LongestIncreasingSubsequence=: ([: LongestIncreasingSubsequenceIndices ]){ ]LongestIncreasingSubsequence=: LongestIncreasingSubsequence f. LongestIncreasingSubsequence 7 1 2 3 LongestIncreasingSubsequence i.0 LongestIncreasingSubsequence 6 1 3 4 2 8 l =: 7 4 4 5 2 7 1 8 13 2 10 4 9 1 4 5 5 4 3 10 3 4 5 8 15 7 11 19 LongestIncreasingSubsequence l 9!:1 [16807 [a=:LongestIncreasingSubsequence 1000?1000 #a 9!:1 [16807 [a=:LongestIncreasingSubsequence ?1000$1000 #a ts=: 6!:2 , 7!:2@] NB. Time and space ts'LongestIncreasingSubsequence 10000?10000' ts'LongestIncreasingSubsequence ?10000$10000' ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
--- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm