C 言語関数プログラミングとアルゴリズム実装事例

成績評価変換関数の設計

数値スコアを受け取り、対応する文字ランクを返す関数を実装します。ここでは switch 文ではなく if-else 構文を用いて条件分岐を行い、90 点以上を A、80 点以上を B という基準で判定します。

#include <stdio.h>

char convert_to_rank(int point);  // 関数プロトタイプ

int main() {
    int point;
    char rank;

    while (scanf("%d", &point) != EOF) {
        rank = convert_to_rank(point);  // 関数呼び出し
        printf("得点:%d, 評価:%c\n\n", point, rank);
    }

    return 0;
}

// 関数本体
char convert_to_rank(int point) {
    char result;

    if (point >= 90) {
        result = 'A';
    } else if (point >= 80) {
        result = 'B';
    } else if (point >= 70) {
        result = 'C';
    } else if (point >= 60) {
        result = 'D';
    } else {
        result = 'E';
    }

    return result;
}

再帰による桁和計算

整数の各桁の数字を合計する処理です。元の反復処理ではなく、再帰呼び出しを用いて実装します。数が 0 になるまで再帰的に桁を分解して加算します。

#include <stdio.h>

int recursive_digit_sum(int value);  // 関数プロトタイプ

int main() {
    int value;
    int result;

    while (printf("数値を入力:"), scanf("%d", &value) != EOF) {
        result = recursive_digit_sum(value);    // 関数呼び出し
        printf("入力:%d, 合計:%d\n\n", value, result);
    }

    return 0;
}

// 関数本体
int recursive_digit_sum(int value) {
    if (value < 10) {
        return value;
    } else {
        return (value % 10) + recursive_digit_sum(value / 10);
    }
}

べき乗計算の高速化

基数と指数を受け取り、べき乗を計算します。単純な乗算ではなく、指数が偶数の場合に半分のべき乗を再利用する分割統治法を適用します。

#include <stdio.h>

int fast_pow(int base, int exponent);    // 関数プロトタイプ

int main() {
    int base, exponent;
    int result;

    while (printf("基数と指数を入力:"), scanf("%d%d", &base, &exponent) != EOF) {
        result = fast_pow(base, exponent);  // 関数呼び出し
        printf("指数:%d, 結果:%d\n\n", exponent, result);
    }

    return 0;
}

// 関数本体
int fast_pow(int base, int exponent) {
    int half;

    if (exponent == 0)
        return 1;
    else if (exponent % 2 != 0)
        return base * fast_pow(base, exponent - 1);
    else {
        half = fast_pow(base, exponent / 2);
        return half * half;
    }
}

双子素数の探索

100 以下の範囲で、差が 2 である素数の組(双子素数)を検出します。素数判定関数を別途定義し、効率的な判定処理を行います。

#include <stdio.h>
#include <math.h>

int verify_prime(int num);
int main() {
    int count = 0;
    printf("100 未満の双子素数リスト:\n");
    for (int i = 2; i < 100; ++i) {
        if (verify_prime(i) && verify_prime(i + 2)) {
            printf("%d と %d\n", i, i + 2);
            count++;
        }
    }
    printf("総数:%d 組\n", count);
    return 0;
}
int verify_prime(int num) {
    if (num <= 1)
        return 0;
    if (num == 2)
        return 1;
    if (num % 2 == 0)
        return 0;
    for (int j = 3; j <= sqrt(num); j += 2) {
        if (num % j == 0) {
            return 0;
        }
    }
        return 1;
}

ハノイの塔再帰解法

n 枚の円盤を移動させる手順を出力します。グローバル変数を用いて移動回数をカウントし、再帰的に問題を解決します。

#include <stdio.h> 

int total_moves = 0;
void transfer_disks(int n, char src, char dest, char aux);
int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        total_moves = 0;
        printf("\n");
        transfer_disks(n, 'A', 'C', 'B');
        printf("\n合計移動回数:%d\n", total_moves);
    }
    return 0;
}
void transfer_disks(int n, char src, char dest, char aux) {
    if (n == 1) {
        total_moves++;
        printf("%d:%c から %c へ\n", n, src, dest);
        return;
    }
    transfer_disks(n - 1, src, aux, dest);
    total_moves++;
    printf("%d:%c から %c へ\n", n, src, dest);
    transfer_disks(n - 1, aux, dest, src);
}

組み合わせ計算の二つの手法

nCr(組み合わせ)を計算する関数です。ここでは計算量を考慮した反復処理版と、定義に基づいた再帰処理版の両方を示します。

#include <stdio.h>
int calculate_nCr(int total, int select);

int main() {
    int total, select;
    int ans;

    while (scanf("%d%d", &total, &select) != EOF) {
        ans = calculate_nCr(total, select);
        printf("n = %d, r = %d, 結果 = %d\n\n", total, select, ans);
    }
    return 0;
}

// 反復処理による実装
int calculate_nCr(int total, int select) {
    if (select < total && select < 0)
        return 0;
    if (select == 0 || select == total)
        return 1;
    if (select > total - select)
        select = total - select;
    long res = 1;
    for (int i = 1; i <= select; ++i) {
        res = res * (total - select + i) / i;
    }
    return (int)res;
}
#include <stdio.h>
int calculate_nCr(int total, int select);

int main() {
    int total, select;
    int ans;

    while (scanf("%d%d", &total, &select) != EOF) {
        ans = calculate_nCr(total, select);
        printf("n = %d, r = %d, 結果 = %d\n\n", total, select, ans);
    }
    return 0;
}

// 再帰処理による実装
int calculate_nCr(int total, int select) {
    if (select > total || select < 0)
        return 0;
    if (select == 0 || select == total)
        return 1;
    return calculate_nCr(total - 1, select) + calculate_nCr(total - 1, select - 1);
}

三数の最大公約数

3 つの整数を受け取り、その最大公約数を求めます。ユークリッドの互除法を補助関数として利用し、効率的に計算を行います。

#include <stdio.h>

int gcd_pair(int a, int b);
int compute_gcd_three(int a, int b, int c);

int main() {
    int a, b, c;
    int ans;

    while (scanf("%d%d%d", &a, &b, &c) != EOF) {
        ans = compute_gcd_three(a, b, c);
        printf("最大公約数:%d\n\n", ans);
    }

    return 0;
}

// 二数の最大公約数
int gcd_pair(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

// 三数の最大公約数
int compute_gcd_three(int a, int b, int c) {
    return gcd_pair(gcd_pair(a, b), c);
}

タグ: C 言語,再帰処理,アルゴリズム,関数定義,数値計算

5月23日 08:21 投稿