C 언어를 활용한 기본 알고리즘 및 함수 구현

이 문서에서는 C 언어를 사용하여 여러 가지 일반적인 프로그래밍 문제에 대한 해결책을 탐구합니다. 점수 등급 변환, 숫자의 자릿수 합 계산, 거듭제곱 연산, 삼각형 분류, 조합 계산, 최대공약수(GCD) 찾기, 그리고 특정 문자 패턴 출력과 같은 다양한 시나리오를 다루며, 각 문제에 대한 함수 구현과 로직을 분석합니다.

1. 점수 등급 변환

주어진 점수를 기준으로 학점을 부여하는 함수를 구현합니다. 일반적으로 90점 이상은 'A', 80점 이상은 'B', 70점 이상은 'C', 60점 이상은 'D', 그 외는 'F'로 분류합니다. 이 예시에서는 60점 미만을 'E'로 처리합니다.


#include <stdio.h>

// 학점을 계산하는 함수 선언
char getGradeFromScore(int numericScore);

int main() {
    int inputScore;
    char assignedGrade;

    printf("점수를 입력하세요 (EOF로 종료): \n");
    while(scanf("%d", &inputScore) != EOF) {
        if (inputScore < 0 || inputScore > 100) {
            printf("유효하지 않은 점수: %d. 0-100 사이의 점수를 입력하세요.\n\n", inputScore);
            continue;
        }
        assignedGrade = getGradeFromScore(inputScore); // 함수 호출
        printf("입력 점수: %d, 부여 등급: %c\n\n", inputScore, assignedGrade);
    }

    return 0;
}

// 학점을 계산하는 함수 정의
char getGradeFromScore(int numericScore) {
    if (numericScore >= 90) {
        return 'A';
    } else if (numericScore >= 80) {
        return 'B';
    } else if (numericScore >= 70) {
        return 'C';
    } else if (numericScore >= 60) {
        return 'D';
    } else {
        return 'E';
    }
}

2. 숫자의 각 자릿수 합 계산

양의 정수를 입력받아 그 숫자를 구성하는 각 자릿수의 합을 계산하는 함수를 작성합니다. 예를 들어, 123을 입력하면 1 + 2 + 3 = 6을 반환합니다.


#include <stdio.h>

// 재귀를 사용하여 자릿수 합을 계산하는 함수 선언
int calculateDigitSum(int number);

int main() {
    int inputNumber;
    int digitSumResult;

    printf("정수를 입력하세요 (EOF로 종료): \n");
    while(scanf("%d", &inputNumber) != EOF) {
        if (inputNumber < 0) {
            printf("음수는 처리할 수 없습니다. 양수를 입력하세요.\n\n");
            continue;
        }
        digitSumResult = calculateDigitSum(inputNumber); // 함수 호출
        printf("입력 숫자: %d, 자릿수 합계: %d\n\n", inputNumber, digitSumResult);
    }

    return 0;
}

// 재귀를 사용하여 자릿수 합을 계산하는 함수 정의
int calculateDigitSum(int number) {
    if (number == 0) {
        return 0; // 숫자가 0이 되면 재귀 종료
    } else {
        // 현재 자릿수를 더하고 나머지 숫자에 대해 재귀 호출
        return (number % 10) + calculateDigitSum(number / 10);
    }
}

3. 거듭제곱(Power) 함수 구현

두 정수 x와 n을 입력받아 x의 n제곱(x^n)을 효율적으로 계산하는 함수를 구현합니다. 특히 n이 큰 경우를 고려하여 재귀적 분할 정복 방식을 사용합니다.


#include <stdio.h>

// 거듭제곱을 계산하는 함수 선언
long long powerEfficient(int base, int exponent);

int main() {
    int val_x, val_n;
    long long result_power;

    printf("밑(x)과 지수(n)를 입력하세요 (EOF로 종료): \n");
    while(scanf("%d%d", &val_x, &val_n) != EOF) {
        if (val_n < 0) {
            printf("음수 지수는 처리하지 않습니다. 양수 또는 0 지수를 입력하세요.\n\n");
            continue;
        }
        result_power = powerEfficient(val_x, val_n); // 함수 호출
        printf("%d의 %d제곱 = %lld\n\n", val_x, val_n, result_power);
    }

    return 0;
}

// 거듭제곱을 효율적으로 계산하는 함수 정의 (재귀)
long long powerEfficient(int base, int exponent) {
    if (exponent == 0) {
        return 1; // 어떤 수의 0제곱은 1
    }
    
    long long half_power = powerEfficient(base, exponent / 2); // 절반 지수에 대한 거듭제곱 계산

    if (exponent % 2 == 0) {
        return half_power * half_power; // 지수가 짝수이면 (x^(n/2))^2
    } else {
        return base * half_power * half_power; // 지수가 홀수이면 x * (x^(n/2))^2
    }
}

4. 삼각형의 종류 분류

세 변의 길이를 입력받아 해당 변들로 삼각형을 구성할 수 있는지 여부와, 구성할 수 있다면 어떤 종류의 삼각형(정삼각형, 이등변삼각형, 직각삼각형, 일반삼각형)인지 분류하는 함수를 작성합니다.


#include <stdio.h>
#include <math.h> // for sqrt, pow if needed, but not strictly for this integer version

// 삼각형 분류 결과를 나타내는 enum
typedef enum {
    INVALID_TRIANGLE = 0,
    SCALENE_TRIANGLE,      // 일반 삼각형
    EQUILATERAL_TRIANGLE,  // 정삼각형
    ISOSCELES_TRIANGLE,    // 이등변 삼각형
    RIGHT_TRIANGLE         // 직각 삼각형
} TriangleType;

// 삼각형을 분류하는 함수 선언
TriangleType determineTriangleType(int sideA, int sideB, int sideC);

int main() {
    int s1, s2, s3;
    TriangleType typeResult;

    printf("세 변의 길이를 입력하세요 (EOF로 종료): \n");
    while (scanf("%d%d%d", &s1, &s2, &s3) != EOF) {
        typeResult = determineTriangleType(s1, s2, s3);
        
        switch (typeResult) {
            case INVALID_TRIANGLE:
                printf("유효하지 않은 삼각형입니다.\n");
                break;
            case SCALENE_TRIANGLE:
                printf("일반 삼각형입니다.\n");
                break;
            case EQUILATERAL_TRIANGLE:
                printf("정삼각형입니다.\n");
                break;
            case ISOSCELES_TRIANGLE:
                printf("이등변 삼각형입니다.\n");
                break;
            case RIGHT_TRIANGLE:
                printf("직각 삼각형입니다.\n");
                break;
            default:
                printf("알 수 없는 오류 발생.\n");
        }
        printf("\n");
    }
    return 0;
}

// 삼각형을 분류하는 함수 정의
TriangleType determineTriangleType(int sideA, int sideB, int sideC) {
    // 1. 유효성 검사: 변의 길이는 양수여야 함
    if (sideA <= 0 || sideB <= 0 || sideC <= 0) {
        return INVALID_TRIANGLE;
    }
    // 2. 유효성 검사: 삼각형 부등식 (두 변의 합은 나머지 한 변보다 커야 함)
    if (sideA + sideB <= sideC || sideA + sideC <= sideB || sideB + sideC <= sideA) {
        return INVALID_TRIANGLE;
    }

    // 3. 정삼각형 확인
    if (sideA == sideB && sideB == sideC) {
        return EQUILATERAL_TRIANGLE;
    }

    // 4. 직각삼각형 확인 (피타고라스 정리: a^2 + b^2 = c^2)
    // 최대 변을 찾고 나머지 두 변과의 관계 확인
    long long a_sq = (long long)sideA * sideA;
    long long b_sq = (long long)sideB * sideB;
    long long c_sq = (long long)sideC * sideC;

    if (a_sq + b_sq == c_sq || a_sq + c_sq == b_sq || b_sq + c_sq == a_sq) {
        return RIGHT_TRIANGLE;
    }

    // 5. 이등변삼각형 확인 (두 변의 길이가 같음)
    if (sideA == sideB || sideA == sideC || sideB == sideC) {
        return ISOSCELES_TRIANGLE;
    }

    // 6. 위의 모든 조건에 해당하지 않으면 일반 삼각형
    return SCALENE_TRIANGLE;
}

5. 조합(Combination) 계산

n개의 항목 중 m개를 선택하는 조합의 수 (nCm)를 계산하는 함수를 구현합니다. 조합은 순서에 상관없이 요소를 선택하는 경우의 수를 나타냅니다. 이 예제에서는 반복적인 방법으로 조합의 수를 계산합니다.


#include <stdio.h>

// 조합의 수를 계산하는 함수 선언 (nCm)
long long calculateCombinations(int n, int m);

int main() {
    int totalItems, chosenItems;
    long long combinationResult;

    printf("총 항목 수(n)와 선택할 항목 수(m)를 입력하세요 (EOF로 종료): \n");
    while (scanf("%d%d", &totalItems, &chosenItems) != EOF) {
        combinationResult = calculateCombinations(totalItems, chosenItems);
        printf("C(%d, %d) = %lld\n\n", totalItems, chosenItems, combinationResult);
    }
    return 0;
}

// 조합의 수를 계산하는 함수 정의 (반복문 사용)
long long calculateCombinations(int n, int m) {
    // 1. 유효성 검사
    if (m < 0 || m > n) {
        return 0; // 선택할 항목 수가 음수이거나 전체 항목 수보다 많으면 0
    }
    if (m == 0 || m == n) {
        return 1; // 0개 또는 n개를 선택하는 경우의 수는 1
    }

    // 2. 대칭성 활용: C(n, m) = C(n, n-m)
    // 계산량을 줄이기 위해 m이 n/2보다 크면 n-m으로 대체
    if (m > n / 2) {
        m = n - m;
    }

    // 3. 반복문을 사용하여 조합 계산
    // C(n, m) = (n * (n-1) * ... * (n-m+1)) / (m * (m-1) * ... * 1)
    // 각 항을 곱하고 나누면서 중간 오버플로우를 방지하기 위해
    // (res * (n - i + 1)) / i  형태로 계산
    long long currentResult = 1; 
    for (int i = 1; i <= m; i++) { 
        currentResult = currentResult * (n - i + 1) / i;
    }

    return currentResult;
}

6. 세 정수의 최대공약수(GCD) 계산

세 정수 a, b, c의 최대공약수(Greatest Common Divisor, GCD)를 계산하는 함수를 작성합니다. 세 수의 GCD는 두 수의 GCD를 확장하여 구할 수 있습니다: GCD(a, b, c) = GCD(GCD(a, b), c).


#include <stdio.h>

// 두 정수의 GCD를 유클리드 호제법으로 계산하는 함수 선언
int euclideanGCD(int num1, int num2);

// 세 정수의 GCD를 계산하는 함수 선언
int findThreeNumGCD(int val1, int val2, int val3);

int main() {
    int n1, n2, n3;
    int commonDivisor;

    printf("세 정수를 입력하세요 (EOF로 종료): \n");
    while (scanf("%d%d%d", &n1, &n2, &n3) != EOF) {
        if (n1 <= 0 || n2 <= 0 || n3 <= 0) {
            printf("양의 정수만 입력하세요.\n\n");
            continue;
        }
        commonDivisor = findThreeNumGCD(n1, n2, n3);   
        printf("%d, %d, %d의 최대공약수: %d\n\n", n1, n2, n3, commonDivisor);
    }

    return 0;
}

// 두 정수의 GCD를 유클리드 호제법으로 계산하는 함수 정의
int euclideanGCD(int num1, int num2) {
    while (num2 != 0) {
        int temp = num2;
        num2 = num1 % num2;
        num1 = temp;
    }
    return num1;
}

// 세 정수의 GCD를 계산하는 함수 정의
int findThreeNumGCD(int val1, int val2, int val3) {
    int gcd_ab = euclideanGCD(val1, val2);
    int gcd_abc = euclideanGCD(gcd_ab, val3);
    return gcd_abc;
}

7. 사용자 지정 크기의 문자 패턴 출력

정수 n을 입력받아 n의 크기에 해당하는 특정 문자 패턴을 출력하는 함수를 구현합니다. 이 패턴은 위에서 아래로 갈수록 폭이 좁아지는 형태의 'O', '<H>', 'I I' 문자로 구성됩니다.


#include <stdio.h>

// 특정 문자 패턴을 출력하는 함수 선언
void printShrinkingPattern(int size);

int main() {
    int patternSize;
    printf("패턴 크기 (n)를 입력하세요: ");
    scanf("%d", &patternSize);
    
    if (patternSize <= 0) {
        printf("양의 정수를 입력해야 합니다.\n");
        return 1;
    }
    
    printShrinkingPattern(patternSize);
    return 0;
}

// 특정 문자 패턴을 출력하는 함수 정의
void printShrinkingPattern(int size) {
    // 각 층은 3줄로 구성됨: 'O', '<H>', 'I I'
    // 'n'은 가장 넓은 부분의 블록 수를 결정. 가장 위는 2n-1 블록
    // 각 층마다 블록 수가 2개씩 줄어듬
    for (int currentLayer = 0; currentLayer < size; currentLayer++) {
        int numBlocks = (2 * size - 1) - (2 * currentLayer); // 현재 층의 블록 수
        int totalWidth = (2 * size - 1) * 4; // 최대 너비 (각 블록은 4칸 차지)
        int currentLayerWidth = numBlocks * 4;
        int leadingSpaces = (totalWidth - currentLayerWidth) / 2; // 중앙 정렬을 위한 앞 공백 수

        // 1. 'O' 줄 출력
        for (int i = 0; i < leadingSpaces; i++) printf(" ");
        for (int i = 0; i < numBlocks; i++) printf(" O  ");
        printf("\n");

        // 2. '<H>' 줄 출력
        for (int i = 0; i < leadingSpaces; i++) printf(" ");
        for (int i = 0; i < numBlocks; i++) printf("<H> ");
        printf("\n");
        
        // 3. 'I I' 줄 출력
        for (int i = 0; i < leadingSpaces; i++) printf(" ");
        for (int i = 0; i < numBlocks; i++) printf("I I ");
        printf("\n");
    }
}

태그: C Functions algorithms recursion ControlFlow

6월 1일 20:14에 게시됨