2020年8月20日 星期四

c776: 106北二1.六邊形屋瓦

解題心得:
國高中數學題變形。
先觀察n=1時,a1=6, d=4
而n每增加1,a1就增加5,因此a1 = 6+(n-1)*5 = 5n+1
至於公差d,則是每次增加3,因此d = 4+(n-1)*3 = 3*n+1

所求由等比公式得知為: a1+(m-1)*d = (5n+1)+(m-1)(3n+1)

程式碼:
#include <iostream>
using namespace std;


int main()
{
    int n,m;
    cin>>n>>m;
    cout<<(5*n+1)+(m-1)*(3*n+1)<<endl;
    return 0;
}

2020年8月18日 星期二

operator overloading

自定義物件的加減乘除等操作。

operator+

例如:
const Complex operator+(const Complex &obj); //member function

使用const+參考是為了效率。

還可以寫成friend function:
friend Comples operator+(Complex &o1,Complex &o2);

記得在外部定義即可:
Complex operator+(Complex &o1,Complex &o2)
{
    return Complex(o1.real+o2.real,o1.imag+o2.imag); // 回傳沒有名字的物件
}

(note:
由上面的例子可得知,constructor本身並非void function,它會回傳沒有名字的物件。)


上面討論的都是 c3=c1+c2,也就是兩個參數都是object的時候。
如果是c3=c1+x呢?(x為任意int)
Complex Complex::operator+(int& x); //裡面傳的參數資料型態改一下

如果是c3=x+c2呢?
原本上面兩個狀況都是由c1這個物件呼叫operator+這個函式,有點像c1.operator+(c2)的感覺,所以才用member function。
現在則沒有物件能呼叫了,所以才用外部定義的friend function。
Complex operator+(int& x,Complex& o);

(note:
c3=(c1+c2) // c3 和 (c1+c2) 是不同物件。(c1+c2)是一個沒有名字的物件,它的值會被拿去給c3)


operator++

有prefix跟postfix兩種,為了區別於是寫法如下,只差在有沒有再傳參數進去。
Point& operator++() // prefix
{
    count++;
    return *this;
}
(note: 回傳值為參考)
Point operator++(int n) // postfix
{
    Point tmp=*this;
    this->count++;
    return tmp;
}
(note: postfix 的 operator++回傳值不是參考!!否則會出現錯誤訊息:"warning: reference to local variable ‘result’ returned [-Wreturn-local-addr] ",因為若回傳tmp參考,tmp本身會再動作結束後消失造成錯誤!!)


可以簡化來看:
operator++()
operator++(int)
值得注意的是為何postfix operator需要額外的傳int進去呢?這是因為C++判斷function的時候,是由它們的signature,也就是參數數量、型別與順序,而非回傳值來看。
參考:overloading postfix and prefix operators
(the function overloading can be achieved by different data type and different number of argument list, but it cannot be different return type.)

operator>> & <<

friend istream& operator>>(istream& in,Complex &c)
{
    in>>c.real>>c.imag;
    return in;
}
friend ostream& operator<<(ostream& out,Complex &c)
{
    out<<c.real<<" "<<c.imag<<endl;
   return out;
}
(note:return in跟return out是為了連續輸入/輸出)

2020年8月16日 星期日

a870: 10. List Maker

解題心得:
vector find: find(vec.begin(),vec.end(),x);
vector insert: vec.insert(it,x); // or vec.insert(vec.begin()+n,x);
vector erase: vec.erase(it) // or vec.erase(vec.begin()+n);

程式碼:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    string command,x,n;
    vector<string> l;
    while(cin>>command)
    {
        if(command=="SHOW") break;
        if(command=="ADD")
        {
            cin>>x;
            l.push_back(x);
        }
        else if(command=="INSERT")
        {
            cin>>x>>n;
            vector<string>::iterator it=find(l.begin(),l.end(),n);
            l.insert(it,x);
        }
        else if(command=="REMOVE")
        {
            cin>>x;
            for(int i=0;i<l.size();i++)
            {
                if(l[i]==x)
                {
                    l.erase(l.begin()+i);
                    break;
                }
            }
        }
    }
    for(int i=0;i<l.size();i++)
        cout<<l[i]<<" ";
    return 0;
}

a787: 9. Mirror to the Stars

程式碼:
#include <iostream>
using namespace std;

int main()
{
    string name,command;
    int width,height;
    char picture[37][25];
    while(cin>>name>>width>>height>>command)
    {
        for(int i=0;i<height;i++)
            for(int j=0;j<width;j++)
                cin>>picture[i][j];
        cout<<name<<endl;
        for(int l=0;l<command.size();l++)
        {
            char copy[37][25];
            for(int i=0;i<height;i++)
                for(int j=0;j<width;j++)
                    copy[i][j]=picture[i][j];
            if(command[l]=='R')
            {
                for(int i=0;i<height;i++)
                    for(int j=0;j<width;j++)
                        picture[i][j]=copy[i][width-1-j];
            }
            else
            {
                for(int i=0;i<height;i++)
                    for(int j=0;j<width;j++)
                        picture[i][j]=copy[height-1-i][j];
            }
        }
        for(int i=0;i<height;i++)
        {
            for(int j=0;j<width;j++)
                cout<<picture[i][j];
            cout<<endl;
        }
    }
    return 0;
}

2020年8月14日 星期五

12918 - Lucky Thief

程式碼:
#include <iostream>
using namespace std;


int main()
{
    int t,n,m;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        long long int up=m-1,down=m-n;
        
        cout<<(up+down)*n/2<<endl;
    }
    return 0;
}

11498 - Division of Nlogonia

程式碼:
#include <iostream>
using namespace std;


int main()
{
    int k,n,m,x,y;
    while(cin>>k)
    {
        if(k==0) break;
        cin>>n>>m;
        for(int i=0;i<k;i++)
        {
            cin>>x>>y;
            if(x==n||y==m) cout<<"divisa"<<endl;
            else if(x>n&&y>m) cout<<"NE"<<endl;
            else if(x>n&&y<m) cout<<"SE"<<endl;
            else if(x<n&&y>m) cout<<"NO"<<endl;
            else cout<<"SO"<<endl;
        }
    }
    return 0;
}

263 - Number Chains

程式碼:
#include <iostream>
#include <vector>
using namespace std;


int main()
{
    
    string s;
    while(cin>>s)
    {
        if(s=="0") break;
        cout<<"Original number was "<<s<<endl;
        string bigToSmall=s,smallToBig=s;
        int chain=0;
        vector<string> list;
        while(1)
        {
            
            chain++;
            bigToSmall=s,smallToBig=s;
            for(int i=0;i<bigToSmall.size();i++)
            {
                for(int j=0;j<bigToSmall.size();j++)
                {
                    if(bigToSmall[i]>bigToSmall[j]) swap(bigToSmall[i],bigToSmall[j]);
                    if(smallToBig[i]<smallToBig[j]) swap(smallToBig[i],smallToBig[j]);
                }
                    
            }
            int big=stoi(bigToSmall),small=stoi(smallToBig),repeat=0;
            s=to_string(big-small);
            cout<<big<<" - "<<small<<" = "<<s<<endl;
            for(int i=0;i<list.size();i++)
            {
                if(s==list[i])
                {
                    repeat=1;
                    break;
                }
            }
            if(repeat) break;
            list.push_back(s);
        }
        cout<<"Chain length "<<chain<<endl<<endl;
    }
    return 0;
}

friend

若某個函式是某class的friend,那個函式就可以存取到private的資料。
它會被宣告在class外面,就像一般的函式一樣。不過在class裡面會多加一個friend在前面。
寫在private或public部分沒有影響,畢竟它不是member function,只是friend。

class CPoint
{
private:
    int x,y;
    friend CPoint offset(CPoint &pt,int diff);
public:
    CPoint(){x=0,y=0;}
    CPoint(int a,int b){x=a,y=b;}
    void Print(){cout<<x<<" "<<y<<endl;}
};
CPoint offset(CPoint &pt,int diff)
{
    pt.x+=diff;pt.y+=diff;
    return pt;
}
int main()
{
    CPoint p1(3,4);
    p1.Print();
    offset(p1,10);
    p1.Print();
    return 0;
}

friend除了用在function上,還能用在class。
如果:
class A
{
    friend class B;
    // other code....
};
那class B裡的所有member function都能取用class A的private資料。
但friend的關係並非雙向!

2020年8月13日 星期四

【Hamilton】The World Was Wide Enough 歌詞筆記

sign on:擔任
number two:副手
terrain:地形
marksman:神槍手
rigor:嚴格的
methodically:有條不紊的
fiddle:撥弄
seconds:副手
send in:派出
set the record straight:澄清是非
take aim:瞄準
wise up:領悟
usher:迎來
wailing:哀號、哭泣
obliterate:抹去不留痕跡

10093 - An Easy Problem!

解題心得:
解題推導參考網路。

程式碼:
#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s;
    while(getline(cin,s))
    {
        int sum=0,temp,max=1;
        for(int i=0;i<s.size();i++)
        {
            if('0'<=s[i]&&s[i]<='9') temp=s[i]-'0';
            else if('A'<=s[i]&&s[i]<='Z') temp=s[i]-'A'+10;
            else if('a'<=s[i]&&s[i]<='z') temp=s[i]-'a'+36;
            else continue;
            
            if(temp>max) max=temp;
            sum+=temp;
        }
        for(int i=max;i<=62;i++)
        {
            if(sum%i==0)
            {
                cout<<(i+1)<<endl;
                break;
            }
            else if(i==62) cout<<"such number is impossible!"<<endl;
        }
    }
    return 0;
}

const member function && const static function

class 的 object 也能像 int, double 等資料型態一樣,被宣告成 const,這代表該object的資料不能被任意更動。
因此只有不會更動到資料的函式,也就是const member function能被這種const object呼叫。

宣告const member function的語法就是在()與{}間加上const:

class ID{
private:
    string name;
public:
    ID(string n){name=n;}
    string getName() const {return name;}
};

這樣一來,如果要在getName()這個函式修改值,像是把name="unknown"的話,就會出現編譯錯誤的訊息。

另外,由於const object不能使用一般的 member function,但 const object 跟 non-const object 都能使用 const member function,在寫某些不會更動值的函式像是accessor時,可以直接加個const。

參考:
https://www.geeksforgeeks.org/const-member-functions-c/


_______________________

static 通常不會單獨出現,而是配合著 const 。
宣告也是在外面,不過是 const + data type 一起。
class CScore { 
protected:
    //declare a static constant
    static const int Max;
};
const int CScore::Max = 100; //outside class