What is the best way to find the period of a (repeating) list in Mathematica?

前端 未结 9 1204
没有蜡笔的小新
没有蜡笔的小新 2021-01-01 15:12

What is the best way to find the period in a repeating list?

For example:

a = {4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2}

has repeat

9条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-01 15:52

    The following assumes that the cycle starts on the first element and gives the period length and the cycle.

    findCyclingList[a_?VectorQ] :=
      Module[{repeats1, repeats2, cl, cLs, vec}, 
      repeats1 = Flatten@Differences[Position[a, First[a]]];
      repeats2 = Flatten[Position[repeats1, First[repeats1]]]; 
      If[Equal @@ Differences[repeats2] && Length[repeats2] > 2(* 
       is potentially cyclic - first element appears cyclically *),
       cl = Plus @@@ Partition[repeats1, First[Differences[repeats2]]];
       cLs = Partition[a, First[cl]];
       If[SameQ @@ cLs  (* candidate cycles all actually the same *), 
        vec = First[cLs];
        {Length[vec], vec}, $Failed], $Failed]  ]
    

    Testing

    b = RandomInteger[50, {100}];
    a = Join[b, b, b, b, Take[b, 27]];
    
    findCyclingList[a]
    
    {100, {47, 15, 42, 10, 14, 29, 12, 29, 11, 37, 6, 19, 14, 50, 4, 38, 
      23, 3, 41, 39, 41, 17, 32, 8, 18, 37, 5, 45, 38, 8, 39, 9, 26, 33, 
      40, 50, 0, 45, 1, 48, 32, 37, 15, 37, 49, 16, 27, 36, 11, 16, 4, 28,
       31, 46, 30, 24, 30, 3, 32, 31, 31, 0, 32, 35, 47, 44, 7, 21, 1, 22,
       43, 13, 44, 35, 29, 38, 31, 31, 17, 37, 49, 22, 15, 28, 21, 8, 31, 
      42, 26, 33, 1, 47, 26, 1, 37, 22, 40, 27, 27, 16}}
    
    b1 = RandomInteger[10000, {100}]; 
    a1 = Join[b1, b1, b1, b1, Take[b1, 23]];
    
    findCyclingList[a1]
    
    {100, {1281, 5325, 8435, 7505, 1355, 857, 2597, 8807, 1095, 4203, 
      3718, 3501, 7054, 4620, 6359, 1624, 6115, 8567, 4030, 5029, 6515, 
      5921, 4875, 2677, 6776, 2468, 7983, 4750, 7609, 9471, 1328, 7830, 
      2241, 4859, 9289, 6294, 7259, 4693, 7188, 2038, 3994, 1907, 2389, 
      6622, 4758, 3171, 1746, 2254, 556, 3010, 1814, 4782, 3849, 6695, 
      4316, 1548, 3824, 5094, 8161, 8423, 8765, 1134, 7442, 8218, 5429, 
      7255, 4131, 9474, 6016, 2438, 403, 6783, 4217, 7452, 2418, 9744, 
      6405, 8757, 9666, 4035, 7833, 2657, 7432, 3066, 9081, 9523, 3284, 
      3661, 1947, 3619, 2550, 4950, 1537, 2772, 5432, 6517, 6142, 9774, 
      1289, 6352}}
    

    This case should fail because it isn't cyclical.

    findCyclingList[Join[b, Take[b, 11], b]]
    
    $Failed
    

    I tried to something with Repeated, e.g. a /. Repeated[t__, {2, 100}] -> {t} but it just doesn't work for me.

提交回复
热议问题