대학교/프로그래밍랩

[프로그래밍 랩] 5주차 - 난수, 확률, 통계

CodeJin 2021. 9. 30. 03:53

문제 1. 난수

난수 n개를 발생시키고 합과 평균을 출력하라.

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

void main()
{
    int i, n, r, sum = 0;
    int start, end;
    //srand(time(NULL)); // 난수값 초기화
    printf("난수의 개수: ");
    scanf("%d", &n);
    //printf("시작과 끝 : ");
    //scanf("%d %d", &start, &end);

    for (i=0;i<n;i++) {
        r = rand();
        // r = start + rand() % (end - start + 1);
        printf("%d ", r);
        sum += r;
    }
    printf("\nsum=%d avg=%d\n", sum, sum / n);
    
}

 

문제 2. 확률 계산

주사위를 n번 굴린 후, 1~6의 빈도수를 확인한다. 또한 번호의 확률을 조작하여 1~5의 경우 10%, 6의 경우 50%인 확률로 나오는 주사위를 만들어보라.

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

void main()
{
    int i, r, ntest, dice;
    int count[6] = { 0 }; // 1 ~ 6 count 를 보관
    srand(time(NULL)); // 난수 초기화
    printf("주사위 횟수 : ");
    scanf("%d", &ntest);
    printf("정상적인 주사위\n");
    for (i = 0; i < ntest; i++) {
        // dice = ?? 0~5 -> 주사위 1~6
        dice = rand() % 6;
        // count[?] = 발생 회수 증가, 완성할 것
        count[dice]++;
    }
    for (i = 0; i < 6; i++) {
        // 화면과 같이 출력
        printf("%d : %d (%5.2lf%%)\n", i + 1, count[i], 100. * (count[i]) / ntest);
    }
    printf("\n");

    // 이상한 주사위
    printf("\n이상한 주사위 6이 50%% 확률\n");
    for (i = 0; i < 6; i++)
        count[i] = 0;
    for (i = 0; i < ntest; i++) {
        // 분포를 0~99로 구하고 0~9, 10~19, 20~29, 30~39, 40~49, 50~99 를
        r = rand() % 100;
        // 1, 2, 3, 4, 5, 6 으로 맵핑
        if (r <= 10) dice = 0;
        else if (r <= 19) dice = 1;
        else if (r <= 29) dice = 2;
        else if (r <= 39) dice = 3;
        else if (r <= 49) dice = 4;
        else dice = 5;
        // 발생 회수 증가
        count[dice]++;
    }
    for (i = 0; i < 6; i++) {
        // 화면과 같이 출력
        printf("%d : %d (%5.2lf%%)\n", i + 1, count[i], 100. * (count[i]) / ntest);
    }
}

 

문제 3. Lotto번호 발생기

1 ~ 45까지의 난수를 발생시켜서 로또번호를 만들어라. 단 난수를 발생시켰을 때 중복되는 번호가 있을 수 있으므로 중복체크를 하여 중복인 숫자를 지워야 한다. 또한 출력할때는 정렬하여 출력하라.

중복제거에서 생각을 해야 한다. 정렬은 stdlib에 qsort함수도 있고, 직접 구현해도 되지만, 그런걸 가져다 쓰면 뭔가 안될 것 같아서(배우질 않았으니) 떠올리기 쉬운 것 같은 버블 정렬을 통해 정렬했다.

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

void sort(int* arr, int len)
{
    int temp;
    for (int i = 0; i < len - 1; i++)
    {
        for (int j = 0; j < len - i - 1; j++) 
        {
            if (arr[j] > arr[j + 1]) 
            {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

void main()
{
    int i, n, l;
    int lotto[6], j;
    srand(time(NULL));
    printf("복권 매 수는 : ");
    scanf("%d", &l);
    while (l--) 
    {
        for (i = 0; i < 6; i++)
            lotto[i] = 0;

        for (i = 0; i < 6; i++) 
        {
            n = rand() % 45 + 1;
            for (j = 0; j < i; j++) // 중복 검사
            {
                if (n == lotto[j]) 
                {
                    n = rand() % 45 + 1;
                    j = 0;
                }
            }
            lotto[i] = n;
        }
        sort(lotto, 6);
        for (i = 0; i < 6; i++) {
            printf("%2d ", lotto[i]);
        }
        printf("\n");
    }
}

 

문제 4. 모의 성적 데이터 발생 1

성적 처리 프로그램을 위한 테스트 케이스를 발생시키고자 한다. A+(>=95), A(>=90), B+(>=85), .. D(>=60), F(<60) 이다. 

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

void main()
{
    int i, j, n, r;
    int sum = 0; // 총점
    // 학점별 인원수 0:A+, 1:A, ... D, 8:F
    char *grade_str[] = {"A+", "A ", "B+", "B ", "C+", "C ", "D+", "D ", "F "};
    int grade_index, grade_count[9] = {0}; 
    int *scores[9];
    int score1;
    
    scanf("%d", &n);
    //for (i=0;i<9;i++)
    //	scores[i] = (int *)malloc(sizeof(int)*n);
    srand(time(NULL)); // 난수 초기화
    for (i=0;i<n;i++) {
        score1 = rand() % 101; // 0 ~ 100
        printf("%d ", score1);
        // sum 을 구한다.
        sum += score1;
        // grade_index 를 구한다. 0:A+, 1:A ...
        if (score1 >= 95) grade_index = 0;
        else if (score1 >= 90) grade_index = 1;
        else if (score1 >= 85) grade_index = 2;
        else if (score1 >= 80) grade_index = 3;
        else if (score1 >= 75) grade_index = 4;
        else if (score1 >= 70) grade_index = 5;
        else if (score1 >= 65) grade_index = 6;
        else if (score1 >= 60) grade_index = 7;
        else grade_index = 8;
        // grade_count[]를 증가시킨다.
        grade_count[grade_index]++;
    }
    printf("\n\nn=%d 평균 = %6.2f\n", n, ((double)sum) / n);
    for (i=0;i<9;i++) {
        // 화면과 같이 출력
        printf("%-2s : %5d (%6.2lf%%)", grade_str[i], grade_count[i], ((double)grade_count[i]) * 100 / n);
        printf("\n");
    }
}

 

문제 5. 모의 성적 데이터 발생 2

문제4와 같이 발생 시키면 A+ ~ F의 비율이 모두 똑같기 때문에, 주사위에서 사용했던 확률 조작을 통해 점수를 발생시켜보자. A+:10%, A:10%, B+:20%, B:25%, C+:15%, C:10%, D+:5%, D:3%, F:2% 의 비율로 맞춘다. 이때 최대 분포를 계산해 두어야 한다. 각 학점별 최대 분포가 소수점으로 인해 정확하게 일치하지 않을 수 있으니 보정해야 한다.

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

void main()
{
    int nstudents, i, j, prob, score;
    double temp;
    int sum = 0;
    int grade; // 0~8, A+ ~ F
    int count[9] = { 0 }; // 0 ~ 8 A+ ~ F 인원수
    int compensaton[9] = { 0 }; // 보정해야할 위치
    // A+:10%, A:10%, B+:20%, B:25%, C+:15%, C:10%, D+:5%, D:3%, F:2%
    char* grade_str[] = { "A+", "A ", "B+", "B ", "C+", "C ", "D+", "D ", "F " };
    int maxcount[9] = { 10, 10, 20, 25, 15, 10, 5, 3, 2 }; // 미리 계산된 최대 인원 -> 100명 기준
    int start[9] = { 95, 90, 85, 80, 75, 70, 65, 60, 0 };//점수시작
    int end[9] = { 100, 94, 89, 84, 79, 74, 69, 64, 59 };//점수끝

    srand(time(NULL));
    scanf("%d", &nstudents);
    j = 0;
    for (i = 0; i < 9; i++)
    {
        //maxcount[i] 를 계산해 둔다
        // maxcount[i] = (int)round(maxcount[i] * nstudents / 100.);
        temp = (maxcount[i] * nstudents / 100.);
        if (temp != (int)temp) // 소수점이 있다면
            compensaton[j++] = i;

        maxcount[i] = (int)temp;
        sum += maxcount[i];
    }
    // maxcount 소수점 보정
    for (i = 0; i < nstudents - sum; i++)
    {
        maxcount[compensaton[i] % j]++;
    }
    sum = 0;
    for (i = 0; i < nstudents; i++) {
        do {
            prob = rand() % 100; // 확률 변수로 사용
            if (0 <= prob && prob <= 9) grade = 0;        // A+
            else if (10 <= prob && prob <= 19) grade = 1; // A
            else if (20 <= prob && prob <= 39) grade = 2; // B+
            else if (40 <= prob && prob <= 64) grade = 3; // B
            else if (65 <= prob && prob <= 79) grade = 4; // C+
            else if (80 <= prob && prob <= 89) grade = 5; // C
            else if (90 <= prob && prob <= 94) grade = 6; // D+
            else if (95 <= prob && prob <= 97) grade = 7; // D
            else grade = 8;                               // F
            // 이미 해당 학점의 점수를 모두 발생하였다면
            // 다른 학점을 발생할 때 까지 반복한다.
        } while (count[grade] + 1 > maxcount[grade]);//인원 check
        // A+의 경우 start=95 end=100
        score = start[grade] + rand() % (end[grade] - start[grade] + 1);
        count[grade]++; // 학점별 count를 증가시킨다	
        sum += score;
        printf("%3d ", score);
        if (i % 10 == 9) printf("\n");
    }
    printf("\n\nn=%d 평균 = %6.2f\n", nstudents, ((double)sum) / nstudents);
    for (i = 0; i < 9; i++) {
        // 화면과 같이 출력
        printf("%s : %5d (%6.2lf%%)", grade_str[i], count[i], ((double)count[i]) * 100 / nstudents);
        printf("\n");
    }
}

 

문제 6. 문장의 알파벳 분포 조사

input.txt를 I/O redirection으로 받아 그 안의 알파벳의 분포를 출력하라.

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

void main()
{
    char c;
    int total=0; // 전체 문자수
    int alpha=0; // 알파벳 문자수
    int blank=0; // blank(space, tab, newline) 문자수
    int digit=0; // 0~9 문자수
    int special=0; // 특수문자 수
    int count[26] = {0};//알파벳별로 count
    while ((c=getchar())!=EOF) { //
        total++;
        // 알파벳 카운트 부분
        if (isalpha(c)) {
            alpha++;
            count[toupper(c) - 'A']++;
        }
    }
    printf("\n\n전체문자수=%d 알파벳수=%d\n", total, alpha);
    for (c='A';c<='Z';c++) {
        // 화면과 같이 출력
        printf("%c:%-3d (%5.2lf%%)", c, count[c - 'A'], count[c - 'A'] * 100. / alpha);
        if ((c - 'A') % 5 == 4)
            printf("\n");
    }
    printf("\n");
}

 

문제 7. 백준 9012번

https://codejin.tistory.com/80

 

백준 9012번 C언어 풀이

https://www.acmicpc.net/problem/9012 9012번: 괄호 괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자..

codejin.tistory.com