MathGroup Archive 1997

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: programing: reduce list to cycle

  • To: mathgroup at smc.vnet.net
  • Subject: [mg8629] Re: [mg8615] Re: programing: reduce list to cycle
  • From: Allan Hayes <hay at haystack.demon.co.uk>
  • Date: Fri, 12 Sep 1997 04:10:43 -0400
  • Sender: owner-wri-mathgroup at wolfram.com

"Xah" <xah at best.com>
in [mg8615] Re: programing: reduce list to cycle
writes

> This is a summary of the shortest cycle problem.
> Problem:
> I want to reduce a list to its shortest cycle. For example, if
> myList={3,1,0,3,3,1,0,3,3,1,0,3}, then the desired result should be
>{3,1,0,3}. How to do it? myList are not always complete cycles, in 
> such case, the whole list should be returned.

He give two solutions, copied below the line *******************.

Here are two variants on the first one


shortestCycle2[x_]:=
  If[MatchQ[Partition[x, #], {u_ ..}],
     Throw[Take[x,#]]
  ]&/@ Divisors[Length[x]]//Catch

This is about the same speed as the original on shorter cycles but,  
due to the use of Divisors is much quicker where there the cycles  
are long

shortestCycle3[x_]:=
  If[Take[x,#]==Take[x,-#] && MatchQ[Partition[x, #], {u_ ..}],
     Throw[Take[x,#]]
  ]&/@ Divisors[Length[x]]//Catch

The opportunistic initial quick check Take[x,#]==Take[x,-#] makes  
this much quicker on the test given - but this speed up cannot be  
guaranteed.

Here are some timing (see below line ************ for details)

shortestCycle2[niceCycle]//Timing
{2.8434 Second,{6,3,9,5,1,5,7,4,7,5,7,9,6,9,6,2,3,6,7,3}}
shortestCycle3[niceCycle]//Timing
{0.23429 Second,{6,3,9,5,1,5,7,4,7,5,7,9,6,9,6,2,3,6,7,3}}
shortestCycle[niceCycle]//Timing
{2.70202 Second,{6,3,9,5,1,5,7,4,7,5,7,9,6,9,6,2,3,6,7,3}}
minrep[niceCycle]//Timing
{2.24899 Second,{6,3,9,5,1,5,7,4,7,5,7,9,6,9,6,2,3,6,7,3}}

shortestCycle2[notCycle];//Timing
{2.10858 Second,Null}
shortestCycle3[notCycle];//Timing
{1.12401 Second,Null}
shortestCycle[notCycle];//Timing
{10.4668 Second,Null}
minrep[notCycle];//Timing
{1.85865 Second,Null}

Allan Hayes
hay at haystack.demon.co.uk
http://www.haystack.demon.co.uk/training.html
voice:+44 (0)116 2714198
fax: +44 (0)116 2718642
Leicester,  UK

******************************************************************
Xah's posting, continued.

Solutions:
(*from a friend*)

shortestCycle[lis_List] :=
        With[{l = Length[lis]},
        Take[lis, Do[If[Mod[l,i]===0 &&  
MatchQ[Partition[lis,i],{(x_)..}],
          Return[i]],{i,1,l}]]];

(*from Will Self wself at viking.emcmt.edu*)

repe[x_List,n_Integer?Positive]:=Flatten[Table[x,{n}],1]

factors[n_Integer?Positive]:= If[n==1,1,
Sort[Flatten[Outer[Times,
Sequence@@(Table[#[[1]]^x,{x,0,#[[2]]}]& /@ FactorInteger[n]) ]]]]

minrep[x_List]:=  Module[{m,f,temp},
m=Length[x];f=factors[m];
Do[If[repe[temp=Take[x,f[[k]] ],m/f[[k]]] == x,
   Return[temp]],{k,1,Length[f]}]]

(*Speed comparison*)

cycList=Table[Random[Integer,{1,9}],{i,1,20}]
niceCycle=Flatten at Table[cycList,{i,1,1000}];
notCycle=Flatten[{niceCycle,a}];
Length at Flatten@niceCycle

{2,9,4,4,1,4,8,6,1,3,7,9,2,9,6,4,5,9,7,5}

20000

a1=Timing at shortestCycle[niceCycle];
a2=Timing at minrep[niceCycle];

b1=Timing at shortestCycle[notCycle];
b2=Timing at minrep[notCycle];

(First/@{a1,a2})
(First/@{b1,b2})

{1.11667 Second,0.933333 Second}

{3.56667 Second,0.966667 Second}

Equal@(Last/@{a1,a2})&&Equal@(Last/@{b1,b2})

True
----------------

They are both based on the same principle: by testing the divisibility of
the length of the list, then compare original to a created list.  
The former
is easy to understand, the latter is faster. There should be a pure  
pattern
matching solution.

 Xah
 xah at best.com
 http://www.best.com/~xah/SpecialPlaneCurves_dir/specialPlaneCurves.html
 Mountain View, CA, USA



  • Prev by Date: Re: interpolating f(x,y) from evaluation
  • Next by Date: Re: interpolating f(x,y) from evaluation
  • Previous by thread: Re: Re: programing: reduce list to cycle
  • Next by thread: Re: Re: programing: reduce list to cycle