/** * Extensões a objectos de javascript * Rotinas de encriptação * Funções matemáticas * @author Vítor Hugo Fernandes (a.k.a Balhau) * @copyright Este documento está licenciado sob os direitos do MIT license */ /** * Objecto que representa propriedades comuns aos algoritmos */ var ALG={}; /** * Número de iteracções feitas pelo algoritmo */ ALG.ITER=0; /** * Variável que representa a chave secreta gerada pelo algoritmo de Vigénere. Isto ocorre sempre * que a chave não é especificada à entrada da função */ ALG.VIGSECRETKEY=""; /** * Método que troca dois elementos num array * @param {int} i Indice da posicao * @param {int} j Indice da posicao */ Array.prototype.troca=function(i,j){ if((i=0) && (j=0)){ var aux=this[i]; this[i]=this[j]; this[j]=aux; } }; Array.prototype.classpos=function(el){ var p; for(var i=0;i 0) { par = xu[0]; if (par[0] != par[1]) grupos[grupos.length] = par; else grupos[grupos.length] = [par[0]]; xu.remove(0); volta=true; while (volta) { volta=false; for (var i = 0; i < xu.length; i++) { dif = xu[i].less(grupos[grupos.length - 1]); if (dif.length == 1) { grupos[grupos.length-1]=grupos[grupos.length - 1].concat(dif); xu.remove(i); i--; volta=true; }else if(dif.length==0){ xu.remove(i); i--; } } } } return grupos; }; /** * Método que devolve um array com os elementos de arrA x arrB (produto de conjuntos) * @param {Array} arrA Array de elementos * @param {Array} arrB Array de elementos * @return {Array} Array de elementos (a,b) onde a em arrA e b em arrB */ Array.produto=function(arrA,arrB){ var out=[]; for(var i=0;i=0;i--){ maximo=i; for(var j=0;jthis[maximo]) maximo=j; } this.troca(i, maximo); } } Array.prototype.ShellSort=function(){ var n=this.length; var passo=Math.round(n/2); var j=null; var val=null; while(passo>0){ for(var i=passo;i=passo && this[j-passo]>val){ this[j]=this[j-passo]; j-=passo; } this[j]=val; } passo=Math.round(passo/2.1); } } /** * Método que efectua a operação and sobre dois arrays. Devolve um array com os elementos * que coincidentes para cada posição * @param {Array} arrA Array * @param {Array} arrB Array * @return {Array} Array com os elementos que coincidem */ Array.and=function(arrA,arrB){ var min=Object.min(arrA,arrB); var max=Object.max(arrA,arrB); var out=[]; for(var i=0;i= this.length) { return this; } this[i]=undefined; for(var j=i;jthis[j+1]) this.troca(j,j+1); ALG.ITER++; } } return this; }; /** * Método que cria um array com valores aleatórios * @param {int} dim Dimensão do array * @param {int} low Valor minimo * @param {int} sup Valor máximo * @param {bool} intarray Valor booleano indicando se o array é composto por valores inteiros ou valores decimais * @return {int} Array aleatório com dim elementos compreendidos entre low e sup */ Array.random=function(dim,low,sup,intarray){ var arr=[]; if(typeof(low)=='undefined') low=0; if(typeof(sup)=='undefined') sup=100; if(typeof(intarray)=='undefined') intarray=true; for(var i=0;i this.length-1) return this; return this.substr(0,index) + chr + this.substr(index+1); } /** * Método que baralha a string de modo a que esta continue legível para o ser humano * @param {String} String para conversão */ String.shuffleText=function(str){ var arr=str.split(" "); var tmp=""; var posA=0; var posB=0; for(var i=0;i0) { expmax=getexp(aux); aux-=Math.pow(2,expmax); expaux=getexp(aux); strout+="1"; if(aux==0 && expmax>=1){ expmax++; } while(--expmax>expaux){ strout+="0"; } } return strout; } /** * Método que devolve um array contendo o código binário da string * @return {Array} arr Array contendo strings com a representação binária de cada um dos caractéres da string */ String.prototype.toByteArray=function(){ var arr=[]; for(var i=0;i=97 && pos<=122){ posA=this.charCodeAt(i)-97; str+=String.fromCharCode(65+posA); } else if(pos>=65 && pos<=122){ str+=this[i]; } //se for o espaço else if(pos==32){ str+=" "; } } return str; } /** * Método que verifica se o caracter com determinada posição na string é uma letra maiuscula * do alfabeto * @param {Int} ind Posição na string * @return {Bool} val Verdadeiro se o caracter for uma letra maiuscula, falso caso contrário */ String.prototype.maiuscula=function(ind){ if(this.charCodeAt(ind)>=65 && this.charCodeAt(ind)<=90) return true; return false; } /** * Método que verifica se o caracter com determinada posição na string é uma letra minuscula * do alfabeto * @param {Int} ind Posição na string * @return {Bool} val Verdadeiro se o caracter for uma letra minuscula, falso caso contrário */ String.prototype.minuscula=function(ind){ if(this.charCodeAt(ind)>=65 && this.charCodeAt(ind)<=90) return true; return false; }; /** * @constructor Construtor da class */ var MathL=function(){}; /** * Expansão do número segundo o problema de Collatz Syracuse Ulam (CSU) * @param Numero inteiro * @return Array Sequência de inteiros até encontrar o valor 1 */ MathL.CSUExpansion=function(n){ var a=n; var out=[a]; while(a!=1){ a=(a%2==0)?a/2:a*3+1; out[out.length]=a; } return out; }; /** * @constructor Construtor do objecto CMarkov que representa uma cadeia de Markov * @param {Array} lstats Lista com os labels dos estados associados à cadeia de markov * @param {Array} pobj Representa a matriz de probabilidades da cadeia de markov * @param {Array} inip Representa o vector de probabilidades inicial para a cadeia de markov */ MathL.CMarkov=function(lstats,pobj,inip){ if(lstats.length*lstats.length!=pobj.length || lstats.length!=inip.length){ throw "As dimensões do número de estados não corresponde à dimensão da matriz de probabilidades ou à dimensão do vector de probabilidades iniciais"; } this.lbels=lstats; this.mp=MathL.Matriz.ArrayToMatriz(lstats.length,lstats.length,pobj); this.auxmit=MathL.Matriz.ArrayToMatriz(1,lstats.length,inip); this.initm=MathL.Matriz.ArrayToMatriz(1,lstats.length,inip); }; MathL.CMarkov.prototype.iterate=function(){ this.auxmit=MathL.Matriz.multMatriz(this.auxmit,this.mp); }; MathL.CMarkov.prototype.restart=function(){ this.auxmit=this.initm; }; MathL.CMarkov.prototype.printIteration=function(){ var std="["; for(var i=0;ierr){ xa=xi; xi=xi-(Math.pow(xi,exp)-val)/(exp*xi); ALG.ITER++; } return xi; }; /** * Método de Simpson para cálculo de integrais * @param {Function} f Função que se pretende integrar * @param {Number} min Minimo do intervalo de integração * @param {Number} max Maximo do intervalo de integração * @param {Number} n Número de intervalos * @return {Number} Integral de Simpson */ MathL.SimpsonInt=function(f,min,max,n){ n=n*2; var sint=f(min); var passo=(max-min)/n; var fact=0; var xi; for(var i=1;i<=n;i++){ //determina o factor para cada iteracção fact=(i==n)?1:(i%2==0)?2:4; xi=min+passo*i; sint+=fact*f(xi); } return sint*(passo/3); } /** * Determinação do integral da função f a partir do método do trapézio * @param {Function} f Função a integrar * @param {Number} min Intervalo minimo de integração * @param {Number} max Intervalo máximo de integração * @param {Number} n Número de intervalos para integração * @return {Number} Integral de f entre min e max */ MathL.TrapzInt=function(f,min,max,n){ var passo=(max-min)/n; var strap=f(min); var fact; var xi; for(var i=1;i<=n;i++){ fact=(i==n)?1:2; xi=min+passo*i; strap+=fact*f(xi); } return strap*(passo/2); } /** * Determina o integral de um intervalo de valores e respectivas imagens a partir do * algoritmo do trapézio * @param {Array} arrx array de coordenadas * @param {Array} arry array das imagens das coordenadas */ MathL.TrapzCInt=function(arrx,arry){ if(arrx.length!=arry.length) return Number.NaN; var soma=0; for(var i=1;i=this._matriz.length){ return this; } this._matriz.remove(ind); return this; }; /** * Método que remove uma coluna da matriz * @param {Int} ind Índice da matriz que pretendemos remover * @return {MathL.Matriz} mat O próprio objecto matriz, para chaining */ MathL.Matriz.prototype.rmColuna=function(ind){ if(ind<0 || ind >=this._matriz[0].length){ return this; } for(var i=0;ithis._matriz.length){ return null; } var ncol=this._matriz[0].length; for(var i=0;ithis._matriz[0].length){ return this; } var nlin=this._matriz.length; for(var i=0;i=0;i--){ if(ms._matriz[i][i]!=0){ ms.MLinha(i,1/ms._matriz[i][i]); for(j=i-1;j>=0;j--){ aux=ms._matriz[j][i]; for(k=i;kMath.sqrt(i)) break; if((i%primos[j])==0) primo=false; } if(primo) primos[primos.length]=i; } return primos; }; /** * Determina a média dos valores contidos no array, aqui assume-se que o array * é preenchido com valores numéricos */ Array.prototype.media=function(){ var cmp=this.length; var m=0; for(var i=0;i Math.sqrt(i)) break; if ((i % primos[j]) == 0) primo = false; ALG.ITER++; } if (primo) primos[primos.length] = i; i++; } return primos; }; /** * Método que devolve o valor de combinações (n,k) * @param {int} n Inteiro (n k) --> n * @param {int} k Inteiro (n k) --> k * @return {int} com Inteiro número de combinações */ MathL.comb=function(n,k){ var res=1; for(var i=1;i<=k;i++){ res*=(n+1-i)/i; } return res; }; var COOkie={}; COOkie.setCookie=function(cookieName,cookieValue,minutos) { var today = new Date(); var expire = new Date(); if (minutos==null || minutos==0) minutos=1; expire.setTime(today.getTime() + 60000*minutos); document.cookie = cookieName+"="+escape(cookieValue) + ";expires="+expire.toGMTString(); }; var Crypto=function(){ }; /** * Função que implementa a criptografia de Ceaser * @param {string} str string a criptografar * @param {int} shift Número de deslocamentos * @return {string} strC String criptografada */ Crypto.cesar=function(str,shift){ var i; var strO=""; var chcod; for(i=0;i "+freq+"%"; } return strO; }; /** * Método que encripta uma string a partir da chave de Vigénere. Este método encripta somente * strings que contenham caracteres do alfabeto * @param {String} str String a encriptar * @param {String} chave Chave encriptadora * @return {String} enc Chave encriptada a partir do algoritmo de vigénere * */ Crypto.VEncripta=function(str,chave){ if(typeof(chave)=='undefined'){ chave=Crypto.vigenereRandomKey(); ALG.VIGSECRETKEY=chave; } else{ chave=chave.toMaiuscula(); ALG.VIGSECRETKEY=chave; } //Se a string a codificar não for válida sai com valor nulo if(!String.isAlphaChar(str)){ return null; } var chcomp=chave.length; var chcod=0; var deslocamentochave=0; var strOut=""; var offset=0; var k=0; str=str.toMaiuscula(); for(var i=0;iarrA[ii]){ k=ii; } } return k; }; //Criar os nós para cada um dos valores for(var i=0;i1){ indA1=getIndMinFreqObj(arrA); noAux1=arrA[indA1]; arrA.remove(indA1); indA2=getIndMinFreqObj(arrA); noAux2=arrA[indA2]; arrA.remove(indA2); noRaiz=new noarvore(noAux1.key+noAux2.key,null); noRaiz.esq=noAux1; noRaiz.dir=noAux2; arrA[arrA.length]=noRaiz; } return noRaiz; }; /** * Método que devolve os códigos dos caracteres a partir da árvore de códigos * @param {noarvore} arvore Árvore contendo a codificação dos caracteres a partir do algoritmo de Huffman * @param {Object} obj Objecto do tipo dicionário que irá conter os códigos de cada um dos caracteres presentes na * arvore de Huffman * @param {Object} str String que será sempre inicializada a vazio, necessária para recorrencia */ Compressao.getTreeCodes = function(arvore,obj,str){ if (arvore != null) { Compressao.getTreeCodes(arvore.esq,obj,str+"1"); Compressao.getTreeCodes(arvore.dir,obj,str+"0"); if (arvore.val != null) { obj[arvore.val] = str; } } return obj; } /** * Algoritmo de Huffman para compressão de dados * @param {Object} Obj Objecto representando a árvore de huffman necessária para a compressão e descompressão dos dados */ Compressao.HuffmanEncoding=function(str){ var arv=Compressao.HuffmanEncodingTree(str); var objC=Compressao.getTreeCodes(arv,new Object(),""); var strO=""; var cod=""; for(var i=0;i final, false-> nao final */ Automato.prototype.sfinal=function(esta,bool){ var b; if(typeof(bool)!='undefined') b=bool; else b=true; if(b){ if(this.finais.has(esta)) return; this.finais[this.finais.length]=esta; } else{ if(!this.finais.has(esta)) return; this.finais.remove(this.finais.pos(esta)); } }; /*** * Atribui final ou nao inicial a um estado * @param {Number} esta Estado * @param {Boolean} bool true-> inicial, false-> nao inicial */ Automato.prototype.sinicial=function(esta,bool){ var b; if(typeof(bool)!='undefined') b=bool; else b=true; if(b){ if(this.iniciais.has(esta)) return; this.iniciais[this.iniciais.length]=esta; } else{ if(!this.iniciais.has(esta)) return; this.iniciais.remove(this.iniciais.pos(esta)); } }; /** * Método que devolve uma string com a descrição do autómato * @return {String} descrição com as transições do autómato */ Automato.prototype.toString=function(){ var out="Alfabeto: "+this.alfabeto.toString()+"\n"; out+="Estados: "+this.estados.toString()+"\n"; out+="Iniciais: "+this.iniciais.toString()+"\n"; out+="Finais: "+this.finais.toString()+"\n"; out+="Transições: "+this.transicoes.toString()+"\n"; return out; }; var noarvore=function(key,val){ this.esq=null; this.dir=null; this.key=key; this.val=val; } var Tree=function(){ this.raiz=new noarvore(null,null); }; /** * Método que insere * @param {Número} key Chave numérica * @param {Object} val Objecto que representa o valor que se encontra nos nós da árvore */ Tree.prototype.insertElement=function(key,val){ //caso a árvore esteja vazia insere imediatamente no lado esquerdo da árvore var elaux=this.dir; if(this.esq==null){ this.esq=new noarvore(key,val); } else{ //Enquanto não estivermos numa folha da árvore while(elaux.dir!=null){ //Se a chave à direita for maior que a chave inserida então percorremos a árvore pela sua folha esquerda if(elaux.key>key){ elaux=elaux.esq; } else{ elaux=elaux.dir; } } } } COOkie.getCookie=function(c_name) { if (document.cookie.length>0) { c_start=document.cookie.indexOf(c_name + "="); if (c_start!=-1) { c_start=c_start + c_name.length+1; c_end=document.cookie.indexOf(";",c_start); if (c_end==-1) c_end=document.cookie.length; return unescape(document.cookie.substring(c_start,c_end)); } } return ""; }; /** * Método que devolve uma string contendo as propriedades deste objecto * @return {string} str String contendo informação sobre as propriedades do objecto */ Object.prototype.inspect=function(){ var str=""; var filho; for(filho in this){ if(typeof(this[filho])=='function') str+="Função: "+filho+"\n"; else str+="Variável: "+filho+"-->"+this[filho]+"\n"; } return str; }; /** * Método privado que devolve uma string com a representação JSON do objecto * @param {Object} obj Objecto que se pretende exportar para JSON * @private */ Object._toJSONString=function(obj){ var str=""; var e; console.log(typeof(obj)); if(obj==null) return "null"; if(typeof(obj)=='number'){ str+=obj; return str; } else if(typeof(obj)=='string'){ str+="'"+obj+"'"; return str; } else if (typeof(obj) == 'object') { if (typeof(obj.length) == "undefined") { str += "{"; var k = 0; for (e in obj) { if (typeof(obj[e]) != "function") { if (k != 0) { str += ","; } str +='"'+e+'":'+ Object._toJSONString(obj[e]); k++; } } str += "}"; } else { str += "["; for (var i = 0; i < obj.length; i++) { if (typeof(obj[i]) != "function") { if (i != 0) { str += ","; } str += Object._toJSONString(obj[i]); } } str += "]"; } } return str; } /** * Método que devolve uma string representando o objecto * @return {String} str string contendo a representação JSON do objecto */ Object.prototype.toJSONString=function(){ return Object._toJSONString(this); } /** * Método que transforma um objecto do tipo dicionário num array binário * @return {Array} arr Array binário contendo os valores do objecto dicionário */ Object.prototype.toDicArray=function(){ var arr=[]; var i=0; for(e in this){ arr[i]=[]; arr[i][0]=e; arr[i][1]=this[e]; i++; } return arr; }; /** * Método que devolve uma string contendo o nome de todos os métodos existentes no objecto * @return {string} strm String com a descrição dos métodos */ Object.prototype.getMetodos=function(){ var str=""; for(var filho in this){ if(typeof(this[filho])=='function') str+="Função: "+filho+"\n"; } return str; }; /** * Método que devolve uma string contendo o nome e valor de todas as propriedades existentes * no objecto * @return {string} strp String com a descrição dos valores do objecto */ Object.prototype.getPropriedades=function(){ var str=""; for(var filho in this){ if(typeof(this[filho])!='function') str="Variavel: "+this[filho]; } return str; }; Object.min=function(strA,strB){ return strB.length>strA.length?strA:strB; }; Object.max=function(strA,strB){ return strA.length>=strB.length?strA:strB; }; /** * Devolve um array com os caracteres que constituem a string * @return {Array} */ String.prototype.alphabet=function(){ var out=[]; var ext={}; for(var i=0;i