I'm new to the site and I am French, so I ask your indulgence for my future mistakes in English.
I would like to optimise the following code :
Proc1V1[x_] :=
Block[
{ListO = x, F°1B1, F°1B1oneseq, F°2B1, F°2B1oneseq, F°3B1, F°4B1, F°1B2,
Res1V1},
F°1B1 = Table[
Partition[ListO, j, 1],
{j, 1, Length[ListO], 1}
];
F°1B1oneseq = Partition[ListO, 1, 1];
F°2B1 = Sort[
Tally [
Flatten[F°1B1, 1]
],
#1 [[2]] > #2 [[2]] &
];
F°2B1oneseq = Tally[F°1B1oneseq][[All, 1]];
F°3B1 = Sort[
F°2B1 [[1 ;; (Position[F°2B1[[All, 2]], 1][[1, 1]])-1]][[All, 1]],
Length[#1] > Length[#2] &
];
F°4B1 = Join[
TakeWhile[F°3B1, Length[#] > 1 &],
F°2B1oneseq
];
F°1B2 = Table[
Position[ F°1B1[[ Length[ F°4B1 [[i]]] ]],F°4B1 [[i]]],
{i, 1, Length[F°4B1], 1}
];
Res1V1 = {F°1B2, F°4B1}
];
After applying AbsoluteTiming
on the different steps of my algorithm, F°1B2
appeared to be the longest step in the calculation. So I focus on it.
The algorithm acting at F°1B2
is responsible for determining the positions of the various lists of numbers stored in F°4B1
and contained in F°1B1
. It may be noted here that ListO
is a simple list of integers or reals.
For example:
ListO = {1, 2, 3, 4, 5, 6, 7}
I've tried using Compile
but this does not work if it has to deal with lists of different size.
I know that finding an alternative to the Position
is a recurring topic on StackExchange but I have yet to find a reliable solution to replace F°1B2
by a faster algorithm, especially because Proc1V1
is the first algorithm to a broader set and therefore it is difficult to change the structure of the data it produces.
Edit n°1
To better understand my project, I will give an overview of the context. My goal is to make an algorithm to detect and store the sequences detected in an ordered list of number (Real or Integer number). To start, I got used to test my code with :
ListTest= IntegerPart [ RandomReal [ 10,50 ] ] ;
Therefore, Proc1V1
must detect the different sequences contained inside ListTest
.
It is important to note here that a set of numbers will be considered as a sequence, if it appears at least twice in ListTest
and if it is length is greater than 1.
To do this (it’s probably perfectible but I have not found better yet), the algorithm I did create partitions of different lengths in the starting list ListTest
. These partitions are compared and sorted at F°2B1
.
All other operations are responsible for ensuring that the definition of the sequences as I defined above is respected.
If all operations are relatively fast, the operation performed under F°1B2
turns long . For the rest of the algorithms which I wrote it, I need that Proc1V1
provide me the positions of these sequences inside F1B2
and obviously the sequences identified.
Final Edit
Tested functions
Proc1V1 : see above.
Proc1V1alt1[list_]:= {#[[1,2]],#[[All,1]]}&/@
ReplaceList[list,{a___,x__,___}:>{Length@{a}+1,
{x}}]~GatherBy~Last~Cases~{_,__};
Proc1V1alt2[list_]:= {#[[1,2]],#[[All,1]]}&/@
(Join@@Table[{i,list[[i;;j]]},{i,Length[list]},
{j,i,Length[list]}])~GatherBy~Last~Cases~{_,__};
Proc1V1alt3[list_]:=
Block[
{bigL=list,z1,z2,z3,z4,z5,z6,z7,minlength},
minlength=1;
z1=Flatten[Position[#,True]]&
/@Rest@ListCorrelate[bigL,bigL,1,x,SameQ,List];
z2=Split[#,(#1+1===#2)&]&/@z1;
z3=DeleteCases[z2,q_List/;Length[q]<minlength,{2}];
z4=DeleteCases[MapIndexed[w[#2,#1]&,z3],w[_,{}]];
z5=Flatten[z4/.w[{u_},q_List]:>Map[w[bigL[[#]],First[#]+{0,u}]&,q]];
z6=Split[Sort[z5],First[#1]===First[#2]&];
z7={#[[1,1]],Union@@(Last/@#)}&/@z6
];
Proc1V1alt4
: See Rasher's post.
With :
Proc1V1
: personal function.
Proc1V1alt1
: Mr Wizard's function n°1.
Proc1V1alt2
: Mr Wizard's function n°2.
Proc1V1alt3
: Wouter's function.
Proc1V1alt4
: Rasher's function
Test code
ValeurPerfTemps=
Table[
AbsoluteTiming[
func[IntegerPart[RandomReal[10,i]]]
][[1]],
{i,50,500,1}
];
ListLinePlot[ValeurPerfTemps]
Result
Conclusion
In the context of my original question, the function n°2 of Mr. Wizard is the most suitable. Nevertheless, it is important to note that my function Proc1V1 takes place in a set of algorithm, and some of which are specifically dedicated to the elimination of sequences "encapsulated" (ex : 123 is contained in 11234). Actually I will use Rasher's function, which is very fast.
Thank you all for your help.
Benchmark
On my computer :
Proc1V1[{3, 0, 1, 0, 3, 2, 2, 0, 3, 0, 1, 3, 0, 2, 3, 3, 0, 0, 1, 2}]
give
{{{{1}, {9}}, {{4}, {8}}, {{2}, {10}, {18}}, {{1}, {9}, {12}, {16}}, \
{{1}, {5}, {9}, {12}, {15}, {16}}, {{2}, {4}, {8}, {10}, {13}, {17}, \
{18}}, {{3}, {11}, {19}}, {{6}, {7}, {14}, {20}}}, {{3, 0, 1}, {0,
3}, {0, 1}, {3, 0}, {3}, {0}, {1}, {2}}}
F°1B2
is a pretty wild variable name ;). I think this is a pretty decent first question, but still I would encourage you to practise formatting your question. Please see the edit that is suggested (and will probably be approved). $\endgroup$ListO
returns a list of empty lists, and there are a lot of error messages along the way. A working example with the desired output can help a lot in a case like this. $\endgroup$F°1B2 = Table[Position[F°1B1[[Length[F°4B1[[i]], F°4B1[[i]]], {j, 1, Length[F°4B1], 1}];
isn'tF°1B2 = Table[Position[F°1B1[[Length[F°4B1[[i]], F°4B1[[i]]], {i, Length[F°4B1]}];
. The main point being about the discrepancy betweeni
andj
, not so much about the unneeded elements in the iteration control list. $\endgroup$