Created
January 14, 2019 07:14
-
-
Save sifue/19a5f1cf080c1ab9a01856ccae0fba3c to your computer and use it in GitHub Desktop.
Scratch3.0からc++に変換したコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Converted by scratch2cpp (https://github.com/yos1up/scratch2cpp). | |
*/ | |
#include <iostream> | |
#include <stdlib.h> | |
#include <string> | |
#include <vector> | |
#include <algorithm> | |
#include <math.h> | |
#define debug cerr << "--" << __LINE__ << "--" << "\n" | |
using namespace std; | |
const double EPS = 1e-8; | |
static int roundToInt(double x){ | |
return (x < 0) ? -(int)(-x + 0.5) : (int)(x + 0.5); | |
} | |
class Var{ // NOTE: immutable | |
public: | |
string sval; | |
double dval; | |
enum VarType {STRING = 0, NUMBER = 1}; | |
VarType type; | |
enum NumericState {UNKNOWN = -1, STRINGY = 0, NUMERIC = 1}; | |
mutable NumericState numericState; | |
Var(){sval = ""; type = STRING; numericState = STRINGY;} // represent null? | |
Var(string s){ | |
sval = s; type = STRING; numericState = UNKNOWN; | |
} | |
Var(double d){dval = d; type = NUMBER; numericState = NUMERIC;} | |
Var(const Var &v){ | |
sval = string(v.sval); dval = v.dval; | |
type = v.type; numericState = v.numericState; | |
} | |
static bool isNumericString(const string &s) { | |
char* ep; | |
strtod(s.c_str(), &ep); | |
return !ep || !*ep; | |
// TODO: In Scratch '000' is regarded as non-numeric (but here regarded as numeric) | |
} | |
bool isNumeric() const{ | |
if (type == NUMBER) return true; | |
if (numericState != UNKNOWN) return numericState == NUMERIC; | |
bool numeric = isNumericString(sval); | |
numericState = (numeric) ? NUMERIC : STRINGY; | |
return numeric; | |
} | |
double asNumber() const{ | |
if (type == NUMBER) return dval; | |
return (isNumeric()) ? atof(sval.c_str()) : 0.0; | |
} | |
static bool isNearInteger(const double &x){ | |
return fabs(round(x) - x) < EPS; | |
// TODO: allow integer type in Var class | |
} | |
static bool isNearNumber(const double &x, const double &y){ | |
return fabs(x - y) < EPS; | |
} | |
string asString() const{ | |
if (type == STRING) return sval; | |
if (isNearInteger(dval)) return to_string(roundToInt(dval)); | |
return to_string(dval); | |
} | |
Var operator+(const Var &y) const{ | |
return Var(this->asNumber() + y.asNumber()); | |
} | |
Var operator+=(const Var &y){ | |
*this = *this + y; | |
return *this; | |
} | |
Var operator-(const Var &y) const{ | |
return Var(this->asNumber() - y.asNumber()); | |
} | |
Var operator*(const Var &y) const{ | |
return Var(this->asNumber() * y.asNumber()); | |
} | |
Var operator/(const Var &y) const{ | |
return Var(this->asNumber() / y.asNumber()); | |
} | |
Var operator%(const Var &y) const{ | |
return Var(fmod(this->asNumber(), y.asNumber())); | |
} | |
bool operator<(const Var &y) const{ | |
if (this->isNumeric() && y.isNumeric()){ | |
return this->asNumber() < y.asNumber(); | |
}// compare as number if both can be interpreted as numeric | |
return this->asString() < y.asString(); | |
} | |
bool operator>(const Var &y) const{ | |
return y < *this; | |
} | |
bool operator==(const Var &y) const{ | |
if (this->isNumeric() && y.isNumeric()){ | |
return this->asNumber() == y.asNumber(); | |
}// compare as numeric if both are numeric | |
return this->asString() == y.asString(); | |
} | |
friend ostream& operator << (ostream& os, const Var& p); | |
friend istream& operator >> (istream& is, const Var& p); | |
}; | |
ostream& operator << (ostream& os, const Var& p){ | |
os << p.asString(); | |
return os; | |
} | |
istream& operator >> (istream& is, Var& p){ | |
string s; is >> s; p = Var(s); | |
return is; | |
} | |
Var letterOf(Var index, Var sourceString){ | |
/* index: 1-origined */ | |
string str = sourceString.asString(); | |
int idx = (int)(index.asNumber() - 1); | |
// seem to be dirty but Scratch seems to do like this. | |
// ex. letterOf(0.01, "world") == "w", letterOf(1.99, "world") == "w", letterOf(5.99, "world") == "d" | |
if (0 <= idx && idx < str.size()) return Var(str.substr(idx, 1)); | |
return Var(); | |
} | |
class VarList{ | |
public: | |
vector<Var> data; | |
VarList(const vector<Var> &x) { data = x; } | |
void push_back(const Var &x){ data.push_back(x); } | |
void pop_back(){ data.pop_back(); } | |
void clear(){ data.clear(); } | |
int size(){ return (int) data.size(); } | |
Var getLineOfList(const Var &index) const{ | |
/* index: 1-origined */ | |
int idx = (int)index.asNumber() - 1; | |
// (unlike 'letterOf', index==0.9 does not work.) | |
if (0 <= idx && idx < data.size()) return data[idx]; | |
return Var(); | |
} | |
void setLineOfListTo(const Var &index, const Var &v){ | |
/* index: 1-origined */ | |
int idx = (int)index.asNumber() - 1; | |
if (0 <= idx && idx < data.size()) data[idx] = v; | |
} | |
void deleteLineOfList(const Var &index){ | |
/* index: 1-origined */ | |
string kwd = index.asString(); | |
if (kwd == "all"){ | |
data.clear(); | |
}else if (kwd == "last"){ | |
data.pop_back(); | |
}else{ | |
int idx = (int)index.asNumber() - 1; | |
if (0 <= idx && idx < data.size()) data.erase(data.begin() + idx); | |
} | |
} | |
void insertAtIndexOfList(const Var &item, const Var &index){ | |
/* index: 1-origined */ | |
int idx = (int)index.asNumber() - 1; | |
if (0 <= idx && idx <= data.size()) data.insert(data.begin() + idx, item); | |
} | |
void insertAtRandomOfList(const Var &item){ | |
int idx = rand() % (data.size() + 1); | |
data.insert(data.begin() + idx, item); | |
} | |
string asString() const{ | |
/* concatenate elements of list with space */ | |
// TODO: concatenated without spaces only if all elements are single characters. | |
// (Is it an official bug? (or feature?)) | |
string ret; | |
for(int i=0;i<data.size();i++){ | |
if (i > 0) ret += ' '; | |
ret += data[i].asString(); | |
} | |
return ret; | |
} | |
int itemNumOfList(const Var &item) const{ | |
auto itr = find(data.begin(), data.end(), item); | |
if (itr == data.end()) return 0; | |
return 1 + (int)(itr - data.begin()); | |
/* index: 1-origined */ | |
} | |
friend ostream& operator << (ostream& os, const VarList& p); | |
}; | |
ostream& operator << (ostream& os, const VarList& p){ | |
os << p.asString(); | |
return os; | |
} | |
double randUniform(double x, double y){ | |
if (x > y) return randUniform(y, x); | |
if (Var::isNearInteger(x) && Var::isNearInteger(y)){ | |
int xi = roundToInt(x), yi = roundToInt(y); | |
return xi + rand() % (yi - xi + 1); | |
}else{ | |
return x + (y - x) * (0.0 + rand()) / RAND_MAX; | |
} | |
} | |
Var buf_answer; // for "answer" | |
// ============================= Scripts ============================= | |
// variable declaration | |
Var var_a(1); | |
Var var_b(2); | |
Var var_c(3); | |
Var var_s("test"); | |
// list declaration | |
// prototype declaration of functions | |
int main(); | |
// contents of functions | |
int main(){ | |
cin >> buf_answer; | |
var_a = buf_answer; | |
cin >> buf_answer; | |
var_b = buf_answer; | |
cin >> buf_answer; | |
var_c = buf_answer; | |
cin >> buf_answer; | |
var_s = buf_answer; | |
cout << Var((var_a + (var_b + var_c)).asString() + Var(Var(" ").asString() + var_s.asString()).asString()) << endl; | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment