[Ajuda] Programa para apresentar combinações de letras

renafi

Power Member
boas. Quero fazer um programa que apresente N combinações de letras do alfabeto, em que N é o número de letras que quero na combinação.

Por ex: n=4

Combinações:
AAAA AAAB AAAC AAAD AAAE ... AAAZ
AABA AABB AABC AABD .... AABZ / AACA AACB AACC AACD.. AACZ
e por ai adiante até cobrir todas as combinações possíveis. Alguém pode ajudar?
 
boas. Quero fazer um programa que apresente N combinações de letras do alfabeto, em que N é o número de letras que quero na combinação.

Por ex: n=4

Combinações:
AAAA AAAB AAAC AAAD AAAE ... AAAZ
AABA AABB AABC AABD .... AABZ / AACA AACB AACC AACD.. AACZ
e por ai adiante até cobrir todas as combinações possíveis. Alguém pode ajudar?

podes fazer um programa recursivo

onde a função chama-se N-1 vezes. em cada função tem 1 ciclo (onde precorres as letras do alfabeto)

por cada nova letra do ciclo multiplicas o tamanho do alfabeto peloo antigo array e replicas n vezes o array original no novo

algo do genero pra um alfabeto de 3 letras

a b c

a b c a b c a b c->aa ba ca ab bb cb ac bc cc

aa ba ca ab bb cb ac bc cc aa ba ca ab bb cb ac bc cc aa ba ca ab bb cb ac bc cc -> aaa baa caa aba bba cba aca bca cca ...
 
Brute force dictionary

Olha para o gajo a querer fazer um dicionário para fazer ataques de força bruta :p

Fiz no outro dia um programa mesmo à pressão para isso

Código:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;


public class Dicionario {
	public static int MAX_SIZE = 11;
	public static String txt = new String("");
	public static String password_aux = new String("");
	
	public Vector aux = new Vector();
	
	
	public void call(int max_size)
	{
		++max_size;
		for(int j = 48; j != 58; ++j)
		{
			aux.add((char)j);
			
			for(int z = 0; z != max_size; ++z)
			{
				txt += aux.get(z);
			}
			txt += "\n";
			System.out.print(txt);
			criaDicionario(txt);
			txt = "";
			if(max_size < MAX_SIZE+1)
				call(max_size);			
			
			aux.remove(aux.size()-1);				
		}		
	}

	public void criaPassword()
	{
		int max_size = 1;
		
		for(int i = 48; i != 58; ++i)
		{
			aux.add((char)i);
			call(max_size);	
			aux.remove(aux.size()-1);
		}
	}
	
	public void criaDicionario(String passwords)
	{
		try {
	        BufferedWriter out = new BufferedWriter(new FileWriter("filename", true));
	        out.write(passwords);
	        out.close();
	    } catch (IOException e) {
	    }
	}
	
	public static void main(String args[])
	{		
		Dicionario d = new Dicionario();		
		d.criaPassword();
	}
}

só precisas de alterar o MAX_SIZE e os valores do ciclo, se não estou enganado este faz para números de 0 a 9

Se tiveres um código mais eficiente gostava de ver, normalmente o meu código é feito a martelo :005:
 
Tenho aqui outro exemplo que fiz... este ainda foi mais a martelo XD
Código:
#include <string>
#include <iostream>
#include <fstream>
#include<stdio.h>
#include<conio.h>

using namespace std;
string alphanum = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string alphacap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;\"\'<>,.?/')^";
string numeric="0123456789";
string escolha=numeric;
int tamanho=8;
int cont=0;

void imprimir(int* pos,ofstream & file)
{
    cont++;
    for (int i=tamanho-1;i>=0;i--)
    {
        //cout<<escolha[pos[i]];
        file<<escolha[pos[i]];
    }
    //cout<<"   "<<cont<<endl;
    file<<endl;

}
int main()
{

cout
 <<"             _____  _______ _______ _______  ______ _______ __   _"<<endl
 <<"            |_____] |_____| |______ |______ |  ____ |______ | \\  |"<<endl
 <<"            |       |     | ______| ______| |_____| |______ |  \\_|"<<endl<<endl<<endl;
                                                       

    cout<<"1 - "<<numeric<<endl<<endl
        <<"2 - "<<alpha<<endl<<endl
        <<"3 - "<<alphacap<<endl<<endl
        <<"4 - "<<alphanum<<endl<<endl
        <<"5 - "<<all<<endl<<endl<<endl;
    cout<<"tipo de caracteres :"<<endl;
    
    int op;
    cin>>op;

    switch(op)
    {
    case 1:escolha=numeric;
        break;
    case 2:escolha=alpha;
        break;
    case 3:escolha=alphacap;
        break;
    case 4:escolha=alphanum;
        break;
    case 5:escolha=all;
        break;
    }
    
    cout<<"numero de digitos: "<<endl;
    cin>>tamanho;

    cout<<"insira o local para guardar o ficheiro : ";
    string local;
    cin>>local;

    ofstream out;
    local+="\passwords.lst";
    cout<<local<<endl;
    out.open(local.c_str());
    if(!out.is_open())
    {
        cout<<"nao foi possivel guardar nessa localizacao"<<endl;
        return -1;
    }
    
    cout<<"A gerar passwords... "<<endl;
    

    int* pos = new int[tamanho];
    for (int i=0;i<tamanho;i++)
    {
        pos[i]=0;
    }
    bool troca=false;
    int j=0;
    bool acabou=false;
    imprimir(pos,out);
    while(!acabou)
    {
        acabou=true;
        troca=false;j=0;
        while(!troca)
        {
            if(pos[j]<escolha.length()-1)
            {
                pos[j]++;
                imprimir(pos,out);
                troca=true;
            }else{
                j++;
                for (int k=0;k<j;k++)pos[k]=0;
            }
        }
        for(int i=0;i<tamanho;i++)
        {
            if(pos[i]!=escolha.length()-1)
            {
                acabou=false;
            }
        }
    }
    

    cout<<"Passwords geradas: "<<cont<<endl;
    
    out.close();
    system("pause");
}

isto serve para mostrar que é impossível fazer ataques bruteforce em tempo útil..
por exemplo, gerar um ficheiro com todas as combinações de 8 digitos com algarismos, resulta num ficheiro com cerca de 900Mb
 
Impossível não é, basta teres um dicionário eficiente, porque a maior parte das pessoas não utiliza passwords do tipo "%Ha=I#g2R{l", é mais tipo "qwerty" "123456" "password" "130577" etc. deve de haver ai pelas internets dicionários das passwords mais utilizadas.

Outra boa maneira é ter tipo um dicionário só com datas de nascimento, reduz bastante o tamanho do ficheiro ou mesmo números de telefone etc...

É usar a imaginação.
 
Sim, mas é melhor voltar-mos a falar de programação.. ;)
o assunto está a fugir para uma área que não me parece que seja permitida discutir...
 
isto serve para mostrar que é impossível fazer ataques bruteforce em tempo útil..
por exemplo, gerar um ficheiro com todas as combinações de 8 digitos com algarismos, resulta num ficheiro com cerca de 900Mb

Para um programa que pretende mostrar isso é bastante ineficiente, no meu pc demorou mais de 4 minutos a gerar as combinação de 5 letras de A a Z, o que com este programa demora menos de 10 segundos.

Código:
#include <stdio.h>

int inc( char *s, int n )
    {
    if( s[n]++ == 'Z' )
        {
        if( n == 0 ) return 0;
        s[n] = 'A';
        return inc( s, n - 1 );
        }
    return 1;
    }

int main( int argc, char **argv )
    {        
    if( argc > 1 )
        {
        int n = atoi(argv[1]);
        char s[ n + 1 ];  
        memset( s, 'A', n );
        s[n] = '\n';
        
        FILE *f = fopen("comb.txt", "w");
        
        do fwrite( s, n+1, 1, f );
            while( inc( s, n - 1 ) ); 
        }         
    return 0;
    }
 
Para um programa que pretende mostrar isso é bastante ineficiente, no meu pc demorou mais de 4 minutos a gerar as combinação de 5 letras de A a Z, o que com este programa demora menos de 10 segundos.

eu sei que o código que postei é ineficiente... este ano, nas aulas de programação falou-se na analise temporal dos algoritmos, coisa com que não me preocupei nesse algoritmo.
Nestes casos com a recursividade ganha-se muita performance.

Apesar de existirem muitos algoritmos, vou tentar fazer outro mais eficiente...
 
Código:
#!/usr/bin/env python2.6

from itertools import *

characters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
              'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Z']
              
number_of_characters = 5

with open("pass.txt", "w") as f:
    f.writelines(str(tuple) for tuple in product(characters, repeat=number_of_characters))
 
Back
Topo