문제 설명

 

ANIMAL_INS 테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다. ANIMAL_INS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, INTAKE_CONDITION, NAME, SEX_UPON_INTAKE는 각각 동물의 아이디, 생물 종, 보호 시작일, 보호 시작 시 상태, 이름, 성별 및 중성화 여부를 나타냅니다.

NAME TYPE NULLABLE
ANIMAL_ID VARCHAR(N) FALSE
ANIMAL_TYPE VARCHAR(N) FALSE
DATETIME DATETIME FALSE
INTAKE_CONDITION VARCHAR(N) FALSE
NAME VARCHAR(N) TRUE
SEX_UPON_INTAKE VARCHAR(N) FALSE

ANIMAL_OUTS 테이블은 동물 보호소에서 입양 보낸 동물의 정보를 담은 테이블입니다. ANIMAL_OUTS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, NAME, SEX_UPON_OUTCOME는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다. ANIMAL_OUTS 테이블의 ANIMAL_ID는 ANIMAL_INS의 ANIMAL_ID의 외래 키입니다.

NAME TYPE NULLABLE
ANIMAL_ID VARCHAR(N) FALSE
ANIMAL_TYPE VARCHAR(N) FALSE
DATETIME DATETIME FALSE
NAME VARCHAR(N) TRUE
SEX_UPON_OUTCOME VARCHAR(N) FALSE

천재지변으로 인해 일부 데이터가 유실되었습니다. 입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.

 

예시

예를 들어, ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블이 다음과 같다면

ANIMAL_INS

ANILMAL_ID ANIMAL_TYPE DATETIME INTAKE_CONDITION NAME SEX_UPON_INTAKE
A352713 Cat 2017-04-13 16:29:00 Normal Gia Spayed Female
A350375 Cat 2017-03-06 15:01:00 Normal Meo Neutered Male

ANIMAL_OUTS

ANILMAL_ID ANIMAL_TYPE DATETIME NAME NAME
A349733 Dog 2017-09-27 19:09:00 Allie Spayed Female
A352713 Cat 2017-04-25 12:25:00 Gia Spayed Female
A349990 Cat 2018-02-02 14:18:00 Spice Spayed Female

ANIMAL_OUTS 테이블에서

  • Allie의 ID는 ANIMAL_INS에 없으므로, Allie의 데이터는 유실되었습니다.
  • Gia의 ID는 ANIMAL_INS에 있으므로, Gia의 데이터는 유실되지 않았습니다.
  • Spice의 ID는 ANIMAL_INS에 없으므로, Spice의 데이터는 유실되었습니다.

따라서 SQL문을 실행하면 다음과 같이 나와야 합니다.

ANIMAL_IDNAME

ANIMAL_ID NAME
A349733 Allie
A349990 Spice

본 문제는 Kaggle의 "Austin Animal Center Shelter Intakes and Outcomes"에서 제공하는 데이터를 사용하였으며 ODbL의 적용을 받습니다.

 

풀이

 

[MySQL]

SELECT ANIMAL_ID, NAME 
FROM ANIMAL_OUTS
WHERE NOT EXISTS 
(SELECT NULL 
FROM ANIMAL_INS 
WHERE ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID)

 

NOT EXISTS구문은 먼저 ANIMAL_OUTS 테이블에 접근해서 하나의 레코드를 가져온 뒤 해당 레코드에 대해서 NOT EXISTS 이하의 서브 쿼리를 실행하고 서브 쿼리가 존재하지 않는지를 확인한다. 이 구문을 이용하여 존재하지 않느느 ANIMAL_ID를 찾아주면 된다.

 

[Oracle]

 

SELECT ANIMAL_ID, NAME 
FROM ANIMAL_OUTS 
WHERE NOT EXISTS 
(SELECT NULL 
FROM ANIMAL_INS 
WHERE ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID) 
ORDER BY ANIMAL_ID

이유는 잘 모르겠지만 Oracle에서 NOT EXISTS를 쓰면 틀렸다고 나와서 ANIMAL_ID를 기준으로 정렬을 해줬더니 정답 처리가 되었다.

 

LEFT OUTER JOIN을 이용한 방법으로도 풀어보자.

SELECT ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.NAME 
FROM ANIMAL_OUTS 
LEFT OUTER JOIN ANIMAL_INS
ON ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID
WHERE ANIMAL_INS.ANIMAL_ID is NULL
ORDER BY ANIMAL_OUTS.ANIMAL_ID

LEFT OUTER JOIN은 왼쪽 테이블을 기준으로 오른쪽 테이블의 레코드를 비교하여 조건이 일치하면 가져와서 JOIN하고 다르면 NULL이 표시된다. ANIMAL_OUTS 테이블을 기준으로 JOIN을 하게 되면 ANIMAL_OUTS에 있지만 ANIMAL_INS에 없는 값들은 NULL로 들어오기 때문에 없어진 기록을 찾을 수 있다.

SELECT ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.NAME 
FROM ANIMAL_OUTS, ANIMAL_INS
WHERE ANIMAL_OUTS.ANIMAL_ID = ANIMAL_INS.ANIMAL_ID(+)
AND ANIMAL_INS.ANIMAL_ID IS NULL
ORDER BY ANIMAL_OUTS.ANIMAL_ID

Oracle에서 (+)를 이용해서 위와 같이 작성할 수도 있다.

 

 

 

 

문제 설명

 

데이터 처리 전문가가 되고 싶은 "어피치"는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자열에서 같은 값이 연속해서 나타나는 것을 그 문자의 개수와 반복되는 값으로 표현하여 더 짧은 문자열로 줄여서 표현하는 알고리즘을 공부하고 있습니다.
간단한 예로 "aabbaccc"의 경우 "2a2ba3c"(문자가 반복되지 않아 한번만 나타난 경우 1은 생략함)와 같이 표현할 수 있는데, 이러한 방식은 반복되는 문자가 적은 경우 압축률이 낮다는 단점이 있습니다. 예를 들면, "abcabcdede"와 같은 문자열은 전혀 압축되지 않습니다. "어피치"는 이러한 단점을 해결하기 위해 문자열을 1개 이상의 단위로 잘라서 압축하여 더 짧은 문자열로 표현할 수 있는지 방법을 찾아보려고 합니다.

예를 들어, "ababcdcdababcdcd"의 경우 문자를 1개 단위로 자르면 전혀 압축되지 않지만, 2개 단위로 잘라서 압축한다면 "2ab2cd2ab2cd"로 표현할 수 있습니다. 다른 방법으로 8개 단위로 잘라서 압축한다면 "2ababcdcd"로 표현할 수 있으며, 이때가 가장 짧게 압축하여 표현할 수 있는 방법입니다.

다른 예로, "abcabcdede"와 같은 경우, 문자를 2개 단위로 잘라서 압축하면 "abcabc2de"가 되지만, 3개 단위로 자른다면 "2abcdede"가 되어 3개 단위가 가장 짧은 압축 방법이 됩니다. 이때 3개 단위로 자르고 마지막에 남는 문자열은 그대로 붙여주면 됩니다.

압축할 문자열 s가 매개변수로 주어질 때, 위에 설명한 방법으로 1개 이상 단위로 문자열을 잘라 압축하여 표현한 문자열 중 가장 짧은 것의 길이를 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • s의 길이는 1 이상 1,000 이하입니다.
  • s는 알파벳 소문자로만 이루어져 있습니다.

입출력 예

s result
"aabbaccc" 7
"ababcdcdababcdcd" 9
"abcabcdede" 8
"abcabcabcabcdededededede" 14
"xababcdcdababcdcd" 17

입출력 예에 대한 설명

입출력 예 #1

문자열을 1개 단위로 잘라 압축했을 때 가장 짧습니다.

 

입출력 예 #2

문자열을 8개 단위로 잘라 압축했을 때 가장 짧습니다.

 

입출력 예 #3

문자열을 3개 단위로 잘라 압축했을 때 가장 짧습니다.

 

입출력 예 #4

문자열을 2개 단위로 자르면 "abcabcabcabc6de" 가 됩니다.
문자열을 3개 단위로 자르면 "4abcdededededede" 가 됩니다.
문자열을 4개 단위로 자르면 "abcabcabcabc3dede" 가 됩니다.
문자열을 6개 단위로 자를 경우 "2abcabc2dedede"가 되며, 이때의 길이가 14로 가장 짧습니다.

 

입출력 예 #5

문자열은 제일 앞부터 정해진 길이만큼 잘라야 합니다.
따라서 주어진 문자열을 x / ababcdcd / ababcdcd 로 자르는 것은 불가능 합니다.
이 경우 어떻게 문자열을 잘라도 압축되지 않으므로 가장 짧은 길이는 17이 됩니다.

 

풀이

 

def solution(s):
    answer = len(s)
   
   #모든 경우의 수 중 가장 짧은 길이
    for i in range(1, len(s)//2+1):	
        answer = min(compress(s, i), answer)
        
    return answer

def compress(s, num):
    comstr = ''
    count = 1
    
    for i in range(0, len(s), num):
    	#같은 문자열 반복하는 경우
        if s[i:i+num] == s[i+num:i+2*num]:
            count += 1
        #다른 문자열이 나오는 경우
        else:
            if count == 1:
                comstr += s[i:i+num]
            else:
                comstr += str(count) + s[i:i+num]
                count = 1
            
    return len(comstr)
테스트 1 〉	통과 (0.04ms, 10.2MB)
테스트 2 〉	통과 (0.46ms, 10.3MB)
테스트 3 〉	통과 (0.35ms, 10.3MB)
테스트 4 〉	통과 (0.05ms, 10.3MB)
테스트 5 〉	통과 (0.00ms, 10.2MB)
테스트 6 〉	통과 (0.05ms, 10.3MB)
테스트 7 〉	통과 (0.78ms, 10.2MB)
테스트 8 〉	통과 (0.61ms, 10.2MB)
테스트 9 〉	통과 (0.88ms, 10.2MB)
테스트 10 〉	통과 (2.88ms, 10.2MB)
테스트 11 〉	통과 (0.11ms, 10.2MB)
테스트 12 〉	통과 (0.11ms, 10.2MB)
테스트 13 〉	통과 (0.20ms, 10.2MB)
테스트 14 〉	통과 (0.97ms, 10.2MB)
테스트 15 〉	통과 (0.22ms, 10.3MB)
테스트 16 〉	통과 (0.02ms, 10.2MB)
테스트 17 〉	통과 (1.40ms, 10.2MB)
테스트 18 〉	통과 (1.35ms, 10.3MB)
테스트 19 〉	통과 (1.35ms, 10.2MB)
테스트 20 〉	통과 (3.76ms, 10.3MB)
테스트 21 〉	통과 (3.23ms, 10.2MB)
테스트 22 〉	통과 (3.24ms, 10.2MB)
테스트 23 〉	통과 (3.10ms, 10.2MB)
테스트 24 〉	통과 (2.94ms, 10.2MB)
테스트 25 〉	통과 (3.21ms, 10.2MB)
테스트 26 〉	통과 (3.20ms, 10.3MB)
테스트 27 〉	통과 (3.17ms, 10.2MB)
테스트 28 〉	통과 (0.02ms, 10.2MB)

 

문자열을 1개 단위로 자르는 경우부터 1씩 증가시켜서 반으로 자르는 경우까지 모든 경우 중 가장 작게 압축되는 케이스를 찾는 과정을 solution 함수에서 수행했다.

 

문자열을 압축하는 과정은 compress라는 함수에서 하는데, 문자열과 함께 문자열을 자르는 단위(num)를 인자로 넘겨주었다. 문자열의 처음부터 끝까지 돌면서 num만큼의 간격으로 앞부분과 뒷부분이 같은지 비교하고 같으면 count를 1만큼 증가시키고 같지 않으면 압축된 문자열을 가리키는 comstr에 반복된 숫자와 문자열을 추가해준다. 이 때, count가 1이라면 숫자를 생략한다. 반복문을 다 돌면 해당 문자열의 길이를 다시 solution에 return해준다.

문제

 

당신은 폰켓몬을 잡기 위한 오랜 여행 끝에, 홍 박사님의 연구실에 도착했습니다. 홍 박사님은 당신에게 자신의 연구실에 있는 총 N 마리의 폰켓몬 중에서 N/2마리를 가져가도 좋다고 했습니다.
홍 박사님 연구실의 폰켓몬은 종류에 따라 번호를 붙여 구분합니다. 따라서 같은 종류의 폰켓몬은 같은 번호를 가지고 있습니다. 예를 들어 연구실에 총 4마리의 폰켓몬이 있고, 각 폰켓몬의 종류 번호가 [3번, 1번, 2번, 3번]이라면 이는 3번 폰켓몬 두 마리, 1번 폰켓몬 한 마리, 2번 폰켓몬 한 마리가 있음을 나타냅니다. 이때, 4마리의 폰켓몬 중 2마리를 고르는 방법은 다음과 같이 6가지가 있습니다.

  1. 첫 번째(3번), 두 번째(1번) 폰켓몬을 선택
  2. 첫 번째(3번), 세 번째(2번) 폰켓몬을 선택
  3. 첫 번째(3번), 네 번째(3번) 폰켓몬을 선택
  4. 두 번째(1번), 세 번째(2번) 폰켓몬을 선택
  5. 두 번째(1번), 네 번째(3번) 폰켓몬을 선택
  6. 세 번째(2번), 네 번째(3번) 폰켓몬을 선택

이때, 첫 번째(3번) 폰켓몬과 네 번째(3번) 폰켓몬을 선택하는 방법은 한 종류(3번 폰켓몬 두 마리)의 폰켓몬만 가질 수 있지만, 다른 방법들은 모두 두 종류의 폰켓몬을 가질 수 있습니다. 따라서 위 예시에서 가질 수 있는 폰켓몬 종류 수의 최댓값은 2가 됩니다.
당신은 최대한 다양한 종류의 폰켓몬을 가지길 원하기 때문에, 최대한 많은 종류의 폰켓몬을 포함해서 N/2마리를 선택하려 합니다. N마리 폰켓몬의 종류 번호가 담긴 배열 nums가 매개변수로 주어질 때, N/2마리의 폰켓몬을 선택하는 방법 중, 가장 많은 종류의 폰켓몬을 선택하는 방법을 찾아, 그때의 폰켓몬 종류 번호의 개수를 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • nums는 폰켓몬의 종류 번호가 담긴 1차원 배열입니다.
  • nums의 길이(N)는 1 이상 10,000 이하의 자연수이며, 항상 짝수로 주어집니다.
  • 폰켓몬의 종류 번호는 1 이상 200,000 이하의 자연수로 나타냅니다.
  • 가장 많은 종류의 폰켓몬을 선택하는 방법이 여러 가지인 경우에도, 선택할 수 있는 폰켓몬 종류 개수의 최댓값 하나만 return 하면 됩니다.

입출력 예

nums result
[3,1,2,3] 2
[3,3,3,2,2,4] 3
[3,3,3,2,2,2,] 2

 

입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

 

입출력 예 #2
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리, 2번 폰켓몬 한 마리, 4번 폰켓몬 한 마리를 고르면 되며, 따라서 3을 return 합니다.

 

입출력 예 #3
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리와 2번 폰켓몬 두 마리를 고르거나, 혹은 3번 폰켓몬 두 마리와 2번 폰켓몬 한 마리를 고르면 됩니다. 따라서 최대 고를 수 있는 폰켓몬 종류의 수는 2입니다.

 

풀이

 

C++

#include <vector>
#include <algorithm>
using namespace std;

int solution(vector<int> nums)
{
    int answer = 0;
    int bring = nums.size()/2; //가지고 갈 수 있는 폰켓몬
    
    sort(nums.begin(), nums.end()); //정렬
    nums.erase(unique(nums.begin(), nums.end()), nums.end()); //중복 제거
    
    return bring > nums.size() ? nums.size() : bring; //작은 것 리턴
}
테스트 1 〉	통과 (0.01ms, 3.81MB)
테스트 2 〉	통과 (0.01ms, 3.99MB)
테스트 3 〉	통과 (0.01ms, 3.99MB)
테스트 4 〉	통과 (0.01ms, 4.34MB)
테스트 5 〉	통과 (0.01ms, 3.99MB)
테스트 6 〉	통과 (0.01ms, 3.81MB)
테스트 7 〉	통과 (0.01ms, 3.76MB)
테스트 8 〉	통과 (0.01ms, 4.35MB)
테스트 9 〉	통과 (0.02ms, 3.66MB)
테스트 10 〉	통과 (0.02ms, 3.69MB)
테스트 11 〉	통과 (0.02ms, 4.34MB)
테스트 12 〉	통과 (0.06ms, 3.97MB)
테스트 13 〉	통과 (0.06ms, 3.75MB)
테스트 14 〉	통과 (0.07ms, 3.99MB)
테스트 15 〉	통과 (0.06ms, 3.75MB)
테스트 16 〉	통과 (0.58ms, 3.99MB)
테스트 17 〉	통과 (0.63ms, 4.02MB)
테스트 18 〉	통과 (0.57ms, 4.02MB)
테스트 19 〉	통과 (0.56ms, 3.95MB)
테스트 20 〉	통과 (0.38ms, 4.08MB)

Python3

def solution(nums):
    return min(len(set(nums)), len(nums)/2);
테스트 1 〉	통과 (0.00ms, 10.1MB)
테스트 2 〉	통과 (0.01ms, 10.2MB)
테스트 3 〉	통과 (0.00ms, 10.2MB)
테스트 4 〉	통과 (0.01ms, 10.2MB)
테스트 5 〉	통과 (0.01ms, 10.1MB)
테스트 6 〉	통과 (0.01ms, 10.2MB)
테스트 7 〉	통과 (0.01ms, 10.2MB)
테스트 8 〉	통과 (0.01ms, 10.1MB)
테스트 9 〉	통과 (0.01ms, 10.2MB)
테스트 10 〉	통과 (0.01ms, 10.2MB)
테스트 11 〉	통과 (0.01ms, 10.3MB)
테스트 12 〉	통과 (0.07ms, 10.2MB)
테스트 13 〉	통과 (0.08ms, 10.3MB)
테스트 14 〉	통과 (0.08ms, 10.4MB)
테스트 15 〉	통과 (0.05ms, 10.3MB)
테스트 16 〉	통과 (0.80ms, 11.1MB)
테스트 17 〉	통과 (0.63ms, 10.6MB)
테스트 18 〉	통과 (0.54ms, 10.7MB)
테스트 19 〉	통과 (0.50ms, 10.3MB)
테스트 20 〉	통과 (0.38ms, 10.4MB)

 

간단하게 가지고 갈 수 있는 폰켓몬 수와 중복을 제거한 폰켓몬 수(폰켓몬의 종류)를 비교해서 더 작은 값을 return 해주면 된다.

 

가지고 갈 수 있는 폰켓몬 수가 폰켓몬의 종류보다 적다면 최대한 많은 폰켓몬을 가지고 가야 하기 때문에 각각 다른 폰켓몬을 가지고 갈 것이므로 N/2마리가 그대로 최댓값이 된다. 반대로 폰켓몬의 종류가 더 적다면 아무리 많이 가져간다고 해도 종류의 수를 넘을 수 없기 때문에 폰켓몬의 종류가 최댓값이 된다.

 

C++에서는 sort, erase, unique 함수를 이용해 중복을 제거한 뒤 삼항 연산자를 이용해서 작은 값을 return했고, Python에서는 중복을 허용하지 않는 set으로 자료형을 바꾼 뒤 길이를 비교하여 작은 값을 return하였다.

문제

임의의 문장을 입력받아 각 단어별로 나눈 후에 단어들의 중복되는 개수를 구하는 프로그램을 작성하시오.

 

<처리조건>
(1) 입력된 스트링은 글자의 제한은 없다. 즉 공백이나 ', ' 등도 입력으로 들어 올 수 있다.
(2) 입력된 문장에서 각 단어사이의 구분은 공백으로 한다.
(3) 단어에는 공백을 제외한 단어들만이 포함된다.

 

입력형식

임의의 문장을 입력받는다.(문장의 길이는 200 이하)

하나의 결과가 나온 후에도 계속 새로운 입력을 받다가, "END"가 입력되면 프로그램을 종료한다. (문장의 개수를 30을 넘지 않는다.)

 

출력형식

 

각 문장 단위로 단어들의 발생 빈도를 오름차순 크기(아스키코드)순으로 출력한다.

 

<코드>

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

typedef struct word{
	char name[100];
	int freq;
}WORD;

typedef struct words{
	int len;
	int capacity;
	WORD *data;
}WORDS;

int compare( const void *n1, const void *n2)
{
	return strcmp((const char *)n1, (const char *)n2);
}

void destroy_words(WORDS *list)
{
	free(list->data);
	list->len = 0;
	list->capacity = 0;

	free(list);
}	

void input(char *name, WORDS *list)
{
	int check = 0;
	
	for(int j=0; j<list->len; j++)
	{
		if(!strcmp(name, list->data[j].name))
		{
			check = 1;
			list -> data[j].freq++;
			break;
		}	
	}
	
	if(!check)
		{
		//full memory
		if(list->capacity == list->len)
		{
			list->data = (WORD*)realloc(list->data, list->capacity * 2 * sizeof(WORD));
			list->capacity *= 2;
		}
		
		strcpy(list->data[list->len].name, name);
		list->data[list->len++].freq = 1;
	}
}

int main()
{
	char arr[200];
	char *ptr;
	
	while(1)
	{
		scanf(" %[^\n]s", arr);
		
		if(!strcmp("END", arr))
			break;
		
		WORDS *list = (WORDS *)malloc(sizeof(WORDS));
	
		list->len = 0;
		list->capacity = 1;
		list->data = (WORD *)malloc(list->capacity*(sizeof(WORD)));
		
		ptr = strtok(arr, " ");

		while (ptr != NULL)
		{
			input(ptr, list);
			ptr = strtok(NULL, " ");
		}
		
		qsort(list->data, list->len, sizeof(WORD), compare);
	
		for(int i=0; i<list->len; i++)
		{
			printf("%s : %d\n", list->data[i].name, list->data[i].freq);
		}
	
		destroy_words(list);
	}
	
	
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1880 : 암호풀기(Message Decowding)  (0) 2020.06.03
2857 : 세로읽기  (0) 2020.06.03
2514 : 문자열 찾기  (0) 2020.06.03
2604 : 그릇  (0) 2020.06.03
3106 : 진법 변환  (0) 2020.06.02

문제

최근 농부 창호에게서 메시지를 암호화(encryption)에 대해서 배운 소들은 너무나 신이 나있다. 

그들은 다른 농장의 소들과 미팅을 할 때 은밀한 메시지를 사용할 경우 이 방법을 사용할 수 있을 것이라고 생각했다. 

소들이 사용하는 암호화 방법은 복잡한 DES 혹은 BlowFish 와 같은 좋은 방법이 아니고 단순히 치환 하는 암호화 기법이다.

소들의 경우 복호화(암호를 해독함)하는 시간이 오래 걸리기 때문에, 

소들과 대화를 할 수 있는 당신에게 복호화 키와 암호 문자를 입력으로 받아 원문을 구하는 프로그램을 구현 해주기를 요청했다.

복호화 키는 26개의 소문자로 주어지며, a,b,c,d... 를 순서대로 복호화 키 문자로 대치한다는 것을 뜻한다.

 

예를 들어, 복호화 키가 "eydbkmiqugjxlvtzpnwohracsf" 와 같이 주어진다고 하자, 

그러면 이는 다음과 같다 - a 문자는 e, b 문자는 y, ..., z 문자는 f로 바꿔 준다.

암호화 된 문자는 대소문자 혹은 공백이 올수 있고 대문자는 대문자로 소문자는 소문자로 치환 규칙에 맞게 출력하고, 공백문자는 그대로 출력한다.

 

입력형식

첫 줄에는 복호화 키가 26개의 소문자로 주어지고, 다음 줄에는 암호화 된 문자가 최대 80 문자로 입력된다.

 

출력형식

암호화 된 문장을 복호화 시켜 원문을 출력한다.

 

<코드>

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

int main()
{
	char key[27];
	char enc[81], dec[81];
	int i;
	
	scanf(" %s %[^\n]s", key, enc);
	
	for(i=0; i<strlen(enc)-1; i++)
	{
		if(enc[i] == ' ')
		{
			dec[i] = ' ';
			continue;
		}
		else if(enc[i]>='A'&&enc[i]<='Z')
			dec[i] = key[enc[i]-'A']-0x20;
		else if(enc[i]>='a'&&enc[i]<='z')
			dec[i] = key[enc[i]-'a'];
	}
	dec[i] = 0;
	
	printf("%s\n", dec);
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1516 : 단어 세기  (0) 2020.06.03
2857 : 세로읽기  (0) 2020.06.03
2514 : 문자열 찾기  (0) 2020.06.03
2604 : 그릇  (0) 2020.06.03
3106 : 진법 변환  (0) 2020.06.02

문제

아직 글을 모르는 영석이가 벽에 걸린 칠판에 자석이 붙어있는 글자들을 붙이는 장난감을 가지고 놀고 있다.

 

이 장난감에 있는 글자들은 영어 대문자 ‘A’부터‘Z’, 영어 소문자 ‘a’부터 ‘z’, 숫자 ‘0’부터 ‘9’이다. 

영석이는 칠판에 글자들을 수평으로 일렬로 붙여서 단어를 만든다. 

다시 그 아래쪽에 글자들을 붙여서 또 다른 단어를 만든다. 

이런 식으로 다섯 개의 단어를 만든다. 

 

아래 그림 1은 영석이가 칠판에 붙여 만든 단어들의 예이다.

 

 

 

한 줄의 단어는 글자들을 빈칸 없이 연속으로 나열해서 최대 15개의 글자들로 이루어진다. 

또한 만들어진 다섯 개의 단어들의 글자 개수는 서로다를 수 있다.

 

심심해진 영석이는 칠판에 만들어진 다섯 개의 단어를 세로로 읽으려 한다. 

세로로 읽을 때, 각 단어의 첫 번째 글자들을 위에서 아래로 세로로 읽는다. 다음에 두 번째 글자들을 세로로 읽는다. 

이런 식으로 왼쪽에서 오른쪽으로 한 자리씩 이동하면서 동일한 자리의 글자들을 세로로 읽어 나간다. 

위의 그림 1의 다섯 번째 자리를 보면 두 번째 줄의 다섯 번째 자리의 글자는 없다. 

이런 경우처럼 세로로 읽을 때 해당 자리의 글자가 없으면, 읽지 않고 그 다음 글자를 계속 읽는다. 

 

그림1의 다섯 번째 자리를 세로로 읽으면 D1gk로 읽는다.

 

그림 1에서 영석이가 세로로 읽은 순서대로 글자들을 공백 없이 출력하면 다음과 같다:
Aa0aPAf985Bz1EhCz2W3D1gkD6x

 

칠판에 붙여진 단어들이 주어질 때, 영석이가 세로로 읽은 순서대로 글자들을 출력하는 프로그램을 작성하시오.

 

 

입력형식

다음 정보가 표준 입력으로 주어진다. 총 다섯줄의 입력이 주어진다.

각 줄에는 최소 1개, 최대15개의 글자들이 빈칸 없이 연속으로 주어진다. 

주어지는 글자는 영어 대문자 ‘A’부터 ‘Z’, 영어소문자 ‘a’부터 ‘z’, 숫자 ‘0’부터 ‘9’ 중 하나이다. 

각 줄의 시작과 마지막에 빈칸은 없다.

 

출력형식

다음 정보를 표준 출력으로 출력한다.

영석이가 세로로 읽은 순서대로 글자들을 출력한다. 

이때, 글자들을 공백 없이 연속해서 출력한다.

 

<코드>

#include <stdio.h>

int main()
{
	char arr[5][16] = {0, };
	int j=0, check;
	
	for(int i=0; i<5; i++)
		scanf("%s", arr[i]);
	
	while(1)
	{
		check = 0;
		for(int i=0; i<5; i++)
		{ 
			if(!arr[i][j])
				continue;
			printf("%c", arr[i][j]);
			check = 1;
		}
		if(!check)
			break;
		j++;
	}
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1516 : 단어 세기  (0) 2020.06.03
1880 : 암호풀기(Message Decowding)  (0) 2020.06.03
2514 : 문자열 찾기  (0) 2020.06.03
2604 : 그릇  (0) 2020.06.03
3106 : 진법 변환  (0) 2020.06.02

문제

주어진 문자열에서 연속 3개의 문자가 IOI 이거나 KOI인 문자열이 각각 몇 개 있는지 찾는 프로그램을 작성하라.

문자열은 알파벳의 대문자로만 이루어진다. 

예를 들어 "KOIOIOI"라는 문자열은 KOI 1개 , IOI 2개가 포함되어있다.

 

 

 

 

 

 

입력형식

입력은 한 줄이며 10,000자 이하의 알파벳 대문자로 구성된다.

 

출력형식

출력은 2줄이며, 첫 번째 줄에는 KOI의 개수, 두 번째 줄에는 IOI의 개수를 각각 출력하라.

 

<코드>

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

int main()
{
	char arr[10000] = {0, };
	int countI=0, countK=0;
	
	scanf("%s", arr);
	
	
	for(int i=0; i<strlen(arr)-2; i++)
	{
		if(arr[i]=='K'&&arr[i+1]=='O'&&arr[i+2]=='I')
			countK++;
		if(arr[i]=='I'&&arr[i+1]=='O'&&arr[i+2]=='I')
			countI++;
		
	}
	
	printf("%d\n%d\n", countK, countI);
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1880 : 암호풀기(Message Decowding)  (0) 2020.06.03
2857 : 세로읽기  (0) 2020.06.03
2604 : 그릇  (0) 2020.06.03
3106 : 진법 변환  (0) 2020.06.02
1534 : 10진수를 2,8,16진수로  (0) 2020.06.02

문제

그릇을 바닥에 놓았을 때 그 높이는 10cm 이다. 

그런데 두 개의 그릇을 같은 방향으로 포개면 그 높이는 5cm만 증가된다. 

만일 그릇이 서로 반대방향으로 쌓이면 높이는 그릇만큼, 즉 10cm 늘어난다. 

그릇을 괄호 기호로 나타내어 설명해보자. 편의상 그릇이 쌓여지는 방향은 왼쪽에서 오른쪽이라고 가정한다. 

그림에서 ‘(’은 그릇이 바닥에 바로 놓인 상태를 나타내며, ‘)’은 그릇이 거꾸로 놓인 상태를 나타낸다.

 

만일 그릇이 포개진 모양이 아래 그림 1(a)와 같다면 전체의 높이는 25cm가 된다. 

왜냐하면 처음 바닥에 있는 그릇의 높이가 10cm이고 

이후 같은 방향으로 3개의 그릇이 포개져 있으므로 늘어난 높이는 5+5+5=15 이기 때문이다. 

그림 1(b)와 같은 경우라면 그 높이는 10*4=40cm가 된다.

 

 


 

여러분은 입력파일에 주어진 모양대로 그릇을 쌓을 때 최종의 전체 그릇 높이를 계산해서 출력해야 한다. 

즉 처음 입력으로 주어진 각 그릇의 방향은 바꿀 수 없다.

 

 

입력형식

입력파일의 첫 줄에는 괄호문자로만 이루어진 문자열이 주어진다.

입력 문자열에서 열린 괄호 ‘(’은 바로 놓인 그릇 닫힌 괄호 ‘)’은 거꾸로 놓인 그릇을 나타난다. 

문자열의 길이는 3이상 50 이하이다.

 

출력형식

여러분은 그릇 방향이 괄호 문자로 표시된 문자열을 읽어서 그 최종의 높이를 정수로 출력해야 한다.

 

 

<코드>

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

int main()
{
	char arr[50] = {0, };
	char before;
	int height = 10;
	
	scanf("%s", arr);
	
	before = arr[0];
	for(int i=1; i<strlen(arr); i++)
	{
		if(arr[i] == '(')
		{
			if(before == '(')
				height += 5;
			else
				height += 10;
		}
		else
		{
			if(before == ')')
				height += 5;
			else
				height += 10;
		}
		
		before = arr[i];
	}
	
	printf("%d\n", height);
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

2857 : 세로읽기  (0) 2020.06.03
2514 : 문자열 찾기  (0) 2020.06.03
3106 : 진법 변환  (0) 2020.06.02
1534 : 10진수를 2,8,16진수로  (0) 2020.06.02
2814 : 이진수  (0) 2020.05.30

문제

A진법 수 N을 입력 받아 B진법 수로 출력하는 프로그램을 작성하시오.

N에 사용되는 값은 0 ~ 9, A ~ Z이다.

(2 <= A, B <= 36) ( 0<= N<= 263-1 )

 

입력형식

입력은 100개 이하의 테스트 케이스가 행으로 구분하여 주어진다.

테스트 케이스의 끝에는 0이 주어진다. 

각 테스트 케이스에는 세 수 A, N, B가 공백으로 구분되어 주어진다.

 

출력형식

각 테스트 케이스에 대하여 A진법수 N을 B진법 수로 변환한 결과를 행으로 구분하여 출력한다.

 

<코드>

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

char convert(int N)
{
	if(N<10)
		return N+0x30;
	else
		return N+0x37;
}

//10진법 -> 2~36진법
void intto(unsigned long long N, int B)
{
	char arr[1000] = {0, };
	int i=0;

	while(1)
	{
		if(N<B)
		{
			arr[i] = convert(N);
			break;
		}

		arr[i] = convert(N%B);
		N /= B;
		i++;
	}
	
	for(; i>=0; i--)
		printf("%c", arr[i]);
	
	printf("\n");
}

int invert(char N)
{
	if('0'<=N && '9'>=N)
		return N-0x30;
	else if('A'<=N && 'Z'>=N)
		return N-0x37;
}

//2~36진법 -> 10진법
unsigned long long toint(char *N, int A)
{
	unsigned long long decimal = 0, tmp;
	int len;
	
	len = strlen(N);
	
	for(int i=len-1; i>=0; i--)
	{
		tmp = invert(N[i]);
		for(int j=0; j<(len-i-1); j++)
			tmp *= A;
		decimal += tmp;
	}
	
	return decimal;
}

int main()
{
	char N[100] = {0, };
	int A, B;
	
	while(1)
	{
		scanf(" %d", &A);
		if(!A)
			break;
		
		scanf("%s %d",N, &B);
		
		intto(toint(N, A), B);
	}
	
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

2514 : 문자열 찾기  (0) 2020.06.03
2604 : 그릇  (0) 2020.06.03
1534 : 10진수를 2,8,16진수로  (0) 2020.06.02
2814 : 이진수  (0) 2020.05.30
2813 : 소수의 개수  (0) 2020.05.29

문제

10진수를 입력 받아서 2, 8, 16진수로 바꾸어 출력하는 프로그램을 작성하시오.

 

입력형식

입력의 첫줄에는 10진수 N(1≤N≤100,000)과 바꿀 진수 B(2, 8, 16)가 공백으로 구분하여 입력된다.

16진수에서 10이상의 수는 순서대로 'A', 'B', 'C', 'D', 'E', 'F'로 나타낸다.

 

출력형식

입력받은 10진수를 B진수로 바꾸어 출력한다.

 

<코드>

#include <stdio.h>

void itob(int N)
{
	int arr[20] = {0, };
	int i=0;
	
	while(1)
	{
		if(N<2)
		{
			arr[i] = N;
			break;
		}
		
		arr[i] = N%2;
		N /= 2;
		i++;	
	}
	
	for(; i>=0; i--)
		printf("%d", arr[i]);
}

void itoo(int N)
{
	int arr[20] = {0, };
	int i=0;
	
	while(1)
	{
		if(N<8)
		{
			arr[i] = N;
			break;
		}

		
		arr[i] = N%8;
		N /= 8;
		i++;
	}
	
	for(; i>=0; i--)
		printf("%d", arr[i]);
}

char convert(int N)
{
	if(N<10)
		return N+0x30;
	else
		return N+0x37;
}

void itoh(int N)
{
	char arr[20] = {0, };
	int i=0;
	
	while(1)
	{
		if(N<16)
		{
			arr[i] = convert(N);
			break;
		}

		arr[i] = convert(N%16);
		N /= 16;
		i++;
	}
	
	for(; i>=0; i--)
		printf("%c", arr[i]);
}

int main()
{
	int N, B;
	
	scanf("%d %d", &N, &B);
	
	switch(B)
	{
		case 2:
			itob(N);
			break;
		case 8:
			itoo(N);
			break;
		case 16:
			itoh(N);
			break;
	}
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

2604 : 그릇  (0) 2020.06.03
3106 : 진법 변환  (0) 2020.06.02
2814 : 이진수  (0) 2020.05.30
2813 : 소수의 개수  (0) 2020.05.29
1901 : 소수 구하기  (0) 2020.05.29

+ Recent posts