16 Mayıs 2014 Cuma

Unrar Kütüphanesiyle Paralel Şifre Bulucu #3


Herşeyden önce Soma'daki kömür madeni kazasından ötürü herkese baş sağlığı dileyerek başlıyorum.

Birşeyler yazmayalı ve yayınlamayalı çok uzun zaman olmuştu. Bu zaman zarfında, bilgisayarı yenileyince başta Euro Truck Simulator gibi her erkeğin hayali olan saçma sapan oyunlar yada eski bilgisayarımda çalışmayan ve uzun zamandır oynamak istediğim oyunlardan dolayı hemen hiçbirşey yapmadığım gibi yazmaya da zaman ayırmadım. O nedenle neredeyse üzerinden bir yıl geçecek olan yazı dizisine hiçbirşey olmamış gibi devam ediyorum. Bir de 4-5 hafta sonrasına yazılması gereken bir rapor var, onu yazmamak için blog yazayım dedim.

Önce seri sürümünün kodunu açıklayacağım. Daha önceki yazılarda da söyledim, benim yazdığım seri sürümden çok daha iyi (ve hızlı) sürümler internette de bulunabilir. Benim yaptığım tek yenilik sözlük dosyasını bilgisayarlar arasında bölüp işlemi paralelleştirmek oldu.

Kodla ilgili açıklamaları yine kodun içerisinde açıklama satırlarında yaptım. Bölük pörçük olmaması için kodu bölen başka bir açıklama girmeyeceğim. Uzun yorum satırları bölünmesin diye karakter boyutunu küçülttüm. İnceleyecek olan zaten kodu Notepad++ yada gedit gibi bir programda inceleyebilirse daha iyi olur.


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

// unrar kutuphanesine ait header dosyalari
#include<raros.hpp>
#include<dll.hpp>


void DosyaCoz(char *arsiv, int sira)    {
    // dosya adlari acik, dosya sifreliyse cozme islemi
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyayla ilgili veriler
    struct RARHeaderData *Baslik;    // RAR icerisindeki dosyalarla ilgili veriler
    char sozluk[] = "sozluk.txt";    // sozluk.txt denenecek kelimelerin oldugu dosya
    char kelime[256];
    FILE *hDosya;
    int status, k1, k2 = 0;

    hDosya = fopen(sozluk, "r");

    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));

    while(!feof(hDosya))        {
    // sozlukten bir kelime oku
        fscanf(hDosya, "%s", kelime);

    // RAR kutuphanesinin dosya acmak icin kullandigi yapi
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

    // RAR dosyasini ac.
        hArsiv = RAROpenArchive(AcmaVerisi);
        Baslik->CmtBuf   = NULL;

        for(k1 = 0; k1 < (sira - 1); k1++)    {
            // ilk sifreli dosyaya kadar oku, yalnizca bazi dosyalar sifrelenmis
            // olabilir.
            RARReadHeader(hArsiv, Baslik);
            RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);
        }

        // ilk sifreli dosyayi oku
        RARReadHeader(hArsiv, Baslik);
        RARSetPassword(hArsiv, kelime);

        // sifreyle birlikte dosyayi test et. eger sifir dondururse sifre dogrudur.
        status = RARProcessFile(hArsiv, RAR_TEST, NULL, NULL);
        fprintf(stdout, "%8d", ++k2);
        fflush(stdout);

        if(status == 0)    break;  // dogru sifre bulunduysa donguyu sonlandir.

        RARCloseArchive(hArsiv);
    }

    // sozluk.txt'nin sonuna gelinmemisse (break ile cikildiysa) sifre bulunmustur
    if(!feof(hDosya))
        // sifre bulunduysa ekrana yaz
        printf("Sifre: %s\n", kelime);
    else
        printf("Sifre bulunamadi.\n\n");

    fclose(hDosya);

    return;

}


void ArsivCoz(char *arsiv)    {
    // dosya adlari sifrelenmisse cozme altprogrami
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyayla ilgili veriler
    struct RARHeaderData *Baslik;    // RAR icerisindeki dosyalarla ilgili veriler
    char sozluk[] = "sozluk.txt";    // sozluk.txt denenecek kelimelerin oldugu dosya
    char kelime[256];
    FILE *hDosya;
    int status;

    hDosya = fopen(sozluk, "r");

    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));

    while(!feof(hDosya))    {
        // sozlukten bir kelime oku
        fscanf(hDosya, "%s", kelime);

        // RAR kutuphanesinin dosya acmak icin kullandigi yapiyi doldur:
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        // doldurulan verilerle RAR dosyayi ac
        hArsiv = RAROpenArchive(AcmaVerisi);

        Baslik->CmtBuf   = NULL;
        RARSetPassword(hArsiv, kelime);
        // sifreyi belirttikten sonra RAR dosya basligini oku
        status = RARReadHeader(hArsiv, Baslik);
   
        // eger baslik okuma isi basariyla sonlanmissa status'da sifir degeri
        // doner. yani sifre bulunmus olur. bu durumda donguyu sonlandir.
        if(status == 0)    break;   

        RARCloseArchive(hArsiv);
    }

   // sozluk.txt'nin sonuna gelinmemisse (break ile cikildiysa) sifre bulunmustur
    if(!feof(hDosya))
        // sifre bulunduysa ekrana yaz
        printf("Sifre: %s\n", kelime);
    else
        printf("Sifre bulunamadi.\n\n");

    fclose(hDosya);
    return;
}


int main(int argc, char *argv[])    {
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;
    struct RARHeaderData *Baslik;
    char dosyaadi[] = "deneme1.rar";   
    // programa parametre olarak herhangi bir dosya adi belirtilmezse bu dosya
    // adindaki RAR dosyayi acmaya calisir.
    int status, k1 = 0, k2 = 1;

    // RAR dosyanin acma verisi icin bellek ayir. malloc'un sonucunu kontrol
    // ettirmedim, ancak istenirse bu kontrol eklenebilir.
    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));

    // programa bir arguman dosya adi verildiyse bu dosya adini ac.
    if(argc > 1)    strcpy(dosyaadi, argv[1]);

    AcmaVerisi->ArcName    = dosyaadi;
    AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
    AcmaVerisi->CmtBuf     = NULL;
    AcmaVerisi->CmtBufSize = 0;
   
    if((hArsiv = RAROpenArchive(AcmaVerisi)) == NULL)    {
        // dosyayi bulamazsa
        printf("Arsivi acma basarisiz oldu.\n");
        return 1;
    }

    // RAR dosyayi ac, baslik icin gereken yapilari bellekte ayir.
    Baslik = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
    Baslik->CmtBuf   = NULL;    // RAR dosyadaki yorumlar okunmayacak

    while(1)    {
        // RAR dosya icerisindeki dosya bilgilerini oku
        status = RARReadHeader(hArsiv, Baslik);
        // eger RAR dosyanin sonuna gelindiyse while'i sonlandir.
        if(status == ERAR_END_ARCHIVE)    break;
        // dosya adlari sifrelenmisse ArsivCoz fonksiyonu cagirilacak
        if(status == ERAR_MISSING_PASSWORD)    {
            printf("Dosya adlari sifrelenmis.\n");
            ArsivCoz(dosyaadi);
            break;
        }

        k1 = k1 + k2;    // ilk adimda k1 = 0, k2 = 1. eger bir tane sifrelenmis
                        // dosya varsa k2 = 0 olacak, sayma islemi sonlandirilacak.
        printf("Arsivdeki dosyanin adi: %s", Baslik->ArcName);
        if(Baslik->Flags & 0x04)    {    // flags'da 3. bitin set edilmesi dosyanin
            printf("*\n");                // sifrelendigini gosterir. sifrelenmis
            k2 = 0;                        // dosyayi yaninda * ile ekrana yazip dosya
        }                                // sayimini sonlandir.
        else    printf("\n");            // dosya sifrelenmemisse * koyma

        status = RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);    // bir sonraki dosyaya gec
        if(status != 0)    printf("Dosyalari islerken birseyler oldu (%d).\n", status);
    }

    RARCloseArchive(hArsiv);

    // k1'de ilk sifreli dosyanin numarasi var.
    if(status != ERAR_MISSING_PASSWORD)
    // eger MISSING_PASSWORD varsa zaten tum dosya sifrelidir.
    // tek bir dosya sifreliyse DosyaCoz fonksiyonunu cagir.
        DosyaCoz(dosyaadi, k1);

    return 0;
}


Bu arada program kodunu vim'de yazıp Notepad++'ya aktardım. Vim'de tabstop 8, Notepad++'da 4 karakter. Bu nedenle de kodun bazı yerlerinde hizalama (indentation) kaydı. Beni suçlamak yerine alıcılarınızın ayarlarıyla oynayın lütfen.

Gelelim bilgisayarına MPI kuracaklar veya hesaplama kümesi erişimi olanlar için asıl olay paralel koda:


#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<mpi.h>

// unrar kutuphanesine ait header dosyalari
#include<raros.hpp>
#include<dll.hpp>

#define MAX_PASS_LENGTH 16
#define MAX_NAME_LENGTH 256        // olabilecek en uzun dosya adi.
#define CALL_ArsivCoz   0x04
#define CALL_DosyaCoz   0x08
#define TAG             0x10

void DosyaCoz(char *arsiv, char *sozluk, int blksiz, int ofset, int sira)    {
    /*
        DosyaCoz(...): Dosya adlari acik, dosya sifreliyse cozme islemi
        arsiv:    RAR dosyanin adini tutan string.
        sozluk:   Sifrelerin listelendigi sozluk dosyasinin adini tutan string
        blksiz:   her bir islemciye sozluk dosyasindan dusen kelime sayisi
        ofset:    her islemcinin sozluk dosyasinin hangi satirini okuyacagi
        sira:     sifresi cozulecek dosyanin arsiv dosyasindaki sirasi
    */
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyayla ilgili veriler
    struct RARHeaderData *Baslik;  // RAR icerisindeki dosyalarla ilgili veriler
    char kelime[MAX_PASS_LENGTH];
    FILE *hDosya;
    int status, k1, k2, rank;
    double sure;

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);    // MPI uzayinda kacinci islemciyim?
    sure = MPI_Wtime();        // sure olcumunu baslat

#ifdef DEBUG
        printf("(%d): blok buyuklugu: %d, ofset: %d\n", rank, blksiz, ofset);
#endif

    hDosya = fopen(sozluk, "r");
        for(k2 = 0; k2 < ofset; k2++)
            fgets(kelime, MAX_PASS_LENGTH, hDosya);
            // her islemci kendi okuyacagi yere kadar gelsin

    // RAR dosya ve icindeki verileri acmak icin gerekli yapilari bellekte ayir
    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
    // burada malloc'un dondurdugu degerlerin test edilmesi eksik
   
    k2 = 0;
    while(k2 < blksiz)        {
        // sozlukten bir kelime oku
        fscanf(hDosya, "%s", kelime);

#ifdef DEBUG
            printf("(%d): (sayac %d) denenen kelime: %s\n", rank, k2, kelime);
            fflush(stdout);
#endif

        // RAR kutuphanesinin dosya acmak icin kullandigi yapi
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        // RAR dosyasini ac
        hArsiv = RAROpenArchive(AcmaVerisi);
        Baslik->CmtBuf   = NULL;

        for(k1 = 0; k1 < (sira - 1); k1++)      {
        // ilk sifreli dosyaya kadar oku, yalnizca bazi dosyalar sifrelenmis
        // olabilir.
        RARReadHeader(hArsiv, Baslik);
        RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);
        }

        // ilk sifreli dosyayi oku
        RARReadHeader(hArsiv, Baslik);
        RARSetPassword(hArsiv, kelime);

        // sifreyle birlikte dosyayi test et. eger sifir dondururse sifre dogrudur.
        status = RARProcessFile(hArsiv, RAR_TEST, NULL, NULL);

        if(status == 0)    break;    // dogru sifre bulunduysa donguyu sonlandir

        RARCloseArchive(hArsiv);
        k2++;
    }

    if(k2 < blksiz)     {    // dongu bitiminde islemci kendisine dusen blogun
        // sonuna gelmemisse arada bir yerde sifreyi buldu demektir.
        printf("Sifre: %s\n", kelime);
        MPI_Abort(MPI_COMM_WORLD, 8);
    }
    else
        printf("Sifre bulunamadi.\n\n");

        printf("Islemci %d icin calisma suresi %f saniye.\n", rank, MPI_Wtime() - sure);
    fclose(hDosya);

    return;

}

void ArsivCoz(char *arsiv, char *sozluk, int blksiz, int ofset)    {
    /*
        ArsivCoz(...): Dosya adlari sifrelenmisse cozme algoritmasi
        arsiv:    RAR dosyanin adini tutan string.
        sozluk:   Sifrelerin listelendigi sozluk dosyasinin adini tutan string
        blksiz:   her bir islemciye sozluk dosyasindan dusen kelime sayisi
        ofset:    her islemcinin sozluk dosyasinin hangi satirini okuyacagi
    */

    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyasiyla ilgili veriler
    struct RARHeaderData *Baslik; // RAR icerisindeki dosyalarla ilgili veriler
    char kelime[MAX_PASS_LENGTH];
    FILE *hDosya;
    int status, k1, rank;
    double sure;

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);    // MPI uzayinda kacinci islemciyim?
    sure = MPI_Wtime();  // sure olcumunu baslat..

#ifdef DEBUG
    printf("(%d): blok buyuklugu: %d, ofset: %d\n", rank, blksiz, ofset);
#endif

    hDosya = fopen(sozluk, "r");

        for(k1 = 0; k1 < ofset; k1++)
            fgets(kelime, MAX_PASS_LENGTH, hDosya);
            // herkes sozluk dosyasinda kendi okuyacagi yere kadar gelsin

    // RAR dosya ve icindeki verileri acmak icin gerekli yapilari bellekte ayir
    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
    // burada malloc'un dondurdugu degerlerin test edilmesi eksik

    k1 = 0;
    while(k1 < blksiz)        {
        // sozlukten bir kelime oku
            fgets(kelime, MAX_PASS_LENGTH, hDosya);

#ifdef DEBUG
        printf("(%d): (sayac %d) denenen kelime: %s\n", rank, k1, kelime);
        fflush(stdout);
#endif

        // RAR kutuphanesinin dosya acmak icin kullandigi yapiyi doldur
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        // doldurulan verilerle RAR dosyayi ac
        hArsiv = RAROpenArchive(AcmaVerisi);

        // CommentBuffer = NULL : Comment'leri okuma
        Baslik->CmtBuf   = NULL;
        RARSetPassword(hArsiv, kelime);
        // sifreyi belirttikten sonra RAR dosya basligini oku
        status = RARReadHeader(hArsiv, Baslik);

        // eger baslik okuma isi basariyla sonlanmissa status'da sifir degeri
        // doner yani sifre bulunmus olur. bu durumda donguyu sonlandir.
        if(status == 0) break;

        RARCloseArchive(hArsiv);
        k1++;
    }

    if(k1 < blksiz)       {    // dongu bitiminde islemci kendisine dusen blogun
        // sonuna gelmemisse arada bir yerde sifreyi buldu demektir.
        printf("Sifre: %s\n", kelime);
        MPI_Abort(MPI_COMM_WORLD, 9);
    }
    else
        printf("Sifre bulunamadi.\n\n");

    printf("Islemci %d icin calisma suresi %f saniye.\n", rank, MPI_Wtime() - sure);
    fclose(hDosya);

        return;
}

int main(int argc, char *argv[])    {
    FILE *hSozluk;
    int size, rank, nsatir, krkt, mesaj, blksiz, ofset, status;
    int k1 = 0, k2 = 1;
    HANDLE PASCAL *hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;
    struct RARHeaderData *Baslik;
    char dosyaadi[MAX_NAME_LENGTH];
    char sozluk[MAX_NAME_LENGTH] = "sozluk.txt";
    char tmp[MAX_PASS_LENGTH];
    double sure;

    MPI_Init(&argc, &argv);
    // MPI'i initle, islemci sayisini ve sira sayilarini al.
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    sure = MPI_Wtime();

    if(argc > 1)    {
        // RAR dosyanin adi programa arguman olarak verilir.
        strcpy(dosyaadi, argv[1]);
        // eger birden fazla arguman verilmisse ikinci arguman sozluk dosyasidir
        if(argc > 2)    strcpy(sozluk, argv[2]);
    }
    else    {
        if(rank == 0)   printf("Kullanim: rarsolve <dosyaadi.rar> [sozluk.txt]\n");
        MPI_Abort(MPI_COMM_WORLD, 1);
        return 1;
    }

    if(rank == 0)    {
        // sifirinci islemci sozlugun satir sayisini belirler
        hSozluk = fopen(sozluk, "r");

        nsatir = 0;

        do    {
        krkt = fgetc(hSozluk);
        if(krkt == '\n')    nsatir++;
        } while(krkt != EOF);

        fclose(hSozluk);
    }

    // satir sayisini butun islemcilere bildir.
    MPI_Bcast(&nsatir, 1, MPI_INT, 0, MPI_COMM_WORLD);
   
    blksiz = nsatir / size;
    ofset  = rank * blksiz;
    // herkes kendine dusen sozluk blogunu ve ilk kelimesini bulsun

    if((nsatir % size) && (rank == (size - 1)))
        blksiz = nsatir - (blksiz * size - blksiz);
        // tamsayi duzenlemeleri

    if(rank == 0)    {
        // RAR dosyanin acma verisi icin bellekte yer ayir.
        AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));

        AcmaVerisi->ArcName    = dosyaadi;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        if((hArsiv = RAROpenArchive(AcmaVerisi)) == NULL)   {
            // dosyayi bulamazsa
            printf("Arsivi acma basarisiz oldu.\n");
            MPI_Abort(MPI_COMM_WORLD, 2);
            return 2;
        }

        // RAR dosyayi ac, baslik icin gereken yapilari bellekte ayir.
        Baslik = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
        Baslik->CmtBuf   = NULL;    // RAR dosyadaki yorumlar okunmayacak

        while(1)    {
            // RAR arsivi icerisindeki dosya bilgilerini oku.
            status = RARReadHeader(hArsiv, Baslik);
            // eger RAR dosyanin sonuna gelindiyse while'i sonlandir.
            if(status == ERAR_END_ARCHIVE)  break;
            // dosya adlari sifrelenmisse ArsivCoz fonksiyonu cagirilacak.
            if(status == ERAR_MISSING_PASSWORD)     {
                printf("Dosya adlari sifrelenmis.\n");
                mesaj = CALL_ArsivCoz;
                for(krkt = 1; krkt < size; krkt++)
                    // sifirinci butun islemcilere ArsivCoz fonksiyonunun
                    // cagirilacagini mesajla bildiriyor.
                    MPI_Send(&mesaj, 1, MPI_INT, krkt, TAG, MPI_COMM_WORLD);
                // sifirinci islemcinin kendisi de ArsivCoz'u cagiriyor.
                ArsivCoz(dosyaadi, sozluk, blksiz, ofset);
                break;
            }

            k1 = k1 + k2;   // ilk adimda k1 = 0, k2 = 1. eger bir tane sifrelenmis dosya varsa
                            // k2 = 0 olacak, sayma islemi sonlandirilacak.
            printf("Arsiv adi: %s", Baslik->ArcName);
            if(Baslik->Flags & 0x04)  {     // flags'da 3. bitin set edilmesi
                printf("*\n");          // dosyanin sifrelendigini gosterir.
                k2 = 0;                  // sifrelenmis dosyayi yaninda * ile yaz
            }
            else    printf("\n");

            status = RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);  // bir sonraki dosyaya gec
            if(status != 0) printf("Dosyalari islerken birseyler oldu (%d).\n", status);
        }

        RARCloseArchive(hArsiv);

        // k1'de ilk sifreli dosyanin numarasi var.
        if(status != ERAR_MISSING_PASSWORD)    {
        // eger MISSING_PASSWORD varsa zaten tum dosya sifrelidir.
                mesaj = CALL_DosyaCoz;
            // sifirinci islemci diger islemcilere DosyaCoz fonksiyonunun
            // cagirilacagini mesajla bildiriyor
                for(krkt = 1; krkt < size; krkt++)
                    MPI_Send(&mesaj, 1, MPI_INT, krkt, TAG, MPI_COMM_WORLD);
                // sifirinci islemcinin kendisi de ArsivCoz'u cagiriyor.
                DosyaCoz(dosyaadi, sozluk, blksiz, ofset, k1);
            }
    }

    else    {
        // sifirinci islemci haricindeki islemciler sifirincidan mesaj bekliyor
        MPI_Recv(&mesaj, 1, MPI_INT, 0, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        if(mesaj == CALL_ArsivCoz)   
            ArsivCoz(dosyaadi, sozluk, blksiz, ofset);
        else if(mesaj == CALL_DosyaCoz)
            DosyaCoz(dosyaadi, sozluk, blksiz, ofset, k1);
    }

    if(rank == 0)
        printf("Toplam %f saniyede %d kelime denendi.\n", MPI_Wtime() - sure, nsatir);
   
    MPI_Finalize();

    return 0;
}



Son olarak herşey tamamsa son bir soru kalıyor: "Sözlük dosyaları nasıl oluşturulacak?" Onun için de basit bir MATLAB kodu yazdım. Yaptığı tek şey belirli kriterlere göre 5 ile 10 karakter arası rastgele kelimeler üretip bunları sozluk.txt dosyasina yazıyor. Aslında bunun için daha amaca daha yönelik araçlar yazılabilir. Örneğin sozluk.txt olarak imla kılavuzunu alıp imla kılavuzundaki kelimelerin başına yada sonuna sayılar eklemek gibi. Matlab kodu görece basit olduğundan pek açıklama yazmayacağım ancak onunla ilgili tek söyleyebileceğim 33 ve 36. satırlardaki iki for döngüsü yüzünden bir hayli yavaş çalıştığı. 


kucuk_harfler = true;
buyuk_harfler = false;
sayilar       = true;
karakterler   = false;
kel_sayi = 200000;        % 200bin kelime uret

kHavuz = [ ];
bharf_tablo = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
kharf_tablo = 'abcdefghijklmnopqrstuvwxyz';
sayi_tablo  = '0123456789';
karak_tablo = '!#$%&()*+,-./:;<=>?@_';

if(kucuk_harfler)
    kHavuz = strcat(kHavuz, kharf_tablo);
end

if(buyuk_harfler)
    kHavuz = strcat(kHavuz, bharf_tablo);
end

if(sayilar)
    kHavuz = strcat(kHavuz, sayi_tablo);
end

if(karakterler)
    kHavuz = strcat(kHavuz, karak_tablo);
end

lHavuz = length(kHavuz);
hSozluk = fopen('sozluk.txt', 'w');

for k1 = 1:kel_sayi
    kelime = [ ];
    uzunluk = floor(rand * 5 + 5);    % kelime uzunluklari rastgele
    for k2 = 1:uzunluk
        Havuz_ptr = floor(rand * lHavuz + 1);
        kelime = strcat(kelime, kHavuz(Havuz_ptr));
    end
    fprintf(hSozluk, '%s\n', kelime);
   
end

fclose(hSozluk);



Buraya kadar kodlardan ötürü bir hayli uzunca bir yazı oldu. Bu ara tekrar yazmak için zaman bulabilirsem gerçekten ne kadar gereksiz işlerle uğraştığımı anlatan bir yazı daha yayınlayabilirim.


Hiç yorum yok:

Yorum Gönder