본문 바로가기

카테고리 없음

[백준]_27964 : 콰트로치즈피자(파이썬 and C언어)

728x90
반응형

 

 

27964번: 콰트로치즈피자

치즈와 피자에 환장하는 비행씨는 매일같이 치즈피자를 사 먹다가 지갑이 거덜 나고 말았다. 만들어 먹는 것이 사 먹는 것보다 싸다는 것을 안 비행씨는 여러 가지 토핑을 가져와서 직접 피자를

www.acmicpc.net

 

전략(Python)

문자열을 잘 이용할 줄 알아야 하는 문제이다. 먼저 파이썬식 논리라면 중복된 토핑들을  제거해야 하기 때문에 입력받은 토핑들을 집합으로 나타낸 후 다시 리스트로 바꾸는 작업을 해야 한다. 또한 문자열 뒤에 있는 6개의 글자가 "Cheese"이기만 하면 토핑으로 인정되는 것이다. 이것은 파이썬의 기능인 슬라이싱으로 확인할 수 있다.


시도 1(Python)

tr=int(input())
topping=list(set(list(map(str, input().split()))))
cnt=0
for top in topping:
    i=0
    while 1:
        if 'Cheese'==top[i:]:
            cnt+=1
            break
        if i==len(top):
            break
        i+=1
if cnt>=4:
    print('yummy')
else:
    print('sad')

참고로 위의 코드는 문제를 처음 풀었을 때 사용했던 발상이다. 문자열의 앞에서 부터 슬라이싱을 하여 "Cheese"와 한 번이라도 일치하기를 기다리는 코드이다. 필자가 앞에서 설명했던 방법에 비하면 꽤나 비효율적임을 알 수 있다.

수정

import sys
input = sys.stdin.readline
tr=input()
topping=list(set(list(map(str, input().split()))))
cnt=0
for top in topping:
    if 'Cheese'==top[len(top)-6:]:
        cnt+=1
if cnt>=4:
    print('yummy')
else:
    print('sad')

전략(C언어)

이제 C언어로는 어떻게 접근해야 할지 생각해보자. 특히 문자열을 다루기가 파이썬에 비해 매우 힘들기 때문에 해줘야 할 일들이 많아. 먼저 전략을 세우자면 다음과 같은 순서일 것이다. 

  1. 문자열을 입력 받는다.
  2. 받은 문자열 중에서 중복을 제거해 준다.
  3. 마지막 6자리가 "Cheese"인지 확인해 준다.
  4. 3번을 만족한 문자열의 개수가 4개 이상이면 'yummy', 아니면 'sad'를 출력한다.

이제 디테일한 사항들로 들어가 보자.

 

1. 문자열을 입력받는다. 

 

문자열 입력 개수가 최대 100개고 문자열 크기도 최대 100이기 때문에 다음과 같은 코드를 짜준다.

char a[101][101];
int time;
int cnt=0;
scanf("%d",&time);
for (int i = 0; i < time; ++i) {
    scanf("%s",a[i]);
}

2. 받은 문자열 중에서 중복을 제거해 준다.

 

상당히 성가신 작업이다. 일단 중복 제거 기능을 main에 담으면 코드가 보기 싫어지기 때문에 set함수로 만들어준다.

set함수에는 다음과 같은 과정을 거칠 것이다.

  1. 문자열 a와 배열의 크기 time을 인자로 전달한다. 하지만 만약 중복이 발견되게 되면 time이 그만큼 줄어들어야 하기 때문에 함수 밖에서도 time의 크기 감소가 영향을 미쳐야 한다. 따라서 time의 주소를 전달하고 포인터인 size로 받는다.
  2. i번째 문자열을 기준으로 j(> i) 번째 문자열을 비교해 준다. 만약 두 문자열이 일치하면(strcmp 사용) j번째 문자열을 기준으로 뒤의 문자열들을 하나씩 앞으로 복사(strcpy)하면서 덮어 씌운다.
  3. size와 j를 1 감소시킨다.
  4. 2번 ~ 4번 과정을 문자열의 끝까지 반복해 준다.
void set(char arr[][101], int *size) {
    for (int i = 0; i < *size; i++) {
        for (int j = i + 1; j < *size; j++) {
            if (strcmp(arr[i], arr[j]) == 0) {
                for (int k = j; k < (*size) - 1; k++) {
                    // 앞으로 한칸씩 땡기기
                    strcpy(arr[k], arr[k + 1]);
                }
                // 땡긴 만큼 size, j 감소
                (*size)--;
                j--;
            }
        }
    }
}

 

3. 마지막 6자리가 "Cheese"인지 확인한다.

strncpy로 문자열 뒤 6자리와 "Cheese"를 strcmp로 비교해 준다. 이 기능 또한 함수로 나타내준다.

void check_cheese(char a[][101], int size) {
    int ans = 0;
    for (int i = 0; i < size; ++i) {
        if (strcmp("Cheese", strncpy(a[i], a[i] + strlen(a[i]) - 6, strlen(a[i]))) == 0)
            ans++;
    }
    if (ans >= 4) printf("yummy");
    else printf("sad");
}

이제 위의 모든 과정을 반복문으로 묶으면 아래와 같은 최종 코드가 나오게 된다.

시도 2(C언어)

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

void set(char arr[][101], int *size) {
    for (int i = 0; i < *size; i++) {
        for (int j = i + 1; j < *size; j++) {
            if (strcmp(arr[i], arr[j]) == 0) {
                for (int k = j; k < (*size) - 1; k++) {
                    // 앞으로 한칸씩 땡기기
                    strcpy(arr[k], arr[k + 1]);
                }
                // 땡긴 만큼 size, j 감소
                (*size)--;
                j--;
            }
        }
    }
}

void check_cheese(char a[][101], int size) {
    int ans = 0;
    for (int i = 0; i < size; ++i) {
        if (strcmp("Cheese", strncpy(a[i], a[i] + strlen(a[i]) - 6, strlen(a[i]))) == 0)
            ans++;
    }
    if (ans >= 4) printf("yummy");
    else printf("sad");
}

int main() {
    char a[101][101];
    int time;
    int cnt = 0;
    scanf("%d", &time);
    for (int i = 0; i < time; ++i) {
        scanf("%s", a[i]);
    }
    set(a, &time);
    check_cheese(a, time);

    return 0;
}

 

728x90
반응형