<ALGORITHM>/NOTE

20210119(화)

CodeGrimie 2021. 1. 19. 17:51

선택 정렬(Selection Sort)

▼ 이론

for(i = n; i > 1; i--)
    max = 0;
    for(j = 1; j < i; j++)
        if(Compare(base[max], base[j]) < 0)
            max = j;
    swap(base[max], base[i-1]);

 

▼ 코드

#include <cstdio>

int Compare(int lhs, int rhs)
{
    return (lhs - rhs);
}

void Swap(int* lhs, int* rhs)
{
    int temp = *lhs;
    *lhs = *rhs;
    *rhs = temp;
}

void SelectionSwap(int* pArr, int length)
{
    for (int i = length; i > 1; i--)
    {
        int max = 0;
        for (int j = 0; j < i; j++)
        {
            if (Compare(pArr[max], pArr[j]) < 0)
                max = j;
        }
        Swap(&pArr[max], &pArr[i - 1]);
    }
}

void PrintArray(const char* pTitle, int* pArr, int length)
{
    printf("%s { ", pTitle);
    for (int i = 0; i < length; i++)
        printf("%d ", pArr[i]);
    printf("}\n");
}

int main()
{
    const int arrMax = 5;
    int iArr[arrMax] = { 3,4,16,2,1 };

    PrintArray("BEFORE", iArr, arrMax);

    SelectionSwap(iArr, arrMax);

    PrintArray("AFTER ", iArr, arrMax);

    return (0);
}

함수로 빼냄으로써 Main 함수 자체는 훨씬 간결해졌다.

 

교환은 한번밖에 일어나지 않지만 순환문을 다 돌기 때문에 큰 속도 차이가 나지 않는다.

야구 게임

중첩 순환문을 연습하기 위한 문제다.

그렇게 어려운 문제가 아닌 만큼 재밌게 작업했다.

(너무 몰두해서 이것저것 더해보다 코드가 더러워졌지만..)

 

▼ 숫자 입력 부분 코드

int GetNum(int* pArr)
{
    wprintf(L"> 숫자값을 입력하세요: ");
    scanf_s("%d %d %d", &pArr[0], &pArr[1], &pArr[2]);

    for (int i = 0; i < 3; i++)
    {
        if (0 > pArr[i] || pArr[i] > 9)
        {
            wprintf(L"경고:잘못된 숫자(%d)입력입니다.\n", pArr[i]);
            return (FALSE);
        }
    }
    return (TRUE);
}

중첩 순환문을 쓰라고 해서 그냥 배열로 숫자 3개를 받았다.

항상 예외 처리하는 버릇을 들이는 게 좋다고 해서 0~9 사이의 숫자만 받도록 했다.

 

▼ 계산 부분 코드

void CheckStrikeBall(int* pComArr, int* pMyArr)
{
    strikeNum = 0;
    ballNum = 0;

    for (int i = 0; i < MAX_NUM; i++)
    {
        if (Compare(pComArr[i], pMyArr[i]) == 0)
        {
            strikeNum++;
            continue;
        }

        for (int j = 0; j < MAX_NUM; j++)
        {
            if (Compare(pComArr[i], pMyArr[j]) == 0)
            {
                ballNum++;
            }
        }
    }
}

계산 부분은 그냥 내부에서 순환문을 한번 더 돌아서 체크했다.

 

▼ 시간 제한으로 디자인을 하다 말았기 때문에 어색하다.

#include <stdio.h>
#include <locale.h>

#include <windows.h>

// DEFINES
#define TRUE 1
#define FALSE 0

#define MAX_NUM  3

// GLOBAL
static int isGameRunning = TRUE;

int strikeNum = 0;
int ballNum = 0;

// FUNCTIONS
int		GetNum(int* pArr);
int		Compare(int lhs, int rhs);
void	CheckStrikeBall(int* pComArr, int* pMyArr);
void	DrawTitle();
void	DrawResult(int strikeNum, int ballNum);

int main(void)
{
    _wsetlocale(LC_ALL, L"Korean");

    int comNum[MAX_NUM] = { 5,2,1 };
    int myNum[MAX_NUM] = { 0,0,0 };

    while (isGameRunning == TRUE)
    {
        //system("cls||clear");
        DrawTitle();

        if (GetNum(myNum) == FALSE)
        {
            continue;
        }

        CheckStrikeBall(comNum, myNum);

        if (strikeNum == MAX_NUM)
        {
            isGameRunning = FALSE;
        }

        DrawResult(strikeNum, ballNum);

    }

    return (0);
}

int Compare(int lhs, int rhs)
{
    return (lhs - rhs);
}

void DrawTitle()
{
    wprintf(L"▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤\n");
    wprintf(L"▤▤           야구 게임            ▤▤\n");
    wprintf(L"▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤\n");
}

void DrawResult(int strikeNum, int ballNum)
{
    wprintf(L"□□□□□□□□□□□□□□□□□□□□\n");
    wprintf(L"□□     %d 스트라이크     %d 볼      □□\n", strikeNum, ballNum);
}

int GetNum(int* pArr)
{
    wprintf(L"> 숫자값을 입력하세요: ");
    scanf_s("%d %d %d", &pArr[0], &pArr[1], &pArr[2]);
    wprintf(L"%d %d %d\n", pArr[0], pArr[1], pArr[2]);

    for (int i = 0; i < 3; i++)
    {
        if (0 > pArr[i] || pArr[i] > 9)
        {
            wprintf(L"경고:잘못된 숫자(%d)입력입니다.\n", pArr[i]);
            return (FALSE);
        }
    }
    return (TRUE);
}

void CheckStrikeBall(int* pComArr, int* pMyArr)
{
    strikeNum = 0;
    ballNum = 0;

    for (int i = 0; i < MAX_NUM; i++)
    {
        if (Compare(pComArr[i], pMyArr[i]) == 0)
        {
            strikeNum++;
            continue;
        }

        for (int j = 0; j < MAX_NUM; j++)
        {
            if (Compare(pComArr[i], pMyArr[j]) == 0)
            {
                ballNum++;
            }
        }
    }
}

구현 제한 시간 때문에 디자인 마무리를 못한 게 아쉽다..

다시 시작하기 입력 받고 화면 초기화만 하면 됐는데..

구구단 문제

순환문과 오칙연산을 이해하고 있는지 묻는 문제다.

일의 자리를 구하기 위해서는 받은 숫자가 10으로 나눠도 더 이상 몫이 없는 상태라는 걸 이해하면 쉽다.

 

▼ 10으로 나눠도 더 이상 몫이 없다면 마지막 자리 수

int GetLastNumber(int currentNum, int* numLength)
{
    while (currentNum > 10)
    {
        currentNum = currentNum % 10;
        (*numLength)--;
    }
    return (currentNum);
}

numLength는 나중에 출력할 때 앞에 여백을 더해주기 위해서 추가했다.

 

▼ 전체 코드

#include <cstdio>

int GetLastNumber(int currentNum, int* numLength);
int GetNumLength(int targetNum);

int main()
{
    int iTarget = 0;
    int numLength = 0;

    // DRAW TITLE
    printf("==================================\n");
    printf("==   THREE&SIX&NINE GENERATOR   ==\n");
    printf("----------------------------------\n");
    // GET NUMBER
    printf("> INPUT TARGET NUMBER : ");
    scanf_s("%d", &iTarget);

    numLength = GetNumLength(iTarget);

    // LOOP
    for (int i = 1; i < iTarget + 1; i++)
    {
        int paddingCount = numLength;

        // GET LAST NUMBER
        int temp = GetLastNumber(i, &paddingCount);

        // CHECK CONDITION(3? 6? 9?)
        if (temp == 3 || temp == 6 || temp == 9)
        {
            printf("*");
        }
        else
        {
            printf("%d", i);
        }

        // ADD "\n" PER 5 
        if (i % 10 == 0)
        {
            printf("\n");
        }
        else
        {
            // ADD PADDING
            for (int i = 0; i < paddingCount; i++)
            {
                printf(" ");
            }
        }
    }
}

int GetLastNumber(int currentNum, int* numLength)
{
    while (currentNum > 10)
    {
        currentNum = currentNum % 10;
        (*numLength)--;
    }
    return (currentNum);
}

int GetNumLength(int targetNum)
{
    int length = 0;
    while (targetNum > 10)
    {
        targetNum = targetNum % 10;
        length++;
    }
    return (length + 1);
}

가위 바위 보 게임

문제를 잘못 이해해서 미리 값들을 받아서 시뮬레이션하는 건 줄 알았다..

굳이 배열을 써서 값을 저장하고 비교한 나의 미련한 코드를 확인 할 수 있다.

 

▼ 전체 코드

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

// 가위바위보 게임
// 1 가위
// 2 바위
// 3 보

#define MAX_SIZE 3

int Compare(int lhs, int rhs)
{
    return (lhs - rhs);
}

int main()
{
    int comArr[MAX_SIZE];
    int myArr[MAX_SIZE];

    while (1)
    {
        // GET PLAYER NUM
        printf("INPUT(%d) : ", MAX_SIZE);
        for (int i = 0; i < MAX_SIZE; i++)
        {
            scanf_s("%d", &myArr[i]);
        }

        printf("====================\n");

        // PLAYER NUM
        printf("PLAYER   : { ");
        for (int i = 0; i < MAX_SIZE; i++)
        {
            printf("%d ", myArr[i]);
        }
        printf("}\n");

        // SET COMPUTER NUM
        printf("COMPUTER : { ");
        for (int i = 0; i < MAX_SIZE; i++)
        {
            comArr[i] = rand() % 3 + 1;
            printf("%d ", comArr[i]);
        }
        printf("}\n");

        printf("====================\n");

        for (int i = 0; i < MAX_SIZE; i++)
        {
            if (Compare(comArr[i], myArr[i]) > 0)
            {
                if (comArr[i] == 2)
                    printf("WIN COM[%d] : MY[%d]\n", comArr[i], myArr[i]);
                else if (comArr[i] == 3)
                    printf("WIN COM[%d] : MY[%d]\n", comArr[i], myArr[i]);
            }
            else if (Compare(comArr[i], myArr[i]) == 0)
            {
                printf("TIE COM[%d] : MY[%d] TIE\n", comArr[i], myArr[i]);
            }
            else if (Compare(comArr[i], myArr[i]) < 0)
            {
                if (comArr[i] == 1)
                    printf("    COM[%d] : MY[%d] WIN\n", comArr[i], myArr[i]);
                else if (comArr[i] == 2)
                    printf("    COM[%d] : MY[%d] WIN\n", comArr[i], myArr[i]);

            }
        }

    }


    return (0);
}