Monday, February 26, 2024

সি শেখানোর করুণ কাহিনী

 অনেক বয়স হয়ে গেল বুঝলেন তো ,একসময় কারোর বয়স বত্রিশ শুনলেই অবজ্ঞায় ঠোঁট বেঁকে যেত ,বুড়ো মাল ,ঘাটের মরা এইসব ভাবতাম ,এড়িয়ে চলতাম বলা চলে ,এখন নিজেই চল্লিশ ,চুল কম পাকলো ,দাড়ি বেশি পেকে গেলো ,সেই দেখে আবার এক বাচ্চা ছেলে দাদু বলে ডেকেছিল 


এই বয়েসে একটা জিনিস লোকে এড়িয়ে চলে ,ফালতু হেনস্থা হওয়া ,কিন্তু মানুষের সঙ্গে কথা বলার কাজ আমার ,কাজেই ওই হেনস্থার জায়গাটা কখনো বন্ধ হবে না ,একটা উদাহরণ দি ,একবার হাওড়া ময়দানে এক বিহারি মেয়েকে পড়াতাম ,জ্ঞান তপস্সিনি বলা যায় ,শিবপুরের ছাত্রী ,তবে এখন আবার শিবপুর কে শিবপুর কেউ বলে না ,আই আই ই এস টি না কি যেন বলে ,হাওড়া ময়দানের ঘুপচি ঘরে পড়াতাম ,কিছুদিন পড়েছিল ,গড়গড় এর দুঃস্বপ্ন বলা চলে ,তবে আমার খারাপ লাগে নি ,দুটো  প্রশ্ন এই পর্যন্ত পড়ে মাংস র মাথায় আসবে ,ঘুপচি ঘরে কি পাং পাং হয়েছিল ,শিবপুরের ছাত্রী আমার মতো অপোগন্ড গণ্ডমূর্খের কাছে পড়লো ইটা কিভাবে সম্ভব ,দুটো প্রশ্নের উত্তর ই হতাশা জনক ,এই পোস্ট হবে শুস্ক কাষ্ঠঙ ,লিখতেও মজা লাগছে ,এ যেন স্কিৎজোফ্রেনিয়া রোগীর ডায়েরি ,নিজের সঙ্গে নিজের কথোপকথন 


শিবপুরের ব্যাপারস্যাপার হলো ক্লাস এসাইনমেন্ট হেবি কঠিন,কিন্তু পরীক্ষা সহজ ,পরিশ্রমী ছাত্র ছাত্রীরা প্রোগ্রামিং করতে গিয়ে একটু সংকটে পড়ে ,আমি কি এই বয়েসে বুঝতাম কিছু ,নাঃ  পানু দেখতাম আর সিনেমা দেখতাম ,বন্ধুদের সঙ্গে হাহা হিহি চলতো ,আদি রসাত্মক ইয়ার্কি না হলে বিরক্ত লাগতো ,হু হু বয়েজ স্কুলের অভিশাপ আর কি 


হেনস্থার প্রসঙ্গে আসি ,ছাত্রী সি প্রোগ্রামিং এ ইনপুট এ একটি বাক্য নিতে পারছে না,খুব উৎসাহ নিয়ে scanf বোঝাতে গেলাম,দেখলাম নিজের ও হলো না ,কেন ,কারণ ডব্লিউ বিউটি তে শেখানো হয় নি ,scanf দিয়ে যদি ইনপুট নেন ,ইউজার যদি ইনপুট এ অতিরিক্ত ব্ল্যান্ক স্পেস  টাইপ করে বা নিউলাইন ক্যারেক্টার টাইপ করে scanf ইনপুট নেবেই না ,ছাত্রী কে আরেকটা কাজ দিয়ে নিজে একটু গুগুল করে নিলাম ,দেখলাম সমস্যার সমাধান আছে ,কপি করে দিলাম 


#include <stdio.h> 

  


int main() 

    char sen[100]; 

    scanf("%[^\n]s", sen  ); 

    printf("Output : %s", sen); 

    return 0; 


এই প্রোগ্রামটি একটা সেন্টেন্স কে ইনপুট হিসেবে নিতে পারে,ছাত্রীকে দেখিয়ে বেশ একটা কের্দানি  করেছি কি করিনি ,ছাত্রী বলে আরে  এতো প্রথম সমস্যা ,মূল সমস্যার ছোট একটি অংশ মাত্র 


আমি ঘাবড়ে গেলাম,বুজলাম আরো হেনস্থা আছে কপালে ,বললাম কি সমস্যা আছে বলো ,মনে মনে ভাবছি বেশি জটিল যেন না হয় ভগবান ,এই মাসের মাইনে  বাকি 



বলে এইভাবে একটা কালেকশন অফ স্ট্রিং নিতে হবে ইনপুট হিসেবে ,স্ট্রিং মানে জানেন তো ,ধরুন আপনার নাম sourav ,s  একটা ক্যারেক্টার ,এরকম  একাধিক ক্যারেক্টার কে হয় একটা স্ট্রিং ,মানে sourav একটা string ,ক্যারেক্টার মানে যা ইচ্ছা হতে পারে ,নাম্বার ও হতে পারে ,সেই হিসেবে ১০০ ও একটা স্ট্রিং হতে পারে,তবে স্ট্রিং ডবল কোটেশনে ঢাকা থাকবে ,"১০০" বা "সৌরভ",ক্যারেক্টার হলে সিঙ্গল কোটেশনে ঢাকা থাকবে 'স',এই হলো গিয়ে সি প্রোগ্রামিং এর নিয়ম কানুন 


বললাম সে ঠিক আছে একটা কালেকশন অফ স্ট্রিং নিতে হবে ,তারপর ,উপরের প্রোগ্রামটি তো একটা কালেকশন অফ স্ট্রিং বা একটি বাক্যকে ইনপুট হিসেবে নিয়ে একটি স্ট্রিং ভ্যারিয়েবল এ স্টোর  করতে পারে তাই না ,তার মানে প্রব্লেম তো সল্ভড 


সে বিরক্ত হয়ে বলে আরে নানা একটা ভ্যারিয়েবল নয় একটা এরে তে স্টোর করতে হবে ,তারপর শব্দগুলো সর্টিং করতে হবে ,সর্টিং মানে কি ,না আলফাবেট এর ক্রোম অনুযায়ী আগে পরে বসবে 


একটা উদাহরণ দি ইন্টারনেট থেকে কপি করে 


ধরুন ইনপুট এসেছে 


Input: arr[] = {“geeks”, “for”, “geeksforgeeks”} 

Output: 

for

geeks

geeksforgeeks


বুঝতেই পারছেন প্রতিটা শব্দের সঙ্গে অন্য শব্দগুলোর তুলনা বলে ,এরকম তুলনার একটা নাম আছে ,lexicographical তুলনা ,এখানে প্রতিটা স্ট্রিং এর প্রতিটা অক্ষর আরেকটি স্ট্রিং এর সিম পজিশনে থাকা অক্ষরের সঙ্গে তুলনা হয় 


ইন্টারনেট থেকে কপি করে একটা প্রোগ্রাম দেখাই 


#include <stdio.h> 

  

void compareStrings(char* s1, char* s2) 

    int i; 

    // comparing each character 

    for (i = 0; s1[i] != '\0' || s2[i] != '\0'; i++) { 

        if (s1[i] > s2[i]) { 

            printf("String 1 is lexicographically greater "

                   "than string 2"); 

            return; 

        } 

        else if (s2[i] > s1[i]) { 

            printf("String 2 is lexicographically greater "

                   "than string 1"); 

            return; 

        } 

    } 

    // comparing length of two strings 

    if (s1[i] != '\0') { 

        printf("String 1 is lexicographically greater than "

               "string 2"); 

    } 

    else if (s2[i] != '\0') { 

        printf("String 2 is lexicographically greater than "

               "string 1"); 

    } 

    else { 

        printf("Both strings are lexicographically equal"); 

    } 

int main() 

  

    // declaring two strings 

    char s1[20] = "help"; 

    char s2[20] = "held"; 

  

    // function call 

    compareStrings(s1, s2); 

    return 0; 

}



এই প্রোগ্রামটি কি করতে পারে ,দুটো স্ট্রিং এর মধ্যে কম্পেয়ার করতে পারে ,কিন্তু এতে আমার কাজ শেষ হচ্ছে না ,আমাকে পুরো বাক্যের প্রতিটা শব্দের বা স্ট্রিং এর সঙ্গে ওপর প্রতিটি বাক্যের বা স্ট্রিং এর এরকম কম্পারিসন করতে হইবে 


এই প্রোগ্রামটি কি ভাবে কাজ করছে সেটাও নেট থেকে কপি করে লিখছি 


Iterate over both the strings using a for-loop.

Compare each character of the two strings till an unmatched character is found.

For the unmatched character at position i, if s1[i] < s2[i], s1 is lexicographically smaller string.

Otherwise, s2 is the lexicographically smaller string.

If no unmatched character is found, compare the length of both strings.

The longer string is lexicographically smaller.


সমস্যার ছোট একটি অংশ সমাধান হলো 


এবার এই অংশ টিকে ব্যবহার করতে হবে এমন একটি প্রোগ্রাম এ যেখানে প্রোগ্রাম প্রতিটা স্ট্রিং এর মধ্যে এই উপরের প্রোগ্রামটি চালাবে 


আবার গুগুল করে চুরি করে লিখে দিলাম একটা ,নির্লজ্জের মতো লাইন বই লাইন কপি বলাই বাহুল্য 


#include<stdio.h>

#include<string.h>

int main()

{

   char str[5][50],temp[50];

   int i,j;


   printf("Enter 5 Words:\n");


   for(i=0;i<5;i++)

   scanf("%s[^\n]",str[i]);


   for(i=0;i<4;i++)

   {

     for(j=i+1;j<5;j++)

     {

       if(strcmp(str[i],str[j])>0)

       {

         strcpy(temp,str[i]); 

         strcpy(str[i],str[j]);

         strcpy(str[j],temp);

       }

     }

   }

   printf("\nIn lexicographical order: \n");


   for(i=0;i<5;i++)

   puts(str[i]);


   return 0;

}


কাজ হচ্ছে ,কিন্তু ছাত্রী খুশি নয় ,বলে ম্যাডাম মানা  করেছেন এরকম স্ট্রিং লাইব্রেরি ব্যবহার করতে ,নিজে ফাঙ্কশন বানাতে হবে 

মাথায় বাজ পড়লো ,বুজলাম দিন খারাপ ,এতো বড় মাপের প্রোগ্রামার কবে হলাম আমি সি প্রোগ্রামিং এর ইন বিল্ট ফাঙ্কশন রিপ্লেস করে নিজের বানাবো 


যায় হোক আবার গুগুল  থেকে চুরি করলাম 


এদিক ওদিক থেকে চুরি করে ঘন্ট টাইপের বানালাম একটা 


int my_strcmp(const char *a, const char *b)

{

    while (*a && *a == *b) { ++a; ++b; }

    return (int)(unsigned char)(*a) - (int)(unsigned char)(*b);

}


যাতে strcmp ফাঙ্কশন টা অন্তত রিপ্লেস হলো,strcmp  না ব্যবহার করে এখন নাহয় my_strcmp ব্যবহার করবো 


ছাত্রী এবার বললো সি তে ইন বিল্ট ফাঙ্কশন পাল্টে (গুগুল থেকে চুরি ) যে ফাঙ্কশন তা লেখা হয়েছে বুঝতে পারছে না 


আবার মাথায় বাজ পড়লো ,গুগুল খুঁজতে আরম্ভ করলাম একই জিনিস আর একটু সহজ ভাবে (পড়তে হবে পয়েন্টার এর জঙ্গল না ইউজ করে বা রেকারসন ব্যবহার না করে)কেউ করেছে কি না 


অনেক খুঁজে মিলিয়ে মিশিয়ে করলাম একটা 


এরকম দাঁড়ালো জিনিসটা 



#include <stdio.h> 

#include<string.h>


  

/*int my_strcmp(const char *a, const char *b)

{

    while (*a && *a == *b) { ++a; ++b; }

    return (int)(unsigned char)(*a) - (int)(unsigned char)(*b);

}*/


int compareStrings(const char *s1, const char *s2) 

    int i; 

    // comparing each character 

    for (i = 0; s1[i] != '\0' || s2[i] != '\0'; i++) { 

        if (s1[i] > s2[i]) { 

            return (int)(unsigned char)(*s1) - (int)(unsigned char)(*s2);

            //printf("String 1 is lexicographically greater ""than string 2"); 

            //return; 

        } 

        else if (s2[i] > s1[i]) { 

            //printf("String 2 is lexicographically greater ""than string 1"); 

            //return; 

            return (int)(unsigned char)(*s1) - (int)(unsigned char)(*s2);

        } 

    } 

    // comparing length of two strings 

    if (s1[i] != '\0') { 

        return (int)(unsigned char)(*s1) - (int)(unsigned char)(*s2);

    } 

    else if (s2[i] != '\0') { 

        return (int)(unsigned char)(*s1) - (int)(unsigned char)(*s2);

    } 

    else { 

        return 0;

    } 


int main()

{

   char str[5][50],temp[50];

   int i,j;


   printf("Enter 5 Words:\n");


   for(i=0;i<5;i++)

   scanf("%s[^\n]",str[i]);


   for(i=0;i<4;i++)

   {

     for(j=i+1;j<5;j++)

     {

       if(compareStrings(str[i],str[j])>0)

       {

         strcpy(temp,str[i]); 

         strcpy(str[i],str[j]);

         strcpy(str[j],temp);

       }

     }

   }

   printf("\In lexicographical order: \n");


   for(i=0;i<5;i++)

   puts(str[i]);


   return 0;

}


তখন ও ছাত্রীর মন ভরেনি ,বুঝে গেলাম এই মরণাত্মক সংগ্রাম আমার পোষাবে না ,অদ্যই শেষ রজনী 


মাইনের আশা আর নেই ,এতো খাটনি (মানে চুরি আর চুরির মাল এসেম্বলি)তো বাড়ির লোক বুজবে না ,ছাত্রী বলবে ইস্সে না হইবা ,মা বলবে মাস্টার ফোটো 


তবে শিক্ষকের সম্মান ,কঠিন ব্যাপার ছিল সেই সময় 


গভীরভাবে বললাম এতে কি খুশি হবেন তোমার ম্যাডাম 


ছাত্রী বললো আচ্ছা strcpy তা প্রতিস্থাপন করা যায় না,তাহলে string.h  লাইব্রেরি ই আর ইম্পোর্ট করতে হবে না 


বললাম দেখছি দাড়াও ,দশ বছর হয়ে গেলো ,সেই দেখা আজ থামেনি ,বুঝে গেছি আমি ভালো প্রোগ্রামার হতে পারবো না 


কয়েকদিন আগে আমার এক বেড়ে পাকা বন্ধুর সঙ্গে এই নিয়ে কথা হচ্ছিলো 


ও বললো আরে এ তো পাইথন এ হেবি সোজা 


এক লাইন জাস্ট 


def sort_words(words):

    return ' '.join(sorted(words.split(), key=str.casefold))



# commands used in solution video for reference

if __name__ == '__main__':

    print(sort_words('banana ORANGE apple')) 




এইটাই হলো সেই ম্যাজিক এক লাইন 


return ' '.join(sorted(words.split(), key=str.casefold))


তাও আমি আশা হারাইনি ,নিশ্চয় সি প্রোগ্রামিং করে একদিন আমি পুন্য অর্জন করবো 



Saturday, February 24, 2024

চটকদারি পাইথন বনাম পুষ্টিকর সি


ধরুন কেউ নতুন নতুন প্রোগ্রামিং শিখছে ,তাকে সি প্রোগ্রামিং শেখানো হচ্ছে ,তার শিক্ষক / শিক্ষকা তাকে শেখাছেন বুঝলে সি তে কিছু প্রিন্ট করতে হলে এরকম করে করতে হয়

#include <stdio.h>
int main() {
   // printf() displays the string inside quotation
   printf("Hello, World!");
   return 0;
}

সে লাইন গুলো লিখলো ,লিখতে গিয়ে ভুল ভ্রান্তি না হলে প্রোগ্রাম কম্পাইল এবং রান হলো সফলভাবে ,স্ক্রিন এ ফুটে উঠলো hello world

সে ভাবলো আচ্ছা তাহলে দুটো শব্দ প্রিন্ট করতে গেলে চারটে লাইন লিখতে হবে

ওদিকে তার বেড়ে পাকা বন্ধু  পাইথন শিখছে

সে লিখলো

print("Hello, World!")

একই রেসাল্ট পেয়ে সে খিকখিক করে হাসতে থাকলো

দেখে আপনার কেমন লাগবে

বা ধরুন আপনার শিক্ষক বা শিক্ষিকা আপনাকে শেখাচ্ছেন কম্পিউটারের একটা বড় কাজ হলো বারবার যা করতে হয় সেটা কম্পিউটার ই একটা নিয়মের মধ্যে ফেলে নিজে করে ফেলে ,আপনাকে বারবার করতে হয় না ,ধরুন আপনি আপনার নামটা পাঁচবার প্রিন্ট করবেন

সি প্রোগ্রামিং এ আপনাকে লিখতে হবে

#include <stdio.h>

int main() {
    int i=1;
    while(i<5)
    {
        Printf("Sourav Bhattacharya");
        i=i+1;
        
    }

    return 0;
}

ওদিকে আপনার পাইথন শেখা বন্ধু এক লাইনে লিখে ফেললো

print("Sourav Bhattacharya\n"*five )

দেখে এবার আপনার একটু একটু হিংসা হতে শুরু করেছে ,কেন যে সি শেখানো হচ্ছে ,একদিকে রাজভোগ আরেকদিকে প্যারা/ঠেকুয়া  যেন

এবার আপনাকে ক্লাস এসাইনমেন্ট দিলেন আপনার শিক্ষক বা শিক্ষিকা

একটা শব্দ পালিনড্রোম কি না চেক করতে হবে ,শব্দটাকে ইনপুট হিসেবে দিতে হবে ,এদিকে স্ট্রিং লাইব্রেরি ইম্পোর্ট না করলে স্ট্রিং সি প্রোগ্রামিং এ  যে নেহাত ই একটি এরে আপনাকে শেখানো হয়েছে ,ফলে আপনি ভাবছেন কি করে করবেন সি  তে এই প্রোগ্রাম ,অনেক ভেবে আপনি করে ফেললেন ,অনেকটা এরকম দাঁড়ালো

#include<stdio.h>

 

void main()
{
char name[]="abba";
char c='z';
int length=0;
char reversename[100];
int j=0;
char signal='T';
printf("%s\n",name);

 

while (c!='\0')
{
c=name[length];
length++;

 

}

printf("the length is %d\n",length-1);

 

for(int i=(length-2);i>=0;i=i-1)

{

printf("name[%d] is %c\n",i,name[i]);
reversename[j]= name[i];
j++;

}
printf("reversename is %s\n",reversename);
j=0;
for(j=0;j<=((length)-2);j=j+1)

{
printf("character reversename[%d]=%c name[%d]=%c is being compared\n",j,reversename[j],j,name[j]);
if (reversename[j]!=name[j])
{
//printf("not matched");
signal='F';
}

 

}
if (signal=='T')
printf("palindrome\n");
else
printf("not pal\n");

}

মনে রাখবেন জীবনে প্রথমবার প্রোগ্রামিং শিখছেন আপনি ,খুব এফিসিয়েন্ট কোডিং যে পারবেন না ইটা প্রত্যাশিত ,আমি ২০০২ সালে কানেতকার  পড়ে এইটা লিখেছিলাম ,কাজ হচ্ছে ,কিন্তু এফিসিয়েন্ট নয় ,কিন্তু প্রথমবার সাফল্য পেয়ে গর্বিত মুখে যেই আপনি বেড়ে পাকা বন্ধুর দিকে তাকিয়েছেন

বেড়ে পাকা বন্ধু বলে অরে পাইথনে এটা  করা খুব সোজা ,এতো লিখতে হয় না ,এই দেখ

x=input()
if x==x[::-1]:
    print('pal')
else:
    print('not pal')


দেখে আপনি এবার খেপে যাবেন ,বলবেন ধুর ছাই সি আর দরকার নেই ,পাইথন ই ভালো শেখার জন্য

ঐটাই আপনার বিরাট ভুল হবে ,সি একটা লিজেন্ডারি ল্যাংগুয়েজ ,স্পিড থেকে এফিসিয়েন্সি অনেক কিছুতে আজ ও এগিয়ে ,মাইকেল যেমন ইংরিজি থেকে বাংলায় ফিরেছিলেন আপনি কি আবার পাইথন থেকে সি তে ফিরতে পারবেন ??খুব কঠিন ওই ট্রানজিশন


Wednesday, February 21, 2024

Filtering data using groupby in sql

select
billingcity,
round(avg(total),2)
from Invoice
where billingcity is not null
GROUP by billingcity
order by  billingcity;


select
billingcity,
round(avg(total),2) as AvgInvoice
from Invoice
where billingcity is not null and billingcity like 'L%'
GROUP by billingcity
order by  billingcity;


we can only use where if the condition is applied to non aggregated field such as billingcity ,in case we like to impose a condition on the aggregated field such as total we have to use having clause,and having will always come after group by clause


select
billingcity,
round(avg(total),2) as AvgInvoice
from Invoice
where billingcity is not null and billingcity like 'L%'
GROUP by billingcity
having AvgInvoice>5
order by  billingcity;

we can group by multiple fields instead of just one ,to do that we have to add the field as non aggregated field in the select statement,and then add the second group by field after the first separated by a comma

select
billingcountry,
billingcity,
round(avg(total),2) as AvgInvoice
from Invoice
where billingcity is not null

GROUP by billingcountry,billingcity
having AvgInvoice>1
order by  billingcountry,AvgInvoice ASC;




Tuesday, February 20, 2024

Aggregate functions example in sql

SELECT
sum(Total) as [Total Sales],
round(Avg(Total),2) as [Average Sales],
Max(Total) as [Max Sale],
Min(Total) as [Min Sale],
Count(*) as [Sales Count]
from Invoice

Getting the age of employees from their birthdate in sql

 SELECT
FirstName,
LastName,
Address,
FirstName ||' '|| LastName || ' ' || Address ||','|| City ||' '||State ||' '||PostalCode as [Mailing Address],
length(PostalCode),
substr(PostalCode,1,5) as [5 digit postal code],
upper(FirstName) as [First Name all caps],
lower(LastName) as [Last Name all lower],
strftime('%Y-%m-%d',BirthDate) as [BirthDate without time code],
strftime('%Y-%m-%d','now')-strftime('%Y-%m-%d',BirthDate) as age
from Employee