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

كيف أجرب كل الامكانيات؟؟

مغلق
بدأه إسماعيل ابراهيم في 30 مايو 2002 · 16 رد · 1,804 مشاهدة · في هندسة البرمجيات
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

القيم الممكنة من 1 الى Z .

يعني بكلمات أخرى : اريد صنع مصفوفة وكل قيمها صفر ثم أرفع قيمة العضو الاول في المصفوفة من 1 الى Z .. وفي كل مرة أقارن المصفوفة ... عندما يصل العضو الاول الى قيمة Z نقوم برفع العضو التالي الى 1 ثم نرجع لنزيد العضو الاول من 1 الىZ... الخ..

يعني :

000000001

000000002

.

.

.

.

.

.

00000000Z

000000010

000000011

000000012

...

00000001Z

000000020

...

...

...

ZZZZZZZZZ

حاولت مع الfor لمّا طلعت روحي... الرجاء من لديه فكرة فليلحقني بها :)

أظن أن البرنامج سيحاول عدد بسيط من المحاولات ... يعني حوالي:

218340105584896 محاولة بس:):'(

#2

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

#3

لكن سؤالي عن الكود:: هل أكتب 9 حلقات "فور"..

وكيف؟

#4

يمكن أن تكتب تسع حلقات for ولكن هذا ليس بطريقة البرمجة الصحيحة لأنه تصور لو عندك 20 خانة .. !!! هل سوف تكتب 20 حلقة for .. :D :D

الأظبط من هذا هو أن تقوم بمحاكاة عملية جمع واحد على الأرقام العادية على السلسلة التي تقوم بتكوينها ...

لأنه عندما تجمع 1 إلى الرقم 9 يصبح 10 وعندما تجمع 1 على 199 يصبح 200 وهكذا ..

هنا عندما تجمع 1 على 1Z سوف يصبح 20 وهكذا ...

كود السي المشروح الذي يقوم بهذا هو التالي:

#include 
#include 

void Increment(char *str, int length)
{
    while (--length > 0) {
        char c = str[length];           

        if (c == '9')               // if the character is '9'
            c = 'A';                // ... then the next is 'A'
        else if (c == 'Z') {        // else if it's 'Z'
            str[length] = '0';      // ... then the next is '0'
            continue;               // ... and carry to the next character
        }
        else c++;                   // else increment the character

        str[length] = c;            // store the new character
        break;                      // and exit
    }
}

int main(int argc, char* argv[])
{
    char str[] = "00000000";                                // the base string
    const int length = sizeof(str) / sizeof(str[1]) - 1;    // the length of the string

    do {
        cout << str << endl;                // print the string
        Increment(str, length);             // Increment the string
    } while (strcmp(str, "00000000") != 0); // loop until we are done

    return 0;
}

لاحظ أن الكود صغير جدا ...

Coding on the Cloud and for the Cloud!

My Blog

#5

في هذا التعديل البسيط في التابع main سوف يظهر البرنامج النتيجة بعد كل 65536 محاولة ..

int main(int argc, char* argv[])
{
    char str[] = "00000000";                                // the base string
    const int length = sizeof(str) / sizeof(str[1]) - 1;    // the length of the string
    int i = 0;

    do {
        if ((i++ & 0x0000ffff) == 0)
            cout << str << endl;                // print the string
        Increment(str, length);             // Increment the string
    } while (strcmp(str, "00000000") != 0); // loop until we are done

    cout << " Done" << endl;

    return 0;
}

Coding on the Cloud and for the Cloud!

My Blog

#6

شكرا جزيلا لك أخ هاني.

الكود تمام بس لما حاولت ادرسه واجهتني بعض المشاكل ارجو ان تشرحها :o

1) لماذا وضعت هذا الشرط :

while (--length>0)

ولم نقل :

while (length>0)

(( أعرف أن الجملة الثانية خطأ فقد جربتها لكن أريد أن أفهم لماذا؟))

2) متى ينتقل البرنامج من الخانة الاولى الى الثانية وهكذا ؟

((أعرف أن هذا يحدث لكن لم أنجح في تحديد مكان حدوثه))

أكرر شكري أخ هاني .. وارجو ان لا أكون قد ((ثقلت دمّي عليك:rolleyes: )

(f) (f)

#7

أولا اعتذر للغلط لأن الشرط يجب أن يكون هكذا :

while (--length >= 0)

أولا هو عبارة عن تنقيص قيمة length بمقدار واحد ومقارنتها مع الصفر ، وإذا كان صفر أو أعلى فإن الحلقة تنفذ ..

length هنا تستخدم أيضا كدليل في السلسلة أو ال string . حيث تبدأ الزيادة في آخر حد حتى الوصول إلى الحد 0 .

طيب لمذا حلقة مو شرط if وخلاص ؟؟ هذه الحلقة بالحالة الاعتيادية سوف تنفذ لمرة واحدة فقط ، أما في حالة يوجد حمل فإنها تنفذ مرة أخرى .

من أجل فهم المبدأ يجب عليك أن تركز في الكود الذي داخل الحلقة :

لاحظ هذا المقطع :

        else if (c == 'Z') {        // else if it's 'Z'
            str[length] = '0';      // ... then the next is '0'
            continue;               // ... and carry to the next character
        }

حيث إذا كان المحرف هو Z فإن الحرف التالي سوف يكون 0 والتعليمة continue تجبر خط التنفيذ على تكرار الحلقة مرة أخرى أي يتم انقاص length والدخول مرة أخرى ..

لاحظ آخر الحلقة :

        str[length] = c;            // store the new character
        break;                      // and exit

التعليمة break تجبر الحلقة على الوقوف ..

وهذا كل شئ :)

الجملة الثانية تبعك خطأ لعدة أسباب ..

أولا length من أجل أن تعمل كدليل في السلسة يجل أن ننقصها 1 . ثانيا من أجل عملية تكرار في الحلقة أريد أن أنقص الدليل من أجل أن أعالج المحرف التالي وهكذا ..

Coding on the Cloud and for the Cloud!

My Blog

#8

الف شكر أخ هاني وأحسدك على تفكيرك البرمجي...

لقد فهمت الكود لكن بعد جهد منك ومني ....

إذا أخذ مني كل هالجهد للفهم فكم سيأخذ مني جهد لإختراع حل كهذا؟؟؟ :o بصراحة أحسدك على براعتك ولا حرمنا الله منك(gift)

#9

حياك الله يا هاني

#10

أخي أبو سارية ... أهلا فيك في موقعك ... أتمنى أن أراك وأرى أصحابي هنا حتى يغنوه بالخبرات القيمة ... (f)

Coding on the Cloud and for the Cloud!

My Blog

#11

مبروك أخي هاني على الوظيفة ونرجوا لك التوفيق الدائم ..

ما شاء الله تفكير متميز من رجل متميز ..

أخي هاني أنا جلست أفكر في دالة تحضر جميع الاحتمالات.. فوجدت الحل عن طريق استخدام الـ Recusion ..

الحل قصير وكل الشغل في الدالة ..

الدالة مكتوبة بلغة C#.NET :

static void GetAllCasses( string str, int numOfTimes )
{
	if( str.Length == numOfTimes ) return ;
	char c = (char) ('0' - 1) ; //رقم الاسكي للحرف الذي يسبق الصفر
	for( int i = 0 ; i < 36 ; i++ )
	{
		if( i == 10 ) c = 'A' ;
		else c++ ;
		Console.WriteLine( str + c ) ;
	}
	c = (char) ('0' - 1 );
	for( int i = 0 ; i < 36 ; i++ )
	{
		if( i == 10 ) c = 'A' ;
		else c++ ;
		GetAllCasses( str + c, numOfTimes ) ; // استدعاء الدالة مرة أخرى
	}
}

عند استدعاء الدالة تكتب

GetAllCasses( "", 5 ) ;
#12

قد يتسائل البعض لماذا قمت بوضع حلقتي for لكن الغرض فقط هو للتنظيم ..

والا نستطيع حلها بالطريقة التالية بالاستغناء عن حلقة for الثانية

static void GetAllCasses( string str, int Length )

{

if( str.Length == Length ) return ;

char c = (char) ('0' - 1) ; //رقم الاسكي للحرف الذي يسبق الصفر

for( int i = 0 ; i :o

:) :)

#13

الكود السابق يقوم بكتابة الحالات من خانة وحدة إلى الخانة المطلوبة ..

أما مع هذا التعديل فسوف يقوم الكود بكتابة الحالات بالطول المطلوب .

static void GetAllCasses( string str, int Length )
{
	if( str.Length == Length ) 
                {
                   Console.WriteLine( str ) ;
                   return ;
                }
	char c = (char) ('0' - 1) ; //رقم الاسكي للحرف الذي يسبق الصفر
	for( int i = 0 ; i < 36 ; i++ )
	{
		if( i == 10 ) c = 'A' ;
		else c++ ;
                  GetAllCasses( str + c, Length ) ;
	}

}
#14

The recursive code consumes the memory very very very much and it's not as fast as the linear code. But your method is very useful to get the different permutation of a given array. Another thing, sometimes we need a function that gives us the next value and then work with that value, but the recursive function doesn’t finish until all the values are calculated. Otherwise, it’s a very good code.

Sorry to write in English cause my computer doesn't support Arabic....

:) :)

Coding on the Cloud and for the Cloud!

My Blog

#15

الأستاذ هاني ..

بالنسبة بأن Recursive تستهلك الذاكرة فهذا صحيح إذا كانت الدالة تتراكم على بعضها بشكل مستمر .. مثلا لو أردنا أن نعكس ترتيب Queue معين بواسطة (recursive) ويحتوي على عناصر كثيرة جداً .. فسوف يكون هناك استهلاك كبير للذاكرة ..

أما في مثالنا الحالي .. فباستقراء بسيط للدالة تجد أن مقدار التراكم للدلة لا يمكن أن يزيد على طول الكلمة .. ولو فرضنا أن الكلمة بطول 20 حرف أي أن أكبر مقدار للتراكم للدالة سوف يكون 20 هل تعتقد أن 20 كبيرة ؟ .. كيف لو كان طول الكلمة 6 أحرف أعتقد أن هذا لن يسبب ازدحاما للذاكرة على الاطلاق :) .. (علما أنني حاولت أن احفظ جميع احتمالات الكلمة بطول ستة أحرف في ملف وانتهى الأمر إلى ان اصبح حجم الملف أكثر من 2.3 GB فما بالك بعشرين حرف :P ;) ..

هل الـ Recursive أبطأ من الذي لا يحتوي على Recursive ؟؟ لماذا ؟ وأين مكمن البطء ؟

أشكرك يا أستاذ هاني من كل قلبي :):) ..

#16

آسف أبو فهد .. أنت كلامك صحيح .. كودك لا يستهلك الذاكرة أنا كنت مفكر بكود تاني وماحللت الكود تبعك .. بالنسبة للسرعة فالاثنين نفس الشي ومافي فرق ..

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

Coding on the Cloud and for the Cloud!

My Blog

#17

للرفع

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

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