C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++入門】数値や文字列の集合からランダムな分割(パーティション)を生成する方法

本記事では、与えられた数値の配列または文字列から、ランダムな分割(ランダムパーティション)を生成するC++プログラムを紹介します。このプログラムは、rand()関数を活用して、要素の総数をランダムなサイズのグループに分割していく仕組みです。

アルゴリズムの流れ

プログラムの処理手順は以下のとおりです。

  1. 数値配列か文字列のどちらを扱うか、選択肢として入力を受け取ります。
  2. 選択が「1」(整数配列)の場合:
    • 要素数 n と、n 個の整数からなる配列を入力します。
    • 配列を走査するためのインデックス変数 l を 0 で初期化します。
    • rand() を使って、n をランダムな整数分割に分解します。
    • 各分割サイズ i に対して、インデックス l から順に i 個の整数を出力します。
  3. 選択が「2」(文字列)の場合:
    • 文字列を配列 ch[] に入力します。
    • strlen() で文字列の長さを求め、インデックス l を 0 で初期化します。
    • 文字列の長さに対してランダムな整数分割を生成します。
    • 各分割サイズ i に対して、インデックス l から順に i 個の文字を出力します。

サンプルコード

以下が実際のC++プログラムです。ユーザーの選択に応じて、整数配列と文字列のどちらかを処理します。

#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
int main() {
    int n, i, j, l, c;
    cout<<"Enter 1 for integer and 2 for character array to generate array: ";
    cin>>c;
    //選択が1の場合(整数配列):
    if(c== 1) {
        cout<<"\nEnter the number of element in the integer array: ";
        cin>>n;
        int a[n];
        cout<<"\nEnter the elements of the array: \n";
        for(i = 0; i < n; i++) {
            cout<<"Enter "<<i+1<<" element: ";
            cin>>a[i];
        }
        cout<<"\nThe random partition of the given array is: \n";
        l = 0;
        while(n > 0) {
            cout<<"\t[";
            i = rand()%n + 1;
            n = n-i;
            for(j = 0; j < i; j++) {
                cout<<a[l]<<" ";
                l++;
            }
            cout<<"]";
        }
    }
    //選択が2の場合(文字列):
    else {
        char ch[100];
        cout<<"Enter the characters: ";
        cin>>ch;
        n = strlen(ch);
        cout<<"\nThe random partition of the given string is: \n";
        l = 0; //配列を走査するため l = 0 を代入
        while(n > 0) {
            cout<<"\t[ ";
            i = rand()%n + 1;
            n = n-i;
            for(j = 0; j < i; j++) {
                cout<<ch[l]<<" ";
                l++;
            }
            cout<<"]";
        }
    }
    return 0;
}

実行例1:整数配列の場合

選択肢に「1」を入力し、10個の整数からなる配列をランダムに分割した例です。

Enter 1 for integer and 2 for character array to generate array: 1
Enter the number of element in the integer array: 10
Enter the elements of the array:
Enter 1 element: 10
Enter 2 element: 9
Enter 3 element: 8
Enter 4 element: 7
Enter 5 element: 6
Enter 6 element: 5
Enter 7 element: 4
Enter 8 element: 3
Enter 9 element: 2
Enter 10 element: 1
The random partition of the given array is:
[10 9 ] [8 7 6 5 ] [4 3 2 ] [1 ]

この例では、10個の要素が「2個」「4個」「3個」「1個」の4つのグループにランダムに分割されました。

実行例2:文字列の場合

選択肢に「2」を入力し、アルファベット26文字の文字列をランダムに分割した例です。

Enter 1 for integer and 2 for character array to generate array: 2
Enter the characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ

The random partition of the given string is:
[ A B C D E F G H I J K L M N O P ] [ Q R S T U V W X ] [ Y ] [ Z ]

26文字の文字列が「16文字」「8文字」「1文字」「1文字」のグループに分割されました。

プログラムのポイント解説

  • ランダムサイズの決定: rand()%n + 1 により、残りの要素数 n の範囲内で1以上のランダムなサイズを生成しています。これにより、すべての要素が必ずどこかのグループに属することが保証されます。
  • 要素の消費: 分割サイズ i を決めるたびに n = n - i で残数を減らし、インデックス l を進めることで、要素の重複や漏れを防いでいます。
  • 終了条件: whileループは n が 0 になった時点で終了するため、全要素をちょうど一度ずつ出力できます。

この手法は、配列や文字列をランダムなグループに分けたい場合のシンプルな実装例として、アルゴリズムの学習にも役立ちます。なお、より厳密な乱数が必要な場合は <random> ヘッダーの mt19937 などを使用することを推奨します。

  1. C++でミドルスクエア法を使って乱数を生成するプログラムの作成方法

    ミドルスクエア法とはミドルスクエア法(中央二乗法)は、乱数を生成する最も単純な手法の一つです。「現在の数値を2乗し、その中央の桁を取り出す」という操作を繰り返すことで次々と乱数を作り出します。この手法は計算機科学の父として知られるジョン・フォン・ノイマンによって考案され、初期のコンピュータ時代に擬似乱数生成の方法として使われていました。基本的な仕組み例えば4桁の乱数を生成する場合、「1234」を2乗すると 1522756 となります。桁数を揃えるため先頭に0を付けて8桁の「01522756」にし、中央の4桁である「5227」を次の乱数として採用します。この操作を繰り返すことで乱数列が得られます

  2. C++で乱数を生成するプログラムの書き方【srand・rand関数の使い方を解説】

    C++を使って乱数を生成する方法を解説します。ここでは、0から指定した値までの範囲で乱数を生成します(このプログラムでは最大値を100に設定しています)。 srand()関数とは 乱数を生成するために使用するのがsrand()関数です。この関数はC標準ライブラリに含まれており、void srand(unsigned int seed)として宣言され、rand()関数が使用する乱数生成器にシード(種)を設定する役割を持ちます。 srand()の宣言は以下のとおりです。 void srand(unsigned int seed) この関数は「シード(seed)」と呼ばれる引数を1つ受け取ります。シ