東華大学復試OJ每日3題練習・第103〜105題の振り返り

基本問題103:入力された文字列から数字を読み取り、'5'をスペースとして扱い、その結果を昇順に並び替えて出力する。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int count;
    scanf("%d", &count);
    getchar();

    while(count--) {
        char line[1000];
        fgets(line, sizeof(line), stdin);
        line[strcspn(line, "\n")] = '\0';

        int numbers[500];
        int length = 0;
        int current = 0;
        int valid = 0;

        for(int i = 0; i < strlen(line); i++) {
            if(line[i] == '5') {
                if(valid) {
                    numbers[length++] = current;
                    valid = 0;
                    current = 0;
                }
            } else if(i == strlen(line) - 1) {
                current = current * 10 + (line[i] - '0');
                valid = 1;
                if(valid) {
                    numbers[length++] = current;
                    valid = 0;
                    current = 0;
                }
            } else {
                current = current * 10 + (line[i] - '0');
                valid = 1;
            }
        }

        // ソート処理
        for(int i = 0; i < length - 1; i++) {
            for(int j = 0; j < length - 1 - i; j++) {
                if(numbers[j] > numbers[j+1]) {
                    int temp = numbers[j];
                    numbers[j] = numbers[j+1];
                    numbers[j+1] = temp;
                }
            }
        }

        for(int i = 0; i < length; i++) {
            printf("%d", numbers[i]);
            if(i != length - 1) printf(" ");
        }
        printf("\n");
    }

    return 0;
}

基本問題104:非負の実数AとBが与えられる。AとBが等しければ"YES"、そうでなければ"NO"を出力する。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int loop;
    scanf("%d", &loop);
    getchar();

    while(loop--) {
        char input[2000];
        fgets(input, sizeof(input), stdin);
        input[strcspn(input, "\n")] = '\0';

        int aInteger = 0, aDecimal = 0;
        int bInteger = 0, bDecimal = 0;
        int state = 0;
        int integer = 1;

        for(int i = 0; i < strlen(input); i++) {
            if(input[i] == '.') {
                integer = 0;
                continue;
            }
            if(input[i] == ' ') {
                state = 1;
                integer = 1;
                continue;
            }
            if(state) {
                if(integer) bInteger = bInteger * 10 + (input[i] - '0');
                else bDecimal = bDecimal * 10 + (input[i] - '0');
            } else {
                if(integer) aInteger = aInteger * 10 + (input[i] - '0');
                else aDecimal = aDecimal * 10 + (input[i] - '0');
            }
        }

        // 小数部末尾の0を削除
        while(aDecimal % 10 == 0 && aDecimal != 0) aDecimal /= 10;
        while(bDecimal % 10 == 0 && bDecimal != 0) bDecimal /= 10;

        if(aInteger == bInteger && aDecimal == bDecimal)
            printf("YES\n");
        else
            printf("NO\n");
    }

    return 0;
}

基本問題105:文字列内に含まれる最長の回文を検索する。ただし、句読点や空白は無視し、アルファベットのみを対象とする。文字列は最大20,000文字である。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char buffer[2000];
    int totalLength = 0;
    int ch;

    while((ch = getchar()) != EOF) {
        buffer[totalLength++] = ch;
    }
    buffer[totalLength++] = '\0';

    char cleaned[2000];
    int cleanLength = 0;
    int indexMap[2000];

    for(int i = 0, j = 0; i < strlen(buffer); i++) {
        if(buffer[i] >= 'A' && buffer[i] <= 'Z') {
            cleaned[j] = buffer[i];
            indexMap[j] = i;
            j++;
            cleanLength++;
        } else if(buffer[i] >= 'a' && buffer[i] <= 'z') {
            cleaned[j] = buffer[i] - 32;
            indexMap[j] = i;
            j++;
            cleanLength++;
        }
    }

    int startIndex = 0;
    int maxLength = 0;

    for(int i = 0; i < cleanLength; i++) {
        int left = cleanLength - 1;
        int found = 1;
        int tempLength = 0;

        while(left > i) {
            found = 1;
            tempLength = 0;
            for(int j = left, k = i; j > i; k++, j--) {
                if(cleaned[k] != cleaned[j]) {
                    found = 0;
                    break;
                } else {
                    tempLength++;
                }
            }
            if(found) {
                if(tempLength > maxLength) {
                    startIndex = i;
                    maxLength = tempLength;
                    break;
                }
            }
            left--;
        }
    }

    printf("%d\n", maxLength);

    for(int i = indexMap[startIndex]; i <= indexMap[startIndex + maxLength - 1]; i++) {
        printf("%c", buffer[i]);
    }
    printf("\n");

    return 0;
}
  • 文字列を直接入力する際には (ch = getchar()) != EOF を使用して1文字ずつ読み込む。int chgetchar() の戻り値がASCIIコードであるため必要である。非ASCIIコードの場合には-1が返される。

コンピュータの予測可能性により、実験が不要であるように思える。なぜなら、実験結果は事前に知ることができるはずだからである。しかし、コンピュータシステムと自然との相互作用が複雑になるほど、予期しない動作が生じることがある。従って、実験と伝統的な科学的手法はコンピュータ科学の重要な要素である。

  • コンピュータの予測可能性が実験を不要にすると思われるが、システムと自然界との相互作用が複雑になると予期せぬ挙動が起こる。そのため実験と科学的手法はコンピュータ科学の中心的要素である。

コンピュータ科学は主に4つの分野に分けられる:ソフトウェア開発、コンピュータアーキテクチャ(ハードウェア)、人間とコンピュータのインタフェース(人間がコンピュータを効率的に使う方法の設計)、人工知能(コンピュータが知的行動を示すことを目指す)。ソフトウェア開発は効率的なコンピュータプログラムを作成することに関わる。コンピュータアーキテクチャは特定の計算ニーズに最適なハードウェアを開発することに関わる。人工知能と人間とコンピュータのインタフェースは、特定の問題解決のためのソフトウェアとハードウェアの両方の開発を含むことが多い。

  • "is concerned with" は「関与する」、「optimal」は「最適な」を意味する。
  • コンピュータ科学は主に4つの分野に分けられる:ソフトウェア開発、コンピュータアーキテクチャ、人間とコンピュータのインタフェース、人工知能。ソフトウェア開発は効率的なコンピュータプログラムを作成することに関係している。コンピュータアーキテクチャは特定の計算ニーズに最適なハードウェアを設計することに関係している。人工知能と人間とコンピュータのインタフェースは、特定の問題解決のためのソフトウェアとハードウェアの両方の開発を行うことが多くなる。

コンピュータソフトウェアの開発において、コンピュータ科学者とエンジニアは、特定のプログラムで最も適切なプログラミング言語やアルゴリズム、情報を効率的に保存・取得する方法、特定のソフトウェアとコンピュータの組み合わせの計算限界など、ソフトウェア設計のさまざまな領域と技術を研究する。ソフトウェア設計者はプログラムを開発する際に多くの要素を考慮しなければならない。しばしば、ある領域でのパフォーマンスはソフトウェア全体のパフォーマンスのために犠牲になる。例えば、コンピュータにはメモリ容量に制限があるため、ソフトウェア設計者はシステムのメモリ容量を超えないように、プログラムに含まれる機能数を制限する必要がある。

  • コンピュータソフトウェアの開発過程において、コンピュータ科学者とエンジニアは特定のプログラムに最適なプログラミング言語やアルゴリズム、情報の効率的な保存および取得方法、特定のソフトウェアとコンピュータの組み合わせにおける計算限界などのソフトウェア設計の分野と技術を調査する。ソフトウェア設計者はプログラムの開発において多くの要素を考慮する必要がある。通常、ある分野でのプログラムの性能はソフトウェア全体の性能のために妥協しなければならない。例えば、コンピュータにはメモリ容量の制限があるため、ソフトウェア設計者はプログラムが使用するメモリ量が設計されたシステムの提供する容量を超えないように、プログラムに含まれる機能数を制限しなければならない。
  • retrieve は「取得する」「since」は「なぜなら」を意味する。

タグ: OJ 復試 文字列処理 アルゴリズム ソート

5月22日 04:11 投稿