| R J Cano on Thu, 11 May 2017 07:29:16 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| Proposing "isperm()" (user featured routine) |
Greetings. Briefly, Motivation, source code, explanation/documentation, and examples in the attachment. Cheers, Remy
/* (PARI) _R. J. Cano_, May 11 2017
isperm(n,{strict=0},{allowRep=1},{stopAt=+oo},{resumeFrom=0}); Description/Purpose:
Find (if exists) the least base "beta" where n is written as a permutation for some of its digits (with/without allowing digits repetition).
Note: An "strict" search (usually also quite slower) means to search only those permutations of 0..k-1 with some k>1;
where for some m<=k, all the first m digits enter (a leading zero, inclusive). */
isperm(n,{strict=1},{allowRep=0},{stopAt=+oo},{resumeFrom=0})={ my(theDigits:vec,tryThese:vecsmall,piano,touch,pass:small,pattern:vecsmall,leadingzero:small);
forstep(Beta=max(2,resumeFrom),max(2,n-1),1, piano*=0*(pass=1); theDigits=digits(n,Beta); tryThese=Vecsmall(theDigits);
for(i=1,#tryThese,
touch=1<<tryThese[i];
if(bitand(touch,piano),if(!allowRep,pass=0;break),piano+=touch) );
if(pass,
leadingzero=!(piano%2);
pattern=Vecsmall(vecsort(concat([0],theDigits),,8));
if(#pattern==leadingzero+hammingweight(piano),if((strict&&(#pattern==sum(u=1,#pattern,pattern[u]==u-1)))||!strict,return(Beta))) );
if(Beta>stopAt,return(-1)) ); /* Nothing found, incomplete search */
return(0) } /* Nothing found, complete search */
\\ Example: 1) Strict search
\\ isperm(27,1) returns 4 since 27 = 123[4] (with/without a leading zero)
\\ isperm(123,1) returns 10 since 123 = 123[10] (Also with/without a leading zero)
\\ In both cases above, respectively 4, and 10 are the least bases where it is possible
\\ to represent n as a permutation, entering all the digits although leading zeros are not written.
\\ 2) Non strict search:
x = 314159265358979323; \\ Some few digits borrowed from Pi.
y = isperm(x,0); \\ returns 34 for this example.
R=digits(x,y);
z=Set(concat([0],R));
t=concat(if(#R<#z,[0],[]),vector(#R,i,-1+vecsearch(z,R[i]))); \\ Appends a leading zero to complete all the digits, if required.
human=concat(vector(#t,j,Strchr(if(0<=t[j]&&t[j]<=9,48,55)+t[j]))); \\ Returns "026435A891BC7" for this example.
\\ As long as we keep stored the map (for this example, in z), we can recover x from "human".
Dictionary(x:str)={my(data=Vec("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"));for(k=1,#data,if(x==data[k],return(k)));return(0)}; \\ By 0 here we mean: Not found.
fromHuman=fromdigits(apply(q->z[q],apply(Dictionary,Vec(human))),y);
\\ (The End?)
/* Sample execution. Output dump:
bash-4.3$ clear; cd ~/gp; gp2c -g isperm.txt > isperm.txt.c; gp2c-run ./isperm.txt.c
Warning:isperm.txt:11: Assignement to a less precise type: vec<-gen
theDigits=digits(n,Beta)
Reading GPRC: /etc/gprc ...Done.
GP/PARI CALCULATOR Version 2.9.2 (released)
amd64 running linux (x86-64/GMP-6.1.1 kernel) 64-bit version
compiled: May 6 2017, gcc version 5.3.0 (GCC)
threading engine: single
(readline v6.3 enabled, extended help enabled)
Copyright (C) 2000-2017 The PARI Group
PARI/GP is free software, covered by the GNU General Public License, and comes WITHOUT ANY WARRANTY WHATSOEVER.
Type ? for help, \q to quit.
Type ?15 for how to get moral (and possibly technical) support.
parisizemax = 4096000000, primelimit = 10000000
(May 11 2017, 00:31 VET) gp > isperm(1231132) \\ Strict search.
time = 1min, 55,095 ms.
%1 = 1231130
(May 11 2017, 00:33 VET) gp > digits(1231132,1231130) \\ Don't forget the leading zero. Must actually be read "012"
%2 = [1, 2]
(May 11 2017, 00:33 VET) gp >
*/