- 2일차 기초 코드 작성 요령 (함수 인자,코드 작성 팁)
해당 포스터는 파킹독님의 유튜브를 보고 작성되는 점 참고해주세요.
https://www.youtube.com/watch?v=6lhVHP8bkPA
함수 인자
다음 두 코드를 보고 차이점을 한 번 생각해보자.
void func(int a){
a++;
}
main(){
int a=1;
func(a);
printf("%d",a);
}
void func(int a[]){
a[0]++;
}
main(){
int a[3]={1,2,3};
func(a);
printf("%d",a[0]);
}
이 둘의 코드를 보고 차이점을 명확하게 설명할 수 있는가?
Yes라고 대답했다면 당신은 평소에 c언어에 대해 잘 이해하고 있다고 할 수 있다.
이 둘의 코드의 차이점은 함수의 매개변수가 call by value의 형태로 넘어가는지, call by address의 형태로 넘어가는지의 차이이다.
(포인터의 주소도 call by value이지만 여기서는 call by address라고 설명하겠다.)
즉, 둘의 결과 값을 비교했을 때 위의 코드는 1의 출력값이 나오고 아래는 2라고 나오게 된다.
위에서 main부분에서 a의 값을 매개변수로 넣어주고 호출을 하면 call by value로 값을 복사해서 넘어가게 된다.
main부분의 a값에는 전혀 변동 사항이 없다는 것이다.
하지만, 아래 코드 같은 경우 배열을 매개변수로 넣어주고 호출했기에 call by address,즉 주소를 넘겨 주게된 것이고 main 부분의 a의 0번째 값이 변동되는 것이다.
자신이 지금 넘겨주려는 형태가 call by value 인지, call by address인지 잘 생각해서 매개변수로 넘겨주자.
코드 작성 꿀팁
이번에는 코드 작성 꿀팁에 대해서 한 번 얘기해보겠다.
우리는 코딩 테스트를 보는 것이지. 실무 작업을 하는 것이 아니다.
즉, 내가 하고 싶은 말은 남들에게 보여주려고 코드를 깔끔하게 짜려고 노력하지 않아도 된다는 것이다.
자신이 코드를 짤 때는 해당하는 문제가 통과하는 범위 내에서 더럽게 짜든 깔끔하게 짜든 상관없이 그냥 문제가 통과하기만 하면 되는 것이다.
그럼 코드 작성에는 어떤 꿀팁이 있는지 한 번 살펴보자.
- 최대한 간결하게 표현할 수 있는 부분은 간결하게 표현해보자.
이게 어떤 의미이냐면 예를 들어서 아래코드를 살펴보자
main(){
int a=10,n=10;
int arr[10];
for(int i=0;i<n;i++){
int t;
scanf("%d",&t);
arr[i]=t;
}
int result[10],cnt=0;;
for(int j=0;j<n;j++){
if(arr[j]>=a){
cnt++;
result[j]=arr[j];
}
}
for(int i=0;i<cnt;i++){
printf("%d ",result[i]);
}
}
main(){
int a=10,n=10;
for(int i=0;i<n;i++){
int t;scanf("%d",&t);
if(t>=a)printf("%d ",t);
}
}
우리가 n번 입력을 받는데, a보다 크거나 같은 수를 출력하는 문제를 만났다고 해보자.
그러면 위처럼 작성할 수 있다.
1. 일단 내가 입력받은 수를 배열에 모두 저장한다.
2. 저장한 값을 돌면서 a를 넘은 수를 확인한다.
3. 확인한 값들을 출력해준다.
이렇게 했을 때 이점은 무엇일까?
코드의 진행이 깔끔하고 남들이 봤을 때 어떤 의미로 쓰였는지 잘 파악할 수 있다.
하지만 코딩테스트는 이렇게 하는 것도 맞지만 자신이 알아볼 수 있다면 ok이다.
아래의 코드를 보면 입력받은 값을 굳이 배열에 저장하지 않고 입력받음과 동시에 바로 if문으로 판단을 하며 출력하고 있다.
이렇게 하면 쓸떼없는 메모리를 더 사용하지 않고 빠르게 정답을 구해낼 수 있다.
(feat. 사실 코드를 작성할 때는 깔끔하고 간결하지만 가독성있게 코드를 작성하는 것이 제일 좋다고 생각한다. 남들이 봤을 때 깔끔하다고 느껴져야 된다고 생각함. 숏코딩은 ..)
(2023/06/20) 문제 풀이 추가 내용
문제 : https://github.com/encrypted-def/basic-algo-lecture/blob/master/workbook/0x02.md
GitHub - encrypted-def/basic-algo-lecture: 바킹독의 실전 알고리즘 강의 자료
바킹독의 실전 알고리즘 강의 자료. Contribute to encrypted-def/basic-algo-lecture development by creating an account on GitHub.
github.com
문제풀이
https://www.acmicpc.net/problem/10871
10871번: X보다 작은 수
첫째 줄에 N과 X가 주어진다. (1 ≤ N, X ≤ 10,000) 둘째 줄에 수열 A를 이루는 정수 N개가 주어진다. 주어지는 정수는 모두 1보다 크거나 같고, 10,000보다 작거나 같은 정수이다.
www.acmicpc.net
#include <stdio.h>
int n,x,t;
main(){scanf("%d %d",&n,&x);
for(int i=0;i<n;i++){
scanf("%d",&t);
if(t<x)printf("%d ",t);
}
}
https://www.acmicpc.net/problem/1000
1000번: A+B
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
www.acmicpc.net
a,b입력받고 더해서 출력하면 된다.
#include <stdio.h>
int a,b;
main(){
scanf("%d %d",&a,&b);
printf("%d",a+b);
}
https://www.acmicpc.net/problem/2557
2557번: Hello World
Hello World!를 출력하시오.
www.acmicpc.net
#include<stdio.h>
main(){
printf("Hello World!");
}
https://www.acmicpc.net/problem/10171
10171번: 고양이
아래 예제와 같이 고양이를 출력하시오.
www.acmicpc.net
#include <stdio.h>
main(){
printf("\\ /\\\n");
printf(" ) ( ')\n");
printf("( / )\n");
printf(" \\(__)|");
}
https://www.acmicpc.net/problem/10869
10869번: 사칙연산
두 자연수 A와 B가 주어진다. 이때, A+B, A-B, A*B, A/B(몫), A%B(나머지)를 출력하는 프로그램을 작성하시오.
www.acmicpc.net
#include <stdio.h>
int a,b;
main(){
scanf("%d %d",&a,&b);
printf("%d\n%d\n%d\n%d\n%d",a+b,a-b,a*b,a/b,a%b);
}
https://www.acmicpc.net/problem/9498
9498번: 시험 성적
시험 점수를 입력받아 90 ~ 100점은 A, 80 ~ 89점은 B, 70 ~ 79점은 C, 60 ~ 69점은 D, 나머지 점수는 F를 출력하는 프로그램을 작성하시오.
www.acmicpc.net
#include <stdio.h>
int a;
main(){scanf("%d",&a);
if(a>=90)printf("A");
else if(a>=80)printf("B");
else if(a>=70)printf("C");
else if(a>=60)printf("D");
else printf("F");
}
https://www.acmicpc.net/problem/2752
2752번: 세수정렬
숫자 세 개가 주어진다. 이 숫자는 1보다 크거나 같고, 1,000,000보다 작거나 같다. 이 숫자는 모두 다르다.
www.acmicpc.net
#include <stdio.h>
#define swap(a,b) int t; t=a,a=b,b=t;
int a,b,c;
main(){scanf("%d %d %d",&a,&b,&c);
if(a>b){
swap(a,b);
}
if(a>c){
swap(a,c);
}
if(b>c){
swap(b,c);
}
printf("%d %d %d",a,b,c);
}
https://www.acmicpc.net/problem/2753
2753번: 윤년
연도가 주어졌을 때, 윤년이면 1, 아니면 0을 출력하는 프로그램을 작성하시오. 윤년은 연도가 4의 배수이면서, 100의 배수가 아닐 때 또는 400의 배수일 때이다. 예를 들어, 2012년은 4의 배수이면서
www.acmicpc.net
#include <stdio.h>
int a;
main(){
scanf("%d",&a);
printf("%d",(a%400==0|| (a%4==0 && a%100!=0)));
}
https://www.acmicpc.net/problem/2480
2480번: 주사위 세개
1에서부터 6까지의 눈을 가진 3개의 주사위를 던져서 다음과 같은 규칙에 따라 상금을 받는 게임이 있다. 같은 눈이 3개가 나오면 10,000원+(같은 눈)×1,000원의 상금을 받게 된다. 같은 눈이 2개
www.acmicpc.net
#include <stdio.h>
#define max(a,b) (a>b?a:b)
int a,b,c;
main(){
scanf("%d %d %d",&a,&b,&c);
if(a==b && b==c){
printf("%d",10000+a*1000);
}
else if(a!=b && b!=c && a!=c){
printf("%d",max(max(a,b),c)*100);
}else if(a==b || a==c){
printf("%d",1000+a*100);
}else if(b==c){
printf("%d",1000+b*100);
}
}
https://www.acmicpc.net/problem/2490
2490번: 윷놀이
우리나라 고유의 윷놀이는 네 개의 윷짝을 던져서 배(0)와 등(1)이 나오는 숫자를 세어 도, 개, 걸, 윷, 모를 결정한다. 네 개 윷짝을 던져서 나온 각 윷짝의 배 혹은 등 정보가 주어질 때 도(배 한
www.acmicpc.net
#include <stdio.h>
int a,b,c,d;
main(){
for(int i=0;i<3;i++){
scanf("%d %d %d %d",&a,&b,&c,&d)
printf("%c\n","DCBAE"[a+b+c+d]);
}
}
https://www.acmicpc.net/problem/2576
2576번: 홀수
7개의 자연수가 주어질 때, 이들 중 홀수인 자연수들을 모두 골라 그 합을 구하고, 고른 홀수들 중 최솟값을 찾는 프로그램을 작성하시오. 예를 들어, 7개의 자연수 12, 77, 38, 41, 53, 92, 85가 주어지
www.acmicpc.net
#include <stdio.h>
#define min(a,b)(a>b?b:a)
int a=100,h;
main(){
for(int i=0,t=0;i<7;i++){
scanf("%d",&t);
if(t&1){
a=min(a,t);
h+=t;
}
}
if(!h)printf("-1");
else printf("%d\n%d",h,a);
}
https://www.acmicpc.net/problem/2587
2587번: 대표값2
어떤 수들이 있을 때, 그 수들을 대표하는 값으로 가장 흔하게 쓰이는 것은 평균이다. 평균은 주어진 모든 수의 합을 수의 개수로 나눈 것이다. 예를 들어 10, 40, 30, 60, 30의 평균은 (10 + 40 + 30 + 60 +
www.acmicpc.net
수를 배열로 입력받고 sort한 뒤에 3번째 출력해주면 된다.
#include <stdio.h>
#include <stdlib.h>
int cmp(void *a,void *b){
return *(int*)a>*(int*)b;
}
int a[5],h;
main(){
for(int i=0;i<5;i++){
scanf("%d",&a[i]);
h+=a[i];
}
qsort(a,5,4,cmp);
printf("%d\n%d",h/5,a[2]);
}
https://www.acmicpc.net/problem/2309
2309번: 일곱 난쟁이
아홉 개의 줄에 걸쳐 난쟁이들의 키가 주어진다. 주어지는 키는 100을 넘지 않는 자연수이며, 아홉 난쟁이의 키는 모두 다르며, 가능한 정답이 여러 가지인 경우에는 아무거나 출력한다.
www.acmicpc.net
입력받은 난쟁이들 오름차순 정렬 후 2개를 골라서 다더한 것에 -100을 뺀 것과 같은지 판별해서 정답 출력해주면 된다.
#include <stdio.h>
#include <stdlib.h>
int cmp(void *a,void *b){
return *(int*)a-*(int*)b;
}
int a[9],h;
int main(){
for(int i=0;i<9;i++){
scanf("%d",&a[i]);
h+=a[i];
}
qsort(a,9,4,cmp);
for(int i=0;i<8;i++){
for(int j=i+1;j<9;j++){
if(a[i]+a[j]==h-100){
for(int z=0;z<9;z++){
if(z==i || z==j)continue;
printf("%d\n",a[z]);
}
return 0;
}
}
}
}
https://www.acmicpc.net/problem/10093
10093번: 숫자
두 양의 정수가 주어졌을 때, 두 수 사이에 있는 정수를 모두 출력하는 프로그램을 작성하시오.
www.acmicpc.net
값이 최대 10^15까지 들어올 수 있으니 long long으로 받아야 하며, a와 b중 누가 더 큰지 모른다.
그렇기 때문에 b가 무조건 큰 걸로 바꾸면 된다.
#include <stdio.h>
#define max(a,b)(a>b?a:b)
#define ll long long
ll a,b;
main(){scanf("%lld %lld",&a,&b);
if(a>b){
ll t=a;
a=b,b=t;
}
printf("%lld\n",max(b-a-1,0));
for(long long i=a+1;i<b;i++)printf("%lld ",i);
}
https://www.acmicpc.net/problem/1267
1267번: 핸드폰 요금
동호가 저번 달에 이용한 통화의 개수 N이 주어진다. N은 20보다 작거나 같은 자연수이다. 둘째 줄에 통화 시간 N개가 주어진다. 통화 시간은 10,000보다 작거나 같은 자연수이다.
www.acmicpc.net
#include <stdio.h>
int n,a,b;
main(){
scanf("%d",&n);
for(int i=0,t;i<n;i++){
scanf("%d",&t);
a+=(t/30+1)*10;
b+=(t/60+1)*15;
}
if(a>b)printf("M %d",b);
else if(b>a)printf("Y %d",a);
else printf("Y M %d",a);
}
https://www.acmicpc.net/problem/10804
10804번: 카드 역배치
1부터 20까지 오름차순으로 놓인 카드들에 대해, 입력으로 주어진 10개의 구간 순서대로 뒤집는 작업을 했을 때 마지막 카드들의 배치를 한 줄에 출력한다.
www.acmicpc.net
#include <stdio.h>
#define swap(a,b,t) (t=a,a=b,b=t)
int arr[21];
void reverse(int x,int y){
for(int i=0,t;i<=(y-x)/2;i++){
swap(arr[x+i],arr[y-i],t);
}
}
main(){
for(int i=1;i<=20;i++)arr[i]=i;
for(int i=0,a,b;i<10;i++){
scanf("%d %d",&a,&b);
reverse(a,b);
}
for(int i=1;i<=20;i++)printf("%d ",arr[i]);
}
https://www.acmicpc.net/problem/15552
15552번: 빠른 A+B
첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.
www.acmicpc.net
c언어는 scanf, printf가 이미 충분히 빠르기에 그냥 사용하면 된다.
#include <stdio.h>
int t,a,b;
main(){
scanf("%d",&t);
while(t--){
scanf("%d %d",&a,&b)
printf("%d\n",a+b);
}
}
https://www.acmicpc.net/problem/2438
2438번: 별 찍기 - 1
첫째 줄에는 별 1개, 둘째 줄에는 별 2개, N번째 줄에는 별 N개를 찍는 문제
www.acmicpc.net
별찍기는 굉장히 어렵다... ㅎ
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2439
2439번: 별 찍기 - 2
첫째 줄에는 별 1개, 둘째 줄에는 별 2개, N번째 줄에는 별 N개를 찍는 문제 하지만, 오른쪽을 기준으로 정렬한 별(예제 참고)을 출력하시오.
www.acmicpc.net
1번에서 약간 응용하면 된다.
별을 출력하기 전 공백을 출력하면 된다.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int z=0;z<n-i-1;z++)printf(" ");
for(int j=0;j<=i;j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2440
2440번: 별 찍기 - 3
첫째 줄에는 별 N개, 둘째 줄에는 별 N-1개, ..., N번째 줄에는 별 1개를 찍는 문제
www.acmicpc.net
별 찍기 1에서 약간 응용하면 된다.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int z=0;z<n-i;z++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2441
2441번: 별 찍기 - 4
첫째 줄에는 별 N개, 둘째 줄에는 별 N-1개, ..., N번째 줄에는 별 1개를 찍는 문제 하지만, 오른쪽을 기준으로 정렬한 별(예제 참고)을 출력하시오.
www.acmicpc.net
3번에서 응용하면 된다.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int j=0;j<i;j++)printf(" ");
for(int z=0;z<n-i;z++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2442
2442번: 별 찍기 - 5
첫째 줄에는 별 1개, 둘째 줄에는 별 3개, ..., N번째 줄에는 별 2×N-1개를 찍는 문제 별은 가운데를 기준으로 대칭이어야 한다.
www.acmicpc.net
별이 찍히는 것의 규칙을 보면 1,3,5,7,9 이런식으로 찍게 된다.
행*2-1개씩 찍히는 것이다.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int z=0;z<n-i-1;z++)printf(" ");
for(int j=0;j<(i+1)*2-1;j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2443
2443번: 별 찍기 - 6
첫째 줄에는 별 2×N-1개, 둘째 줄에는 별 2×N-3개, ..., N번째 줄에는 별 1개를 찍는 문제 별은 가운데를 기준으로 대칭이어야 한다.
www.acmicpc.net
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int z=0;z<i;z++)printf(" ");
for(int j=0;j<(n-i)*2-1;j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2444
2444번: 별 찍기 - 7
첫째 줄부터 2×N-1번째 줄까지 차례대로 별을 출력한다.
www.acmicpc.net
위 아래를 분리해서 아래는 6번과 동일하게 놔두고, 윗 부분만 아랫부분을 역으로 만들면 된다.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n-1;i++){
for(int z=0;z<(n-i-1);z++)printf(" ");
for(int j=0;j<(i+1)*2-1;j++)printf("*");
printf("\n");
}
for(int i=0;i<n;i++){
for(int z=0;z<i;z++)printf(" ");
for(int j=0;j<(n-i)*2-1;j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2445
2445번: 별 찍기 - 8
첫째 줄부터 2×N-1번째 줄까지 차례대로 별을 출력한다.
www.acmicpc.net
열을 기준으로 가운데에서 절반 쪼개보면 왼쪽과 오른쪽 모양이 일치함. 그렇기에
왼쪽 출력되는 부분을 2번 반복하면 됨.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++)printf("*");
for(int z=0;z<(n-i-1)*2;z++)printf(" ");
for(int j=0;j<=i;j++)printf("*");
printf("\n");
}
for(int i=0;i<n-1;i++){
for(int j=0;j<(n-1-i);j++)printf("*");
for(int z=0;z<(i+1)*2;z++)printf(" ");
for(int j=0;j<(n-1-i);j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2446
2446번: 별 찍기 - 9
첫째 줄부터 2×N-1번째 줄까지 차례대로 별을 출력한다.
www.acmicpc.net
이번에는 행을 기준으로 절반을 나눠서 위와 아래를 분리해 구현한다.
위는 점점 줄어드는 모래시계를 만들고, 아래는 점점 늘어나는 모래시계를 만들면 이해하기 쉬울 것이다.
#include <stdio.h>
int n;
main(){scanf("%d",&n);
for(int i=0;i<n-1;i++){
for(int z=0;z<i;z++)printf(" ");
for(int j=0;j<(n-i)*2-1;j++)printf("*");
printf("\n");
}
for(int i=0;i<n;i++){
for(int z=0;z<(n-1-i);z++)printf(" ");
for(int j=0;j<(i+1)*2-1;j++)printf("*");
printf("\n");
}
}
https://www.acmicpc.net/problem/2562
2562번: 최댓값
9개의 서로 다른 자연수가 주어질 때, 이들 중 최댓값을 찾고 그 최댓값이 몇 번째 수인지를 구하는 프로그램을 작성하시오. 예를 들어, 서로 다른 9개의 자연수 3, 29, 38, 12, 57, 74, 40, 85, 61 이 주어
www.acmicpc.net
단순하게 입력받을 때 입력받은 인덱스와 같이 값을 저장하고 오름차순 정렬한 뒤에 idx값을 출력해주었다.
#include <stdio.h>
#include <stdlib.h>
typedef struct my{
int v,idx;
}my;
my arr[9];
int cmp(void *a,void *b){
return ((my*)a)->v-((my*)b)->v;
}
main(){
for(int i=0;i<9;i++)scanf("%d",&arr[i].v),arr[i].idx=i;
qsort(arr,9,sizeof(my),cmp);
printf("%d\n%d",arr[8].v,arr[8].idx+1);
}