الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

w ايجاد power set

مغلقمُجاب
بدأه MemoryLess في 11 يناير 2014 · 7 رد · 1,182 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

مرحبا..

عندي ملف نصي يحتوي:

9 1 2 3 4 5 6 7 8 9
7 3 5 6 7 8 9 2
9 1 2 4 3 5 6 9 8 7
6 1 2 4 5 6 7
5 2 4 5 6 7
9 2 3 4 5 9 6 7 1 8
6 2 3 1 5 9 7

بحيث أن الرقم الأول من اليسار عبارة عن عدد العناصر في كل سطر

 

 

قمت بتعديل برنامج وجدته على النت لحساب عدد مرات تكرار كل عنصر:

int threshold;            /* User input threshold */int numItem;            /* Number of items in the database */int numRows;            /* Number of rows in the database */char dataFile[100];        /* File name of the database */int *numLarge;            /* numLarge[k-1] = no. of large k-itemsets found. */int *support1;            /* stores # of occurrence of each itemes*/int *largeItem1;        /* large items >=  threshold*/typedef struct Itemsetnode *LargeItemPtr; // A list to store large items in descending order of their supports.struct Itemsetnode{    int support;    int *itemset;    LargeItemPtr next;};LargeItemPtr *largeItemset;    /* largeItemset[k-1] = array of large k-items */void pass2(){int RowSize;    int item;    FILE *fp;    int i, j;    /* Initialize the itemes list and support list */    support1 = (int *)malloc(sizeof(int)* numItem );    largeItem1 = (int *)malloc(sizeof(int)* numItem );    if ((support1 == NULL) || (largeItem1 == NULL)) {        cout << "out of memory\n";        exit(1);    }    for (i = 0; i < numItem; i++) {        support1 = 0; // Support = support of the large stored in largeItem        largeItem1 = i; // largeItem1[]    -> Array to store 1-items    }    /* scan DB to count the frequency of each item */    if ((fp = fopen(dataFile, "r")) == NULL) // Database file    {        cout << "Can't open data file " << dataFile << "\n";        exit(1);    }    /* Scan each row of the DB */    for (i = 0; i < numRows; i++)    {        /* Read the row size */        fscanf(fp, "%d", &RowSize);                /* Read the items in the row */        for (j = 0; j < RowSize; j++) {            fscanf(fp, "%d", &item);            support1[item]++;        }    }    fclose(fp);    for (i = 0; i < Rowsize; i++)  {        largeItemset = NULL;        numLarge = 0;    }    /* Sort the supports of 1-itemsets in descending order */    q_sortD(&(support1[0]), largeItem1, 0, numItem - 1, numItem);    numLarge[0] = 0;    while ((numLarge[0] < numItem) && (support1[numLarge[0]] >= threshold))        (numLarge[0])++;    cout << "\n No. of large 1-itemsets (numLarge[0]) = " << numLarge[0] << "\n";    for (i = 0; i < numItem; i++)    {        if (support1 >= threshold)        {            printf("%d [%d] ", largeItem1, support1);            cout << "\n";        }    }    cout << "\n";   return;}

وحصلت على هده النتيجة:

7 [7]
5 [7]
2 [7]
6 [6]
3 [5]
4 [5]
1 [5]
9 [5]
8 [4]
 

 

أريد الآن.. تعديل البرنامج ليقوم بحساب جميع الأزواج من النتيجة السابقة لتكون النتيجة:

7 5 [7]
7 2 [7]
5 2 [7]
6 5 [6]
6 2 [6]
6 7 [6]
7 3 [5]
5 3 [5]
2 3 [5]
9 3 [5]
4 5 [5]
4 7 [5]
4 2 [5]
4 6 [5]
5 1 [5]
2 1 [5]
7 1 [5]
9 5 [5]
9 2 [5]
9 7 [5]
8 7 [4]
8 6 [4]
8 5 [4]
8 2 [4]
8 3 [4]
8 9 [4]
1 3 [4]
6 3 [4]
4 1 [4]
9 1 [4]
6 1 [4]
9 6 [4]
8 4 [3]
8 1 [3]
4 3 [3]
4 9 [3]
 

 

قمت بالتعديل التالي:

/* Scan each row of the DB */
    for (i = 0; i < numRows; i++)     {

        /* Read the row size */
        fscanf(fp, "%d", &RowSize);

        /* Read the items1 in the row*/
        for (j = 0; j < transSize; j++) {
            fscanf(fp, "%d", &item1);
                        /* Read the items2 in the row*/
            for (k = j + 1; k < transSize; k++) {
                fscanf(fp, "%d", &item2);
                support2[item1][item2]+=1;
            }
        }
    }
    fclose(fp);

ولم احصل على النتيجة المطلوبة

 

الرجاء المساعدة

وشكرا

#2
اقتباس
أريد الآن.. تعديل البرنامج ليقوم بحساب جميع الأزواج من النتيجة السابقة لتكون النتيجة:

هل بالإمكان توضيح أكثر لذاك السطر؟

 

 

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة C++er في 11 يناير 2014 في 06:44

مدونتي: C++ Tips and Tricks

#3
C++er كتب:

هل بالإمكان توضيح أكثر لذاك السطر؟

 

 

و الله ولي التوفيق

 

شكرا جزيلا للرد

 

في المرة الأولى تم حساب التكرار لكل عنصر

 

يعني مثلا

العنصر (1) متكرر 5 مرات في الداتا

العنصر (2) متكرر 7 مرات في الداتا

العنصر (3) متكرر 5 مرات في الداتا

.

,

العنصر (9) متكرر 5 مرات في الداتا

 

والأن أريد حساب:

العنصر (1,2) متكرر مرات 5 في الداتا

العنصر (1,3) متكرر مرات 4 في الداتا

.

.

العنصر (1,9) متكرر مرات 4 في الداتا

العنصر (2,3) متكرر مرات 5 في الداتا

.

,

.

العنصر (2,9) متكرر مرات 5 في الداتا

العنصر (3,4) متكرر مرات 3 في الداتا

.

.

.

.

.

.

.

.

.

.

.

.

إلى أن

 

العنصر (9,8) متكرر مرات 4 في الداتا

 

وبعد الحصول على هذه النتيجة استفيد منها لأكمل

العنصر (1,2,3) متكرر مرات 4 في الداتا

.

.

إلى أن أصل..

العنصر (1,2,3,4,5,6,7,8,9) متكرر مرة واحدة في الداتا

#4

لست هنا لأجيب عن السؤال ولكن لأعترض على الأسلوب المنتشر , لماذا تبدأ من برنامج تجده على النت وتعدل عليه ؟

البرنامج أبعد ما يكون عن ما تريده ..

 

اكتب مخططا لما تريد أن تقوم به , نظم أفكارك , واكتب الكود بنفسك

 

بالتوفيق

1
#5

أولا انا اتفق مع الأخ مصطفي فى ان الكود الخاص بك يقوم بأمور لا علاقة لها بما تريدي فتوجد طريقة أسهل لفعل ما تريد و بكود صغير و سأعطيك الخطوات و قومي أنت بكتابة الكود و إن احتجت مساعدة فضعيها هنا.

 

المدخلات: ملف يحتوى على مجموعة سطور و كل سطر يحتوى على مجموعة أرقام و أولهم هو عدد الأرقام الموجوده حتى نهاية السطر. الأرقام نفسها يبدو انها فى المدى من 1 حتى 9.

المخرجات: (حسب فهمي) هو تكوين قوائم هى تبادل العناصر بدون تكرار و اعطاء عدد مرات وجود محتويات القائمه بحيث عندما تكون عدد عناصر القائمة أكبر من عنصر واحد يكون عدد توجد عناصر القائمه معا هو أقل عدد مرات تكرار اى عنصر منهم.

 

مثال

5 5 3 2 1 4
6 2 6 7 7 7 1
9 5 5 6 6 7 7 8 8 6

{1} -> 2
{2} -> 2
{3} -> 1
{4} -> 1
{5} -> 3
{6} -> 4
{7} -> 5
{8} -> 1

{1, 2} -> min_count({1, 2}) -> 2
{1, 3} -> min_count({1, 3}) -> 1

{5, 6} -> min_count({5, 6}) -> 3
{5, 7} -> min_count({5, 7}) -> 3

{6, 7} -> min_count({6, 7}) -> 4

إذا كان ما شرحته هو ما تريدي، أعلميني حتى اشرح لك الخطوات (إن لم تكوني قد عرفتيها بعد).

 

 

و الله ولي التوفيق

مدونتي: C++ Tips and Tricks

#6

مرحبا وشكرا على الفكرة

ولكنها فكرة مختلفة

أولا بالنسبة للمدخلات: يجب أن لا يوجد تكرار لنفس العنصر في الصف الواحد

 

فلو فرضنا المثال التالي:

5 5 3 2 1 44 2 6 7 14 5 6 7 83 1 2 3

نجد

{3} -> 2
{5} -> 2

 

لكن

{3,5}-> 1

موجودة  (معا) في الصف الأول فقط

أما بقية الصفوف فلا تتواجد معا

 

 

شكرا جزيلا لكم

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 12 يناير 2014 في 14:28 — السبب: إزالة الاقتباس

1
#7 أفضل إجابة
اقتباس

يجب أن لا يوجد تكرار لنفس العنصر في الصف الواحد

هذا سيسهل العديد من الأمور.

1- نقوم بتجميع محتويات كل سطر على حدى.

2- نقوم بالحصول على الأرقام الموجوده بكل السطور بدون تكرار و ذلك لإنشاء التحليل بين الأرقام المستخدمه فقط.

3- نبدأ فى إجراء التحليل بالإعتماد على الأرقام التى حصلنا عليها من 1 و 2.

 

الخطوه الأولي ذات مستوى متوسط الصعوبة، و فيها نقوم بفتح الملف و قراءة كل محتوياته ثم تحليلها داخل مصفوفة من نوع struct و الذى يحتوى على معلومات السطر.

// line information
typedef struct _row
{
    // number of elements in row
    int  count;
    // each element will have 1 if it is present, 0 if missing
    char value[10];
} row;

// get lines information from disk file
row* read_file(const char* file_name, int* line_count);

التركيب row يمثل السطر و يحتوى على المتغير count و هو عدد الأرقام الموجوده بالسطر و المصفوفه value هى العناصر الموجوده بالسطر و قيمة العنصر هى موقعه بالمصفوفة و إذا كان حاضرا فقيمته 1 و إذا كان غائبا فقيمته 0، مثال:

5 7 3 9 2 5

row.count = 5;
row.value[0] = 0;
row.value[1] = 0;
row.value[2] = 1;
row.value[3] = 1;
row.value[4] = 0;
row.value[5] = 1;
row.value[6] = 0;
row.value[7] = 1;
row.value[8] = 0;
row.value[9] = 1;

هذا الإسلوب يتيح الوصول للعنصر بشكل سريع. التركيب row يتعامل فقط مع الأرقام فى المدى من صفر و حتى 9 فإذا حدث و أن تم تغيير المدى فلابد من تغيير عدد عناصر المصفوفة value.

 

الدالة read_file تقوم بتنفيذ الخطوة الأولي حيث تستقبل مسار الملف داخل file_name و تقوم بالعودة بمصفوفة من نوع row و عدد عناصرها يتم الرجوع به من خلال مؤشر يتم تمرير كمعامل ثاني للدالة و إسمه line_count.

 

بالنسبة لي فقد قمت بتقسيم الخطوة الأولي لدالتين الأولي هى read_file تقوم بفتح الملف و الحصول على محتوياته و تمريرها لدالة أخرى ثم تقوم بتحرير الذاكرة و غلق الملف و إعادة القيمة المعادة من الدالة الثانية. الدالة الثانية read_string تقوم بتحليل النص و حجز الذاكرة لمصفوفة row. هذه الدالة تأخذ الشكل التالي:

row* read_text(const char* string, int size, int* line_count)

المعامل الأول هو النص المراد تحليله و المعامل الثاني هو حجم النص و المعامل الثالث سيحتوى على عدد عناصر المصفوفة row التى سيتم العودة بها.

 

سبب فصل كود تحليل النص عن كود التعامل مع الملف لتسهيل تنقيح الكود و ايضا لإتاحة فرصة تمرير نص بدلا من ملف.

 

الكود الخاص بالخطوه الأولي:

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

#define VALUES_COUNT 10

// line information
typedef struct _row
{
    // number of elements in row
    int  count;
    // each element will have 1 if it is present, 0 if missing
    char value[VALUES_COUNT];
} row;

// get lines information from disk file
row* read_file(const char* file_name, int* line_count);
// get line information from in-memory string
row* read_text(const char* string, int size, int* line_count);


int main(int count, char** args)
{
    row* nums = NULL;
    int line_count = 0;

    if (count != 2) return 1;

    // get data-sets
    nums = read_file(args[1], &line_count);
}

row* read_file(const char* file_name, int* line_count)
{
    // result line information array
    row* res = NULL;
    // file size
    int size = 0;
    // file data
    char* string = NULL;

    // open file
    FILE* file = fopen(file_name, "rb");
    if (file == NULL) return NULL;

    // get file size and allocate temp buffer
    fseek(file, 0, SEEK_END);
    size = ftell(file);
    string = (char*)malloc(ftell(file)+1);

    // get data
    fseek(file, 0, SEEK_SET);
    fread((void*)string, 1, size, file);
    string[size] = 0;
    fclose(file);

    // get result
    res = read_text(string, size, line_count);
    free(string);

    return res;
}

row* read_text(const char* string, int size, int* line_count)
{
    // used to track a position in array 
    int index = 0;
    // index of currently scanning line
    int cur_line = 0;
    // temporary counter
    int i = 0;
    // line information
    row* rows = NULL;
    // string contains at least one line
    *line_count = 1;

    // get number of lines
    for(; index<size; ++index)
    {
        if (string[index] == '\n') ++*line_count;
    }

    // allocate buffer
    rows = (row*)malloc(sizeof(row) * *line_count);
    if (rows == NULL) return NULL;
    rows[0].count = 0;

    // zero data-set
    memset((void*)rows, 0, sizeof(row) * *line_count);

    // scan line content
    for(index=0; index<size; ++index)
    {
        // if new line mark
        if (string[index] == '\n')
        {
            // update current line index, and skip
            ++cur_line;
            continue;
        }

        // skip carriage-return
        if (string[index] == '\r') continue;

        // get number of digits in line
        rows[cur_line].count = string[index] - '0';

        // number of digits scanned in this line
        i = 0;

        // get row digits
        while (i<rows[cur_line].count)
        {
            // skip character if it's whitespace
            if (isspace(string[++index])) continue;

            // update information
            rows[cur_line].value[ string[index] - '0' ] = 1;

            // update number of scanned digits
            ++i;
        }
    }

    return rows;
}

الدالة main يتم تمرير مسار الملف عن طريق الـ debugger.

 

المتغير nums سيتم وضع محتويات السكور به بعد تحليلها و المتغير line_count سيحتوى على عدد السطور.

 

الخطوة الثانية مستواها سهل حيث سنقوم بالمرور على كل عناصر المصفوفة row لكل السطور و تحديد الأرقام الموجوده بدون تكرار.

 

الدالة get_present_nums تقوم بهذه العملية و شكلها كالتالي:

// get present numbers in all rowsvoid get_present_nums(row* rows, int count, row* present_nums){    // temporary counters    int i=0, j=0;    // zero result-set    memset((void*)present_nums, 0, sizeof(row));    for (i=0; i<count; ++i)    {        for (j=0; j<VALUES_COUNT; ++j)        {            // if current element is not present, skip it            if (rows.value[j] != 1) continue;            // if current digit already counted, skip it            if (present_nums->value[j] == 1) continue;            present_nums->value[j] = 1;            ++present_nums->count;        }    }}

يتم تمرير مصفوفة من نوع row كأول معامل و عدد عناصرها كمعامل ثاني و المعامل الثالث هو مؤشر لمتغير من نوع row ليتم تحديث قيمته بالعناصر الموجوده.

 

الأكواد السابقه يمكن إضافة العديد من التحسينات عليها و لكنه أمر غير محبذ لأن البرنامج بأكمله لم ينتهي.

 

الخطوه الثالثة الخاصة بالإحصاء من المفترض ان تكون يسيرة لأنك الأن لديك المتغير من نوع row الذى يحتوى على كافة الأرقام الموجوده بكل السطور بدون تكرار لذا بإستخدام عددهم (row.count) سيتم عمل حلقة تكرار خارجية و بداخلها سيتم عمل حلقة تكرار أخرى و هى التي ستقوم بتنقيح الـ data-set.

 

حاولي تقسيم هذه الخطوه على مجموعة من الدوال و كل واحدة تقوم بأمر محدد لأنه بغير ذلك سيصبح الأمر شاق و صعب، أيضا لا تدمجي كود الطباعة مع كود الإحصاء لأن هذا سيصعب من تنقيح الكود.

 

التركيب الخاص بالإحصاء قد يأخذ الشكل التالي:

// statistics about data-set
typedef struct _state
{
    // the set of number that represent this statistics
    row num;
    // number of times num existed
    int count;
} state;

حيث المتغير num هو الرقم أو الأرقام التى يتم إحصاءها معا مثل {1} أو {1,9} و حيث ان محتويات row مرتبه و معلوم عدد العناصر بهم فلن توجد مشكلة فى طباعتهم.

المتغير count هو عدد مرات تكرار قيمة row داخل مصفوفة من row.

 

يوجد أمر أخير يستوجب الذكر و هو عدد عناصر مصفوفة state النهائية و يمكن حسابه بإستخدام المعادلة التالية:

n * (n-1) + 1

حيث n هو عدد العناصر التى سيتم حساب التابدل لهم بدون تكرار و الواحد الأخير لأنه سيتم إضافة كل العناصر الموجوده داخل الإحصاء النهائي، مثال:

{1}

set_size    = 1
state_count = 1 * (1 - 1) + 1 = 1 * 0 + 1 = 0 + 1 = 1

[1] = 1

*********************
{1, 2}

set_size    = 2
state_count = 2 * (2 - 1) + 1 = 2 * 1 + 1 = 2 + 1 = 3

[1] = 1
[2] = 2
[3] = 1 2

*********************
{1, 2, 3}

set_size    = 3
state_count = 3 * (3 - 1) + 1 = 3 * 2 + 1 = 6 + 1 = 7

[1] = 1
[2] = 2
[3] = 3
[4] = 1 2
[5] = 1 3
[6] = 2 3
[7] = 1 2 3

*********************
{1, 2, 3, 4}

set_size    = 4
state_count = 4 * (4 - 1) + 1 = 4 * 3 + 1 = 12 + 1 = 13

[ 1] = 1
[ 2] = 2
[ 3] = 3
[ 4] = 4
[ 5] = 1 2
[ 6] = 1 3
[ 7] = 1 4
[ 8] = 2 3
[ 9] = 2 4
[10] = 3 4
[11] = 1 2 3
[12] = 1 2 4
[13] = 1 2 3 4

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة C++er في 12 يناير 2014 في 11:13

1

مدونتي: C++ Tips and Tricks

#8

الأستاذ الكريم C++er

جزاك الله كل خير

شرح واضح ومفيد وبارك الله فيك

هذا الموضوع مغلق.

مواضيع مشابهة