백준 15552번

백준 15552번 빠른 A+B 풀이를 하려 한다. 이 문제에 빠른이라는 특징이 붙은 이유는 시간 제한이 있기 때문이다.

Java를 사용하고 있다면 Scanner 대신 BufferedReader, System.out.println 대신 BufferedWriter를 사용할 수 있다.

무엇이 다르길래 Scanner와 System.out.println 대신 사용하라는 것일까?


Scanner 대신 BufferedReader

우선 Scanner와 BufferedReader를 비교해보자.

Scanner는 어떤 입력에 대하여 parse하는 것을 알 수 있다. 무슨말이냐면, 우리가 scanner를 통해 입력을 받을 때, 다음과 같은 함수들을 사용할 수 있다.

int i = scan.nextInt();
byte b = scan.nextByte();
String s = scan.next();
float f = scan.nextFloat();
double d = scan.nextDouble();

반면에 bufferedReader는 다음과 같은 함수만 사용할 수 있다.

char c = bufferedReader.read();
String s = bufferedReader.readLine();

여기서 우리가 알 수 있는 것은 String = Array of Character이고, 따라서 입력 문자를 그대로 읽기만 할 수 있는 것이다.

어느 정도 감이 잡힐 텐데, 속도차이가 발생하는 이유는 바로 문자를 특정하게 읽을 것이냐 vs 있는 그대로 읽을 것이냐의 차이가 있기 때문이다.

여기서 한가지 팁을 얻을 수 있는데, 우리가 파일을 읽을 때는 parsing이 필요 없고, 따라서 bufferedReader를 사용하는 것이 좋다.


Syso 대신 BufferedWriter

그러면 System.out.println과 BufferedWriter는 어떻게 다를까?

Scanner와 BufferedReader의 차이와 비슷한데, 우선 System.out.println은 PrintWriter고, BufferedWriter는 BufferedWriter다.

여기서 Scanner와 BufferedReader의 차이와 같은 이유로 속도의 차이가 발생한다.

PrintWriter는 형식화된 표현을 출력하고, BufferedWriter는 character를 그대로 출력하는 데, 이 때 BufferedWriter의 이름에서 볼 수 있듯이 후자가 buffer관리에 조금 더 유리하다.


정리하자면,
Scanner와 System.out.println은 어떤 정형화된 입출력을 다루고, BufferedReader / BufferedWriter는 있는 그대로의 데이터에 대하여 입출력을 수행하기 때문에 속도차이가 발생한다.

BufferedReader와 BufferedWriter의 사용법은 알고리즘에서 중요한 내용이 아니기 때문에, 단순하게 적고 가겠다.

Scanner scan = new Scanner(System.in)과 같이 Buffered Reader도 인풋을 받는 녀석이 필요하며, 이 때 Stream형식으로 설정다.

BufferedWriter의 경우, 마찬가지로 출력대상이 필요하며, Stream형식으로 설정한다.

해당 문제를 풀기 위한 나머지는 A+B와 같고, 따라서 설명은 생략하도록 하겠다.


해당 문제의 최종 코드는 다음과 같다.

import java.io.*;

public class Number15552 {
    public static void main(String args[]) {
        try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))){
            try(BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out))){
                int T = Integer.parseInt(bufferedReader.readLine());
                for(int i = 0; i < T; i++){
                    String values = bufferedReader.readLine();
                    int A = Integer.parseInt(values.split(" ")[0]);
                    int B = Integer.parseInt(values.split(" ")[1]);

                    bufferedWriter.write(A+B + "\n");
                }
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }
}

결과는 정답!

오늘은 백준 2884번 문제에 대해 풀어볼 것이다.

알람시계 문제

이 문제는 Summer Time이라고 흔히 알고있는 시간 설정문제다. 실제보다 빠르게 시간을 설정하는 내용인데, 이 문제는 실제 설정시간보다 45분 빠르게 알람이 설정되면 된다.

알람은 N시 M분에 울리기 때문에, 입력 값으로 "N M"이 주어지면, 해당 시간에서 45분을 빼면 된다.

오늘은 입력 값을 받을 때 java.util.Scanner를 사용하지 않고, java.io.BufferedReader와 java.io.InputStreamReader를 사용했다.


시간에서 단순히 45분을 빼어주면 되는데, if문을 사용하여 시간 연산을 해도 된다.

하지만 알고리즘을 공부하는 우리는 시간은 분으로 표현할 수 있다.라는 특징을 이용하여 문제를 해결할 것이다.

1시간 = 60분

1시간은 60분으로 표현할 수 있고, 우리는 주어진 시간에서 45분을 빼야 한다.

즉, 시간을 입력 받았을 때, 분을 다음과 같이 설정할 수 있다.

M = N * 60 + M - 45

위 식을 통해 입력 된 시간에 대하여 전체 분으로 설정하였다.

0시 0분이 입력된다면, -45분이 되고,13시 50분이 입력된다면, 13시 05분이 된다. ( 13*60 + 50 - 45 = 785, 780 = 13*60 )

이제 분을 시간으로 표현 해 줘야 하는데,1시간=60분이고 따라서 다음과 같이 표현된다.

N = M / 60

이제 분을 표현해야 하는데, 분은 위에 써있듯이 입력 된 시간이 0시 45분보다 빠르다면, 음수값이 된다.

시간은 음수로 존재하지 않고, 문제에서는 24시 표현을 사용하고 있기 때문에, 오후 N시를 표현하면 된다. 즉, 12시간에 해당하는 분을 더해주면 오후에 맞는 시간을 찾아갈 것이다. 따라서 다음과 같은 조건을 추가해주면 된다.

if M < 0 Then M += 1440 Else M;

다만, 이 때 분은 시간의 정보도 갖고 있기 때문에 60으로 나눈 후의 나머지만 사용하여야 한다.

M %= 60;

이제 위의 식을 코드로 표현해주면 된다!

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

public class Number2884 {
    public static void main(String args[])
    {
        try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)))
        {
            String time = bufferedReader.readLine();
            int hour = Integer.parseInt(time.split(" ")[0]);
            int min = Integer.parseInt(time.split(" ")[1]);

            min += hour * 60 - 45;
            min = (min < 0 ? min + 1440 : min);

            hour = min / 60;
            min %= 60;
            System.out.println(hour + " " + min);
        } catch (IOException e){
            e.printStackTrace();
        }
    }
}

결과는 정답!

맥북 클램쉘 모드를 사용하려면 기본적으로는 반드시 전원을 충전중여야만 된다.
근데 계속 충전하면서 쓰는건 배터리에 안좋을거라는 생각도 들어서 클램쉘 모드를 전원 연결 없이 쓰는 법을 찾게 됐고, 1시간의 노력의 결과를 공유하려 한다.

[MacBook Air 교체] 맥북 에어 교체 수령 후기!!

드!디!어! 나의 맥북 에어가 집에 도착했다!! 저번에는 5영업일 걸렸지만, 이번에는 6영업일 걸려서! 받았다! Anyway! 받았다! 저번에도 한번 뜯었던 박스지만, 이게 뭐라고 애플은 날 또 설레게할까

dev-whoan.xyz

[벨킨 USB 허브] 벨킨 USB-C 허브  개봉기 및 후기 F4U092btSGY

드!디!어! 내 맥북이 도착했다! [MacBook Air 교체] 맥북 에어 교체 수령 후기!! 드!디!어! 나의 맥북 에어가 집에 도착했다!! 저번에는 5영업일 걸렸지만, 이번에는 6영업일 걸려서! 받았다! Anyway! 받았

dev-whoan.xyz

위 두 글의 사진을 잘 보면 맥북에 전원이 연결되어 있지 않다!
이렇게 클램쉘을 전원 연결없이 사용하려면 Amphetamine 어플을 설치해줘야 한다.

바로 이 어플리케이션! 검색창의 오타는 신경쓰지말자..

해당 어플리케이션은 App Store에서 설치 가능하다. 맥북이 잠들지 않게 해준다는데, 진짜 안잔다.
해당 어플리케이션을 설치하고 실행시키면 위 상태표시줄(? 아직 명칭을 모르겠다.. 맥 어려웡..)에 아래 사진과 같은 친구가 생기는데, 이 친구의 옵션을 열어서 설정을 눌러준다.

빨간 밑줄이 그어진 녀석이 Amphetamine 어플리케이션이다.

이후 '트리거' 메뉴로 이동하여 '트리거 허용'을 체크한 뒤, 다음과 같은 트리거를 추가해준다.

배터리 충전량은 원하는 값으로 설정해주면 된다.

이 때, '디스플레이가 닫혔을 때 시스템이 잠자는걸 허용'이 원래는 체크되어있고, 이를 해제하게되면 다음과 같은 문구가 발생하는데, 나는 무서워서 Enhancer를 추가로 설치했다.

오 물론 Enhancer 앱을 켰을 때 있는 두 개 다 설치했다. (내 맥북은 소중하니까..)

External ... No Power의 이름은 원하는대로 설정하면 되고, 제일 아래의 '다음 유휴시간 이후 화면 보호기 시작: 0시간 45분'은 딱히 안만져도 된다.
이후 저장한 뒤 암페타민의 켜져있는 모든 세션을 종료한다. 그러면 저 상태표시줄의 어플리케이션이(||) 모양에서 마치 햄버거처럼 세로바가 가로로 눕게된다.

이렇게 눕는다!

이후, 외부 모니터를 연결하고 맥북을 덮으면 된다. (짝짝짝)
주의할 점이 있다. 만약 이렇게 사용하다가 배터리가 없어서 전원을 연결할 경우, 트리거불만족 상태로 변하게되고 맥북의 기본 클램쉘모드로 설정되어서 화면이 한번 꺼졌다가 켜질 것이다. 놀라지 말자! 버그가 아니다!
어.. 그런데 글을 작성하던 도중에 반대 상황이 갑자기 궁금해져서 테스트 해 봤는데 만약에 충전 하면서 클램쉘 모드를 사용하다가 전원을 제거해보니, 화면이 꺼진다!
이를 방지하기 위해서는 Amphetamine 설정에서 다음 설정을 체크 해제해야하는데, 나는 이건 또 싫어서 그냥 쓰기로 결정했다.

닫았을 때는 이유가 있겠지!

모든 설정이 끝났다! 이제 사용하면 된다!

드!디!어! 내 맥북이 도착했다!

 

[MacBook Air 교체] 맥북 에어 교체 수령 후기!!

드!디!어! 나의 맥북 에어가 집에 도착했다!! 저번에는 5영업일 걸렸지만, 이번에는 6영업일 걸려서! 받았다! Anyway! 받았다! 저번에도 한번 뜯었던 박스지만, 이게 뭐라고 애플은 날 또 설레게할까

dev-whoan.xyz


해당 맥북을 보면 알겠지만, 클램쉘 모드로 큰 모니터에서 맥북을 사용하고 있다.
바로 맞다!!! 난 저 클램쉘 모드에 사용된 허브에 대한 개봉기를 지금 쓰고 있다!!!ㅋㅋㅋ (말투무엇)
해당 제품은 F4U092btSGY로, 여자친구가 생일선물로 사줬다.(갓자친구..ㅠㅠ)
정상 제품(?)은 쿠팡에서 10만 9천원에 판매하고 있는데, 나는 박스 손상 제품을 구매하여서 10만1천원에 구매할 수 있었다. (지난주에 봤을 때는 9만 6천원이었는데.....ㅠ 역시 고민은 배송을 늦추고 가격을 올릴 뿐...)
여튼!! usb-c 허브 제품을 선택할 때 나의 기준은 다음과 같았다.

1. USB-A는 USB 3.0 이상을 지원해야 한다. (속도)
2. SD 혹은 Micro SD카드를 사용할 수 있어야 한다. (확장성으로 인해.. 은근 sd카드 쓸 일이 많더라..)
3. HDMI / DP 중 하나를 통해 외부 모니터로 확장할 수 있어야 한다.
4. 전원 충전이 가능해야 한다.(근데 사실 벽돌 문제로 없어도 상관 없었다.)

싼 제품을 쓰자니, 발열로 인해 모니터의 끊김이나 usb 외부장치가 끊기는 오류가 종종 있다 해서 저렴한 제품은 패스!
그래서 남은게 벨킨, 유그린, 사테치 제품밖에 없었다. (독 제품은 너무 비싸서 아예 고려도 안함..)
일단 유그린은 국내에서 구매하려면 모두 해외배송이라 (...) 제외했고, 사테치랑 벨킨 중에는 벨킨을 사용하는 사람이 좀 더 많은 것 같아서 벨킨으로 샀다. (많이 쓰는데는 이유가 있겠지!)


그래서 받은 제품!!

이 제품의 포트는 USB-A *2 (일단 3.0이상이다!), USB-C (PD 지원 최대 60W) *1, SD *1, HDMI *1, Ethernet 1GB *1 로 구성되어 있다.

근데 잘 보면 박스 손상 제품인데, 별 차이 안난다. 이 정도 손상은 뭐 택배 오다가 잠깐 쿵 해도 날 수 있는 정도?? 기분 나쁠정도의 손상은 전혀 없었고, 쿠팡의 안내대로 미개봉 새제품이었다.

구성품은 위와 같다. 와 근데 본체를 저 투명한 고정장치 에서 떼어 내는게 생각보다 힘을 줘야한다. 테이프가 엄청 강하게 붙어있음!

실제 사용할 때의 모습은 위와 같다. 깔깔.
어..근데 이게 생각보다 발열이 있다! 보면 알겠지만 내 무선 마우스를 위한 동글이와 HDMI만 연결해서 사용중인데, 뜨겁다! 생각보다 뜨거움! 그래서 노트북 쿨러에 어떻게 올려보려 했는데, 그렇게되면 사용성이 너무 제한되어서 기각.. (허브 선을 구부려야하는데 단선될거같다... 당장은 안되더라도 뭐 언젠간 단선되겠지.. 그래서..못하겠다..)
마지막은.. HDMI를 통한 외부 모니터 사용 사진!


21.07.21 추가

드디어 외장 SSD를 구매했고, 이 허브에 달린 USB A 포트들을 테스트 했다!!

일단 속도는 다음 링크를 통해 확인해주면 땡큐!

 

[외장 SSD] 삼성 포터블 SSD T5 개봉기 및 후기

오늘 m1 맥북 에어에 사용할 외장 ssd를 샀다. 맥북 ssd 용량이 256밖에 안됐고, 무엇보다 윈도우 맥 간의 파일 이동이 생각보다 귀찮아서 ssd를 마련했다. 근데,, 가격이,,ㅠㅠ,,과거에 누나가 동일제

dev-whoan.xyz

두개 다 정상적으로 인식이 되는데, 문제는 속도가 아니다.

현재 벨킨 허브에 HDMI, 무선마우스 동글, 그리고 SSD 이렇게만 꽂았는데 마우스 움직일 때 렉걸린다. 음...

화면이 끊기지는 않지만, 타 장치들에 렉이 조금 발생한다. 음... 신경쓰일정도로..ㅋㅋ.. 뚝- 뚜둑.! (맥북에서 gif 어떻게 만드나요?ㅠ)

심지어, 나는 노트북 쿨러 위에 같이 얹어두고 쓰는데도 렉걸린다. 오..ㅋㅋ 10만원짜리에서 렉이 걸려도 되나..

이전까지는 별점 5개였지만.. 이로 인해 별점은..

★★★☆☆

드!디!어! 나의 맥북 에어가 집에 도착했다!!

짝짝짝!

저번에는 5영업일 걸렸지만, 이번에는 6영업일 걸려서! 받았다! Anyway! 받았다!

저번에도 한번 뜯었던 박스지만, 이게 뭐라고 애플은 날 또 설레게할까

뜯었을 때 보이는 저 "MacBook Air" ,,, 몽롱하다.. 어쨋건! 개봉기는 저번에 (부족하지만) 썼으니, 오늘은 두 대를 개봉하면서 느낀 흔히 알려진 불량 검사에 대해 적으려고 한다.

이게 아무래도 블로그를 시작한지 얼마 안됐고(?), 갑자기 든 생각이라.. 사진 및 영상 없이 글로만 정리하는 점, 양해 바란다.

1. 맥북이 휘어있다면 꼭 교환해라. 난 두 대를 뜯었지만 둘다 평평했고, 따라서 휘었다면, 가볍게 넘길 문제가 아님!
2. 맥북 모서리를 눌렀을 때, 소리가 난다면 교환해라. 마찬가지로 같은 이유다.
3. 디스플레이의 코팅 불량은 개선된듯 하다. 마찬가지로 같은 이유다.
4. 찍힘이 있다면 그 또한 교환해라. 저번 제품의 교체 이유가 키보드 찍힘이었고, 새 제품을 받은 결과 찍힘이 없다.
5. 첫번째 맥북은 엄청 빠릿빠릿 했는데, 지금 맥북은 막 빠릿빠릿 하다는 느낌은 없다. (흑흑..) 수율 차이인듯 하다.
6. 음질, 키 눌림, 트랙패드 눌림 등에 문제가 있다면 그 또한 교환해라.
7. 맥북을 닫고 흔들었을 때 소리가 나는건 정상인 것 같다. 

7번과 관련된 내용이 참,, 좀 그런 점인데, 맥북을 특정 각도로 흔들면 소리가 난다. 영상을 찍어서 올리려 했는데, 영상에는 소리가 포착이 안된다. 그만큼 아주 작게 소리가 난다. 관련 내용을 찾아보니, 더운 날씨에 소리가 커진단다. 

설계상의 미스로, 소리의 원인을 제공하는 부분이 압력에 의해 흔들리지 않게 설계 됐지만, 더운 날씨에는 공기가 팽창하게 되고, 따라서 해당 부분의 공간이 넓어져 무언가가 흔들린단다. 실제로 에어컨을 끄고 시간이 조금 흐른뒤에 흔들어보니 소리가 조금 더 크게남...

이거 때문에 교환하자니, 이미 두 개의 맥북을 사용해 봤을 때 둘 다 소리가 나는데, 새로운 맥에서 소리가 안날거라는 보장도 없고 설계상의 미스라니 뭐 어쩌겠는가!

후후...

개봉기의 끝은 맥북 사용사진!

오랜만에 MariaDB root 계정으로 로그인해야하는 일이 생겼는데,, 거의 2년만에 로그인 하는거라 비밀번호를 까먹었다.
나 말고도 많은 사람이 비밀번호를 자주 까먹는 것 같아서 어떻게 초기화 할 수 있는지 공유하고자 이 글을 쓴다.
일단, MariaDB를 종료시켜야 한다.

$ sudo systemctl stop mariadb
$ sudo systemctl stop mysql

이후에 mysql을 안전모드로 시작해야 한다. 그 이유는 비밀번호를 사용하지 않고 접속하기 위해서임! (이때 뒤에 & 문자를 붙이는 이유는 프로세스를 백그라운드에서 mysql이 동작하게 하는 리눅스 명령어임. 그냥..ㅋㅋ 은근 모르는 사람 많길래..)

$ sudo mysqld_safe --skip-grant-tables &

실행했으면, root 계정으로 실행시켜주자.

$ mysql -u root

MariaDB가 정상적으로 실행되면 안전모드 진입에 성공했다! 와!(짝짝짝)
이제 계정 초기화를 해 주면 된다.

$ mysql > SET PASSWORD FOR 'root'@'localhost' = PASSWORD('PASSWORD');

만약 다음과 같은 오류가 발생하면, 다음 명령어를 실행해주고, 다시 비밀번호를 설정하면 된다.

The MariaDB server is running with the --skip-grant-tables option so it cannot execute this statement

$ mysql > flush privileges;
$ mysql > SET PASSWORD FOR 'root'@'localhost' = PASSWORD('PASSWORD');
$ mysql > flush privileges;

이제 비밀번호 재설정이 완료됐다! 백그라운드에서 실행중인 mysqld_safe를 종료시키고, MariaDB를 재시작 하면 정상적으로 내가 설정한 비밀번호를 통해 로그인 할 수 있다.
간혹, SET PASSWORD ... 질의문으로 비밀번호 변경이 안된다면, 다음 질의를 실행해보라

$ mysql > ALTER USER 'root'@'localhost' IDENTIFIED BY 'PASSWORD';

 

쉬운건 빨리빨리 풀자!

쉬운건 빨리빨리 풀자!

다음은 사분면을 구분하는 문제인데, 사분면은 우리가 수학적 지식이 있으면 쉽게 알 수 있으니, 바로 정리하겠다.

x가 양수이면 1 또는 4사분면이다.
y가 양수이면 1 또는 2사분면이다.

정리가 끝났다! 해당 문제를 풀기 위해 배열을 사용할 것이다. 조건문을 쓰면, 너무 중첩되어야 해서 귀찮다.

배열의 크기는 2며, x를 먼저 판별하여 0번에는 작은 사분면이, 1번에는 큰 사분면을 넣을 것이다. 설명하자면, x > 0일 경우, result[0] = 1, result[1] = 4 이고, x < 0일 경우, result[0] = 2, result[1] = 3이 될 것이다.

이후에, x>0에서 y가 양수라면, 정답은 1일 것이고, y가 음수라면, 정답은 4가 될 것이다.

전체 코드는 다음과 같다.

import java.util.Scanner;

public class Number14981 {
	public static void main(String args[]) {
		try(Scanner scan = new Scanner(System.in)){
			int result[] = {1, 4};
			int x = scan.nextInt();
			if(x < 0) {
				result[0] = 2;
				result[1] = 3;
			}
			int y = scan.nextInt();
			
			System.out.println( (y > 0 ? result[0] : result[1]) );
		}
	}
}

 

오늘은 백준 2단계 if문의 2753번 윤년과 관련된 문제를 풀이할거다.

if문과 관련된 문제는 주제 그대로 조건문을 잘 활용하면 된다. 특히 2753번의 경우, 조건이 이미 적혀있기 때문에, 크게 어려운 문제는 아니다.

제일 첫 조건에 대한 문장을 보면 다음과 같이 정리할 수 있다.

조건
(년도가 4의 배수다.) AND (100의 배수가 아니다. OR 400의 배수다.)

해당 조건만 보면 100의 배수가 아닌데 400의 배수가 어떻게 걸리는지 잘 모르겠다. (400은 100의 배수이고, 100은 또한 4의 배수이기 때문에..)

하지만 그 다음 문장을 보면 그 말을 확실하게 이해할 수 있다. "1900년은 100의 배수이지만, 400의 배수가 아니라 윤년이 아니다."

즉, 100의 배수면서 400의 배수인 연도는 윤년인 걸 알 수 있다.

또한 "2012년은 4의 배수면서 100의 배수가 아니기 때문에 윤년이다."를 보면, 100의 배수면 윤년이 아닌걸 알 수 있다.

따라서 조건은 다음과 같이 재정리 된다.

조건
1. 4의 배수고, 100의 배수가 아니면 윤년이다.
2. 4의 배수고, 100과 400의 배수면 윤년이다.

이 때, 두 조건에 공통적으로 있는 4의 배수여야 한다를 하나의 조건으로 추가할 것이고, 따라서 다음과 같이 변한다.

조건
0. 4의 배수다.
그리고
1. 100의 배수가 아니면 윤년이다.
혹은
2. 100과 400의 공약수면 윤년이다.

이 둘은 AND 연산이 아니고 OR연산인 것은 모두가 알 수 있을거라 생각한다.

1, 2번 조건 모두 나머지 연산을 통해 구할 수 있다.

1번의 경우, 연도를 (4 * 100)으로 나눴을 때 나머지가 0이어야 하고, 2번의 경우 4로 나눴을 때 나머지는 0이지만, 100으로 나눴을 때 나머지가 0이 아니면 된다.

따라서 전체 코드는 다음과 같다.

import java.util.Scanner;

public class Number2753 {
	public static void main(String args[]) {
		try(Scanner scan = new Scanner(System.in)){
			int year = scan.nextInt();

			boolean baseCondition = (year % 4 == 0);
			boolean firstCondition = (year % 100 != 0);
			boolean secondCondition = (year % 100 == 0) && (year % 400 == 0);

			if(baseCondition && (firstCondition || secondCondition)) {
				System.out.println("1");
			} else {
				System.out.println("0");
			}
		}
	}
}

이런..

아.. 왜자꾸 같은 실수를 하는지 모르겠다..

compile error는 Scanner를 import 시키지 않았고, 중간에 틀린건 내가 확인하려고 만들어노는 println문을 지우지 않아서 출력 형태가 정답과 달랐다.. ㅋㅋ..

ㅋㅋ..이런.. 해당 println문을 지우니 정답!

+ Recent posts