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

خوارزمية Palindrome كلمة كلمة ,,

مغلق
بدأه Khaled.Alshaya في 16 أبريل 2007 · 11 رد · 8,701 مشاهدة · في قسم المواضيع الهامة في قسم السي /سي++
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

لمن يعرف ما هو الـ Palindrome ,, فقد قمت بكتابة مثال للتحقق إذا كانت الجملة عبارة عن Palindrome أم لا ,,

لمن لا يعرف ما أتكلم عنه ,, خذ الجملة التالية مثلاً :

I am, Who Am I ?

المقصود هنا أنه إذا كان بالإمكان قراءة الكلمات من اليمين إلى اليسار و من اليسار إلى اليمين (h) فهو Palindrome ,,

مع ملاحظة أن الكود يهتم بالكلمات و ليس بالأحرف ,, و المعنى أن الكلمات لو أعيد ترتيبها من اليسار إلى اليمين أو من اليمين إلى اليسار فستعطي نفس الجملة ,,

هناك نوع آخر من Palindrome و هو يهتم إذا كانت أحرف الجملة من اليمين إلى اليسار يمكن أن تقرأ من اليسار لليمين ,, و التحقق طبعاً يكون أسهل من التحقق من المثال الذي في الأعلى ,, مثال :

POP

فهذه الكلمة يمكن قرائتها من اليمين إلى اليسار و من اليسار إلى اليمين و لكن هذا النوع ليس موضع اهتمامنا ,,

-------------------------------------------------------------------------------------------------------

من مميزات الكود أنه لا يهتم إذا كانت الأحرف صغيرة أو كبيرة ,, و لا يهتم بعلامات الترقيم كالفاصلة و النقطة و غيرها ,, فقط يهتم بالأحرف و apostrophe s ,,

apostrophe s : هي s الملكية مثالها ,,

We are God's Creation.

كلمة God's يعتبرها البرنامج كلمة واحدة و لا يعتبر s الملكية علامة ترقيم ,,

المهم لنذهب للاطلاع على الكود ,,

قمت بتصميم دالة تستقبل نص للتحقق إذا كانت الجملة Palindrome أم لا ,, و تقوم بإرجاع true أو false :

bool IsPal ( string Str ){
		string Word;
		queue <string> PalQ;
		stack <string> PalS;
		int   Counter = 0;
		for ( unsigned int I = 0; I < Str.length(); I++ ){
			if ( isalpha ( Str[ I ] ) && isupper ( Str[ I ]  ) )
				Str[ I ] = tolower ( Str[ I ] );
		}
		while ( Str[ Counter ] ){
			Word = "";
			if ( !(isalpha ( Str [ Counter ] )) && (Str [ Counter ] != '\'') ){
				Counter++;
				continue;
			}
			while ( (isalpha ( Str [ Counter ] )) || (Str [ Counter ] == '\'') ){
				Word += Str[ Counter ];
				Counter++;
			}
			PalQ.push ( Word );
			PalS.push ( Word );
		}

	   unsigned int WordsCount = PalQ.size();
	  // Fixed by Shreef.
		for ( unsigned int I = 0; I < WordsCount; I++ ){
			if ( PalQ.front() != PalS.top() )
				return false;
			PalQ.pop(); PalS.pop();
		}
		return true;
	}

و الدالة تستعمل المكتبات التالية ,,

#include <stack>
	#include <queue>
	#include <string>
	#include <cctype>

طبعاً شرح خفيف للدالة سيكون كالتالي ,,

for ( unsigned int I = 0; I < Str.length(); I++ ){
			if ( isalpha ( Str[ I ] ) && isupper ( Str[ I ]  ) )
				Str[ I ] = tolower ( Str[ I ] );
	}

هنا يتم تحويل جميع الأحرف الكبيرة إلى أحرف صغيرة في النص الذي تم تمريره ,, النص الأصلي لن يتأثر لأننا مررنا النص بالقيمة و ليس بالمرجع في الدالة ,,

الحلقة ستمر على كل حرف و ترى إذا كان حرفاً و كان Capital فسوف يتم تحويله إلى Small ,,

	while ( Str[ Counter ] ){
			Word = "";
			if ( !(isalpha ( Str [ Counter ] )) && (Str [ Counter ] != '\'') ){
				Counter++;
				continue;
			}
			while ( (isalpha ( Str [ Counter ] )) || (Str [ Counter ] == '\'') ){
				Word += Str[ Counter ];
				Counter++;
			}
			PalQ.push ( Word );
			PalS.push ( Word );
		}

الحلقة هنا ستتكرر مادام النص لم يصل إلى نهايته ,, و الملاحظ أنه في if الأولى إذا لم يكن الحرف حرفاً هجائياً أو apostrophe s فسوف تزيد الحلقة المتغير Counter و تعيد تكرار الحلقة بالكلمة المحجوزة continue ,,

أما إذا كان حرفاً هجائياً أو apostrophe s فسوف تقوم الحلقة بتكوين الكلمة ثم إضافتها للـ Stack و الـ Queue اللذان تم تعريفها سابقاً ,,

	for ( unsigned int I = 0; I < PalQ.size(); I++ ){
			if ( PalQ.front() != PalS.top() )
				return false;
			PalQ.pop(); PalS.pop();
		}

هنا سوف يتم التحقق من غرض الدالة ,, عن طريق الـ Stack و الـ Queue ,,

---------------------------------------------------------------------------------------

في المرفقات ستجد الدالة مع مثال لها عن كيفية تطبيقها ,,

إذا كان لديك أي استفسار أو تعديل على الكود فلا تتردد

----------------------------------------------------------------------------------------

تحديث ...

اكتشف الأخ Shreef bug في البرنامج ,,

الـBug كانت في for loop

الأخيرة و تم إصلاحها

تحياتي ,,

Palindrome.cpp

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 19 أبريل 2007 في 01:57

#2

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

أعلم أن طرح برنامج ما لن يؤدي إلى نقاش ,, لذلك أود أن أعرض جزئية معينة و يعرض الأخوة آراءهم و اقتراحاتهم حولها ,,

الجزئية هي عملية تقسيم الجملة إلى كلمات ,, هل يمكن تطويرها ؟ هل هناك طريقة أفضل ؟ أسهل ؟ أسرع ؟ أغرب !! :rolleyes:

و هذه هي الفقرة :

   while ( Str[ Counter ] ){
		Word = "";
		if ( !(isalpha ( Str [ Counter ] )) && (Str [ Counter ] != '\'') ){
			Counter++;
			continue;
		}
		while ( (isalpha ( Str [ Counter ] )) || (Str [ Counter ] == '\'') ){
			Word += Str[ Counter ];
			Counter++;
		}
		PalQ.push ( Word );
		PalS.push ( Word );
	}

طبعاً شرح الكود موجود بالأعلى لمن اراد الإستزادة !

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 17 أبريل 2007 في 04:43

#3

انا مش مبرمج ++C/C بس اجرب بردو اعمل تغيير فى ترتيب الكود على الأقل :)

Word = "";
   while ( Str[ Counter ] ){

		if ( (isalpha ( Str [ Counter ] )) || (Str [ Counter ] == '\'') ){
			Word += Str[ Counter ];
			Counter++;
			continue;
		} 

		Counter++;
		PalQ.push ( Word );
		PalS.push ( Word );
		Word = "";
	}

اعتقد دى حتكون اسرع نسبياً إن شاء الله

Web Citizen

ShrefInLife.gif

__________

General blog : Shref In Life

#4

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

أهلاً بيك أخ شريف ,, نورت الموضوع ,,

في مشكلة واحدة في التعديل رغم أن الفكرة جميلة ,, و هي أن تتحقق من المطلوب فقط دون التحقق من علامات الترقيم ,, :rolleyes:

المشكلة أنه عند وجود أكثر من علامة ترقيم أو فراغات متتالية سيتم إضافة Word في كل مرة أي أن Word ستكون تساوي "" أي نص فارغ ,,

سأحاول أن أقوم بعرض محاولتك بعد التعديل بعد إذنك طبعاً ,,

تحياتي أخ شريف ,,

#5

السﻻم عليكم

Khaled.Alshaya كتب:
المشكلة أنه عند وجود أكثر من علامة ترقيم أو فراغات متتالية سيتم إضافة Word في كل مرة أي أن Word ستكون تساوي "" أي نص فارغ ,,

سأحاول أن أقوم بعرض محاولتك بعد التعديل بعد إذنك طبعاً ,,

:rolleyes: اه عدت علية دى اسف, ممكن إذا أتاكدنا من قيمة Word قبل اضافتها للـ Queue و الـ Stack حتكون اتحلت المشكلة إن شاء الله

Word = "";
   while ( Str[ Counter ] ){

		if ( (isalpha ( Str [ Counter ] )) || (Str [ Counter ] == '\'') ){
			Word += Str[ Counter ];
			Counter++;
			continue;
		}

		if (Word != ""){
			PalQ.push ( Word );
			PalS.push ( Word );

			Word = "";
		}

		Counter++;		
	}

شكرا خالد

Web Citizen

ShrefInLife.gif

__________

General blog : Shref In Life

#6

احنا اخذنا هالفكره بشيت بس على القورذم

فهذا هو الالقورذم الي عندي

Pre pointer for top and first and last stack , integer for length the ward
Post Given an English word and an integer representing the length of the word
Return true if ward balendrom and fulse ifit is not

1 first = last = top
2 loop ( last ->next not eqal null )

   1  last = last -> next;

3  if (length mod 2 equal to 0 )
4  int L= length / 2
5  else   L= length +1 /2
6  int i=1

7 loop ( i lees or equal L )

	1  if (first -> data not equal last-> data )

		   1 return false 

	2 else  

		   1  first = first -> next 
			2  last = last -> back
			3   i=i+1


8   endloop
9 return true
10 end algorithm
#7

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

سبقتني أخ شريف و عدلت البرنامج :D

أعتقد أن البرنامج بعد التعديل أصبح أسهل للقراءة من الأول ,, راح أضيف التعديل عندي ,,

( الأخ , الأخت ) إيليان ,, الخوارزمية التي وضعتيها لا أدري إن كنت فهمتها حقيقة و لكنها ليست للنوع الذي عرضته ,, أعتقد أنها Palindrome للحروف و ليست للكلمات ,, شكراً للمشاركة بالمعلومة على كل حال ,,

تحياتي ,,

#8

السﻻم عليكم :) ,

خالد, كنت عايز اعمل compile عشان اجرب الكود, VS2005 عندى بس معرفتش ازاى اضيف references للمكتبات دى :( , رحت على جهاز لينوكس و جربت على ++g و مشى الموضوع بس لمة جربت البرنامج لقيته بيقف فى نص العملية و مش بيكمل لﻷخر, المشكلة كانت فى الجزئية دى

	for ( unsigned int I = 0; I < PalQ.size(); I++ ){
		if ( PalQ.front() != PalS.top() )
			return false;
		PalQ.pop(); PalS.pop();
	}

الـ loop مكانتش بتخلص لﻷخر , يتيجى عند النص تقريبا و تقف عشان مع كل استدعاء لـ PalQ.pop بتقل القيمة المرتجعة من PalQ.size بمقدار عدد واحد

دة الكود المعدل

	unsigned int WordsCount = PalQ.size();

	for ( unsigned int I = 0; I < WordsCount; I++ ){

		if ( PalQ.front() != PalS.top() )
			return false;

		PalQ.pop(); PalS.pop();

	}

السﻻم عليكم

Web Citizen

ShrefInLife.gif

__________

General blog : Shref In Life

#9

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

أهلاً أخ شريف,,

أول ثغرة في البرنامج يتم اكتشافها :D و تسجل لرصيد الأخ شريف ,,

و تم تعديل البرنامج اللي موجود في المشاركة الرئيسية ,,

بالنسبة لعملية المقارنة بين الـStack و Queue فلازم يكون في متغير زي ما ذكرت يا أخ شريف و إلا راح توصل الحلقة للنصف و توقف ,,

بالنسبة للـ وVS2005 و الله أنا ما عندي فكرة و لا استخدمت برامج Microsoft أبداً,, بس ما اعتقدش انه لازم تضيف Reference للمكتبات لأنها Standard و تجي مع أغلب الـ Compilers إذا ما كان كلها على ما أعتقد ( STL تجي VC++2005 بشكل افتراضي ) ,, بالنسبة للـ ++g فهو المفضل عندي طبعاً :D

تحياتي ,,

#10

لا اخوي هي للكلمات بس الاقوريذم الي كتبته يحسب عدد الاحرف الموجوده فالكلمه ويوشوف اذا الكمله Palindrome ولا لا

#11

السلام عليكم أخ خالد

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

بخصوص مقارنة الكلمة من اليسار إلى اليمين ومن اليمين إلى اليسار

كودى البسيط

#include <iostream>

using std::endl;
using std::cout;
using std::cin;
#include <string>
using std::string;
bool  test(string );

int main()
{

  cout << test("Waled");

  return 0;
	}

bool test(string str)
{
	 string s1;
	 for(int i = str.length(); i  > -1;i--)
	 {
	  s1 += str;
	 } 

	 for(int x = 0; x < s1.length(); x++)
	 {
			if(s1[x+1] != str[x]) 
			 {
			  return false;	   
			 return 0;

			  }
		 // cout << str[x] << " " <<s1[x+1]  << endl;			
			 }   
	   return true;
	   //return ( s1.compare(str) ? "true" : "false");

}

بس للأسف هو مش مراعى لحالة الأحرف

متى يصـــل البُنيان تمامــه *** إذا كنت تبنيه وغـيرك يهدمه

لـو كان سهماً واحــداً لتقيته *** ولكنه ســهم وثانيـــة وثالثه

#12

صديقي sql_ado إن برنامجك يحسب الرموز و الفواصل, و ما يتم طرحه لا ياخذ إلا الأحرف.

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

إذا كان النص زوجي تكون النواة حرفين (يجب أن يكونا متطابقين) و إذا كان النص فردي تكون النواة ثلاثة أحرف الحرفين الأول و الثالث متطابقين .

و من ثم متابعة البحث في كلا الحالتين متماثلة.

و في هذه الحالة يكون الوصول إلى النتيجة بشكل أسرع في حالة كون النص غير palindrome

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

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