در این قسمت پاسخ های شرکت کنندگان در چالش برنامه نویسی با موضوع نوشتن دیکدر کد مورس به زبان C را مشاهده کنید.
در این چالش از شرکت کنندگان خواسته شده بود که یک برنامه برای دیکد کردن کد مورس که از طریق کیبرد وارد میشود ارائه دهند. برای وارد کردن کد مورس از دو کلید - و . استفاده میشود و پس از پایان هر ورودی از کلید space استفاده کنند، همچنین با وارد کردن slash یک فاصله در خروجی چاپ شود.
مثال :
... --- ... / - . ... - / .---- ..--- ...-- | ورودی | |
SOS TEST 123 | خروجی |
کد شماره 1 : دریافت کد
نویسنده @vdarioush
توضیحات:
اولین راهی که به ذهنم خطور کرد این بود که همه ی حالات ممکن کدها رو به ترتیب حروف و اعداد و علائم نگارشی توی یک آرایه از رشتهها ذخیره کنیم. با تفکیک هر حرف با تشخیص space و slash، اون کد رو توی آرایهای که داریم جستجو کنیم و بفهمیم حرف وارد شده کدومه. موقعی که خواستم از این راه مقایسه رشتهها با تابع strcmp فرار کنم، دنبال روابط ریاضی کد مورس میگشتم که عکس زیر رو دیدم.
اول اینکه میشه کد مورس رو مثل یک دنباله دید، یعنی یک به یک کاراکترهای وارد شده رو میخونیم تا وقتی که یک حرف تمام بشه. نیازی نیست اول تشخیص بدیم کجا حرف تموم شده و کل کد مورس به دست اومده رو توی آرایه جستجو کنیم. دوم اینکه این دنباله رو میشه با یک ساختار داده درختی، پیاده سازی کرد. اگر یک درخت مثل شکل زیر داشته باشیم، گره ۱ ریشه درخت هست و گرههای ۴ ، ۵ ، ۶ و ۷ برگها. اگر زیر درختی شامل گرههای ۲ ، ۴ و ۵ داشته باشیم، گره ۲ رو والد میگیم و گرههای ۴و ۵ رو به ترتیب فرزند چپ و راست (این درخت، یک درخت تمام باینری هست یعنی هر گره ۲ یا صفر فرزند داره مثل درخت مربوط به کد مورس)
حالا اگر این ساختار داده رو به صورت یک آرایه یک بعدی مثل زیر با پیمایش به ترتیب عدد روی گرهها، دربیاریم، با داشتن اندیس (شاخص) هر خونه میتونیم به فرزندهاش دسترسی داشته باشیم. اندیس فرزند چپ میشه دو برابر اندیس والد و اندیس فرزند راست میشه دوبرابر اندیس والد به اضافه یک.
چون درخت کد مورس، برگهایی در راستترین و چپترین قسمت خودش داره، مجبوریم کل درخت رو با در نظر گرفتن گرههای خالی پیاده سازی کنیم. همون آرایه کاراکتری morse_tree. اندیس ۱ میشه گره start و به ترتیب ۲ میشه گره E ، ۳ گره T و ... حالا یکی یکی کاراکترهای ورودی رو میخونیم، تا زمانیکه به space یا slash نرسیدیم، اندیس فرزند گرهی که داریم رو پیدا میکنیم به این شکل که اگر کاراکتر نقطه بود به سراغ فرزند چپ و اگر خط بود به سراغ فرزند راست میریم. به محض رسیدن به اون دو تا کاراکتر خاص space یا slash، مقدار نهایی اندیس محاسبه شده رو در دست داریم و به آرایه morse_tree مراجعه میکنیم تا مقدار(Key) اون گره رو به دست بیاریم. مثلا برای رشته "..-" :
متغیری که ممکنه دیده باشید whitespace هست. ممکنه چندین space متوالی یا همراه با یک یا چند slash داشته باشیم. برای اینکه این فواصل اضافی رو در رشته خروجی نداشته باشیم به محض اینکه به یک space یا slash رسیدیم، عمل مربوطش مثلا فاصله به ازای slash رو انجام میدیم و متغیر whitespace رو یک میکنیم. حالا تا دوباره کاراکترهای نقطه یا خط نبینیم، این متغیر یک میمونه و اجازه فاصله های پشت سر هم رو برای چاپ در خروجی نمیده. این متغیر مثل ساختار bool و در کاربرد flag هست. برای اطمینان از اینکه متغیر به جز صفر و یک مقدار دیگه ای نداشته باشه میتونیم از نوع متغیر bool استفاده کنیم.
main.c
/** * Morse Decoder * By @vdarioush * Sponsored by IOElectro * 1401/08/13 */ #include "main.h" int main(int argc, char *argv[]) { char code[500]; char result[100]; int i=0, counter = 0; int index=1; int whitespace = 0; //Whitespace and " / " flag scanf("%[^\n]s", code); do { if(code[i]!=' ' && code[i]!='/') { whitespace = 0; if(code[i] == '.') index = index * 2; else if (code[i] == '-') index = index*2 + 1; else break; } else if(code[i]==' ') { if(!whitespace) { result[counter] = morse_tree[index]; counter++; index=1; } whitespace = 1; } else { if(!whitespace) { result[counter] = morse_tree[index]; counter++; index=1; } result[counter] = ' '; counter++; whitespace = 1; } i++; }while(code[i]); if(index!=1) result[counter] = morse_tree[index]; //Last character counter++; result[counter] = '\0'; printf("%s",result); }
main.h
/** * Morse Decoder * By @vdarioush * Sponsored by IOElectro * 1401/08/13 */ #ifndef _MAIN_H_ #define _MAIN_H_ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> const char morse_tree[64] = { '?', '?', 'E', 'T', 'I', 'A', 'N', 'M', 'S', 'U', 'R', 'W', 'D', 'K', 'G', 'O', 'H', 'V', 'F', '?', 'L', '?', 'P', 'J', 'B', 'X', 'C', 'Y', 'Z', 'Q', '?', '?', '5', '4', '?', '3', '?', '?', '?', '2', '?', '?', '+', '?', '?', '?', '?', '1', '6', '=', '/', //Slash is going to be the word dividers '?', '?', '?', '?', '?', '7', '?', '?', '?', '8', '?', '9', '0' }; #endif
کد شماره 2 : دریافت کد
/** * Morse Decoder * By @rezabakhshi_98 * Sponsored by IOElectro * 1401/08/13 */ #include <stdio.h> #include <string.h> char input[300]; char output[100]; char *morseAlphabet[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."}; // a-z char *morseNumber[] = {"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."}; // 0-9 char buffer[50]; unsigned char counter = 0, outputCounter = 0; char findCharacter(char in[]) { if (strlen(in) < 5) { for (int a = 0; a < 26; a++) { if (strcmp(in, morseAlphabet[a]) == 0) { return 'A' + a; } } } else { for (int a = 0; a < 10; a++) { if (strcmp(in, morseNumber[a]) == 0) { return '0' + a; } } } return '?'; } int main() { printf("Enter morse code: "); scanf("%[^\n]", input); for (int a = 0; a < strlen(input)+1; a++) { if ((input[a] == 32)) { output[outputCounter++] = findCharacter(buffer); memset(buffer, '\0', 50); counter = 0; } else if (input[a] == '/') { output[outputCounter++] = ' '; a++; } else { buffer[counter] = input[a]; counter++; } } if(counter>1) { output[outputCounter++]='?'; counter=0; } printf("your text: %s", output); return 0; }
کد شماره 3 : دریافت کد
/** * Morse Decoder * By @theghaffarzadeh * Sponsored by IOElectro * 1401/08/13 */ #include <stdio.h> #include <conio.h> #include <string.h> #define mors_A ".-" #define mors_B "-..." #define mors_C "-.-." #define mors_D "-.." #define mors_E "." #define mors_F "..-." #define mors_G "--." #define mors_H "...." #define mors_I ".." #define mors_J ".---" #define mors_K "-.-" #define mors_L ".-.." #define mors_M "--" #define mors_N "-." #define mors_O "---" #define mors_P ".--." #define mors_Q "--.-" #define mors_R ".-." #define mors_S "..." #define mors_T "-" #define mors_U "..-" #define mors_V "...-" #define mors_W ".--" #define mors_X "-..-" #define mors_Y "-.--" #define mors_Z "--.." #define mors_1 ".----" #define mors_2 "..---" #define mors_3 "...--" #define mors_4 "....-" #define mors_5 "....." #define mors_6 "-...." #define mors_7 "--..." #define mors_8 "---.." #define mors_9 "----." #define mors_0 "-----" char str[100]; char mors[7]; char c; int i=0,j=0; void clear(void) { for(int a=0;a<6;a++) { mors[a]='\0'; } j=0; } int mors_dec() { if(strcmp(mors,mors_A)==0)str[i]='A'; else if(strcmp(mors,mors_B)==0)str[i]='B'; else if(strcmp(mors,mors_C)==0)str[i]='C'; else if(strcmp(mors,mors_D)==0)str[i]='D'; else if(strcmp(mors,mors_E)==0)str[i]='E'; else if(strcmp(mors,mors_F)==0)str[i]='F'; else if(strcmp(mors,mors_G)==0)str[i]='G'; else if(strcmp(mors,mors_H)==0)str[i]='H'; else if(strcmp(mors,mors_I)==0)str[i]='I'; else if(strcmp(mors,mors_J)==0)str[i]='J'; else if(strcmp(mors,mors_K)==0)str[i]='K'; else if(strcmp(mors,mors_L)==0)str[i]='L'; else if(strcmp(mors,mors_M)==0)str[i]='M'; else if(strcmp(mors,mors_N)==0)str[i]='N'; else if(strcmp(mors,mors_O)==0)str[i]='O'; else if(strcmp(mors,mors_P)==0)str[i]='P'; else if(strcmp(mors,mors_Q)==0)str[i]='Q'; else if(strcmp(mors,mors_R)==0)str[i]='R'; else if(strcmp(mors,mors_S)==0)str[i]='S'; else if(strcmp(mors,mors_T)==0)str[i]='T'; else if(strcmp(mors,mors_U)==0)str[i]='U'; else if(strcmp(mors,mors_V)==0)str[i]='V'; else if(strcmp(mors,mors_W)==0)str[i]='W'; else if(strcmp(mors,mors_X)==0)str[i]='X'; else if(strcmp(mors,mors_Y)==0)str[i]='Y'; else if(strcmp(mors,mors_Z)==0)str[i]='Z'; else if(strcmp(mors,mors_1)==0)str[i]='1'; else if(strcmp(mors,mors_2)==0)str[i]='2'; else if(strcmp(mors,mors_3)==0)str[i]='3'; else if(strcmp(mors,mors_4)==0)str[i]='4'; else if(strcmp(mors,mors_5)==0)str[i]='5'; else if(strcmp(mors,mors_6)==0)str[i]='6'; else if(strcmp(mors,mors_7)==0)str[i]='7'; else if(strcmp(mors,mors_8)==0)str[i]='8'; else if(strcmp(mors,mors_9)==0)str[i]='9'; else if(strcmp(mors,mors_0)==0)str[i]='0'; else return -1; i++; return 0; } int main (void) { while(c!='\r') { c=getch(); putchar(c); if((c=='.') || (c=='-')) { if(j<6)mors[j++]=c; } else if(c==' ') { mors[j]='\0'; if(mors_dec())if(j)str[i++]='?'; clear(); } else if(c=='/')str[i++]=' '; } str[i]='\0'; printf("\r\n"); puts(str); return 0; }
کد شماره 4 : دریافت کد
/** * Morse Decoder * By IOElectro * 1401/08/13 */ #include <stdio.h> #include <ctype.h> #include <string.h> #define BUFFER_SIZE 256 // 26 Code + 10 Num const char morse[][6]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."}; int serchMorse(char sign[]) { int i,s; s=sizeof(morse)/sizeof(morse[0]); for(i=0;i<s;i++)if(!strncmp(sign,morse[i],6))return i; return -1; } int main() { int j=0,i=0; char buf[BUFFER_SIZE],mBuf[6]; gets(buf); while(1) { if(buf[j]=='.'||buf[j]=='-') { if(i<6)mBuf[i++]=buf[j]; } else if(buf[j]==' '||buf[j]=='\0'||buf[j]=='/') { if(!i) { if(buf[j]=='/')putchar(' '); if(buf[j]!='\0')j++; else break; continue; } mBuf[i]='\0'; i=serchMorse(mBuf); if(i<0)putchar('?'); else if(i<26)putchar('A'+i); else putchar('0'+i-26); if(buf[j]=='/')putchar(' '); else if(buf[j]=='\0')break; i=0; } else i=0; j++; } return 0; }