একটি সংকলক সময় জটিলতা


54

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

আমার অনুমানটি হ'ল কিছু অপ্টিমাইজেশন পদক্ষেপ রয়েছে যা ঘনিষ্ঠ, তবে যার প্রকৃত সময়ে খুব কম প্রভাব পড়ে। উদাহরণস্বরূপ, সংখ্যার উপর ভিত্তি করে সূচকীয় একটি ফাংশনের আর্গুমেন্ট।

আমার মাথার শীর্ষ থেকে, আমি বলব যে এএসটি গাছ উত্পন্ন করা লিনিয়ার হবে। আইআর প্রজন্মের বর্ধমান টেবিলগুলিতে মান সন্ধানের সময় গাছের মধ্য দিয়ে পদক্ষেপ নেওয়া প্রয়োজন, সুতরাং বা । কোড জেনারেশন এবং লিঙ্কিং একই ধরণের অপারেশন হবে। অতএব, যদি আমরা বাস্তবের বর্ধন না করে এমন ভেরিয়েবলগুলির ক্ষতচিহ্নগুলি সরিয়ে ফেলি তবে আমার অনুমান হবে।( এন লগ এন ) ( এন 2 )O(n2)O(nlogn)O(n2)

যদিও আমি সম্পূর্ণ ভুল হতে পারি। কারও কি এতে কোন চিন্তাভাবনা আছে?


7
আপনি যে কোনও কিছু "ক্ষতিকারক", "রৈখিক", , বা দাবি করার সময় আপনাকে সতর্ক থাকতে হবে । অন্তত আমার কাছে, তাই না সব সময়ে সুস্পষ্ট আপনি আপনার ইনপুট কিভাবে পরিমাপ (সূচকীয় কি কি করে? হয় জন্য দাঁড়ানো?)( এন লগ এন ) এনO(n2)O(nlogn)n
Juho

2
আপনি যখন এলএলভিএম বলছেন, তখন আপনার অর্থ ঝনঝন? এলএলভিএম বেশ কয়েকটি বিভিন্ন সংকলক সাবপ্রজেক্ট সহ একটি বড় প্রকল্প তাই এটি কিছুটা অস্পষ্ট।
নেট সি কে

5
সি # এর ক্ষেত্রে এটি সর্বনিম্ন খারাপ সমস্যাগুলির জন্য কমপক্ষে তাত্পর্যপূর্ণ (আপনি সি # তে এনপি সম্পূর্ণ এসএটি সমস্যা এনকোড করতে পারেন)। এটি কেবল অপ্টিমাইজেশন নয়, কোনও ফাংশনের সঠিক ওভারলোড চয়ন করার জন্য এটি প্রয়োজন। সি ++ এর মতো ভাষার জন্য এটি অনস্বীকার্য হবে, যেহেতু টেমপ্লেটগুলি সম্পূর্ণরূপে টুরিং হয়।
কোডসইনচওস

2
@ জেন আমি আপনার বক্তব্য বুঝতে পারি না। সংকলনের সময় টেমপ্লেট ইনস্ট্যান্টেশন ঘটে। আপনি সঠিক সমস্যাগুলি এমনভাবে টেমপ্লেটগুলিতে এনকোড করতে পারেন যা সংকলককে সঠিক আউটপুট উত্পাদন করতে সমস্যাটি সমাধান করতে বাধ্য করে। আপনি সংকলক টিউরিং সম্পূর্ণ টেম্পলেট প্রোগ্রামিং ভাষার একটি দোভাষী বিবেচনা করতে পারে।
কোডসইনচওস

3
ল্যাম্বদা এক্সপ্রেশন সহ একাধিক ওভারলোডগুলি একত্রিত করার সময় সি # ওভারলোড রেজোলিউশনটি বেশ জটিল। আপনি এটি এমনভাবে কোনও বুলিয়ান সূত্রটি এনকোড করতে ব্যবহার করতে পারেন, প্রযোজ্য ওভারলোড রয়েছে কিনা তা নির্ধারণের জন্য এনপি-সম্পূর্ণ 3 এসএটি সমস্যা প্রয়োজন। সমস্যাটি প্রকৃতপক্ষে সংকলন করতে, সংকলকটিকে প্রকৃতপক্ষে সেই সূত্রটির সমাধান খুঁজে বের করতে হবে, এটি আরও শক্তও হতে পারে। এরিক লিপার্ট তার ব্লগ পোস্ট ল্যাম্বডা এক্সপ্রেশনস বনাম অজ্ঞাত পদ্ধতিতে,
পঞ্চম

উত্তর:


50

আপনার প্রশ্নের উত্তরের সর্বোত্তম বইটি সম্ভবত: কুপার এবং টর্কসন, "ইঞ্জিনিয়ারিং একটি সংকলক," 2003. আপনার যদি বিশ্ববিদ্যালয়ের লাইব্রেরিতে অ্যাক্সেস থাকে তবে আপনার একটি অনুলিপি ধার নিতে সক্ষম হওয়া উচিত।

এলএলভিএম বা জিসিসির মতো প্রোডাকশন সংকলনে ডিজাইনাররা সমস্ত অ্যালগোরিদমগুলিকে নীচে রাখার জন্য সর্বাত্মক প্রচেষ্টা করেন যেখানে আকার। "অপ্টিমাইজেশন" পর্যায়ে কিছু বিশ্লেষণের জন্য এর অর্থ হ'ল সত্যিকারের অনুকূল কোড তৈরি করার পরিবর্তে আপনাকে হিউরিস্টিক ব্যবহার করা দরকার।এনO(n2)n

লেক্সার একটি সসীম স্টেট মেশিন, সুতরাং ইনপুট (আকারে এর আকারে এবং পার্সারে পৌঁছে যাওয়া টোকেনগুলির একটি প্রবাহ তৈরি করে ।( এন )O(n)O(n)

অনেক ভাষার জন্য বহু সংকলকগুলির জন্য পার্সার হল LALR (1) এবং এভাবে ইনপুট টোকেনের সংখ্যায় সময়ে টোকেন স্ট্রিমটি প্রক্রিয়া করে । পার্সিংয়ের সময় আপনাকে সাধারণত একটি চিহ্ন টেবিলের উপর নজর রাখতে হয়, তবে, অনেক ভাষার ক্ষেত্রে, এটি হ্যাশ টেবিলের স্ট্যাক ("অভিধান") দিয়ে পরিচালনা করা যায়। প্রতিটি অভিধানের অ্যাক্সেস , তবে আপনাকে মাঝে মধ্যে একটি চিহ্ন সন্ধান করতে স্ট্যাকটি হাঁটা করতে হতে পারে। স্ট্যাকের গভীরতা যেখানে সুযোগ এর পাখির গভীরতা। (সুতরাং সি-এর মতো ভাষাগুলিতে আপনার ভিতরে কোঁকড়ানো ধনুর্বন্ধনীগুলির কতগুলি স্তর রয়েছে))( 1 ) ( গুলি ) এসO(n)O(1)O(s)s

তারপরে পার্স গাছটি একটি নিয়ন্ত্রণ প্রবাহের গ্রাফে সাধারণত "সমতল" হয়। নিয়ন্ত্রণ ফ্লো গ্রাফের নোডগুলি 3-ঠিকানা নির্দেশাবলী (কোনও RISC সমাবেশ ভাষার অনুরূপ) হতে পারে এবং নিয়ন্ত্রণ প্রবাহ গ্রাফের আকার সাধারণত পার্স গাছের আকারে লিনিয়ার হতে পারে।

তারপরে ধারাবাহিকভাবে অপ্রয়োজনীয় নির্মূলকরণ পদক্ষেপগুলি প্রয়োগ করা হয় (প্রচলিত স্যুবপ্রেসেশন নির্মূলকরণ, লুপ ইনগ্রেন্ট কোড গতি, ধ্রুবক প্রচার, ...)। (এটি প্রায়শই "অপ্টিমাইজেশন" নামে অভিহিত হয় যদিও ফলাফল সম্পর্কে খুব কমই অনুকূল কিছু পাওয়া যায়, আসল লক্ষ্য হ'ল সংকলকটিতে আমরা যে সময় এবং স্থানের সীমাবদ্ধতা রেখেছি তার মধ্যে যতটা সম্ভব কোডের উন্নতি করা)) প্রতিটি অপ্রয়োজনীয় নির্মূলকরণ পদক্ষেপটি হবে সাধারণত নিয়ন্ত্রণ প্রবাহ গ্রাফ সম্পর্কে কিছু তথ্যের প্রমাণ প্রয়োজন। এই প্রমাণগুলি সাধারণত ডেটা প্রবাহ বিশ্লেষণ ব্যবহার করে করা হয় । বেশিরভাগ ডেটা-প্রবাহ বিশ্লেষণগুলি এমনভাবে নকশাকৃত করা হয় যাতে তারা প্রবাহের গ্রাফের ওপারে ঘুরে বেড়াবে যেখানে (প্রায় কথা বলছে) লুপ নেস্টিংয়ের গভীরতা এবং প্রবাহের গ্রাফের উপর দিয়ে যাওয়ার জন্য সময় নেবেডি ( এন ) এনO(d)dO(n)যেখানে হল 3-ঠিকানা নির্দেশের সংখ্যা।n

আরও পরিশীলিত অপ্টিমাইজেশনের জন্য আপনি আরও পরিশীলিত বিশ্লেষণ করতে চাইতে পারেন। এই মুহুর্তে আপনি ট্রেড অফে দৌড় শুরু করেন। আপনি চান যে আপনার বিশ্লেষণ অ্যালগরিদমগুলি চেয়ে অনেক কম গ্রহণ করবেO(n2)পুরো প্রোগ্রামের প্রবাহের গ্রাফের আকারের সময়, তবে এর অর্থ আপনাকে কোনও তথ্য ছাড়াই (এবং প্রোগ্রামের উন্নতি রূপান্তরকরণ) করা দরকার যা প্রমাণ করতে ব্যয়বহুল। এর সর্বোত্তম উদাহরণ হ'ল ওরফে বিশ্লেষণ, যেখানে কিছু জোড়া মেমরি লেখার জন্য আপনি প্রমাণ করতে চাইবেন যে দুজন লেখক কখনই একই মেমরির অবস্থানকে লক্ষ্য করতে পারে না। (আপনি যদি একটি নির্দেশকে অন্যের উপরের দিকে চালিত করতে পারেন তবে এটির জন্য আপনি একটি উপাধ বিশ্লেষণ করতে চাইতে পারেন But) তবে এলিয়াস সম্পর্কে সঠিক তথ্য পাওয়ার জন্য আপনাকে প্রোগ্রামের মাধ্যমে প্রতিটি সম্ভাব্য নিয়ন্ত্রণের পাথ বিশ্লেষণ করতে হতে পারে, যা শাখাগুলির সংখ্যায় তাত্পর্যপূর্ণ is প্রোগ্রামে (এবং এইভাবে নিয়ন্ত্রণ প্রবাহ গ্রাফের নোডের সংখ্যায় তাত্পর্যপূর্ণ))

পরবর্তী আপনি নিবন্ধকরণ বরাদ্দ পেতে। রেজিস্টার বরাদ্দকে গ্রাফ-বর্ণের সমস্যা হিসাবে চিহ্নিত করা যায় এবং ন্যূনতম সংখ্যক রঙের সাথে একটি গ্রাফের রঙিন করা এনপি-হার্ড হিসাবে পরিচিত। সুতরাং বেশিরভাগ সংকলক যুক্তিসঙ্গত সময়সীমার মধ্যে যতটা সম্ভব রেজিস্টার স্পিলের সংখ্যা হ্রাস করার লক্ষ্যে রেজিস্টার স্পিলিংয়ের সাথে একত্রে লোভী হিউরিস্টিক ব্যবহার করে।

শেষ পর্যন্ত আপনি কোড জেনারেশনে প্রবেশ করুন। কোড জেনারেশন সাধারণত এমন সময়ে সর্বাধিক বেসিক-ব্লক করা হয় যেখানে একটি মৌলিক ব্লক একক প্রবেশ এবং একক প্রস্থান সহ লিনিয়ারালি সংযুক্ত নিয়ন্ত্রণ ফ্লো গ্রাফ নোডগুলির সেট। এটি গ্রাফের আচ্ছাদন সমস্যা হিসাবে সংশোধন করা যেতে পারে যেখানে আপনি যে গ্রাফটি কভার করার চেষ্টা করছেন সেটি হ'ল বেসিক ব্লকের 3-ঠিকানা নির্দেশের সেটের নির্ভরতা গ্রাফ এবং আপনি উপলব্ধ মেশিনের প্রতিনিধিত্বকারী গ্রাফের একটি সেট দিয়ে কভার করার চেষ্টা করছেন নির্দেশাবলী। বৃহত্তম বেসিক ব্লকের আকারে এই সমস্যাটি ক্ষণস্থায়ী (যা নীতিগতভাবে পুরো প্রোগ্রামের আকার হিসাবে একই ক্রম হতে পারে), তাই এটি আবার সাধারণত হিউরিস্টিক্স দিয়ে সম্পন্ন হয় যেখানে সম্ভাব্য আচ্ছাদনগুলির কেবলমাত্র একটি ছোট উপসাগর হয় পরীক্ষা।


4
Thirded! ঘটনাচক্রে, সংকলকরা যে সমস্যাগুলি সমাধান করার চেষ্টা করে তাদের অনেকগুলি (যেমন নিবন্ধকরণ বরাদ্দ) এনপি-হার্ড, তবে অন্যরা আনুষ্ঠানিকভাবে অনির্বাচিত। ধরুন, উদাহরণস্বরূপ, আপনার কাছে একটি কল পি () রয়েছে যার পরে একটি কল q () রয়েছে। যদি পি একটি খাঁটি ফাংশন হয় তবে আপনি কলগুলি সুরক্ষিতভাবে পুনরায় অর্ডার করতে পারবেন যতক্ষণ না প () অসীম লুপ না থাকে। এটি প্রমাণ করার জন্য থামার সমস্যাটি সমাধান করা দরকার। এনপি-হার্ড সমস্যাগুলির মতো, একটি সংকলক লেখক যতটা সম্ভব সমাধান সমাধানের পক্ষে প্রায় বা তত কম প্রচেষ্টা করতে পারেন।
ছদ্মনাম

4
ওহ, আরও একটি বিষয়: বর্তমানে কিছু ধরণের সিস্টেম ব্যবহার করা হচ্ছে যা তত্ত্বের ক্ষেত্রে খুব জটিল। হ্যান্ডলি-মিলনার ধরণের অনুমানটি ডেক্সপটাইম-সম্পূর্ণ হিসাবে পরিচিত এবং এমএল-জাতীয় ভাষাগুলি অবশ্যই এটি সঠিকভাবে প্রয়োগ করতে পারে। তবে রান সময়টি বাস্তবে রৈখিক, কারণ) ক) প্যাথলজিকাল কেস রিয়েল-ওয়ার্ল্ড প্রোগ্রামগুলিতে কখনই সামনে আসে না, এবং খ) রিয়েল-ওয়ার্ল্ড প্রোগ্রামাররা আরও ভাল ত্রুটির বার্তা পাওয়ার জন্য টাইপ টীকাতে থাকে।
ছদ্মনাম

1
দুর্দান্ত উত্তর, একমাত্র জিনিসটি অনুপস্থিত বলে মনে হচ্ছে তা হ'ল ব্যাখ্যাটির সহজ অংশ, সহজ ভাষায় বানান: একটি প্রোগ্রাম সংকলন ও (এন) এ করা যেতে পারে। সংকলনের আগে একটি প্রোগ্রামকে অনুকূলকরণ করা, যে কোনও আধুনিক সংকলক যেমন করত, তেমন কার্যত সীমাহীন task প্রকৃতপক্ষে যে সময়টি লাগে এটি কোনও কার্যের অন্তর্নিহিত সীমা দ্বারা পরিচালিত হয় না, বরং লোকেদের অপেক্ষায় ক্লান্ত হওয়ার আগে সংকলকটির কোনও এক পর্যায়ে শেষ করার ব্যবহারিক প্রয়োজন দ্বারা। এটি সর্বদা একটি আপস হয়।
আআআআআআআআআআআআআআআআআআআআআআআআআআআআআ

@ ছদ্মনাম, যে সংকলকটি অনেকবার থামার সমস্যাটি সমাধান করতে হবে (বা খুব বাজে এনপি হার্ড সমস্যাগুলি) যে কারণে মান সংকলক লেখককে অনির্ধারিত আচরণটি ঘটে না তা ধরে নেওয়ার ক্ষেত্রে এক কারণ বলে মনে করে (অসীম লুপ এবং এর মতো )।
ভনব্রান্ড

15

প্রকৃতপক্ষে, কয়েকটি ভাষা (যেমন সি ++, লিস্প এবং ডি) সংকলনের সময় টুরিং-সম্পূর্ণ হয়, তাই তাদের সংকলন সাধারণভাবে অনির্বাচিত। সি ++ এর জন্য এটি পুনরাবৃত্ত টেম্পলেট ইনস্ট্যান্টেশনের কারণে। লিস্প এবং ডি এর জন্য, আপনি কমপাইল সময়ে প্রায় কোনও কোড কার্যকর করতে পারেন, তাই আপনি চাইলে সংকলকটিকে একটি অসীম লুপে ফেলে দিতে পারেন।


3
হাস্কেলের (এক্সটেনশন সহ) এবং স্কালার টাইপ সিস্টেমগুলিও টুরিং-সম্পূর্ণ, অর্থাত্ টাইপ-চেকিংয়ে অসীম পরিমাণ সময় নিতে পারে। স্কালায় এখন ট্যুরিং-সম্পূর্ণ ম্যাক্রো রয়েছে।
জার্গ ডব্লু মিটাগ

5

সি # সংকলকটির সাথে আমার বাস্তব অভিজ্ঞতা থেকে, আমি বলতে পারি যে নির্দিষ্ট প্রোগ্রামগুলির জন্য ইনপুট উত্সের আকারের সাথে আউটপুট বাইনারি আকারের আকার তাত্পর্যপূর্ণভাবে বৃদ্ধি পায় (এটি আসলে সি # স্পিকার দ্বারা প্রয়োজনীয় এবং এটি হ্রাস করা যায় না), তাই সময়ের জটিলতা কমপক্ষে তাত্পর্যপূর্ণও হওয়া উচিত।

সি # তে সাধারণ ওভারলোড রেজোলিউশন টাস্কটি এনপি-হার্ড হিসাবে পরিচিত (এবং প্রকৃত বাস্তবায়নের জটিলতাটি কমপক্ষে ঘৃণ্য)।

সি # উত্সগুলিতে এক্সএমএল ডকুমেন্টেশন মন্তব্যের একটি প্রসেসিংয়ের জন্য সংকলন সময়ে নির্বিচারে এক্সপথ ০.০ এক্সপ্রেশন মূল্যায়ন করা প্রয়োজন, এটিও ঘৃণ্য, এএফএইসি।


সি # বাইনারিগুলি কীভাবে উড়ে যায়? আমার কাছে ভাষা বাগের মতো শোনাচ্ছে ...
ভোনব্র্যান্ড

1
মেটাডেটাতে জেনেরিক প্রকারগুলি কীভাবে এনকোড করা হয় সেভাবেই এটি। class X<A,B,C,D,E> { class Y : X<Y,Y,Y,Y,Y> { Y.Y.Y.Y.Y.Y.Y.Y.Y y; } }
ভ্লাদিমির রেশেটনিকভ 20

-2

ওপেন সোর্স প্রকল্পগুলির সেট হিসাবে বাস্তববাদী কোড বেসগুলির সাথে এটি পরিমাপ করুন। যদি আপনি ফলাফলগুলি (কোডসাইজ, ফিনিশটাইম) হিসাবে প্লট করেন তবে আপনি সেই গ্রাফগুলি প্লট করতে পারেন। যদি আপনার ডেটা f (x) = y হয় O (n), তবে g = f (x) / x প্লট করে ডেটা বড় হওয়া শুরু হওয়ার পরে আপনাকে একটি সরলরেখা দেওয়া উচিত।

প্লট f (x) / x, f (x) / lg (x), f (x) / (x * lg (x)), f (x) / (x * x), ইত্যাদি গ্রাফ হয় ডুব দেবে শূন্য বন্ধ, আবদ্ধ ছাড়া বৃদ্ধি, বা সমতল। এই ধারণাটি খালি ডাটাবেস থেকে সন্নিবেশের সময়গুলি পরিমাপ করার মতো পরিস্থিতিতে (যেমন: দীর্ঘ সময়ের জন্য 'পারফরম্যান্স ফাঁস' সন্ধান করা)) এর জন্য কার্যকর।


1
চলমান সময়ের অভিজ্ঞতাগত পরিমাপ গণনা জটিলতা প্রতিষ্ঠা করে না। প্রথমত, গণনার জটিলতা সবচেয়ে খারাপ ক্ষেত্রে চলমান সময়ের ক্ষেত্রে সবচেয়ে বেশি প্রকাশিত হয়। দ্বিতীয়ত, আপনি যদি একরকম গড় কেসটি পরিমাপ করতে চেয়েছিলেন তবে আপনাকে অবশ্যই এটি স্থাপন করতে হবে যে আপনার ইনপুটগুলি সেই অর্থে "গড়"।
ডেভিড রিচার্বি

ঠিক আছে এটি নিশ্চিতভাবেই। তবে প্রচুর বাস্তব ডেটা সহ সাধারণ অভিজ্ঞতামূলক পরীক্ষাগুলি (একগুচ্ছ গিট রিপোর জন্য প্রতিটি প্রতিশ্রুতি) একটি সতর্কতার সাথে মডেলকে ভালভাবে পরাজিত করতে পারে। যাইহোক, কোনও ফাংশন যদি সত্যিই O (n ^ 3) হয় এবং আপনি f (n) / (n n n) প্লট করেন তবে আপনার প্রায় শূন্যের slালু সহ একটি গোলমাল রেখা পাওয়া উচিত। আপনি যদি কেবল ও (N ^ 3) / (n * n) কে ষড়যন্ত্র করেন তবে আপনি দেখবেন এটি রৈখিকভাবে বেড়েছে। আপনি যদি অতিরিক্ত মূল্যায়ন করেন এবং লাইনটি দ্রুত শূন্যের দিকে ডুব দেন তবে এটি সত্যিই সুস্পষ্ট।
রব

1
উদাহরণস্বরূপ, বেশিরভাগ সময় ইনপুট ডেটাতে কুইকোর্টটি চালায় তবে কিছু বাস্তবায়নে সবচেয়ে খারাপ অবস্থায় চলমান সময় থাকে (সাধারণত, ইতিমধ্যে সাজানো ইনপুটটিতে)। তবে, আপনি যদি কেবল চলমান সময়ের পরিকল্পনা করেন, আপনি কেস চেয়ে বেশি চালানোর সম্ভাবনা বেশি । Θ ( এন 2 ) Θ ( এন লগ ইন করুন এন ) Θ ( এন 2 )Θ(nlogn)Θ(n2)Θ(nlogn)Θ(n2)
ডেভিড রিচার্বি

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

1
নং প্রশ্নটি সমস্যার সময় জটিলতা সম্পর্কে জিজ্ঞাসা করে। এটি সাধারণত সবচেয়ে খারাপ চলমান সময় হিসাবে ব্যাখ্যা করা হয়, যা জোরালোভাবে সংগ্রহস্থলের কোডগুলিতে চলমান সময় নয়। আপনার প্রস্তাবিত পরীক্ষাগুলি একটি প্রদত্ত কোডের টুকরোটি সংকলকটি গ্রহণ করতে কতক্ষণ আশা করতে পারে তার পক্ষে যুক্তিসঙ্গত হ্যান্ডেল দেয় যা জানা এবং ভাল জিনিসটি জানা উচিত। তবে তারা আপনাকে সমস্যার গণনামূলক জটিলতা সম্পর্কে প্রায় কিছুই বলবে না।
ডেভিড রিচার্বি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.