[C++/C]式と演算子

int main() {
    
    cout << "1+2=" << 1+2 << "です。\n"; 
    cout << "3+4=" << 3*4 << "です。\n";
    return 0; 
}
int main() {
    
    int num1, num2;

    cout << "整数1を入力してください。\n";
    cin >> num1;

    cout << "整数2を入力してください。\n";
    cin >> num2;

    cout << "結果は" << num1 + num2 << "です。\n";
    return 0; 
}

演算子の種類
+, -, *, /, %, +, -, ~, &, |, ^, <<, >>, ++, –, >, >=, < 前後のインクレメント b = ++a; は代入前なので1となる。 代入演算子のバリエーション +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=

int main() {
    
    int sum = 0;
    int num = 0;

    cout << "1番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "2番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "3番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "合計値は" << sum << "です。\n";
    return 0; 
}

SRM150 InterestingDigits

The digits 3 and 9 share an interesting property. If you take any multiple of 3 and sum its digits, you get another multiple of 3. For example, 118*3 = 354 and 3+5+4 = 12, which is a multiple of 3. Similarly, if you take any multiple of 9 and sum its digits, you get another multiple of 9. For example, 75*9 = 675 and 6+7+5 = 18, which is a multiple of 9. Call any digit for which this property holds interesting, except for 0 and 1, for which the property holds trivially.

A digit that is interesting in one base is not necessarily interesting in another base. For example, 3 is interesting in base 10 but uninteresting in base 5. Given an int base, your task is to return all the interesting digits for that base in increasing order. To determine whether a particular digit is interesting or not, you need not consider all multiples of the digit. You can be certain that, if the property holds for all multiples of the digit with fewer than four digits, then it also holds for multiples with more digits. For example, in base 10, you would not need to consider any multiples greater than 999.

#include <vector>
using namespace std;

class InterestingDigits {
    public:
        vector <int> digists(int base) {
            vector <int> ans;

            for(int n=2; n<base; n++) {
                bool ok = true;
                for(int k1=0; k1<base; k++) {
                    for(int k2=0; k2<base; k2++) {
                        (for int k3=0; k3<base; k3++) {
                            if((k1 + k2*base + k3*base*base) % n == 0
                                &&(k1 + k2 + 3)%n != 0){
                                    ok = false;
                                    break;
                                }
                        }
                        if (!ok) break;
                    }
                    if(!ok) break;
                }
                if(ok) ans.push_back(n);
            }
            return ans;
        }
}

対象の答えがあったときは配列にappendしていく。
桁数が複数あるときは、*base, *base*base と表現する。

n真数で表した1と10が、baseで割った余りと等しければ、どの桁もbaseで割った余りが等しいことが証明可能となる

#include <vector>
using namespace std;

class InterestingDigits {
    public:
        vector <int> digits(int base){
            vector <int> ans;

            for (int i=2; i<base; i++) {
                if (((base - 1) % 1) == 0) ans.push_back(i);
            }
        }
}

数学知識があると大分違うようです。

[bitcoin基礎技術] ECDSA署名と検証

m: 署名対象のメッセージ
Q = dG : Q公開鍵、dは秘密鍵、Gはsecp256k1ベースポイント
n: secp256k1の位数

### ECDSA署名の生成
1. ハッシュ関数にメッセージmを渡し、ハッシュ値m’を取得する(m’=H(m))
2. [1, n-1]の範囲からkを選択し、楕円曲線上の点Rを k*Gで求める (R = kG)
3. R= rx, ry とする。Rのx座標rxを位数nで割った余剰を求める r = rx mod n
4. s = (m'(ハッシュしたメッセージ) + d(秘密鍵)*r(Rのx座標)) / k(任意の点) mod n
5. (r, s)が m に対する署名となる

### ECDSA署名の検証
1. P = (px, py)とする
P = m’/s * G + r / s * Q (公開鍵)(mod n)
この時、Px = r(mod n) となるとき、署名検証に成功

パラメータkを生成
$ openssl ecparam -genkey -name secp256k1 -out k.pem; ls k.pem
$ openssl ec -in k.pem -outform DER | tail -c +8 | head -c 32 | xxd -p -c 32
read EC key
writing EC key
a891fce013c907a3ce5e157d1edc474bbdf7efc0c133b41cad14aca3566c914c
$ k=a891fce013c907a3ce5e157d1edc474bbdf7efc0c133b41cad14aca3566c914c

Rを生成
$ openssl ec -in k.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65
read EC key
writing EC key
042ce7c2a48e71ad11e4445b3901d4afe715c0298ed1504cb4ce47b426d83bfaa7bb4665d4c92b9484c4b0ce5cfcabe089e1e2a7c8e32a3c6b5f2d2c0ba301fb97
$ R=042ce7c2a48e71ad11e4445b3901d4afe715c0298ed1504cb4ce47b426d83bfaa7bb4665d4c92b9484c4b0ce5cfcabe089e1e2a7c8e32a3c6b5f2d2c0ba301fb97

Rからrxを取り出し、変数rxに格納
$ rx=`echo $R | cut -c3-66`; echo $rx
2ce7c2a48e71ad11e4445b3901d4afe715c0298ed1504cb4ce47b426d83bfaa7

メッセージのハッシュ値を生成し、変数mhに格納
$ mh=`cat message.txt | xxd -r -p | openssl dgst -sha256 | cut -c10-`; echo $mh
stdin)= 45f83d17e10b34fca01eb8f4454dac34a777d9404a464e732cf4abf2c0da94c4

公開鍵をQに格納
$ Q=$pubKey; echo $Q
047a2b8a7974ed6f4b7817b0f354c6c81ceacb210e53e093eadcd4d4ece0bb4d60a0864e802eb58b813183cd4bae108588e062ec61e6bff36f68ad530ee11cff15

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def multiply_inv(a, m):
    if a < 0:
        a = a % m
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('multiply modular inverse does not exist')
    else:
        return x % m

[C++/C] 型, 変数, キーボードからの入力, 定数

基本型
bool, char, unsigned char(符号なし), short int, unsigned short int, int, unsigned int, long int, unsigned long int, float, double, long double

bitとbytes
2進数の1桁分をbitと呼ぶ
00101110

2進数の8桁の数値はbyteと呼ぶ

### 変数の利用

#include <iostream>
using namespace std;

int main() {
    int num;
    num = 3;

    cout << "変数numの値は" << num << "です。\n";

    return 0;
}

変数の値を変更

int main() {
    int num = 3;
    cout << "変数numの値は" << num << "です。\n";

    num = 5;

    cout << "新しい変数numの値は" << num << "です。\n";

    return 0;
}

他の変数の値を代入

int main() {
    int num1, num2;
    num1 = 3;

    cout << "変数num1の値は" << num1 << "です。\n";

    num2 = num1;

    cout << "変数num2の値は" << num2 << "です。\n";

    return 0;
}

値の代入と型変換

int main() {
    int num1;
    double num2;

    num1 = 3.14;
    num2 = 3.14;

    cout << "変数num1の値は" << num1 << "です。\n";
    cout << "変数num2の値は" << num2 << "です。\n";

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
変数num1の値は3です。
変数num2の値は3.14です。
// 小数点以下は切り捨てられる

キーボードからの入力
=> cin >> 変数; と記載する

int main() {
    int num = 0;

    cout << "整数を入力してください。\n";

    cin >> num;

    cout << num << "が入力されました。\n";

    return 0;
}

2つ以上の数値の入力

int main() {
    int num1, num2;

    cout << "整数を2つ入力してください。\n";

    cin >> num1 >> num2;

    cout << "最初に" << num1 << "が入力されました。\n";
    cout << "次に" << num2 << "が入力されました。\n";

    return 0;
}

定数はconstを指定する
初期化によって変数を変更できないようにする

int main() {
    const double pi = 3.1415;

    cout << "円周率の値は" << pi << "です。\n";

    return 0;
}

practice 1

int main() {
    double pi;

    cout << "円周率の値は幾つですか?\n";

    cin >> pi;

    cout << "円周率の値は" << pi << "です。\n";

    return 0;
}

practice 2

int main() {
    char str;

    cout << "アルファベットの最初の文字は何ですか?\n";

    cin >> str;

    cout << "アルファベットの最初の文字は" << str << "です。\n";

    return 0;
}

practice 3

int main() {
    double height, weight;

    cout << "身長と体重を入力してください。\n";

    cin >> height >> weight;

    cout << "身長は" << height << "です。\n";
    cout << "体重は" << weight << "です。\n";

    return 0;
}

c++では文字列の変数名はstrよりもchの方が型との違いがなく表現としては望ましそうです。

SRM 480 Cryptography

Problem Statement TopCoder Security Agency (TSA, established today) has just invented a new encryption system! This encryption system takes as its input a list of numbers to encrypt. You work at TSA and your task is to implement a very important part of the encryption process. You are allowed to pick one number in the input list and increment its value by 1. This should be done in such way that the product of all numbers in the list after this change becomes as large as possible. Given the list of numbers as vector numbers, return the maximum product you can obtain. It is guaranteed that the return value will not exceed 2^62. Definition Class: Cryptography Method:encrypt Parameters:vector Returns:long long Method signature:long long encrypt(vector numbers) (be sure your method is public) Constraints – numbers will contain between 2 and 50 elements, inclusive. – Each element of numbers will be between 1 and 1000, inclusive. – The return value will not exceed 2^62. Examples 0) {1,2,3} Returns: 12 If we increment the first number, we get 2*2*3 = 12. If we increment the second, we get 1*3*3 = 9. If we increment the third, we get 1*2*4 = 8. Hence, the correct return value is 12. 1) {1,3,2,1,1,3} Returns: 36 The elements of numbers are not necessarily unique. 2) {1000,999,998,997,996,995} Returns: 986074810223904000 The answer may be very big, but will not exceed 2^62. 3) {1,1,1,1} Returns: 2 This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited.

#include <vector>
using namespace std;

class Cryptography {
    public:
        long long encrypt(vector <int> numbers) {
            long long ans = 0;

            for(int i=0; i<numbers.size(); i++) {
                long long seki=1;
                for (int j=0; j<numbers.length; j++){
                    if (i==j) {
                        seki *= (numbers[j] + 1);
                    } else {
                        seki *= numbers[j];
                    }
                }
                ans = max(ans, seki);
            }
            return ans;
        }
}

この問題は小さい数字に1を足す。その場合、増加率が最も大きくなる。

#include <vector>
#include <algorithm>
using namespace std;

class Cryptography {
    public:
        long long encrypt(vector <int> numbers) {
            long long ret = 1;
            sort(numbers.bigin(), numbers.end());
            numbers[0]++;

            for (int i = 0; i < number.size(); i++){
                ret *= numbers[i];
            }
            return ret;
        }
}

[C++/C] ポインタ

ポインタは変数のアドレスを持つ変数のこと
変数のアドレス場所を表すには、変数の頭に&をつける

ポインタ型とは、変数のアドレスを保存しておくための型
下記は同じ意味

char* test;
char *test;
#include <stdio.h>

int main(void) {

    char buf[50] = "bitcoin";
    char *test;

    test = buf;
    printf("%s", test);
    return 0;
}

文字列の後ろにつけるアスタリスクがあるのかと勘違いしてしまいますね。

[C++/C] uint256

uint256は256bitの符号付き整数型を宣言する
cpp uint256は、C++言語で使用される256ビットの符号なし整数型です。このデータ型は、非常に大きな整数値を扱うために使用されます。cpp uint256は、暗号通貨やブロックチェーンの開発において、特にハッシュ計算や暗号学的な操作に必要とされます。この型は、十進数や16進数などの異なる形式で整数を表現することもできます。cpp uint256は、その大きな範囲と精度のために、セキュリティや数値計算の要件を満たすために重要な役割を果たします。

The function uint256.ToString() is a method that convert a 256-bit unsigned integer into a string representation. This function is commonly used in cryptographic algorithms.

#include <iostream>
#include <string>

using namespace std;
using namespace boost::multiprecision;

int main() {
    
    uint256_t value = 1000000000000000000000000000000000000000000000000000000000000000;
    string str_value = value.ToString();
    cout << "Value as string: " << str_value << endl;
    return 0;
}


Boost.Multiprecisionから提供される多倍長整数

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

namespace mp = boost::multiprecision;

int main() {
    
    mp::cpp_int x = 1;

    for (unsigned int i = 1; i <= 100; ++i) {
        x *= i;
    }

    std::cout << x << std::endl;
    return 0;
}

$ g++ -o sample sample.cpp && ./sample
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

[C++] iteratorとは?

イテレータとはコンテナ内での要素の位置を指すもので、ポインタのように扱うことができる。イテレータを使用することで、コンテナの種類に依存しないで処理を共通化できる。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    
    vector<int> x = {0, 1, 2, 3, 4};

    // begin()でコンテナ内の先頭要素を指す
    auto it = x.begin();

    cout << *it << endl;

    ++it;

    cout << *it << endl;

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
0
1

end()は要素の1つ先となる。

    vector<int> x = {0, 1, 2, 3, 4};
    for (auto it = x.begin(); it != x.end(); ++it) {
        cout << *it << endl;
    }

    return 0;

この性質によってコンテナの種類に依存せず algorithmで提供される機能を使用できる。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    
    vector<int> x = {0, 1, 2, 3, 4};
    auto n = std::count_if(x.begin(), x.end(), [](const int v){
        if (v <= 0) {
            return false;
        }
        if (v % 2 != 0){
            return false;
        }
        return true;
    });
    cout << n << endl;

    return 0;
}

[C++] endlとは

endl; とは出力の最後に改行を押し込むという意味

#include <iostream>
using namespace std;

int main() {
    
    cout << "I'm hpscript!" << endl;

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
I’m hpscript!

[C++] Ubuntu22.04にBoost install

Boost is a set of libraries for the C++ programming language that provides support for tasks and structures such as linear algebra, pseudorandom number generation, multithreading, image processing, regular expressions, and unit testing.

$ sudo apt-get install libboost-all-dev

#include <iostream>
#include <boost/version.hpp>

int main() {
    
    std::cout << "Ver." << BOOST_VERSION << '\n' <<
        "Lib Ver." << BOOST_LIB_VERSION << std::endl;

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
Ver.107400
Lib Ver.1_74