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

سلسلة - شغل مخك (21) - خاص سي++

مغلق
بدأه هاني الأتاسي في 23 يونيو 2002 · 20 رد · 3,326 مشاهدة · في هندسة البرمجيات
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

=============

تم حل سؤال فيبوناشي وبقي سؤال أبراج هانوي .. :)

============

كيف ممكن أن تجعل مترجم السي++ يقوم بحساب سلسلة فيبوناشي الشهيرة أثناء عملية الترجمة ..:)

أيضا كيف ممكن أن تحل أبراج هانوي أثناء عملية الترجمة .. :)

مساعدة : استخدم templates ..:D

Coding on the Cloud and for the Cloud!

My Blog

#2

بالنسبة لهانوي فراجع الرابط التالي :

http://www.dcs.napier.ac.uk/a.cumming/hano...oi/rechelp.html

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

بالنسبة لفيبوناشي فهي سهلة ..:

Fib[0] = 1
Fib[1] = 1
Fib[n] = Fib[n-2] + Fib[n-1]     ... where n > 1

أي أن سلسلة فيبوناشي هي :

Fib[2] = Fib[0] + Fib[1] = 1 + 1 = 2
Fib[3] = Fib[1] + Fib[2] = 1 + 2 = 3
Fib[4] = Fib[2] + Fib[3] = 2 + 3 = 5
.
.
.

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

طبعا جميع الحلول يتم تنفيذها أثناء وقت تنفيذ البرنامج أي بعد ما تكبس run .. أنا أريد حل بحيث يتم حسابهم أثناء ترجمة البرنامج !! أي قبل run وخلال فترة compile بحيث أثناء تنفيذ البرنامج يتم طباعة الحلول فقط .. :)

Coding on the Cloud and for the Cloud!

My Blog

#3

أرجو أن يكون هذا هو الحل الصحيح .. لأنه لو كان غلط بأنجن.. أنا ضيعت أجازتي اليوم(الجمعة) وأنا بأبحث وادوّر حتى توصلت أخيرا الى هذا الحل .. إذا كان مش صحيح على الدنيا السلام..

#include 

template  int fibat() { 
	int helper,a1=1,a2=1;
	for( int i=2;i	{
                 helper=a1; وضع قيمة العضو السابق هنا

                 a1=a2; العضو سابق يتحول الى عضو الحالي 
	a2=a2+helper; جمع العضو السابق الحالي
	cout<	}
	return 0;
}

int main() {
	cout<<"1 n1 n";
	fibat<10>();
	return 0;
}

:'( بعد وضع الحل بديت أشك في صحته ...:confused: :confused: هل يمكن أن تنفذ حلقة وطياعة خلال الـترجمة:confused: :confused: :'( :'( :'(

#5

لا لا مايصير .. هيك ماصار أثناء الترجمة ... بس محاولة جيدة ...

بدو كان مخك عصر شوي زيادة ... بعطيك مساعدة استخدم التعاودية مع ال template من أجل حل فيبوناشي ..

وبعدين شو هي المصفوفة .. المفروض الحل من غير مصفوفات ..

لازم يكون عندك تابع يعطي قيمة الرقم التي في سلسلة فيبوناشي .. مثلا عندما تعطيه 1 يعطي 1 وعندما تعطيه 4 بيعطيك 5

Coding on the Cloud and for the Cloud!

My Blog

#6

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

#7
#include 

int main()
{
int num;
long result=0,f1=0,f2=0;
 printf("Enter f(n):");
 scanf("%d",&num);
 for (int i=1 ;i<=num;i++)
  {
	if (i==1) f1=1;
	else
	 f1=f2;

	if (i==2) f2=1;
	 else
	  f2=result;


	result=f1+f2;
  }
  printf("nresult = %ld" , result);
 return 0;
}
#8

السلام عليكم ,,,

أستاذ هاني :

ليش من الافضل إستخدام الــ templates ؟

ممكن تون بدون هيك مو ؟

#include

long Fib(int num);

main()

{

int val;

cout << "Please Enter a Number To Get The Fib Value ? " ;

cin >> val;

cout :) .

مع تحياتي ,,,

#9

يا اخوان يا اخوان يا اخوان ...

السؤال واضح .. أريد البرنامج أن يعرف أرقام فيبوناشي أثناء الترجمة وليس أثناء التنفيذ .. أيضا االطلب الآخر أريد حل أبراج هانوي أثناء الترجمة أي أثناء التنفيذ أطبع القيم فقط ...

:'( :'(

Coding on the Cloud and for the Cloud!

My Blog

#10

هذه محاولة لكنها فاشلة :P

#include 

template 
int fib() 
{
    return ( a==0 || a==1 ) ?  1 :  (fib()+fib());
} 

void main() 
{ 
	cout << "fib(6)=";
	cout << fib<6>();
	cout << endl;
}

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

وبالنسبة للسؤال فهل يقوم المستخدم بادخال الرقم الذي سيتم اعطاءه للدالة fib أم أنه يتم تحديده في البرنامج ؟ اذا كانت الأولى فأعتقد أن ذلك أصعب :confused:

#11

حلو كتير كتير كتير !!! لكن غلط :)

ال template للتوابع هي فقط من أجل تمرير أنواع ولا أعتقد ممكنة من أجل تمرير قيم ...

حاول استخدام الtemplate تبع ال classes .. :)

ولا تقرب على if أو return أو while أو علامة ال (؟) لأن كل هذول لا يمكن تنفيذهم أثناء الترجمة ..

لا لا - بتم تحدبد القيمة من البرنامج :)

Coding on the Cloud and for the Cloud!

My Blog

#12

طيب استاذ اعطينا مساعدة مثل ايش هي الأوامر التي تنفذ خلال الترجمة وايش هي اللي تنفذ خلال التنفيذ :(

وما بدي ارد اسويها شات ;)

وشكرا

(f) (f)

#13

استخدم template مع class وحاول تستخدم inline functions بالاضافة إلى أن تستخدم فقط استدعائات إلى inline static functions .. أيضا ال enum ممتازة من أجل حفظ قيمة أثناء الترجمة بدلا من استخدام int ..

بصراحة أنا هيك حليت سؤال فيبوناشي ..

أيضا حاول أن تقلب كل الشروط if إلى استدعائات و الحلقات إلى تعاودية .. :)

Coding on the Cloud and for the Cloud!

My Blog

#14

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

أولا العديد غير فاهم إلى الآن ماهو المطلوب من السؤال ..

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

الغرض من السؤال هو كيفية ايجاد قيمة من سلسلة فيبوناشي أثناء الترجمة وطباعتها فقط أثناء التنفيذ .

السؤال التاني : كيف ممكن حل أبراج هانوي أثناء الترجمة وطباعة الناتج أثناء التنفيذ .

ماهو ال template ..

ال template ممكن أن نعتلره امتداد لل macro في السي ولكن ال macro غبي لدرجة أنه يعتبر مثل نسخ ولصق كود أما ال template فممكن أن ترتبط بالتوابع وال classes من أجل بناء توابع عامة أو classes عامة ..

أقصد بعامة أي أنها ممكن أن تعمل على أي نوع من المعطيات .. سوف أعطي هذا المثال البسيط .. فرضا لو سألت أن تكتب تابع يقوم بارجاع القيمة الكبرى بين قيمتين بحيث يعمل من أجل كل الأنواع؟ في حالة كانة اجابتك تابع واحد كالتالي فعشرة على عشرة :

template 
T max(T& a, T& B)
{
     return a > b ? a : b;
}

الكلمة class التي داخل template تدل على أن T قد تكون أي نوع معرف داخل البرنامج .. ممكن أيضا أن تستخد الكلمة typename بدلا من class وبصراحة أنا أفضل استخدام typename .

الكود السابق يعني أن المترجم داخليا سوف يصنع كود مشابه في حالة استدعيت التابع باستخدام بارامترات int وأيضا سوف يصنعه إذا استعديته باستخدام نوع آخر مثل float .. مثلا :

int a = 5, b = 8;
float x = 10.0, z = 15.0;

cout B) B)
{
     return a > b ? a : b;
}

float max(float& a, float& B)
{
     return a > b ? a : b;
}

عوضا عن استخدام class او typename في الtemplate ممكن استخدام أنواع عادية .. مثلا :

template 
void Print()
{
    cout << "int = " << A << endl;
    cout << "float = " << B << endl;
}

سوف يقوم المترجم ببناء تابع من أجل كل قيمة مختلفة نمررها كالتالي :

Print<1, 1.5>();
Print<5, 100.25>();

يجب أن نلاحظ أمر هام وهو ليس من الداعي أن نذكر اسم النوع الذي نريد أن نمرره لل template في التوابع ، أما مع ال classes فيجب ذكر النوع صراحة كما سوف نرى ذلك بعد قليل .. طبعا بالنسبة لل template التي تستخدم أنواع مثل int أو float أو غيرها فيجب تمريرها صراحة في التوابع وال classes ..

قبل أن أذكر الحل لمسألة فيبوناشي .. دعوني أذكر مثال على استخدام ال template في ال classes ..

لو أحببنا أن نبرمج class لstack بحيث نقوم بتحديد حجم المكدس أثناء تعريف المتحول .. أحد الطرق هو صنع template كالتالي .. (طبعا هذا حل سئ ولكن أريد أن أشرح الفكرة فقط )

template 
class Stack {
   .
   .
   .
private:
    int buff[SIZE]
};

نستطيع أن نستخدمه كالتالي :

Stack<100> my_big_stack;
Stack<10> my_small_stack;

طبعا لا أنصح أحد أن يبني stack بالطريق السابقة لأنها تستهلك كود كبير وأمر آخر يجب أن يكون ال stack ديناميكيا وليس مصفوفة عادية .:)

على فرض أردنا أن نصنع stack لكل الأنواع الممكنة فيمكن أن نكتب التالي :

template 
class Stack {
   .
   .
   .
private:
    T *buff;
};

نستطيع أن نستخدمه كالتالي :

Stack my_int_stack;
Stack my_string_stack;

================

الآن نرجع لسؤال سلسلة فيبوناشي ..

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

أثناء الترجمة يستحيل أن ندخل الحلقات والشروط كالكود العادي ولكن يجب أن نجعل كل الأمور تعمل عن طريق بناء template .

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

ماذا يحدث لو صنعت الكود التالي :

template 
struct dummy {
	static Print() {
		cout << T << endl;
		dummy::Print();
	}
};

dummy<1>::Print();

سوف يترجم البرنامج ، وتصبح شاشاتك كلها واحدات حتى ينفجر عندك المكدس ويغلق البرنامج .:)

لكن ماذا سوف يحدث إذا عملت تعديل جدا بسيط على الكود السابق وهو داخل ال struct كالتالي :

template 
struct dummy {
	static Print() {
		cout << T;
		dummy::Print();
	}
};

هنا أثناء الترجمة سوف يكون أول struct يحتوي هلى 1 ومن بعدها سوف يجد المترجم أنه يحتاج إلى dummy ذات القيمة 1+1 أو 2 وسوف يصنع struct آخر .. وهكذا حتى ينفجر مكدس المترجم ولن يظهر شئ على الشاشة وتظهر رسالة خطأ من المترجم أنه جن ..:)

في المثال السابق استطعنا أن نقحم المترجم في عملية تعاودية لا نهائية .. ولكن كيف ننهي التعاودية ؟؟؟؟؟؟؟؟

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

على فرض أردنا أن نغير البرنامج التالي بأن يطبع القيم حتى ال10 فسوف يكون كالتالي :

template 
struct dummy {
	static Print() {
		cout << T << endl;
		dummy::Print();
	}
};

template <>
struct dummy<10> {
	static Print() {
		cout << T << endl;
	}
};

dummy<1>::Print();

لاحظ كيف قمنا بتعريف الtemplate الثاني من أجل أن يتم استخدامه في حالة ال 10 وداخله حذفنا الاستدعاء التعاودي ..

المثال السابق يوضح كيفية صنع حلقة أثناء الترجمة .. :)

بقي أمر آخر وهو ماذا لو أردنا حفظ قيمة من نوع int أثناء الترجمة .. الحل الوحيد هو استخدام enum كالتالي :

template 
struct anything {
  enum { value = T * 2 + 1 }
};

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

    cout << anything<5>::value;     // will print 11
    cout << anything<10>::value;     // will print 21

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

الآن ببساطة بعد أن عرفنا كيف يتم ذلك ممكن أن نحل سلسلة فيبوناشي وهي كالتالي :

template
struct Fib {
	enum { value = Fib::value + Fib::value };
};

template<>
struct Fib<0> {
	enum { value = 1 };
};

template<>
struct Fib<1> {
	enum { value = 1 };
};

وعند استخدامها مثلا ممكن أن نعرف مصفوفة تحتوي على قيم السلسة كالتالي :

int FibArr[] = {
	Fib<0>::value, Fib<1>::value,
	Fib<2>::value, Fib<3>::value,
	Fib<4>::value, Fib<5>::value,
	Fib<6>::value, Fib<7>::value };

وأثناء الترجمو سوف تحول إلى :

int FibArr[] = {
                1, 1, 
                2, 3, 
                5, 8, 
                13, 21};

:):):):):):):):) وهذا كل شئ ...

من أجل حل أبراج هانوي يجب أن تعرف كيف ممكن أن تصنع شرط if أثناء الترجمة وهو كالتالي :

template 
struct Test {};

// The true case template
template <>
struct Test
{
	static inline void clause() {
	     cout << "TRUE" << end;
	}
};

// The false case template
template <>
struct Test
{
	static inline void clause() {
	     cout << "FALSE" << end;
	}
};

وهي تستخدم تماما كما بالسابق كالتالي :

Test<1 == 5>::clause();    // Will print FALSE
Test<1 <= 5>::clause();    // Will print TRUE

:)

Coding on the Cloud and for the Cloud!

My Blog

#15

استاذ هاني ارجوا ان لا تضع حل سؤال ابراج هانوي واترك مدة حل السؤال مدة مفتوحة

لأنه فكرة حل السؤال أثناء الترجمة هي اللي مصعبة الموضوع وحل هذا النوع من الأسئلة بده ممارسة

(f) (f) (f)

#16

بفهم حل سؤال فيبوناشي ممكن حل سؤال هانوي ب 5 دقائق .. :)

بس أنا ماراح أحلو وتارككم أنتو تفكرو :):)

Coding on the Cloud and for the Cloud!

My Blog

#17

هذا الحل اللي توصلتله بعد شرح الأستاذ هاني لحل مسألة فيبوناشي بس فيه بعض الأخطاء :(

#include "iostream.h"

int n,A,B,C;
void move(int,int,int,int);

template 
struct Test { 
static inline void clause();
};

template <> 
struct Test
{ 
	static inline void clause() {  
		cout<<"Move from "<<1<<" to "<<3<    } 
}; 

template <> 
struct Test
{ 
	static inline void clause() { 
        move(n-1, A, B, C);
		move(1, A, C, B);
		move(n-1, B, C, A);	 	
	} 
};


int main()
{
	int n;
	cin>>n;
	move(n,1,3,2);
	return 0;
}

void move(int,int,int,int)
{
	Test::clause();
	Test<(n>1)>::clause();
}

أنا عارف انه خطأ بس هذا اللي طلع معي

#18
template 
struct tower
{
	tower(int src, int aux, int des)
	{
		tower b(src, des, aux);
		printf("Move from %d to %dn", src, des);
		tower f(aux, src, des);
	}

};

template <>
struct tower<0>
{
	tower(int a, int f, int t)
	{
		printf("%s", "bye bye");
	}
};

int main(int argc, char* argv[])
{
	printf("Hello World!n");

	tower<5> n(1, 2, 3);

	return 0;
}
#19

لن ينجح معك هكذا! .. هل قمت بتجربته ورأيت كود الأسمبلي؟

Coding on the Cloud and for the Cloud!

My Blog

#20
void Move(int n, char source, char destination, char temporary)
{
    if (n <= 1)
    {						// base case
        cout << "Move the top disk from " << source;
        cout << " to " << destination << endl;
    }
    else
    {						// General case
        Move(n-1, source, temporary, destination);
        Move(1, source, destination, temporary);
        Move(n-1, temporary, destination, source);
    }

ولكم خالص تحياتي

#21

لقد استخدم في الحل Recursion

template
class Hanoi
{
	.
	.
	.
	void Move(int n, T source, T destination, T temporary);
	.	
	.
};

	void Hanoi::Move(int n, T source, T destination, T temporary)
	{
	    if (n <= 1)
	    {						// base case
        	cout << "Move the top disk from " << source;
        	cout << " to " << destination << endl;
	     }
	    else
	    {						// General case
 	       Move(n-1, source, temporary, destination);
  	       Move(1, source, destination, temporary);
 	       Move(n-1, temporary, destination, source);
	    }
	}

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

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