본문 바로가기
개발자 전향 프로젝트

[백준] [알고리즘 1110번: 더하기 사이클] JAVA

by 샘오리 2022. 7. 2.

문제

https://www.acmicpc.net/problem/1110

 

1110번: 더하기 사이클

0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음,

www.acmicpc.net

 

문제

0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음, 주어진 수의 가장 오른쪽 자리 수와 앞에서 구한 합의 가장 오른쪽 자리 수를 이어 붙이면 새로운 수를 만들 수 있다. 다음 예를 보자.

26부터 시작한다. 2+6 = 8이다. 새로운 수는 68이다. 6+8 = 14이다. 새로운 수는 84이다. 8+4 = 12이다. 새로운 수는 42이다. 4+2 = 6이다. 새로운 수는 26이다.

위의 예는 4번만에 원래 수로 돌아올 수 있다. 따라서 26의 사이클의 길이는 4이다.

N이 주어졌을 때, N의 사이클의 길이를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. N은 0보다 크거나 같고, 99보다 작거나 같은 정수이다.

출력

첫째 줄에 N의 사이클 길이를 출력한다.

예제 입력 1 복사

26

예제 출력 1 복사

4
 
 
 

풀이

이 문제는 일단 입력을 받아서 풀어야 하는 문제이기 때문에

사용자의 키보드로부터 어떠한 값을 입력을 받을 수 있게 해주는 Scanner 혹은 BufferedReader등을 이용해야한다.

 

이번에는

메모리 사용량이 적고 속도가 더 빠른 BufferedReader와 BufferedWriter 을 이용하여 문제를 풀어보자!

 

가장 먼저 공식과도 같은 BufferedReader= 입력, BufferedWriter= 출력을 소환할 수 있는 선언문이다.

쉽게 생각해서 이 아이들의 전화번호라고 생각하고 부르기 위해서는 외우자.   

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

이제 값을 입력을 받아야 하는데 우리가 입력받아야 할 것이 숫자(정수)이고 Buffered 패밀리들은 기본적으로 문자열을 제공하고 받기 때문에 일종의 변환을 해줘야 한다.

 

마치 해외에 나가서 콘센트 규격이 달라 어댑터를 끼우는 느낌으로다가

Integer.parseInt라는 메소드로 위에 입력을 담당했던 BufferedReader의 인스턴스를 소환하여 입력한 값을 감싸주겠다. 

n이라는 변수에 담아서 이제 키보드로 입력한 정수를 n에다가 담아 쓰겠다고 선언을 한 것이다. 

int n = Integer.parseInt(br.readLine());

이 문제의 포인트는 이 n이라는 변수에 담은 값, 즉 처음으로 입력한 값이 더하기 사이클을 돌다가 결국 처음 값과 같아지게 되면 사이클을 멈추는 것이므로 n이라는 변수와 비교를 해줄 변수가 하나 필요하고 사이클이 몇번이나 도는지 확인해야 하기 때문에 사이클 횟수를 세는 변수도 필요하다. x를 비교하는 변수, cnt를 사이클 횟수를 세는 변수로 선언했다.

int x = n;
int cnt = 0;

 

숫자를 자리별로 나누는 방법은 나누기와 나머지 연산자를 통해 쉽게 얻을 수 있고

예: 26을  2와 6으로 나누고 싶으면 일단 10의 자리(앞자리)를 구하기 위해 26을 10으로 나눈다.

10으로 나누게 되면 2.6인데 정수는 말 그대로 소수를 무시하기 때문에 앞 자리인 2만 남겨두게 된다.

이번에는 1의 자리를 구하기 위해 나머지 연산자를 통해 26을 %10으로 나눠서 남는 숫자인 6을 얻을 수 있다.

 

위 논리로

앞자리를 left 의 l, 뒷자리를 right의 r 로 하고 따로 나누어 변수에 저장하였다. 26에서는 2가 l에 6이 r에 저장된다.

int l = x / 10;
int r = x % 10;

이제 본격적인 연산이 들어간다. 이 문제 설명에 의하면 입력한 값 기준으로 1의 자리를 10의자리로 두고  더해진 값을 1의 자리로 둬야 한다.  쉽게 12를 입력했다면 1의 자리인 2가 앞으로 오고 1과2를 더한 3이 뒤에 오게 만드는 것이다.

12는 결국 23이 되는 원리이다. 이 연산을 하기 위해서 l과 r을 더하여서 더한 값을 의미하는 sum이라는 변수에 담아주고

뒷자리(1의 자리인) r 변수에 10을 곱하여서 앞자리(10의 자리)로 이동시켜주고 더한 값(sum)의 가장 오른쪽에 있는 숫자를 받기 위해 다시 한번 나머지 연산자를 사용해야 한다. 

 

int sum = l + r;
x = r * 10 + sum % 10;

이제 이 연산을 반복문에 담고 그 사이클을 cnt 변수로 세면서

어떤 조건에 멈출지만 정하면 되는데 그건 간단하게 아래처럼 조건문에 break를 걸어서 할 수 있다.

while (true) {
  int l = x / 10;
  int r = x % 10;
  int sum = l + r;
  x = r * 10 + sum % 10;
  cnt++;
  if (x == n) {
    break;
  }
}

 

반복문을 통해 특정 조건이 되어 멈추기 전까지 몇번의 사이클을 돌았는지 cnt 변수에 담아주었다.

 

이제 이를 BufferedWriter을 통해 출력을 해줘야 하는데 위에서 언급한대로 Buffered 패밀리들은 문자열을 받고 제공하기 때문에 정수로 변환된 값을 다시 문자열로 변환을 해주어야 한다.

 

아래 처럼 String.valueOf라는 메소드로 감싸주어서 문자열로 출력을 하도록 하고 flush()라는 메소드를 통해 남아있는 모든 값들을 출력해주고 마지막으로 소환해둔 친구들을 다시 집으로 돌려보내야 한다. 열었던 기능들은 닫아주는 것이 메모리를 위해서도 좋다.

bw.write(String.valueOf(cnt));
bw.flush();
bw.close();
br.close();

최종 코드는 아래와 같다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Main {

  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    int n = Integer.parseInt(br.readLine());
    int x = n;
    int cnt = 0;

    while (true) {
      int l = x / 10;
      int r = x % 10;
      int sum = l + r;
      x = r * 10 + sum % 10;
      cnt++;
      if (x == n) {
        break;
      }
    }
    bw.write(String.valueOf(cnt));
    bw.flush();
    bw.close();
    br.close();
  }
}