थियोरेक्टिक अंकगणितीय सेट करें
परिसर
पहले से ही कुछ चुनौतियां हैं, जिसमें गुणा संचालक ( यहां और यहां ) के बिना गुणा करना शामिल है और यह चुनौती एक ही नस (दूसरी कड़ी के समान) में है।
यह चुनौती, उन पिछली के विपरीत, प्राकृतिक संख्याओं ( एन ) की एक निर्धारित सिद्धांतात्मक परिभाषा का उपयोग करेगी :
तथा
उदाहरण के लिए,
और इसी तरह।
चुनौती
हमारा लक्ष्य प्राकृतिक संख्याओं को जोड़ने और गुणा करने के लिए सेट ऑपरेशन (नीचे देखें) का उपयोग करना है। इस प्रयोजन के लिए, सभी प्रविष्टियाँ उसी 'निर्धारित भाषा' में होंगी जिसका दुभाषिया नीचे है । यह स्थिरता के साथ-साथ आसान स्कोरिंग प्रदान करेगा।
यह दुभाषिया आपको सेट के रूप में प्राकृतिक संख्या में हेरफेर करने की अनुमति देता है। आपका कार्य दो प्रोग्राम बॉडी (नीचे देखें) लिखना होगा, जिनमें से एक प्राकृतिक संख्या को जोड़ता है, जिनमें से दूसरा उन्हें गुणा करता है।
सेट पर प्रारंभिक नोट्स
सेट सामान्य गणितीय संरचना का पालन करते हैं। यहाँ कुछ महत्वपूर्ण बिंदु हैं:
- सेट के आदेश नहीं हैं।
- कोई भी सेट अपने आप में नहीं होता
- तत्व या तो एक सेट में हैं या नहीं, यह बूलियन है। इसलिए सेट तत्वों की बहुलता नहीं हो सकती है (अर्थात एक तत्व कई बार सेट में नहीं हो सकता है।)
दुभाषिया और बारीकियाँ
इस चुनौती के लिए एक 'प्रोग्राम' को 'सेट लैंग्वेज' में लिखा जाता है और इसमें दो भाग होते हैं: एक हेडर और एक बॉडी।
हैडर
हेडर बहुत सरल है। यह दुभाषिया को बताता है कि आप किस कार्यक्रम को हल कर रहे हैं। हैडर प्रोग्राम की शुरुआती लाइन है। यह +
या तो *
चरित्र या अक्षर से शुरू होता है , इसके बाद दो पूर्णांक, स्थान को सीमांकित किया जाता है। उदाहरण के लिए:
+ 3 5
या
* 19 2
मान्य हेडर हैं। पहला इंगित करता है कि आप हल करने की कोशिश कर रहे हैं 3+5
, जिसका अर्थ है कि आपका उत्तर होना चाहिए 8
। गुणा के अलावा दूसरा समान है।
तन
शरीर वह है जहाँ दुभाषिया के लिए आपके वास्तविक निर्देश हैं। यह वही है जो वास्तव में आपके "जोड़" या "गुणन" कार्यक्रम का गठन करता है। आपके उत्तर में दो कार्यक्रम निकाय शामिल होंगे, प्रत्येक कार्य के लिए एक। फिर आप वास्तव में परीक्षण मामलों को पूरा करने के लिए हेडर बदलेंगे।
सिंटेक्स और निर्देश
निर्देशों में शून्य या अधिक मापदंडों के बाद एक कमांड शामिल है। निम्नलिखित प्रदर्शनों के प्रयोजनों के लिए, कोई भी वर्ण वर्ण वर्ण का नाम है। याद रखें कि सभी चर सेट हैं। label
एक लेबल का नाम है (लेबल सेमीकोलन (यानी main_loop:
) के बाद आने वाले शब्द हैं , int
एक पूर्णांक है। निम्नलिखित वैध हैं:
jump label
लेबल पर बिना शर्त कूदें। एक लेबल एक 'शब्द' है जिसके बाद अर्धविराम होता है: उदाहरण केmain_loop:
लिए एक लेबल है।je A label
यदि ए खाली है तो लेबल पर जाएंjne A label
यदि गैर-रिक्त है तो लेबल पर जाएंjic A B label
यदि A में B है तो लेबल पर जाएंjidc A B label
यदि A में B नहीं है तो लेबल पर जाएं
print A
A के वास्तविक मान को प्रिंट करता है, जहां {} खाली सेट हैprinti variable
यदि यह मौजूद है, तो A के पूर्णांक प्रतिनिधित्व को प्रिंट करता है, अन्यथा त्रुटि उत्पन्न होती है।
;
अर्धविराम इंगित करता है कि शेष पंक्ति एक टिप्पणी है और दुभाषिया द्वारा अनदेखा किया जाएगा
आगे की जानकारी
कार्यक्रम की शुरुआत में, तीन पहले से मौजूद चर हैं। वे हैं set1
,set2
और ANSWER
। set1
पहले हेडर पैरामीटर का मान लेता है। set2
दूसरे का मान लेता है। ANSWER
शुरू में खाली सेट है। कार्यक्रम के पूरा होने पर, ANSWER
हैडर में परिभाषित अंकगणितीय समस्या के उत्तर के पूर्णांक निरूपण के लिए दुभाषिया जाँच करता है। यदि यह है, तो यह स्टडआउट के लिए एक संदेश के साथ इंगित करता है।
दुभाषिया उपयोग किए जाने वाले संचालन की संख्या को भी प्रदर्शित करता है। हर निर्देश एक ऑपरेशन है। लेबल शुरू करने में भी एक ऑपरेशन का खर्च आता है (लेबल केवल एक बार शुरू किया जा सकता है)।
आपके पास अधिकतम 20 चर (3 पूर्वनिर्धारित चर सहित) और 20 लेबल हो सकते हैं।
दुभाषिया कोड
इस इंटरप्रेन्योर पर महत्वपूर्ण सूचनाएँइस दुभाषिया में बड़ी संख्या (> 30) का उपयोग करते समय चीजें बहुत धीमी होती हैं। मैं इसके कारणों को रेखांकित करूंगा।
- सेट की संरचनाएं ऐसी हैं कि एक प्राकृतिक संख्या से बढ़ने पर, आप प्रभावी रूप से सेट संरचना के आकार को दोगुना कर देते हैं। N वें प्राकृतिक संख्या है 2 ^ n यह भीतर खाली सेट (इस मेरा मतलब है कि अगर आप देखो द्वारा n एक पेड़ के रूप में, देखते हैं n खाली सेट। नोट केवल खाली सेट पत्ते हो सकता है।) इसका मतलब है कि 30 के साथ काम कर काफी है 20 या 10 से निपटने की तुलना में अधिक महंगा (आप 2 ^ 10 बनाम 2 ^ 20 बनाम 2 ^ 30 देख रहे हैं)।
- समानता की जाँच पुनरावर्ती है। चूँकि सेट कथित रूप से अनियंत्रित हैं, इसलिए यह इससे निपटने का स्वाभाविक तरीका था।
- दो मेमोरी लीक हैं जिन्हें मैं ठीक नहीं कर पाया। मैं C / C ++ में बुरा हूँ, क्षमा करें। चूंकि हम केवल छोटी संख्या के साथ काम कर रहे हैं, और आवंटित स्मृति को कार्यक्रम के अंत में मुक्त कर दिया गया है, इसलिए यह वास्तव में एक मुद्दा नहीं होना चाहिए। (इससे पहले कि कोई कुछ भी कहे, हाँ मुझे पता है
std::vector
; मैं इसे सीखने की कवायद के रूप में कर रहा था। यदि आप इसे ठीक करना जानते हैं, तो कृपया मुझे बताएं और मैं संपादन कर दूंगा, अन्यथा, क्योंकि यह काम करता है, मैं इसे छोड़ दूँगा जैसा है।)
इसके अलावा, फ़ाइल set.h
में शामिल पथ पर ध्यान दें interpreter.cpp
। आगे की हलचल के बिना, स्रोत कोड (C ++):
set.h
using namespace std;
//MEMORY LEAK IN THE ADD_SELF METHOD
class set {
private:
long m_size;
set* m_elements;
bool m_initialized;
long m_value;
public:
set() {
m_size =0;
m_initialized = false;
m_value=0;
}
~set() {
if(m_initialized) {
//delete[] m_elements;
}
}
void init() {
if(!m_initialized) {
m_elements = new set[0];
m_initialized = true;
}
}
void uninit() {
if(m_initialized) {
//delete[] m_elements;
}
}
long size() {
return m_size;
}
set* elements() {
return m_elements;
}
bool is_empty() {
if(m_size ==0) {return true;}
else {return false;}
}
bool is_eq(set otherset) {
if( (*this).size() != otherset.size() ) {
return false;
}
else if ( (*this).size()==0 && otherset.size()==0 ) {
return true;
}
else {
for(int i=0;i<m_size;i++) {
bool matched = false;
for(int j=0;j<otherset.size();j++) {
matched = (*(m_elements+i)).is_eq( *(otherset.elements()+j) );
if( matched) {
break;
}
}
if(!matched) {
return false;
}
}
return true;
}
}
bool contains(set set1) {
for(int i=0;i<m_size;i++) {
if( (*(m_elements+i)).is_eq(set1) ) {
return true;
}
}
return false;
}
void add(set element) {
(*this).init();
bool alreadythere = false;
for(int i=0;i<m_size;i++) {
if( (*(m_elements+i)).is_eq(element) ) {
alreadythere=true;
}
}
if(!alreadythere) {
set *temp = new set[m_size+1];
for(int i=0; i<m_size; i++) {
*(temp+i)= *(m_elements+i);
}
*(temp+m_size)=element;
m_size++;
delete[] m_elements;
m_elements = new set[m_size];
for(int i=0;i<m_size;i++) {
*(m_elements+i) = *(temp+i);
}
delete[] temp;
}
}
void add_self() {
set temp_set;
for(int i=0;i<m_size;i++) {
temp_set.add( *(m_elements+i) );
}
(*this).add(temp_set);
temp_set.uninit();
}
void remove(set set1) {
(*this).init();
for(int i=0;i<m_size;i++) {
if( (*(m_elements+i)).is_eq(set1) ) {
set* temp = new set[m_size-1];
for(int j=0;j<m_size;j++) {
if(j<i) {
*(temp+j)=*(m_elements+j);
}
else if(j>i) {
*(temp+j-1)=*(m_elements+j);
}
}
delete[] m_elements;
m_size--;
m_elements = new set[m_size];
for(int j=0;j<m_size;j++) {
*(m_elements+j)= *(temp+j);
}
delete[] temp;
break;
}
}
}
void join(set set1) {
for(int i=0;i<set1.size();i++) {
(*this).add( *(set1.elements()+i) );
}
}
void diff(set set1) {
for(int i=0;i<set1.size();i++) {
(*this).remove( *(set1.elements()+i) );
}
}
void intersect(set set1) {
for(int i=0;i<m_size;i++) {
bool keep = false;
for(int j=0;j<set1.size();j++) {
if( (*(m_elements+i)).is_eq( *(set1.elements()+j) ) ) {
keep = true;
break;
}
}
if(!keep) {
(*this).remove( *(m_elements+i) );
}
}
}
void natural(long number) {
//////////////////////////
//MEMORY LEAK?
//delete[] m_elements;
/////////////////////////
m_size = 0;
m_elements = new set[m_size];
for(long i=1;i<=number;i++) {
(*this).add_self();
}
m_value = number;
}
void disp() {
if( m_size==0) {cout<<"{}";}
else {
cout<<"{";
for(int i=0; i<m_size; i++) {
(*(m_elements+i)).disp();
if(i<m_size-1) {cout<<", ";}
//else{cout<<" ";}
}
cout<<"}";
}
}
long value() {
return m_value;
}
};
const set EMPTY_SET;
interpreter.cpp
#include<fstream>
#include<iostream>
#include<string>
#include<assert.h>
#include<cmath>
#include "headers/set.h"
using namespace std;
string labels[20];
int jump_points[20];
int label_index=0;
const int max_var = 20;
set* set_ptrs[max_var];
string set_names[max_var];
long OPERATIONS = 0;
void assign_var(string name, set other_set) {
static int index = 0;
bool exists = false;
int i = 0;
while(i<index) {
if(name==set_names[i]) {
exists = true;
break;
}
i++;
}
if(exists && index<max_var) {
*(set_ptrs[i]) = other_set;
}
else if(!exists && index<max_var) {
set_ptrs[index] = new set;
*(set_ptrs[index]) = other_set;
set_names[index] = name;
index++;
}
}
int getJumpPoint(string str) {
for(int i=0;i<label_index;i++) {
//cout<<labels[i]<<"\n";
if(labels[i]==str) {
//cout<<jump_points[i];
return jump_points[i];
}
}
cerr<<"Invalid Label Name: '"<<str<<"'\n";
//assert(0);
return -1;
}
long strToLong(string str) {
long j=str.size()-1;
long value = 0;
for(long i=0;i<str.size();i++) {
long x = str[i]-48;
assert(x>=0 && x<=9); // Crash if there was a non digit character
value+=x*floor( pow(10,j) );
j--;
}
return value;
}
long getValue(string str) {
for(int i=0;i<max_var;i++) {
if(set_names[i]==str) {
set set1;
set1.natural( (*(set_ptrs[i])).size() );
if( set1.is_eq( *(set_ptrs[i]) ) ) {
return (*(set_ptrs[i])).size();
}
else {
cerr<<"That is not a valid integer construction";
return 0;
}
}
}
return strToLong(str);
}
int main(int argc, char** argv){
if(argc<2){std::cerr<<"No input file given"; return 1;}
ifstream inf(argv[1]);
if(!inf){std::cerr<<"File open failed";return 1;}
assign_var("ANSWER", EMPTY_SET);
int answer;
string str;
inf>>str;
if(str=="*") {
inf>>str;
long a = strToLong(str);
inf>>str;
long b = strToLong(str);
answer = a*b;
set set1; set set2;
set1.natural(a); set2.natural(b);
assign_var("set1", set1);
assign_var("set2",set2);
//cout<<answer;
}
else if(str=="+") {
inf>>str;
long a = strToLong(str);
inf>>str;
long b = strToLong(str);
answer = a+b;
set set1; set set2;
set1.natural(a); set2.natural(b);
assign_var("set1", set1);
assign_var("set2",set2);
//cout<<answer;
}
else{
cerr<<"file must start with '+' or '*'";
return 1;
}
// parse for labels
while(inf) {
if(inf) {
inf>>str;
if(str[str.size()-1]==':') {
str.erase(str.size()-1);
labels[label_index] = str;
jump_points[label_index] = inf.tellg();
//cout<<str<<": "<<jump_points[label_index]<<"\n";
label_index++;
OPERATIONS++;
}
}
}
inf.clear();
inf.seekg(0,ios::beg);
// parse for everything else
while(inf) {
if(inf) {
inf>>str;
if(str==";") {
getline(inf, str,'\n');
}
// jump label
if(str=="jump") {
inf>>str;
inf.seekg( getJumpPoint(str),ios::beg);
OPERATIONS++;
}
// je set label
if(str=="je") {
inf>>str;
for(int i=0;i<max_var;i++) {
if( set_names[i]==str) {
if( (*(set_ptrs[i])).is_eq(EMPTY_SET) ) {
inf>>str;
inf.seekg( getJumpPoint(str),ios::beg);
OPERATIONS++;
}
break;
}
}
}
// jne set label
if(str=="jne") {
inf>>str;
for(int i=0;i<max_var;i++) {
if( set_names[i]==str) {
if(! (*(set_ptrs[i])).is_eq(EMPTY_SET) ) {
inf>>str;
inf.seekg( getJumpPoint(str),ios::beg);
OPERATIONS++;
}
break;
}
}
}
// jic set1 set2 label
// jump if set1 contains set2
if(str=="jic") {
inf>>str;
string str2;
inf>>str2;
set set1;
set set2;
for(int i=0;i<max_var;i++) {
if( set_names[i]==str ) {
set1 = *(set_ptrs[i]);
}
if(set_names[i]==str2) {
set2 = *(set_ptrs[i]);
}
}
if( set1.contains(set2) ) {
inf>>str;
inf.seekg( getJumpPoint(str),ios::beg);
OPERATIONS++;
}
else {inf>>str;}
}
// jidc set1 set2 label
// jump if set1 doesn't contain set2
if(str=="jidc") {
inf>>str;
string str2;
inf>>str2;
set set1;
set set2;
for(int i=0;i<max_var;i++) {
if( set_names[i]==str ) {
set1 = *(set_ptrs[i]);
}
if(set_names[i]==str2) {
set2 = *(set_ptrs[i]);
}
}
if( !set1.contains(set2) ) {
inf>>str;
inf.seekg( getJumpPoint(str),ios::beg);
OPERATIONS++;
}
else {inf>>str;}
}
// assign variable set/int
if(str=="assign") {
inf>>str;
string str2;
inf>>str2;
set set1;
set1.natural( getValue(str2) );
assign_var(str,set1);
OPERATIONS++;
}
// union set1 set2 set3
// set1 = set2 u set3
if(str=="union") {
inf>>str;
int i=0;
while(i<max_var) {
if( set_names[i] == str ) {
break;
}
i++;
}
set set1;
set set2;
string str1;
inf>>str1;
string str2;
inf>>str2;
for(int j=0;j<max_var;j++) {
if( str1 == set_names[j] ) {
set1= *(set_ptrs[j]);
}
if( str2 == set_names[j] ) {
set2= *(set_ptrs[j]);
}
}
set1.join(set2);
if(i==max_var) {
assign_var(str,set1);
}
else {
set_names[i]= str;
set_ptrs[i] = new set;
*(set_ptrs[i]) = set1;
}
OPERATIONS++;
}
// intersect set1 set2 set3
// set1 = set2^set3
if(str == "intersect") {
inf>>str;
int i=0;
while(i<max_var) {
if( set_names[i] == str ) {
break;
}
i++;
}
set set1;
set set2;
string str1;
inf>>str1;
string str2;
inf>>str2;
for(int j=0;j<max_var;j++) {
if( str1 == set_names[j] ) {
set1= *(set_ptrs[j]);
}
if( str2 == set_names[j] ) {
set2= *(set_ptrs[j]);
}
}
set1.intersect(set2);
if(i==max_var) {
assign_var(str,set1);
}
else {
set_names[i]= str;
set_ptrs[i] = new set;
*(set_ptrs[i]) = set1;
}
OPERATIONS++;
}
// difference set1 set2 set3
// set1 = set2\set3
if(str == "difference") {
inf>>str;
int i=0;
while(i<max_var) {
if( set_names[i] == str ) {
break;
}
i++;
}
set set1;
set set2;
string str1;
inf>>str1;
string str2;
inf>>str2;
for(int j=0;j<max_var;j++) {
if( str1 == set_names[j] ) {
set1= *(set_ptrs[j]);
}
if( str2 == set_names[j] ) {
set2= *(set_ptrs[j]);
}
}
set1.diff(set2);
if(i==max_var) {
assign_var(str,set1);
}
else {
set_names[i]= str;
set_ptrs[i] = new set;
*(set_ptrs[i]) = set1;
}
OPERATIONS++;
}
// add set1 set2
// put set2 in set 1
if(str=="add") {
inf>>str;
int i = 0; int j =0;
while(i<max_var) {
if(set_names[i]==str) {
break;
}
i++;
}
inf>>str;
while(j<max_var) {
if(set_names[j]==str) {
break;
}
j++;
}
set set2 = *(set_ptrs[j]);
if( ! (*(set_ptrs[i])).is_eq(set2) ){
(*(set_ptrs[i])).add(set2);
}
else {
(*(set_ptrs[i])).add_self();
}
OPERATIONS++;
}
// remove set1 set2
// remove set2 from set1
if(str=="remove") {
inf>>str;
int i = 0; int j =0;
while(i<max_var) {
if(set_names[i]==str) {
break;
}
i++;
}
inf>>str;
while(j<max_var) {
if(set_names[j]==str) {
break;
}
j++;
}
set set2 = *(set_ptrs[j]);
(*(set_ptrs[i])).remove(set2);
OPERATIONS++;
}
// print set
// prints true representation of set
if(str=="print") {
inf>>str;
for(int i=0;i<max_var;i++) {
if(set_names[i]==str) {
(*(set_ptrs[i])).disp();
}
}
cout<<"\n";
}
// printi set
// prints integer representation of set, if exists.
if(str=="printi") {
inf>>str;
cout<<getValue(str);
cout<<"\n";
}
}
}
cout<<"You used "<<OPERATIONS<<" operations\n";
set testset;
testset.natural(answer);
switch( testset.is_eq( *(set_ptrs[0]) ) ) {
case 1:
cout<<"Your answer is correct, the set 'ANSWER' is equivalent "<<answer<<".\n";
break;
case 0:
cout<<"Your answer is incorrect\n";
}
// cout<<"\n";
return 0;
}
जीतने की स्थिति
आप दो दो प्रोग्राम BODIES लिख रहे हैं , जिनमें से एक हेडर में संख्याओं को गुणा करता है, जिनमें से अन्य हेडर में संख्याओं को जोड़ता है।
यह सबसे तेज़-कोड चुनौती है। प्रत्येक कार्यक्रम के लिए दो परीक्षण मामलों को हल करने के लिए उपयोग किए जाने वाले संचालन की संख्या से सबसे तेज़ क्या निर्धारित किया जाएगा। परीक्षण के मामले निम्नलिखित हेडर लाइन हैं:
इसके अलावा:
+ 15 12
तथा
+ 12 15
और गुणन के लिए
* 4 5
तथा
* 5 4
प्रत्येक मामले के लिए एक स्कोर उपयोग किए जाने वाले संचालन की संख्या है (दुभाषिया कार्यक्रम पूरा होने पर इस संख्या को इंगित करेगा)। कुल अंक प्रत्येक परीक्षण मामले के लिए अंकों का योग है।
मान्य प्रविष्टि के उदाहरण के लिए मेरा उदाहरण प्रविष्टि देखें।
एक जीतने वाला निम्नलिखित को संतुष्ट करता है:
- इसमें दो प्रोग्राम बॉडीज शामिल हैं, एक जो गुणा करता है और एक जो जोड़ता है
- सबसे कम कुल स्कोर (परीक्षण मामलों में स्कोर का योग) है
- पर्याप्त समय और स्मृति को देखते हुए, किसी भी पूर्णांक के लिए काम करता है जिसे दुभाषिया द्वारा नियंत्रित किया जा सकता है (~ 2 ^ 31)
- जब कोई त्रुटि प्रदर्शित करता है
- डिबगिंग कमांड का उपयोग नहीं करता है
- दुभाषिया में दोषों का शोषण नहीं करता है। इसका मतलब यह है कि आपका वास्तविक कार्यक्रम छद्म-कोड के साथ-साथ 'निर्धारित भाषा' में व्याख्यात्मक कार्यक्रम के रूप में मान्य होना चाहिए।
- मानक खामियों का फायदा नहीं उठाता (इसका मतलब है कि हार्डकॉपी परीक्षण के मामले नहीं।)
कृपया संदर्भ कार्यान्वयन और भाषा के उदाहरण उपयोग के लिए मेरा उदाहरण देखें।
$$...$$
मेटा पर काम करता है, लेकिन मेन पर नहीं। मैं छवियों को उत्पन्न करने के लिए CodeCogs का उपयोग करता था।