Karim Belabas on Thu, 29 Dec 2022 15:17:41 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: veccount


* Ruud H.G. van Tol [2022-12-29 13:04]:
> A different case:
> 
> ? binary(92)
> %3 = [1, 0, 1, 1, 1, 0, 0]
> 
> How to effectively transform that to [1,1,3,2] (run-lengths),
> and next to 3 (the number of different run-length values)?

Note that Rosetta Code includes lots of PARI/GP snippets for standard
programming tasks, e.g.,

  https://rosettacode.org/wiki/Run-length_encoding#PARI/GP

> ? {
>   my(D= 1, v= binary(92), c= 1, x= v[1],r= List());
>   if(D,print(v));
>   for(i= 2, #v, if(x == v[i], c++;if(i == #v,listput(r,c)),
> listput(r,c);c=1;x=v[i]));
>   r= Vec(r); if(D,print(r));
>   r= matreduce(r)[,1]~; if(D,print(r));
>   print(#r);
> }
> [1, 0, 1, 1, 1, 0, 0]
> [1, 1, 3, 2]
> [1, 2, 3]
> 3
> 
> Only the last result is relevant to A165413,
> so a condensed way from binary(92) to 3 would already help,

Something like

  /* assume v is a non-empty vector */
  rlev(v) =
  { my(x = v[1], c = 1, L = List());
    for (i = 2, #v, if (v[i] == x, c++, listput(L,c); x = v[i]; c = 1));
    listput(L,c); #Set(L);
  }

  ? rlev(binary(92))
  %2 = 3

  ? setrand(1); v = vector(10^6, i, random(2));
  ? rlev(v)
  time = 894 ms.
  %4 = 20

One can save a log factor by using a counting sort to replace the list L
and final #Set(L):

  /* assume v is a non-empty vector */
  rlev2(v) =
  { my(x = v[1], c = 1, w = vector(#v));
    for (i = 2, #v, if (v[i] == x, c++, w[c] = 1; x = v[i]; c = 1));
    w[c] = 1; hammingweight(w);
  }

  ? rlev2(v)
  time = 437 ms.
  %5 = 20

Cheers,

    K.B.

--
Karim Belabas  /  U. Bordeaux,  vice-président en charge du Numérique
Institut de Mathématiques de Bordeaux UMR 5251 - (+33) 05 40 00 29 77
http://www.math.u-bordeaux.fr/~kbelabas/
`