supplement-02-a.gp

\\ Encoding strings as vectors of numbers, and decoding vectors of
\\ numbers to strings.
encode(s)=
{
   local(u);
   u=Vec(Vecsmall(s));
   if((vecmin(u) < 96) || (vecmax(u) > 122),
      error("input should only contain a-z"););
   return(u-vector(length(u),x,97));
}
decode(u)=
{
   if ((vecmin(u) < -1) || (vecmax(u) > 25),
       error("input should be in the range [0, .., 25]"));
   return(Strchr(u+vector(length(u),x,97)));
}

\\ Helper functions.
wrappedapply(f,s)=decode(apply(f, encode(s)));

caesar(k,s)=wrappedapply(x->(x+k)%26, s);
decaesar(k,s)=caesar(-k,s);

vigenere(k,s)=
{
   local(i,u,v);
   v=encode(s);
   u=vector(length(v));
   for(i=1,length(v),
      if(k[((i-1)%length(k))+1]==26,
	 u[i] = -1,
	 u[i] = (v[i]+k[((i-1)%length(k))+1])%26));
   return(decode(u));
}
devigenere(k,s)=vigenere(vector(length(k),i,-k[i]), s);

invertpermutation(k)=
{
   my(u,v);
   u = encode(k);
   v = vector(26, i, -1);
   for(i=1,length(u),
      if(u[i] != -1,
	 v[u[i]+1] = i-1));
   return(decode(v));
}

substitution(k, s)=
{
   my(v);
   v = encode(k);
   wrappedapply(x -> v[x+1], s);
}
desubstitution(k,s)=substitution(invertpermutation(k), s);

subsequence(v,i,n)=
{
   return(vector(floor(length(v)/n),j,v[i+(j-1)*n]));
}

frequency(v)=
{
   local(i,j,u,r);
   u=vecsort(v);
   i = 1;
   r = [];
   while(i <= length(u),
	 j=i+1;
	 while(j <= length(u),
	       if(u[j] != u[i],
		  break);
	       j = j+1);
	 r = concat(r, [[u[i], j-i]]);
	 i = j);
   return(vecsort(r,2,4));
}

keyguesses(v)=
{
   local(i,k,u,s);
   u = frequency(v);
   for(i=1,5,
      k=(u[i][2]-4)%26;
      print(k, " <-> ", decode(vector(5, j, (u[j][2]-k)%26))));
}

IC(v)=
{
   local(fr);
   fr=frequency(v);
   return(1.0/(length(v)*(length(v)-1))*sum(i=1,26,fr[i][3]*(fr[i][3]-1)));
}

makepermutation(pairs)=
{
   local(u,i);
   u=vector(26, i, -1);
   for(i=1,length(pairs),
      a=Vec(pairs[i]);
      b=encode(a[1])[1];
      c=encode(a[2])[1];
      u[b+1] = c);
   return(decode(u));
}

digrams(s)=
{
   local(u,v,i);
   u=Vec(s);
   return(vector(length(u)-1, i, Str(u[i], u[i+1])));
}
trigrams(s)=
{
   local(u,v,i);
   u=Vec(s);
   return(vector(length(u)-2, i, Str(u[i], u[i+1], u[i+2])));
}
2010-09-02, Kristian Gjøsteen