• 0
هاني الأتاسي

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

سؤال

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

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

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

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

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

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

20 إجابة على هذا السؤال .

  • 0

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

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 بحيث أثناء تنفيذ البرنامج يتم طباعة الحلول فقط .. :)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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



#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: :'( :'( :'(

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

يمكن هيك؟؟

#include

template int* fibat() {

int helper,a1=1,a2=1;

int static strr[10];

for( int i=2;i

{

helper=a1;

a1=a2;

a2=a2+helper;

strr[i-2]=a2;

}

return strr;

}

int main() {

int * alhal;

cout<<"1 n1 n";

alhal= fibat<10>();

for(int r=0;r:D

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

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

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

#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;
}

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

أستاذ هاني :

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

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

 

#include

long Fib(int num);

main()

{

int val;

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

cin >> val;

cout :) .

مع تحياتي ,,,

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

:'( :'(

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

هذه محاولة لكنها فاشلة :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:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

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

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

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

وشكرا

(f) (f)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

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

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

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

ماهو ال 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

:)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

(f) (f) (f)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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


#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();
}

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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;
}

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

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);
}

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لقد استخدم في الحل 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);
}
}

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .