본문 바로가기

코딩테스트/백준

[백준/C++] 1094번. 막대기

문제

 

1094번: 막대기

지민이는 길이가 64cm인 막대를 가지고 있다. 어느 날, 그는 길이가 Xcm인 막대가 가지고 싶어졌다. 지민이는 원래 가지고 있던 막대를 더 작은 막대로 자른다음에, 풀로 붙여서 길이가 Xcm인 막대

www.acmicpc.net


1. 첫 번째 풀이 (마지막 풀이)

사고 과정

- 막대기의 크기는 2의 지수승만 가능하다. (64, 32, 16, 8, 4, 2, 1)

- 몇 번 잘랐는 지가 아닌, 몇 개를 붙였는가를 묻는 문제.

- 2진수로 표현 후 1의 개수를 세는 문제.

 

1. 입력 값을 2진수로 변환

2. 2진수의 1의 개수를 세서 반환

 

코드

#include <stdio.h>

int main() {
	int x, count = 0;
	scanf("%d", &x);

	for (int i = 0; i < 8; i++) {
		if ((x >> i) & 1) {
			count++;
		}
	}

	printf("%d", count);
}

 

결과

어렵지 않게 성공


개선

사고 과정

- 좀 더 간결하게 작성할 순 없을까?

- 결국 x >> 1이 0이냐, 1이냐로 나뉘니, 바로 더하면 될 것 같다.

코드

#include <stdio.h>

int main() {
	int x, count = 0, i = 7;
	scanf("%d", &x);

	while (i--) {
		count += ((x >> i) & 1);
	}

	printf("%d", count);
}

중괄호는 코딩 스타일이라, 굳이 제거하지 않았다. 공백과 중괄호를 모두 제거하면 7줄 내로 작성 가능하다.

 

결과

이번에도 문제는 없다.


가장 효율적인 코드

https://www.acmicpc.net/source/4586893

behind06님의 코드. 짧고 간결한 한 줄이 특징

 

내 코드와 비교

1. 변수 선언을 k; main(N)으로 끝내셨다. ...이게 왜 된 거지?

1-1. chatGPT에게 물어봐도 이게 변수로 선언될 순 없다고 한다. 백준 환경에 답이 있는 걸까?

2. for의 초기식; 조건식; 증감식을 잘 이용하셨다. 초기식에 scanf를, 조건식은 N, 증감식엔 k += N & 1과 N /= 2를 작성하셨다. N을 2로 나눠가며, k에 1의 개수를 더한 뒤 출력. 한 문장으로 같은 일을 수행했다.

2-1. 조건식이 N인 건, 2로 나눠가다 0이 되면 종료되게 하기 위함이다.


강평

2진수나 비트 개념을 알고 있다면 쉽게 풀 수 있는 문제. 풀 수 있는 방법은 다양하다. 오랜만에 비트 연산을 써볼 수 있어서 좋은 문제였다.