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

مطابقة نص معقد بدون التعابير المنتظمة Regex

بدأه Mr.B في 28 أكتوبر 2012 · 9 رد · 1,835 مشاهدة · في هندسة البرمجيات
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

لنفترض أنك تريد التأكد من أن نصّ يطابق سلسة معينة تحددها, مثلاً تريد التأكد من أن النص يبدأ بالحرف a متبوع بحرف b مرة أو أكثر وينتهي بـf. في الحالة العادية ربما تستخدم التعابير المنتظمة regular expressions ويُمكنك تمثيله بـ:

^ab+f$

مثال مع بايثون :

>>> import re
>>>
>>> e = re.compile("^ab+f$")
>>>
>>> e.match("ab")
>>> e.match("abf")
<_sre.SRE_Match object at 0x018AFF60> # يعني أن النص مطابق
>>>
>>> e.match("abbbbbbbbf")
<_sre.SRE_Match object at 0x018AFA20> # يعني أن النص مطابق
>>> e.match("abbbbbbbbfq")
>>>

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

بحث عن هذا الموضوع في قوقل ووجدت إشارات لشيء يُسمى الـfinite state automata وبصراحة أنني لم أفهم أي شيء, فيبدو أن الموضوع يدرس في الجامعات لطلاب الحاسب وكل الكلام الذي وجدته نظري×نظري, رُموز رياضية ومصطلحات وأشياء لافائدة منها. لما حاولت أن أتابع هذه المحاظرة :

نمت وصحيت اليوم الثاني :haha: .

عموماً وجدت تطبيق بسيط جداً جداً وكان كل ما أحتاجه لفهم الموضوع, رجاءً إطلع عليه : Simple Finite State Machine In C

الفكرة بسيطة جداً, مثلاً في مثالنا الأول قنا أننا نريد أن نتأكّد من أنّ نصّ معين يجب أن يبدأ بـa يتبعه b فأكثر وينتهي بـf, أي سيطابق نصوص مثل:

abf
abbbf
abbbbbbbbbbbbf

لإختبارها سنقوم بالتالي:

post-231926-036958100 1351371376_thumb.p

إنتبه لأشياء :

  • الأسهم تمثّل قفزات لجزء آخر من البرنامج كدالة أو قفزة فعليه بإستخدام goto.
  • والدوائر تُمثل الإختبار نفسه وهذا الإختبار يكون في دالة أو label إذا إستخدمت goto.

لنطبّق هذا الكلام في برنامج:

#include <stdio.h>


int main(int argc, char **argv)
{
    char *c = argv[1];

START:
    if( c == '\0' )
        goto ERROR;
    else if( *c++ == 'a' )
        goto CHECK_B;
    else
        goto ERROR;

CHECK_B:
    if( c == '\0' )
        goto ERROR;
    else if( *c++ == 'b' )
        goto CHECK_OTHER_B;
    else
        goto ERROR;

CHECK_OTHER_B:
    if( c == '\0' )
        goto ERROR;
    else if( *c == 'b' ) {
        *c++;
        goto CHECK_OTHER_B;
    }
    else if( *c == 'f' ) {
        *c++;
        goto CHECK_END;
    }
    else
        goto ERROR;

CHECK_END:
    if( *c++ == '\0' )
        goto SUCCEED;
    else
        goto ERROR;

SUCCEED:
    printf("OK! :)\n");
    return 0;

ERROR:
    printf("Error! :(\n");
    return -1;
}

إذا لم ترد إستخدام سطر الأوامر ضع النص بدل :

char *c = argv[1];

ليصبح مثلاً:

char *c = "abbbf";

لنصرفه ونجري بعض الإختبارات:

> gcc implementation.c -o lex.exe
>
> ./lex.exe abf
OK! :)
> ./lex.exe abbbf
OK! :)
> ./lex.exe abbbbbbbf
OK! :)
> ./lex.exe abbbbbbbfq
Error! :(
> ./lex.exe af
Error! :(
>

طبعاً إستخدام goto شيء محرّم في جميع اللغات لذا سنعيد بناء البرنامج ليبدو أفضل ونضيف بعض الميزات مثل التنقيح:

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

typedef enum _State {
    STATE_MATCH_INIT = 0,
    STATE_MATCH_FIRST_B,
    STATE_MATCH_OTHER_B,
    STATE_MATCH_LAST_F,
    STATE_SUCCEED,
    STATE_ERROR,
} State;

const char *state_string[] = {
    "STATE_MATCH_INIT",
    "STATE_MATCH_FIRST_B",
    "STATE_MATCH_OTHER_B",
    "STATE_MATCH_LAST_F",
    "STATE_SUCCEED",
    "STATE_ERROR"
};

void state_dbg(char c, State state);
int state_scan(char *str);
State state_match_init(char c);
State state_match_first_b(char c);
State state_match_other_b(char c);
State state_match_last_f(char c);

int main(int argc, char **argv)
{
    char *str = argv[1]; /* OR: char *str = "abbbbbbf"; */

    if( str == NULL ) {
        printf("Usage: %s [string]\n", argv[0]);
        return -1;
    }

    if( state_scan(str) == STATE_SUCCEED)
        printf("Done  : it matches.\n");
    else
        printf("Error : it doesn't mactch.\n");
    return 0;
}

int state_scan(char *str)
{
    char c = 0;
    State state = STATE_MATCH_INIT;

    while( (state != STATE_ERROR) && (state != STATE_SUCCEED) ) {
        c = *str++;
        state_dbg(c, state);

       switch(state) {
            case STATE_MATCH_INIT:
                state = state_match_init(c);
                break;
            case STATE_MATCH_FIRST_B:
                state = state_match_first_b(c);
                break;
            case STATE_MATCH_OTHER_B:
                state = state_match_other_b(c);
                break;
            case STATE_MATCH_LAST_F:
                state = state_match_last_f(c);
                break;
            default:
                state = STATE_ERROR;
        }
    }

    return state;
}

void state_dbg(char c, State state)
{
    c = isprint(c) ? c : '?';
    printf("Debug : %c | State = %s\n", c, state_string[state]);
}

State state_match_init(char c)
{
    if( c == 'a' )
        return STATE_MATCH_FIRST_B;
    return STATE_ERROR;
}

State state_match_first_b(char c)
{
    if( c == 'b' )
        return STATE_MATCH_OTHER_B;
    return STATE_ERROR;
}

State state_match_other_b(char c)
{
    if( c == 'b' )
        return STATE_MATCH_OTHER_B;
    else if( c == 'f' )
        return STATE_MATCH_LAST_F;
    return STATE_ERROR;
}

State state_match_last_f(char c)
{
    if( c == '\0' )
        return STATE_SUCCEED;
    return STATE_ERROR;
}

تجربته :

> ./lex.exe abf
Debug : a | State = STATE_MATCH_INIT
Debug : b | State = STATE_MATCH_FIRST_B
Debug : f | State = STATE_MATCH_OTHER_B
Debug : ? | State = STATE_MATCH_LAST_F
Done  : it matches.
> ./lex.exe abbbbf
Debug : a | State = STATE_MATCH_INIT
Debug : b | State = STATE_MATCH_FIRST_B
Debug : b | State = STATE_MATCH_OTHER_B
Debug : b | State = STATE_MATCH_OTHER_B
Debug : b | State = STATE_MATCH_OTHER_B
Debug : f | State = STATE_MATCH_OTHER_B
Debug : ? | State = STATE_MATCH_LAST_F
Done  : it matches.
> ./lex.exe abbbbfq
Debug : a | State = STATE_MATCH_INIT
Debug : b | State = STATE_MATCH_FIRST_B
Debug : b | State = STATE_MATCH_OTHER_B
Debug : b | State = STATE_MATCH_OTHER_B
Debug : b | State = STATE_MATCH_OTHER_B
Debug : f | State = STATE_MATCH_OTHER_B
Debug : q | State = STATE_MATCH_LAST_F
Error : it doesn't mactch.
> ./lex.exe af
Debug : a | State = STATE_MATCH_INIT
Debug : f | State = STATE_MATCH_FIRST_B
Error : it doesn't mactch.
>

أجمل وأنظف. حلقة التكرار while ستستمر في تمرير الحرف التالي مالم تجد خطأ أو ينتهي التحليل و switch ستعمل كموجه والإنتقال للدالة التالية. لاتعتقد أنه معقد, فقط تتبعه منذ البداية وستفهم كم هو بسيط.

مميزات هذه الطريقة :

  • مهما بلغت درجة تعقيد النص فإذا أحسنت تصميم السلسلة فسيصبح تطبيقه سهل جداً, أغلب تلك الأجزاء تتكرر.
  • لاتعقيد, لاحظ أنني لم أستخدم أي تخصيص للذاكرة أو دوال النصوص. ولا يوجد هناك إحتمال للخطأ, إذا كان تصميك صحيح.
  • لاحاجة لإستخدام مكتبات خارجية إذا أردت مطابقة أشياء بسيطة. وأيضاً البرنامج النتاج أسرع من أي محرك تعابير المنتظمة. جرب وضع نصّ طويل وقارن سرعة التنفيذ مع أي محرك للتعابير المنظمة كـPCRE فستجده أسرع.

العيوب :

  • البرنامج أطول, مقارنة بعدد من الأسطر لو إستخدمت مكتبة جاهزة للتعابير المنظمة.
  • إذا صممت سلسلة وطبقتها فمن الصعب بعض الشيء أن تعدلها.

مثال لمطابقة نص أكثر تعقيد مثل عملية الإسناد في لغات البرمجة :

foo = "ABCD"; // نصّ
bar = 1234;   // رقم

  1. يُمكن للمعرف أن يبدأ بحرف كبير أو صغير أو _ فقط.
  2. يُمكن للمعرف أن يحتوي بعدها على رقم أو حرف أو _.
  3. يلزم وجود علامة مساواة. ويليها رقم أو نصّ بين علامتي تنصيص"".
  4. يجب أن تنتهي كل عملية إسناد بفاصلة منقوطة للفصل بين عمليات الإسناد.

البرنامج, كتبته الصباح ولم يأخذ الا قرابة الساعة (بدون تخطيط):

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

typedef enum _State {
    STATE_MATCH_INIT = 0,
    STATE_MATCH_ALPHA,
    STATE_MACH_VALUE_INIT,
    STATE_MACH_NUMBER,
    STATE_MATCH_ASSIGN,
    STATE_MATCH_STRING_INT,
    STATE_MATCH_STRING_END,
    STATE_MATCH_SEMICOLON,
    STATE_MATCH_END,
    STATE_ERROR,
    STATE_SUCCEED
} State;

const char *state_string[] = {
    "STATE_MATCH_INIT",
    "STATE_MATCH_ALPHA",
    "STATE_MACH_VALUE_INIT",
    "STATE_MACH_NUMBER",
    "STATE_MATCH_ASSIGN",
    "STATE_MATCH_STRING_INT",
    "STATE_MATCH_STRING_END",
    "STATE_MATCH_SEMICOLON",
    "STATE_MATCH_END",
    "STATE_ERROR",
    "STATE_SUCCEED"
};

void parser_debug(char c, State state);
State parser_scan(char *data);

State parser_state_match_init(char c);
State parser_state_match_alpha(char c);
State parser_state_match_assign(char c);
State parser_state_match_value_init(char c);
State parser_state_match_number(char c);
State parser_state_match_string_init(char c);
State parser_state_match_string_end(char c);
State parser_state_match_semicolon(char c);
State parser_state_match_end(char c);

int main(int argc, char **argv)
{
    char *expr = "foo = \"ABCD\";\n bar = 1234;\n\n";

    printf("%s\n", expr);
    parser_scan(expr);

    return 0;
}

void parser_debug(char c, State state)
{
    if( c == -1 ) {
        printf("Debug: START | Next: %s\n", state_string[state]);
    }
    else {
        c = isprint(c) ? c : '?';
        printf("Debug: %c     | Next: %s\n", c, state_string[state]);
    }
}

State parser_scan(char *data)
{
    char c = -1;
    State state = STATE_MATCH_INIT;

    parser_debug(c, state);

    while( (state != STATE_ERROR) && (state != STATE_SUCCEED) ) {

        c = *data++;

        switch(state) {
            case STATE_MATCH_INIT:
                state = parser_state_match_init(c);
                break;
            case STATE_MATCH_ALPHA:
                state = parser_state_match_alpha(c);
                break;
            case STATE_MACH_VALUE_INIT:
                state = parser_state_match_value_init(c);
                break;
            case STATE_MACH_NUMBER:
                state = parser_state_match_number(c);
                break;
            case STATE_MATCH_ASSIGN:
                state = parser_state_match_assign(c);
                break;
            case STATE_MATCH_STRING_INT:
                state = parser_state_match_string_init(c);
                break;
            case STATE_MATCH_STRING_END:
                state = parser_state_match_string_end(c);
                break;
            case STATE_MATCH_SEMICOLON:
                state = parser_state_match_semicolon(c);
                break;
            case STATE_MATCH_END:
                state = parser_state_match_end(c);
                break;
            default:
                return STATE_ERROR;
        }

        parser_debug(c, state);
    }

    return state;
}

State parser_state_match_init(char c)
{
    if( c == ' ' )
        return STATE_MATCH_INIT;
    if( isalpha(c) || (c == '_') )
        return STATE_MATCH_ALPHA;
    return STATE_ERROR;
}

State parser_state_match_alpha(char c)
{
    if( c == ' ' )
        return STATE_MATCH_ASSIGN;
    else if( isalnum(c) || (c == '_') )
        return STATE_MATCH_ALPHA;
    else if( c == '=' )
        return STATE_MACH_VALUE_INIT;
    return STATE_ERROR;
}

State parser_state_match_assign(char c)
{
    if( c == ' ' )
        return STATE_MATCH_ASSIGN;
    else if( c == '=' )
        return STATE_MACH_VALUE_INIT;
    return STATE_ERROR;
}

State parser_state_match_value_init(char c)
{
    if( c == ' ' )
        return STATE_MACH_VALUE_INIT;
    else if( isdigit(c) )
        return STATE_MACH_NUMBER;
    else if( c == '"' )
        return STATE_MATCH_STRING_INT;
    return STATE_ERROR;
}

State parser_state_match_number(char c)
{
    if( isdigit(c) )
        return STATE_MACH_NUMBER;
    else if( isdigit(c) )
        return STATE_MACH_NUMBER;
    else if( c == ';' )
        return STATE_SUCCEED;
    else if( c == ' ' )
        return STATE_MATCH_SEMICOLON;
    return STATE_ERROR;
}

State parser_state_match_string_init(char c)
{
    if( c == '\0' )
        return STATE_ERROR;
    return STATE_MATCH_STRING_END;
}

State parser_state_match_string_end(char c)
{
    if(c == '\0')
        return STATE_ERROR;
    else if( c == '"' )
        return STATE_MATCH_SEMICOLON;
    return STATE_MATCH_STRING_END;
}

State parser_state_match_semicolon(char c)
{
    if( c == ' ' )
        return STATE_MATCH_SEMICOLON;
    else if( c == ';' )
        return STATE_MATCH_END;
    return STATE_ERROR;
}

State parser_state_match_end(char c)
{
    if( c == '\0' )
        return STATE_SUCCEED;
    else if( (c == ' ') || ( c == '\n' ) || (c == '\r') )
        return STATE_MATCH_END;
    else if( isalpha(c) || (c == '_') )
        return STATE_MATCH_ALPHA;
    return STATE_ERROR;
}

نتيجة التحليل :

Debug: START | Next: STATE_MATCH_INIT
Debug: f     | Next: STATE_MATCH_ALPHA
Debug: o     | Next: STATE_MATCH_ALPHA
Debug: o     | Next: STATE_MATCH_ALPHA
Debug:       | Next: STATE_MATCH_ASSIGN
Debug: =     | Next: STATE_MACH_VALUE_INIT
Debug:       | Next: STATE_MACH_VALUE_INIT
Debug: "     | Next: STATE_MATCH_STRING_INT
Debug: A     | Next: STATE_MATCH_STRING_END
Debug: B     | Next: STATE_MATCH_STRING_END
Debug: C     | Next: STATE_MATCH_STRING_END
Debug: D     | Next: STATE_MATCH_STRING_END
Debug: "     | Next: STATE_MATCH_SEMICOLON
Debug: ;     | Next: STATE_MATCH_END
Debug: ?     | Next: STATE_MATCH_END
Debug:       | Next: STATE_MATCH_END
Debug: b     | Next: STATE_MATCH_ALPHA
Debug: a     | Next: STATE_MATCH_ALPHA
Debug: r     | Next: STATE_MATCH_ALPHA
Debug:       | Next: STATE_MATCH_ASSIGN
Debug: =     | Next: STATE_MACH_VALUE_INIT
Debug:       | Next: STATE_MACH_VALUE_INIT
Debug: 1     | Next: STATE_MACH_NUMBER
Debug: 2     | Next: STATE_MACH_NUMBER
Debug: 3     | Next: STATE_MACH_NUMBER
Debug: 4     | Next: STATE_MACH_NUMBER
Debug: ;     | Next: STATE_SUCCEED

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

بالتوفيق

المرفقات
Untitled 1.png

تم تعديل هذه المشاركة بواسطة Mr.B في 28 أكتوبر 2012 في 00:18

4
#2

هذا الفرع هو فرعAutomata (فرع شيق جدا :) الكثير من الأمور النظرية ولكن ستستفيد كثيرا )

لكل RE يوجد Finite State Machine يمكن التحويل إليها بخوارزميات محددة -التحويل الغير مدروس سيسبب مشكلات عديدة وبالطبع يختلف بإختلاف تعقيد التعبير، لذا إما إستخدام الخوارزميات القياسية أو إستخدام مكتبة للتعبيرات المنتظمة مباشرة :)

تم تعديل هذه المشاركة بواسطة ahmed_youssef في 28 أكتوبر 2012 في 00:34

1
(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#3

أهلاً أحمد. صدقني أنه لاحاجة لقراءة أي نظرية أغلب الكلام المكتوب فقط تكلف, لا أستطيع إستيعابها أبداً بلك الصيغة.

إذا كنت تقصد بـ"لكل RE يوجد Finite State Machine يمكن التحويل إليها بخوارزميات محددة" مثل الجزء الموجود تحت العنوان Converting Regular Expressions to NFAs في هذه الصفحة, فأغلب هذه العمليات طبقتها بدون أن أقرأها. فمثلاً هذا الجزء :

اقتباس

The NFA for e+ also creates a loop, but one that requires passing through e at least once:

fig9.png

هو نفسه الجزء, من البرنامج الأول :

State state_match_other_b(char c)
{
    if( c == 'b' )			/* <- */
        return STATE_MATCH_OTHER_B;	/* <- */
    else if( c == 'f' )
        return STATE_MATCH_LAST_F;
    return STATE_ERROR;
}

وهذا :

اقتباس

The NFA for the alternation e1|e2 adds a new start state with a choice of either the e1 machine or the e2 machine.

fig6.png

مثل هذا الجزء من البرنامج الثاني :

State parser_state_match_end(char c)
{
    if( c == '\0' )
        return STATE_SUCCEED;
    else if( (c == ' ') || ( c == '\n' ) || (c == '\r') ) /* <- */
        return STATE_MATCH_END;
    else if( isalpha(c) || (c == '_') )
        return STATE_MATCH_ALPHA;
    return STATE_ERROR;
}

وأجزاء كثيرة طبقتها دون أن أضطر لقراءة أي نظرية, الموضوع بديهي ولايحتاج ذلك التعقيد.

#4
اقتباس
أهلاً أحمد. صدقني أنه لاحاجة لقراءة أي نظرية أغلب الكلام المكتوب فقط تكلف, لا أستطيع إستيعابها أبداً بلك الصيغة.

نتحدث بجدية!؟ لأن ذلك الأمر من المسلمات

الأمر يتخطى تحويل alternation او one or more :D على سبيل المثال التحويل ل DFA ثم الoptimization وفوق كل ذلك العمومية!

تم تعديل هذه المشاركة بواسطة ahmed_youssef في 28 أكتوبر 2012 في 02:48

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#5

الregular expression تستخدم لتمثيل اللغة لانه اذا كان فيه regular expression تمثل اللغة فهناك finite automata لها .

#6
ahmed_youssef كتب:

نتحدث بجدية!؟ لأن ذلك الأمر من المسلمات الأمر يتخطى تحويل alternation او one or more :D على سبيل المثال التحويل ل DFA ثم الoptimization وفوق كل ذلك العمومية!

أظنك تتحدث عن بناء "محرك" للتعابير المنتظمة؟ المقال يتحدث عن بناء محلل لسلسلة معينة بدل إستخدام التعابير المنظمة وليس عن بناء محرك لها.

@Eisa Ayed: صدقني ماني فاهم عليك :lol:, لم أدرس لغات البرمجة أو أقرأ عنها الكثير لذا لا أعرف كثير من التفاصيل.

رجاء شباب الإنتباه لأشياء :

  • هذا المقال لاعلاقة له بموضوع بناء لغة أو ماشابهها.
  • هذه المعلومات تستطيع إستخدامها إذا أردت مثلاً البحث أو مطابقة نص معين في ملف أو تحليل مدخلات مستخدم والتحقق من صحتها ولاتريد إستخدام أي مكتبة خارجية.
  • لما بحث في قوقل وجدت أن أغلب الأفكار تدور حول موضوع النصوص وإلا في الواقع أنه يُمكن إستخدام فكرة توزيع الشروط في أي مجال آخر. خصوصاً في الحالات التي تتطلب شروط معقدة ومتشابكة. في الألعاب مثلاً إذا أردت تمثيل الحالات التي يُمكن أن تواجهها الشخصية في اللعبة ,خصوصاً الشخصيات التي تتصرف بنفسها, فيُمكنك إستخدام نفس الفكرة وستساعدك على توزيع الشروط بطريقة أفضل.
#7

الامر ليس له علاقة بالبرمجة (مباشرة)، الامر بتعلق بالوحده الاساسية للاجهزة (والحاسب احدها) وطريقة تعاطي الاجهزة المختلفة مع الاوامر ..

الfinite automata هي الabstract اللي كل الحاسبات شغاله عليه (حتى القوانتم كومبيوتنق اعتقد لها finite automata )

انت ممكن تشوف مالها داعي لكنها هي الmathmatical model الاساسي للحاسب (طبعاً الفاينيت اوتيميتا ليست الا البداية)

مااعتقد اننا مختلفين في شئ لكني قرات جملة/

اقتباس
رُموز رياضية ومصطلحات وأشياء لافائدة منها.

وهذا تجني على الComputational Computing واتفق معك بانها ممكن مالها فائدة (في موضوعك)..

موضوع الfinite automata والDFA NFA Turing machine كلها مواضيع تحتاج لصبر لفهمها هذا اذا وفق الله استاذ المادة لتفهيمها للطلاب otherwise بتطلع من المادة مانت فاهم شئ.

بالتوفيق

#8

أحسنت أخي Eisa Ayed، وأحسنت أيضا أخي Mr.B على موضوعك الجميل.

كيف تقارن الـAntiVirus الفيروسات بالتواقيع الموجودة في فاعدة بياناتها؟ الموضوع له علاقة بمقارنة النصوص والـfinite automaton

وفي هذا الحال اخترع لنا "الرياضيون" برموزهم "المثيرة" خوارزميات مقارنة سموها Multi-Pattern String Matching والتي لها القدرة على البحث عن عدة كلمات "مختلفة" -دفعة واحدة- في نص معين وفي مرور وحيد على النص. (الطريقة الكلاسيكية هي المرور على النص مرة لكل كلمة نبحث عنها!).

أخي Mr.B لك عقلية نظيفة، وتدخل في مواضيع قلما يتكلم عنها الأعضاء للأسف، وددت منك لو تأخذ نفحة عن mathematical representation الخاص بعلوم الحاسب، وصدقني ستكمل بهذا صورة جميلة وفهم أعمق.

تم تعديل هذه المشاركة بواسطة A.S Hack في 28 أكتوبر 2012 في 12:38

1

" إن الله كتب الإحسان على كل شيء"

::

الإرادة ... تحقق السيادة.

#9

حياكم الله شباب وأشكركم على إضافتكم. لم أشر أو قلت أنه لافائدة منها, فالموضوع عبارة عن تطبيق لها. لكنني ضد تنظير الأمور وإقحام الرياضيات والرموز بالموضوع وهو لاعلاقة له بها. فالواقع وعند التطبيق الأمور تختلف تماماً. ربما هذه عينه توضح كيف أن الموضوع مزعج:

اقتباس

Formal theory

Let Σ be an alphabet, a non-empty finite set. Elements of Σ are called symbols or characters. A string (or word) over Σ is any finite sequence of characters from Σ. For example, if Σ = {0, 1}, then 0101 is a string over Σ.

The length of a string is the number of characters in the string (the length of the sequence) and can be any non-negative integer. The empty string is the unique string over Σ of length 0, and is denoted ε or λ.

The set of all strings over Σ of length n is denoted Σn. For example, if Σ = {0, 1}, then Σ
2
= {00, 01, 10, 11}. Note that Σ
0
= {ε} for any alphabet Σ.

The set of all strings over Σ of any length is the Kleene closure of Σ and is denoted Σ*. In terms of Σn,

b84d3acf4eab356d641b6c4fab13c556.png

For example, if Σ = {0, 1}, Σ
*
= {ε, 0, 1, 00, 01, 10, 11, 000, 001, 010, 011, ...}. Although Σ
*
itself is countably infinite, all elements of Σ
*
have finite length.

A set of strings over Σ (i.e. any subset of Σ
*
) is called a formal language over Σ. For example, if Σ = {0, 1}, the set of strings with an even number of zeros ({ε, 1, 00, 11, 001, 010, 100, 111, 0000, 0011, 0101, 0110, 1001, 1010, 1100, 1111, ...}) is a formal language over Σ.

الإقتباس السابق تعريف "السلسلة النصية" وخصائصها كالطول, نفسها السلسلة النصية التي يعرفها أي مبتدء في البرمجة.

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

1
#10

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

عندما قلت بإنها تسبب مشاكل بين علماء الرياضيات مثلا اعطيك مثال للعالم Oliver Heaviside الذي قام باكتشاف الكثير من الاشياء في علم الرياضيات و الهندسه الكهربائية ولكن لم تقبل نظرياته بسبب انها لم تكن موصوفه بشكل رياضي دقيق واذا قرأت عنه سوف تجد انه اكتشف الكثير من الاشياء التي نسبت الى علماء اخرين جاءوا من بعده، انا عن نفسي استخدم طريقة هيفيسايد في حل الكسور الجزئية واجد انها طريقه رائعة وسريعه جدا ولم تخذلني في يوم من الايام.

كما قال الاخ A.S.Hack عقليتك نظيفه، واتمنى لك المزيد من التقدم.

تحياتي

1

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

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

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…