Atur Aritmatika Teoretis
Premis
Sudah ada beberapa tantangan yang melibatkan perkalian tanpa operator perkalian (di sini dan di sini ) dan tantangan ini berada di jalur yang sama (paling mirip dengan tautan kedua).
Tantangan ini, tidak seperti yang sebelumnya, akan menggunakan definisi teoretis himpunan bilangan asli ( N ):
dan
sebagai contoh,
dan seterusnya.
Tantangan
Tujuan kami adalah menggunakan operasi yang ditetapkan (lihat di bawah), untuk menambah dan mengalikan bilangan asli. Untuk tujuan ini, semua entri akan berada dalam 'bahasa setel' yang sama dengan juru bahasa di bawah ini . Ini akan memberikan konsistensi dan penilaian yang lebih mudah.
Penerjemah ini memungkinkan Anda untuk memanipulasi bilangan asli sebagai set. Tugas Anda adalah menulis dua badan program (lihat di bawah), yang satu menambahkan bilangan asli, yang lain mengalikannya.
Catatan Pendahuluan tentang Perangkat
Set mengikuti struktur matematika yang biasa. Inilah beberapa poin penting:
- Set tidak dipesan.
- Tidak ada set yang berisi dirinya sendiri
- Elemen-elemen ada dalam satu set atau tidak, ini boolean. Oleh karena itu elemen set tidak dapat memiliki multiplisitas (yaitu elemen tidak dapat di set beberapa kali.)
Penerjemah dan spesifik
'Program' untuk tantangan ini ditulis dalam 'set language' dan terdiri dari dua bagian: header dan body.
Header
Headernya sangat sederhana. Ini memberi tahu juru bahasa program apa yang sedang Anda selesaikan. Header adalah garis pembuka program. Ini dimulai dengan karakter +
atau *
, diikuti oleh dua bilangan bulat, ruang dibatasi. Sebagai contoh:
+ 3 5
atau
* 19 2
adalah tajuk yang valid. Yang pertama menunjukkan bahwa Anda sedang berusaha menyelesaikannya 3+5
, artinya jawaban Anda seharusnya 8
. Yang kedua mirip kecuali dengan perkalian.
Tubuh
Tubuh adalah tempat instruksi aktual Anda kepada penerjemah. Inilah yang benar-benar merupakan program "penjumlahan" atau "penggandaan" Anda. Jawaban Anda terdiri dari dua badan program, satu untuk setiap tugas. Anda kemudian akan mengubah header untuk benar-benar melaksanakan kasus uji.
Sintaks dan Instruksi
Instruksi terdiri dari perintah yang diikuti oleh nol atau lebih parameter. Untuk keperluan demonstrasi berikut ini, karakter alfabet apa pun adalah nama variabel. Ingatlah bahwa semua variabel adalah set. label
adalah nama label (label adalah kata-kata yang diikuti oleh titik koma (yaitu main_loop:
), int
adalah bilangan bulat. Berikut ini adalah instruksi yang valid:
jump label
melompat tanpa syarat ke label. Label adalah 'kata' diikuti dengan tanda titik koma: misalnyamain_loop:
label.je A label
lompat ke label jika A kosongjne A label
lompat ke label jika A tidak kosongjic A B label
lompat ke label jika A mengandung Bjidc A B label
lompat ke label jika A tidak mengandung B
print A
mencetak nilai sebenarnya dari A, di mana {} adalah himpunan kosongprinti variable
mencetak representasi integer dari A, jika ada, jika tidak, output kesalahan.
;
Tanda titik koma menunjukkan bahwa sisa baris adalah komentar dan akan diabaikan oleh penerjemah
Info lebih lanjut
Pada awal program, ada tiga variabel yang sudah ada sebelumnya. Mereka set1
,set2
dan ANSWER
. set1
mengambil nilai parameter header pertama. set2
mengambil nilai yang kedua. ANSWER
awalnya set kosong. Setelah penyelesaian program, penerjemah memeriksa apakah ANSWER
representasi bilangan bulat dari jawaban untuk masalah aritmatika didefinisikan dalam header. Jika ya, ini menunjukkan ini dengan pesan ke stdout.
Juru bahasa juga menampilkan jumlah operasi yang digunakan. Setiap instruksi adalah satu operasi. Memulai label juga membutuhkan satu operasi (Label hanya dapat dimulai satu kali).
Anda mungkin memiliki maksimal 20 variabel (termasuk 3 variabel yang ditentukan sebelumnya) dan 20 label.
Kode penerjemah
CATATAN PENTING PADA INTERPRETER INIHal-hal sangat lambat saat menggunakan angka besar (> 30) pada juru bahasa ini. Saya akan menguraikan alasan untuk ini.
- Struktur himpunan sedemikian rupa sehingga dalam meningkatkan satu bilangan alami, Anda secara efektif menggandakan ukuran struktur himpunan. The n th nomor alam memiliki 2 ^ n set kosong di dalamnya (dengan ini saya maksudkan bahwa jika Anda melihat n pohon, ada n set kosong. Catatan hanya himpunan kosong bisa daun.) Ini berarti bahwa berurusan dengan 30 secara signifikan lebih mahal daripada berurusan dengan 20 atau 10 (Anda melihat 2 ^ 10 vs 2 ^ 20 vs 2 ^ 30).
- Pemeriksaan kesetaraan bersifat rekursif. Karena set diduga tidak teratur, ini sepertinya cara alami untuk mengatasi ini.
- Ada dua kebocoran memori yang saya tidak tahu cara memperbaikinya. Saya buruk di C / C ++, maaf. Karena kita berhadapan dengan angka-angka kecil saja, dan memori yang dialokasikan dibebaskan pada akhir program, ini seharusnya tidak terlalu menjadi masalah. (Sebelum ada yang mengatakan apa-apa, ya saya tahu
std::vector
; saya melakukan ini sebagai latihan pembelajaran. Jika Anda tahu cara memperbaikinya, tolong beri tahu saya dan saya akan mengeditnya, jika tidak, karena berhasil, saya akan meninggalkannya. dengan adanya.)
Juga, perhatikan path include ke set.h
dalam interpreter.cpp
file. Tanpa basa-basi lagi, kode sumber (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;
}
Kondisi menang
Anda berdua menulis dua BODI program , salah satunya mengalikan angka di header, yang lain menambahkan angka di header.
Ini adalah tantangan kode tercepat . Apa yang tercepat akan ditentukan oleh jumlah operasi yang digunakan untuk menyelesaikan dua kasus uji untuk setiap program. Kasus uji adalah baris tajuk berikut:
Untuk tambahan:
+ 15 12
dan
+ 12 15
dan untuk penggandaan
* 4 5
dan
* 5 4
Skor untuk setiap kasus adalah jumlah operasi yang digunakan (penerjemah akan menunjukkan nomor ini setelah penyelesaian program). Skor total adalah jumlah skor untuk setiap kasus uji.
Lihat entri contoh saya untuk contoh entri yang valid.
Kiriman yang menang memenuhi yang berikut:
- berisi dua badan program, satu yang mengalikan dan satu yang menambahkan
- memiliki skor total terendah (jumlah skor dalam kasus uji)
- Dengan waktu dan memori yang cukup, bekerja untuk bilangan bulat apa saja yang dapat ditangani oleh penerjemah (~ 2 ^ 31)
- Menampilkan tidak ada kesalahan saat dijalankan
- Tidak menggunakan perintah debugging
- Tidak mengeksploitasi kelemahan pada penerjemah. Ini berarti bahwa program Anda yang sebenarnya harus valid sebagai kode semu serta program yang dapat ditafsirkan dalam 'set language'.
- Tidak mengeksploitasi celah standar (ini berarti tidak ada kasus uji hardcoding.)
Silakan lihat contoh saya untuk implementasi referensi dan contoh penggunaan bahasa.
sumber
$$...$$
bekerja di Meta, tetapi tidak pada Main. Saya menggunakan CodeCogs untuk menghasilkan gambar.Jawaban:
Contoh Jawaban, 1323 Operasi
Perhatikan bahwa ini adalah contoh, bukan entri nyata.
Badan Penambahan
Perhatikan bahwa tubuh ini tidak akan berjalan tanpa header.
Komentar tidak diperlukan dalam jawaban yang sebenarnya, tetapi ada di sana untuk membantu mengajarkan dasar-dasar bahasa.
Untuk test case
menggunakan
440 operations
dan untuk test casemenggunakan
299 operations
.Badan Multiplikasi
Untuk test case
menggunakan
305 operations
dan untuk test casemenggunakan
279 operations
.Karenanya total skor saya adalah
440+299+305+279 =
1323
sumber
min
danmax
menggunakanunion
danintersection
, sehingga dua penambahan dan dua perkalian mendapatkan skor yang sama (lebih rendah). Itu tidak tampak seperti peningkatan yang cukup untuk merobek sisa solusi referensi ini. ;)