W3: 코드업 기초 100제 70번 대 이후 문제들 중 가장 어려웠던 10문제 write-up 작성하기
코드업 기초 (22.05.02 ~ 22.05.08)
코드업 마지막 과제로 71번부터 99번까지 풀어보았다
이번에는 정답률이 낮은 문제가 이전보다 많았고,
기초임에도 while문 탈출 조건을 제대로 고려하지 못해 틀린 문제가 몇몇 있었다
# 1079: [기초-통합] 원하는 문자가 입력될 때까지 반복 출력하기
[문제] 'q'가 입력될 때까지 입력한 문자를 계속 출력하는 프로그램을 작성해보자
[입력]
문자들이 1개씩 계속해서 입력된다.
[출력]
q'가 입력될 때까지 입력된 문자를 줄을 바꿔 한 줄씩 출력한다.
[풀이]
#include<stdio.h>
int main(){
char input;
while(1){
scanf("%c ",&input);
if(input=='q'){
printf("%c",input);
break;
}
else{
printf("%c",input);
printf("\n");
}
}
}
표현 에러로 채점이 되지 않았던 문제
코드업에서 표현 에러는 다음과 같이 3가지 경우라고 한다
표현 에러 : 출력 결과가 정답과 유사하나 공백, 빈 줄과 같은 사소한 문제로 인해 출력 결과가 일치하지 않는 경우입니다.
1. 입출력 예제의 출력을 다시 한번 보시고 공백 처리가 똑같은지 확인하세요.
2. 출력의 마지막에 불필요한 공백이 있는지 없는지 확인하세요.(입출력 예시와 맞출 것)
3. 두 칸이나 두 줄이상 띄운 곳이 있는지 확인하세요.
대표적인 예) printf("Hello, World! \n"); // \n앞에 공백을 준 경우
출력과 관련하여 에러가 많이 나는 것 같아 확인해보았지만 문제를 알 수 없어서
게시판을 조금 봤는데 다른 분들도 표현 에러로 고생을 많이 하신 것 같았다
그러다가 입력 시 %c뒤에 공백 한 칸을 주면 문제가 풀린다는 댓글을 보고 시도해봤는데
바로 채점이 되었다...(?)
다른 문제와 다르게 이 문제에서 공백을 주는 이유는 잘 모르겠지만
표현 에러는 알고리즘 문제 채점 시 중요한 요소가 되는 것은 맞다고 생각해서
앞으로도 잘 확인해야겠다고 느꼈다
# 1080: [기초-통합] 언제까지 더해야 할까?
[문제] 1, 2, 3 ... 을 계속 더해 나갈 때,
그 합이 입력한 정수(0 ~ 1000)보다 같거나 작을 때까지
계속 더하는 프로그램을 작성해보자.
즉, 1부터 n까지 정수를 계속 더한다고 할 때,
어디까지 더해야 입력한 수보다 같거나 커지는지 알아보고자 하는 문제이다.
[입력]
정수 1개가 입력된다.
[출력]
1, 2, 3, 4, 5 ... 를 순서대로 계속 더해 합을 만들어가다가,
입력된 정수와 같거나 커졌을 때, 마지막에 더한 정수를 출력한다.
[풀이]
#include<stdio.h>
int main(){
int a;
int i=0;
int sum=0;
scanf("%d",&a);
while(1){
if(sum>=a){
printf("%d",i);
break;
}
else{
i++;
sum+=i;
}
}
}
처음에는 깊게 생각하지 않고 while안의 else 구문에서 sum에 i를 더하고 그 이후에 i를 증가했는데,
else를 실행하는 과정에서 sum과 같아지거나 커질 경우에 그 당시 i가 업데이트 되는 것이 아닌
실행 이후 i가 하나 더 증가하기 때문에 원하는 출력 값 보다 1큰 숫자가 출력되는 것을 확인할 수 있었다.
따라서 i를 0부터 시작하고 sum에 더하기 전에 i를 증가시켜 실행문의 순서를 바꾸었더니 문제를 해결할 수 있었다
# 1082: [기초-통합] 16진수 구구단?
[문제] 16진수(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F)를 배운
영일(01)이는 16진수끼리 곱하는 16진수 구구단?에 대해서 궁금해졌다.
A, B, C, D, E, F 중 하나가 입력될 때,
1부터 F까지 곱한 16진수 구구단의 내용을 출력해보자.
(단, A ~ F 까지만 입력된다.)
[입력]
16진수로 한 자리 수가 입력된다.
단, A ~ F 까지만 입력된다.
[출력]
입력된 16진수에 1~F까지 순서대로 곱한, 16진수 구구단을 줄을 바꿔 출력한다.
계산 결과도 16진수로 출력해야 한다.
[풀이]
#include<stdio.h>
int main(){
char input;
int a;
scanf("%c", &input);
a = input - 55;
for(int i=1;i<16;i++){
printf("%X*%X=%X\n",a,i,a*i);
}
}
아스키코드로 A는 10진수로 65이며 실제 16진수를 10진수로 생각했을 때 A는 10을 나타낸다.
아스키코드 표를 처음부터 찾아봤다면 쉽게 생각할 수 있었을 텐데
char로 입력받은 숫자를 실제 숫자로 나타내는 식을 작성해 틀렸었다.
(그래도 한 번 틀리게 채점되고 정신차려서 다행이었다 ^^..)
# 1085: [기초-통합] 소리 파일 저장용량 계산하기
[문제] 소리가 컴퓨터에 저장될 때에는 디지털 데이터화 되어 저장된다.
마이크를 통해 1초에 적게는 수십 번, 많게는 수만 번 소리의 강약을 체크해
그 값을 정수값으로 바꾸고, 그 값을 저장해 소리를 파일로 저장할 수 있다.
값을 저장할 때에는 비트를 사용하는 정도에 따라 세세한 녹음 정도를 결정할 수 있고,
좌우(스테레오) 채널로 저장하면 2배… 5.1채널이면 6배의 저장공간이 필요하고,
녹음 시간이 길면 그 만큼 더 많은 저장공간이 필요하다.
1초 동안 마이크로 소리강약을 체크하는 수를 h
(헤르쯔, Hz 는 1초에 몇 번? 체크하는가를 의미한다.)
한 번 체크한 결과를 저장하는 비트 b
(2비트를 사용하면 0 또는 1 두 가지, 16비트를 사용하면 65536가지..)
좌우 등 소리를 저장할 트랙 개수인 채널 c
(모노는 1개, 스테레오는 2개의 트랙으로 저장함을 의미한다.)
녹음할 시간 s가 주어질 때,
필요한 저장 용량을 계산하는 프로그램을 작성해보자.
실제로 일반적인 CD 음질(44.1KHz, 16bit, 스테레오)로 1초 동안 저장하려면
44100 * 16 * 2 * 1 bit의 저장공간이 필요하다.
이렇게 녹음하는 방식을 PCM(Pulse Code Modulation) 방법이라고 하는데,
압축하지 않은 순수한(raw) 소리 데이터 파일은 대표적으로 *.wav 가 있다.
**
8 bit(비트) = 1byte(바이트) // 8bit=1Byte
1024 Byte(210 byte) = 1KB(킬로 바이트) // 1024bit=1KB
1024 KB(210 KB) = 1MB(메가 바이트)
1024 MB(210 MB) = 1GB(기가 바이트)
1024 GB(210 GB) = 1TB(테라 바이트)
[입력]
h, b, c, s 가 공백을 두고 입력된다.
h는 48,000이하, b는 32이하(단, 8의배수), c는 5이하, s는 6,000이하의 자연수이다.
[출력]
필요한 저장 공간을 MB 단위로 바꾸어 출력한다.
단, 소수점 둘째 자리에서 반올림해 첫째 자리까지 출력하고 MB를 공백을 두고 출력한다.
[풀이]
#include<stdio.h>
int main(){
long long h,b,c,s;
scanf("%lld %lld %lld %lld",&h,&b,&c,&s);
printf("%.1lf MB",((double)h*b*c*s/8)/1024/1024);
}
첫 풀이 시 계산 결과의 리턴 값을 생각하지 않고 lf 포맷으로 출력하려 시도해서 틀렸었다
계산 과정에 하나라도 double형으로 변환해준다면 계산 결과도 double이 되는 것을 알고
위와 같이 풀이를 수정하여 문제를 해결할 수 있었다
# 1090: [기초-종합] 수 나열하기2
[문제] 어떤 규칙에 따라 수를 순서대로 나열한 것을 수열이라고 한다.
예를 들어
2 6 18 54 162 486 ... 은
2부터 시작해 이전에 만든 수에 3을 곱해 다음 수를 만든 수열이다.
이러한 것을 수학에서는 앞뒤 수들의 비율이 같다고 하여
등비(비율이 같다의 한문 말) 수열이라고 한다.
등비 수열을 알게된 영일이는 갑자기 궁금해졌다.
"그럼.... 13번째 나오는 수는 뭘까?"
영일이는 프로그램을 만들어 더 큰 수도 자동으로 계산하고 싶어졌다.
시작 값(a), 등비(r), 몇 번째인지를 나타내는 정수(n)가 입력될 때
n번째 수를 출력하는 프로그램을 만들어보자.
[입력]
시작 값(a), 등비의 값(r), 몇 번째 인지를 나타내는 정수(n)가
공백을 두고 입력된다.(모두 0 ~ 10)
[출력]
n번째 수를 출력한다.
[풀이]
#include<stdio.h>
#include<math.h>
int main(){
long long a, r, n;
scanf("%lld %lld %lld",&a,&r,&n);
printf("%.0lf",n==1?(double)a:a*pow((double)r,(double)(n-1)));
}
문제 풀이 시 등비수열의 개념보다는 pow 함수에 전달되는 인자와 리턴 값에 대해 알고 있어야 했던 문제였다.
함수의 리턴되는 형식과 출력 포맷 형식이 맞지 않아 출력이 되지 않았다는 것을 알 수 있었고,
pow 계산 과정에서 이해할 수 없는 숫자들이 계산되었는데 이는 인자의 형식이 맞지 않아서 발생한 문제라고 생각했다.
double pow(double x, double y);
# 1091: [기초-종합] 수 나열하기3
[문제] 어떤 규칙에 따라 수를 순서대로 나열한 것을 수열이라고 한다.
예를 들어
1 -1 3 -5 11 -21 43 ... 은
1부터 시작해 이전에 만든 수에 -2를 곱한 다음 1을 더해 다음 수를 만든 수열이다.
이런 이상한 수열을 알게 된 영일이는 또 궁금해졌다.
"그럼.... 13번째 나오는 수는 뭘까?"
영일이는 물론 수학을 아주 잘하지만 이런 문제는 본 적이 거의 없었다...
그래서 프로그램을 만들어 더 큰 수도 자동으로 계산하고 싶어졌다.
시작 값(a), 곱할 값(m), 더할 값(d), 몇 번째인지를 나타내는 정수(n)가 입력될 때,
n번째 수를 출력하는 프로그램을 만들어보자.
[입력]
1 -2 1 8
[출력]
-85
[풀이]
#include<stdio.h>
int main(){
int a, m, d, n;
scanf("%d %d %d %d",&a,&m,&d,&n);
int i=2;
long long sum=a;
if(n==1){
printf("%d",a);
}
else{
while(i<=n){
sum = sum*m+d;
i++;
}
printf("%lld",sum);
}
}
조금 바보같이 접근하려 했던 문제라서 뽑은 문제이다
개인적으로 점화식을 공부하지 않는 교육과정을 지내와서 등차수열, 등비수열이 아니면 점화식을 사용한다는 것이 아직 머리에 남아있었다
문제를 보고 어... 점화식으로 푸는 문제인가?라고 생각해 급하게 점화식을 찾아봤지만 규칙에 맞게 수를 나열하던 중
그냥 내가 계산하는 것을 단순하게 명령문으로 구현하면 된다는 생각이 들었고 그 이후 바로 풀 수 있었던 문제였다^^,,
가끔 쉬운 문제를 어렵게 접근할 때가 종종있는데 이 문제가 그랬던 문제였던 것 같다
# 1094: [기초-1차원배열] 이상한 출석 번호 부르기2
[문제] 정보 선생님은 수업을 시작하기 전에 이상한 출석을 부른다.
학생들의 얼굴과 이름을 빨리 익히기 위해 번호를 무작위(랜덤)으로 부르는데,
영일이는 선생님이 부른 번호들을 기억하고 있다가 거꾸로 불러보는 것을 해보고 싶어졌다.
출석 번호를 n번 무작위로 불렀을 때, 부른 번호를 거꾸로 출력해 보자.
[입력]
번호를 부른 횟수(n, 1 ~ 10000)가 첫 줄에 입력된다.
n개의 랜덤 번호(k, 1 ~ 23)가 두 번째 줄에 공백을 사이에 두고 순서대로 입력된다.
[출력]
출석을 부른 번호 순서를 바꾸어 공백을 두고 출력한다.
[풀이]
#include<stdio.h>
int main(){
int n=0;
int num[10001];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
for(int j=n-1;j>=0;j--)
printf("%d ",num[j]);
}
출력 for문에서 j가 0과 같은 인덱스의 숫자를 출력하지 않아서 틀렸던 문제이다
(당연한 사실인데 습관에 밴 코드 작성...이 문제인 것 같다 0으로 초기화하고 크기보다 작을 때까지 반복하고 이런 패턴에 익숙해져서..?)
# 1097: [기초-2차원배열] 바둑알 십자 뒤집기
[문제] 부모님을 기다리던 영일이는 검정/흰 색 바둑알을 바둑판에 꽉 채워 깔아 놓고 놀다가...
"십(+)자 뒤집기를 해볼까?"하고 생각했다.
바둑판(19 * 19)에 흰 돌(1) 또는 검정 돌(0)이 모두 꽉 채워져 놓여있을 때,
n개의 좌표를 입력받아 십(+)자 뒤집기한 결과를 출력하는 프로그램을 작성해보자.
참고
가로 번호, 세로 번호를 사용할 수 있는 2차원 배열을 사용하면
이러한 형태를 쉽게 기록하고 사용할 수 있다. 물론 더 확장한 n차원 배열도 만들 수 있다.
[입력]
바둑알이 깔려 있는 상황이 19 * 19 크기의 정수값으로 입력된다.
십자 뒤집기 횟수(n)가 입력된다.
십자 뒤집기 좌표가 횟수(n) 만큼 입력된다. 단, n은 10이하의 자연수이다.
[출력]
십자 뒤집기 결과를 출력한다.
[풀이]
#include<stdio.h>
int main(){
int n, i, j, x, y;
int a[20][20]={};
for(i=1; i<=19; i++)
for(j=1; j<=19; j++)
scanf("%d", &a[i][j]);
scanf("%d", &n);
for(i=1; i<=n; i++)
{
scanf("%d %d", &x, &y);
for(j=1; j<=19; j++)
{
if(a[x][j]==0) a[x][j]=1;
else a[x][j] = 0;
}
for(j=1; j<=19; j++)
{
if(a[j][y]==0) a[j][y]=1;
else a[j][y] = 0;
}
}
for(i=1; i<=19; i++){
for(j=1; j<=19; j++)
printf("%d ", a[i][j]);
printf("\n");
}
}
이 문제는 틀려서 뽑았기 보다 아무 생각 없이 위치 값을 인덱스 값으로 생각하고 풀었는데 조금이나마 저장 공간을 줄이기 위해
배열 크기를 19*19로 선언하고 각 인덱스를 입력받는 위치의 인덱스 -1로 계산하여 표현할 수 있지 않을까 생각한 문제이다
(실제로 이 이후에 나오는 2차원 배열 문제들은 그렇게 풀어보았다)
# 1098: [기초-2차원 배열] 설탕과자 뽑기
[문제] 부모님과 함께 유원지에 놀러간 영일이는
설탕과자(설탕을 녹여 물고기 등의 모양을 만든 것) 뽑기를 보게 되었다.
길이가 다른 몇 개의 막대를 바둑판과 같은 격자판에 놓는데,
막대에 있는 설탕과자 이름 아래에 있는 번호를 뽑으면 설탕과자를 가져가는 게임이었다.
(잉어, 붕어, 용 등 여러 가지가 적혀있다.)
격자판의 세로(h), 가로(w), 막대의 개수(n), 각 막대의 길이(l),
막대를 놓는 방향(d:가로는 0, 세로는 1)과
막대를 놓는 막대의 가장 왼쪽 또는 위쪽의 위치(x, y)가 주어질 때,
격자판을 채운 막대의 모양을 출력하는 프로그램을 만들어보자.
[입력]
첫 줄에 격자판의 세로(h), 가로(w) 가 공백을 두고 입력되고,
두 번째 줄에 놓을 수 있는 막대의 개수(n)
세 번째 줄부터 각 막대의 길이(l), 방향(d), 좌표(x, y)가 입력된다.
입력값의 정의역은 다음과 같다.
1 <= w, h <= 100
1 <= n <= 10
d = 0 or 1
1 <= x <= 100-h
1 <= y <= 100-w
[출력]
모든 막대를 놓은 격자판의 상태를 출력한다.
막대에 의해 가려진 경우 1, 아닌 경우 0으로 출력한다.
단, 각 숫자는 공백으로 구분하여 출력한다.
[풀이]
#include<stdio.h>
int main(){
int h,w,n,l,d,x,y,i,j;
int location[100][100]={};
scanf("%d %d",&h, &w);
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d %d %d %d",&l,&d,&x,&y);
if(d==0){
for(j=0;j<l;j++){
location[x-1][y+j-1]=1;
}
}
else{
for(j=0;j<l;j++){
location[x+j-1][y-1]=1;
}
}
}
for(i=0;i<h;i++){
for(j=0;j<w;j++){
printf("%d ",location[i][j]);
}
printf("\n");
}
}
1097번에서 생각한 내용을 토대로 인덱스-1을 사용하여 주어진 크기만큼의 배열을 만들어 해결하려고 노력한 문제였다
# 1099: [기초-2차원 배열] 성실한 개미
[문제] 영일이는 생명과학에 관심이 생겨 왕개미를 연구하고 있었다.
왕개미를 유심히 살펴보던 중 특별히 성실해 보이는 개미가 있었는데,
그 개미는 개미굴에서 나와 먹이까지 가장 빠른 길로 이동하는 것이었다.
개미는 오른쪽으로 움직이다가 벽을 만나면 아래쪽으로 움직여 가장 빠른 길로 움직였다.
(오른쪽에 길이 나타나면 다시 오른쪽으로 움직인다.)
이에 호기심이 생긴 영일이는 그 개미를 미로 상자에 넣고 살펴보기 시작하였다.
미로 상자에 넣은 개미는 먹이를 찾았거나, 더 이상 움직일 수 없을 때까지
오른쪽 또는 아래쪽으로만 움직였다.
미로 상자의 구조가 0(갈 수 있는 곳), 1(벽 또는 장애물)로 주어지고,
먹이가 2로 주어질 때, 성실한 개미의 이동 경로를 예상해보자.
단, 맨 아래의 가장 오른쪽에 도착한 경우, 더 이상 움직일 수 없는 경우, 먹이를 찾은 경우에는
더이상 이동하지 않고 그 곳에 머무른다고 가정한다.
미로 상자의 테두리는 모두 벽으로 되어 있으며,
개미집은 반드시 (2, 2)에 존재하기 때문에 개미는 (2, 2)에서 출발한다.
[입력]
10*10 크기의 미로 상자의 구조와 먹이의 위치가 입력된다.
[출력]
성실한 개미가 이동한 경로를 9로 표시해 출력한다.
[풀이]
#include<stdio.h>
int main(){
int map[10][10]={};
int i,j;
for(i=0;i<10;i++){
for(j=0;j<10;j++){
scanf("%d",&map[i][j]);
}
}
i=1;j=1;
while(1){
if(i==9&&j==9) {
map[i][j] = 9;
break;
}
else if(map[i+1][j]==1&&map[i][j+1]==1){
map[i][j]=9;
break;
}
else if(map[i][j]==2){
map[i][j]=9;
break;
}
else if(map[i][j+1]==0||map[i][j+1]==2){
map[i][j]=9;
j++;
}
else if(map[i+1][j]==0||map[i+1][j]==2){
map[i][j]=9;
i++;
}
}
for(i=0;i<10;i++){
for(j=0;j<10;j++){
printf("%d ",map[i][j]);
}
printf("\n");
}
}
오른쪽이나 아래쪽에 먹이가 있는 위치일 때 움직이는 코드를 작성하지 않아 무한루프에 빠졌던 문제였다
내가 짠 코드를 바탕으로 그림을 그리고 개미를 움직이면서 문제점을 찾을 수 있었다 ^^,,
(새로 코드를 추가하지 않고 else if에서 위/아래가 2인 경우를 OR를 사용해 조건으로 추가해 주었다)
'etc... > 빡공팟(P4C) 4기' 카테고리의 다른 글
[P4C] W7: 올드 스쿨 취약점과 올드 스쿨 공격 기법 공부하기 (0) | 2022.06.05 |
---|---|
[P4C] W6: Double Linked List CRUD 구현, 어셈블리로 구구단 구현, Stack 개념 공부하기 (0) | 2022.05.29 |
[P4C] W4-W5: C언어로 HTTP 서버 구현 (0) | 2022.05.21 |
[P4C] W2: 코드업 기초 100제 70번 이하 문제들 중 가장 어려웠던 5문제 write-up 작성하기 (0) | 2022.04.29 |
[P4C] W1: 코드업 기초 100제 20번~30번대 문제들 중 가장 어려웠던 5문제 write-up 작성하기 (0) | 2022.04.23 |