데이터의 유형

구분 형태 특징
정성적 데이터 언어, 문자 등 회사 매출이 증가함 등 저장, 검색, 분석에
많은 비용이 소모됨
정량적 데이터 수치, 도형, 기호 등 나이, 몸무게, 주가 등 정형화가 된 데이터로 비용 소모가 적음

 

지식경영의 핵심 이슈

구분 의미 특징 상호작용
암묵지 학습과 경험을 통해 개인에게 체화되어 있지만 겉으로 드러나지 않는 지식 김장김치 담그기,
자전거 타기
사회적으로 중요하지만 공유되기는 힘들다 공통화, 내면화
형식지 문서나 매뉴얼처럼 형상화된 지식 교과서, 비디오, DB 전달과 공유가 용이 표출화, 연결화

암묵지 : 개인에게 축적된 내면화 지식 -> 조직의 지식으로 공통화

형식지 : 언어,기호,숫자로 표출화된 지식 -> 개인의 지식으로 연결화

 

 

 

DIKW 피라미드

데이터 개별 데이터 자체로는 의미가 중요하지 않은 객관적인 사실
A마트는 100원에, B마트는 200원에 연필을 판매한다.
정보 데이터의 가공, 처리와 데이터간 연관관계 속에서 의미가 도출된 것
A마트의 연필이 더 싸다.
지식 데이터를 통해 도출된 다양한 정보를 구조화하여 유의미한 정보를 분류하고
개인적인 경험을 결합시켜 고유의 지식으로 내재화된 것
상대적으로 저렴한 A마트에서 연필을 사야겠다.
지혜 지식의 축적과 아이디어가 결합된 창의적인 산물
A마트의 다른 상품들도 B마트보다 쌀 것이라고 판단한다.

 

 

데이터베이스의 정의

체계적이거나 조직적으로 정리되고 전자식 또는 기타 수단으로 개별적으로 접근할 수 있는 독립된 저작물, 데이터 또는 기타 소재의 수집물(EU의 정의)

 

 

데이터베이스 특징

통합된 데이터 동일한 내용의 데이터가 중복되어 있지 않다는 것을 의미
저장된 데이터 자기 디스크나 자기 테이프 등과 같이 컴퓨터가 접근 할 수 있는 저장매체임을 의미
공용 데이터 여러 사용자가 서로 다른 목적으로 데이터를 공동으로 이용한다는 것을 의미
변화되는 데이터 변화가 계속해서 일어나지만 항상 정확한 데이터를 유지

 

#오류에 대해 지적해 주시면 수정하겠습니다.

 

다형성이란?

객체 지향 프로그래밍의 중요한 특징 중의 하나로 함수 이름이나 연산자가 목적으로 사용될 수 있는 것을 의미.

객체 지향에서 다형성이란 클래스가 하나의 메시지에 대해 각 클래스가 가지고 있는 고유한 방법으로 응답할 수 있는 능력을 의미하며, 응용 프로그램에서 하나의 함수가 연산자 두 개 이상의 서로 다른 클래스의 인스턴스들을 같은 클래스에 속한 인스턴스처럼 수행 할 수 있도록 하는 것을 말한다.

 

 


 

 

자바에서의 다형성

자바에서의 다형성은 하나의 객체가 여러가지 타입을 가진다는 것을 의미한다. 자바에서는 이러한 다형성을 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를 참조하는 방식으로 구현하게 된다.

아래의 Parent 클래스와 Child 클래스를 보면 Parent 클래스가 자신을 상속받고 있는 Child 클래스를 참조할 수 있음을 확인 할 수 있다.

 

 

 

하지만 반대의 경우는 성립 되지 않는다. Child class가 Parent class를 상속 받았기 때문에, Child class에서 사용할 수 있는 멤버의 개수는 Parent class보다 무조건 많거나 최소 같을 것이다. 그러므로 아래와 같은 경우 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수보다 많기 때문에 다음과 같이 쓸 수 없다.

 

 

오류가 났다!

 

 

일반 클래스 뿐만 아니라 자체로 객체 생성이 불가능한 인터페이스도 해당 인터페이스를 implements한 클래스를 참조하는 방식으로 다음과 같이 작성할 수 있다.

 

 

 

 

 


 

다형성을 사용하는 이유

1. 동적할당

 

2. 기능 제한

 

3. 기능변경 / 추가

 


 

 

 

instanceof

instanceof는 변수의 타입을 확인할 수 있는 예약어로 true/false를 반환한다.

프로그램의 안정적 동작을 위해 객체의 형변환시 변환하려는 참조변수의 타입을 확인할 때 사용한다.

아래의 경우 b인스턴스는 Bus를 참조하고 있지만, b는 Bus가 상속받고 있는 Vehicle 또한 참조할 수 있으므로 아래와 같은 코드에서 b instanceof Vehicle은 true를 반환하게 된다.

 

(+) Serializable이나 Comparable과 같은 인터페이스를 상속받았는지 확인 할 때도 많이 쓴다고 한다!

 

 

 


 

 

 

Overloading / Overriding

사실 overloading은 자바의 다형성과는 관련이 없지만 overriding과 이름이 비슷하기 때문에 같이 다뤘다.

 

 

-overloading

단어 뜻을 보자면 겹쳐서 짐따위를 싣는다는 것이다. 

우리가 매일같이 쓰는 println을 보면 똑같은 이름의 메서드로 여러개가 만들어져 있음을 알 수 있다. 이처럼 오버로딩은 이름이 같은 함수를 여러개 선언하는 것을 의미한다.

이름만 똑같으면 되고, 반환형은 달라도 상관없으며, 매개변수는 반드시 달라야 한다. 또한 접근제어자도 상관없이 사용할 수 있다.

 

 

 

-overriding

단어 뜻을 보자면 치환한다는 것이다. 다시 말해서 부모의 메소드를 자식 클래스에서 재정의 하는 것을 의미한다.

아래의 경우를 보면, 여러 종류의 자동차 클래스들이 Vehicle을 상속받고 있고 maxPassenger 메소드를 overriding 하고 있다. overriding을 할 땐, 메소드명, 매개변수, 리턴형이 반드시 같아야하며 접근제어자는 부모 클래스의 메소드의 접근 제어자보다 더 넓은 범위의 접근 제어자를 자식 클래스의 메소드에서 설정할 수 있다.

 

(+) 리스코프 치환원칙에 따라 더 넓은 범위의 접근 제어자를 써야한다.

https://stackoverflow.com/questions/5378995/confused-with-java-overriding-the-access-level

 

 

오버라이딩을 사용해서 구현하면 장점이 무엇이 있을까?

다음 코드에서 v객체의 참조형을 변경해가면서 각각 오버라이딩한 메서드를 호출하는 것을 확인해 볼 수 있다.

override를 적절히 활용하면 코드가 유연해지고 유지보수성이 높아진다. 

 

 

 

결론

다형성이란, 부모 클래스가 자신을 상속받은 다른 클래스들의 형태로 변할 수 있다는 것.이를 사용해 오버라이딩에 대해 정리 해봤고, 이름이 비슷한 오버로딩도 같이 정리해 봤다.

  오버로딩 오버라이딩
접근제어자 상관없다. 부모클래스보다 더 넓은 범위여야한다.
리턴형 상관없다. 반드시 같아야한다
메소드명 반드시 같아야한다 반드시 같아야한다
파라미터 반드시 달라야한다 반드시 같아야한다

 

/* 문제설명 */

정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다.

  • 1+1+1+1
  • 1+1+2
  • 1+2+1
  • 2+1+1
  • 2+2
  • 1+3
  • 3+1

정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 11보다 작다.

출력

각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 출력한다.

 

 

 


 

 

 

/* 풀이방법 */

전형적인 DP문제로, 메모이제이션 기법을 사용해서 풀었다.

d[1] = { 1 } = 1가지

d[2] = { 1+1 , 2 } = 2가지

d[3] = { 1+1+1 , 1+2 , 2+1 , 3 } = 4가지

위에 문제를 보면 d[4] = 7가지 임을 알 수있다. 이를 미루어 보아 

d[n] = d[n] + d[n-1] + d[n-2]

이러한 점화식을 세울 수 있다.

                         

 


 

/* 해답코드 */

package baekjoon;

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

//dp의 시작
//1,2,3더하기
public class b9095 {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		int[] d = new int[11];
		for(int i=0;i<T;i++) {
			int n = Integer.parseInt(br.readLine());
			
			//d[n] = d[n-2]+d[n-1]+d[n]
			d[1]=1;
			d[2]=2;
			d[3]=4;
			for(int j=4;j<=n;j++) {
				d[j] = d[j-1]+d[j-2]+d[j-3];
			}
			System.out.println(d[n]);
		}
	}
}

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준][1074]Z  (0) 2021.08.17
[백준]선물 전달  (0) 2021.08.16
[백준]설탕배달  (0) 2021.08.14
[백준]개미  (0) 2021.08.08
[백준]경비원  (0) 2021.08.07

/* 문제설명 */

상근이는 요즘 설탕공장에서 설탕을 배달하고 있다. 상근이는 지금 사탕가게에 설탕을 정확하게 N킬로그램을 배달해야 한다. 설탕공장에서 만드는 설탕은 봉지에 담겨져 있다. 봉지는 3킬로그램 봉지와 5킬로그램 봉지가 있다.

상근이는 귀찮기 때문에, 최대한 적은 봉지를 들고 가려고 한다. 예를 들어, 18킬로그램 설탕을 배달해야 할 때, 3킬로그램 봉지 6개를 가져가도 되지만, 5킬로그램 3개와 3킬로그램 1개를 배달하면, 더 적은 개수의 봉지를 배달할 수 있다.

상근이가 설탕을 정확하게 N킬로그램 배달해야 할 때, 봉지 몇 개를 가져가면 되는지 그 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (3 ≤ N ≤ 5000)

출력

상근이가 배달하는 봉지의 최소 개수를 출력한다. 만약, 정확하게 N킬로그램을 만들 수 없다면 -1을 출력한다.

 

 

 

 


 

 

 

/* 풀이방법 */

동적계획법 기법중 메모이제이션 기법을 사용했다.

처음에 N크기만한 배열을 생성하고 -1로 초기화 했다.

그리고 설탕의 최소 크기인 3과 5 를 1로 초기화 한다 --->이때 배열의 범위에 유의해라!

그리고 그 이후 목적지(d[N])까지 반복문을 통해 이동하는데, 

이때 d[i-3]이나 d[i-5]가 -1이 아니라면 해당 위치 +1이 가장 최소값이 된다.

왜냐하면, d[i-3]에는 i-3까지 도착하는 최소값이 기록되어 있으므로 거기에 설탕 3kg하나 더하는 것이다.

d[i-3]과 d[i-5], 둘 다 -1이라면 당연히 현재위치도 -1이 된다.

이러한 방식으로 동적계획법을 구현했다.

 


 

/* 해답코드 */

package baekjoon;

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

//설탕배달
//dp의 기본
public class b2839 {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		int[] d = new int[N+1];
		for(int i=0;i<=N;i++) {
			d[i]=-1;
		}
		if(N>=3)
			d[3] = 1;
		if(N>=5)
			d[5] = 1;
		for(int i=6;i<=N;i++) {
			if(d[i-3]==-1&&d[i-5]==-1)
				continue;
			else if(d[i-3]==-1)
				d[i]=d[i-5]+1;
			else if(d[i-5]==-1)
				d[i]=d[i-3]+1;
			else
				d[i]=Math.min(d[i-3]+1, d[i-5]+1);
		}
		System.out.println(d[N]);
	}

}

 

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준]선물 전달  (0) 2021.08.16
[백준]1,2,3 더하기  (0) 2021.08.14
[백준]개미  (0) 2021.08.08
[백준]경비원  (0) 2021.08.07
[백준]색종이  (0) 2021.08.07

#오류에 대해 지적해 주시면 수정하겠습니다.

 

직렬화(Serialization)

객체 등 특정 구조의 데이터를 이후 복원할 수 있는 형태의 데이터로 전환하는 과정

 

역직렬화(Deserialization)

직렬화된 데이터를 복구하는 과정

 

하지만 이렇게만 보기엔 왜 이름이 직렬화인지 와닿지 않을 수 있으므로

좀더 와닿게 써보자.

 

 

 

이미지의 직렬화 과정

나는 컴퓨터 비전이라는 과목에서 직렬화를 처음 접했다.

컴퓨터비전은 영상이나 이미지속에서 특정 물체를 검출하거나 배경 검출, 색상 검출 등등 을 하는데 이미지를 바로 처리할 수 없으므로 항상 직렬화를 해야했다.

그림과 같이 이미지는 0 1로 구성된 화소들의 집합인데, 이것을 저렇게 직선으로 하나하나 펴서 배열로 처리를 하게된다. 그렇기 때문에 이름이 직렬화가 아닐까.

 

 

 

 

 


 

 

 

직렬화/역직렬화를 하기에 앞서

일단 그전에 직렬화/역직렬화를 할 객체에 Serializable interface을 상속받아야한다!

Serializable을 상속받은 User class

이 Serializable interface는 단순 마커 인터페이스이기 때문에 안이 텅텅 비어있다. 그래서 추가로 구현해야할 메소드도 없다! 단지 선언만 하면 된다.

하지만 직렬화/반직렬화 과정에서 Serializable이 있는지 없는지 체크하기 때문에 없다면 NotSerializableException이 발생하므로 반드시 상속받아놔야한다.

 

(+) instanceOf를 이용해 직렬화가 가능한 객체인지 확인하기도 좋다

 

 

직렬화

직렬화 할 땐, ObjectOutputStream class의 writeObject메소드를 이용해서 한다.

ObjectOutputSteam 인스턴스를 생성시 생성자안에 ByteStream계열을 넣어줘야한다.

직렬화 예시코드

 

 

역직렬화

역직렬화 할 땐, ObjectInputStream class의 readObject메소드를 이용해서 한다.

ObjectInputSteam 인스턴스를 생성할때 역시 생성자안에 ByteStream계열을 넣어줘야한다.

역직렬화 예시코드

 

 

 

 

방금 직렬화/역직렬화 과정을 그림으로 나타내보면 위와 같겠다

 

 

 

 

 


 

 

 

직렬화 관련 이슈사항

사실 직렬화 관련해서 이슈사항은 굉장히 많다. 이번 글에서 아래 두 가지에 대해 정리해 보겠다.

 

- 보이지 않는 생성자, readObject

- 싱글톤 패턴 객체 직렬화 시

 

 

 

보이지 않는 생성자, readObject

일단 직렬화를 할 객체를 생성했다. PositiveNumber객체로 직렬화를 위해 Serializable을 상속받았음을 확인 할 수있다.그리고 이름값을 하기 위해 필드에 선언되어있는 value는 양수의 값만 가져야 할 것이다.그렇게 되게 하기 위해 개발자는 생성자 내부에 value가 양수인지 확인하는 if문을 삽입했다.그럼 이 객체에 양수가 아닌 다른 의도하지 않은 수가 들어 올 수 없을까?

 

PositiveNumber 객체

 

정답은 NO이다. 

 

이 객체를 직렬화 하게 된다면

직렬화된 객체를 다시 반직렬화하는 과정에서 readObject 메서드를 호출하게 되는데 이과정은 개발자가 만든 생성자를 거쳐서 만들어지지 않기 때문에 value가 양수인지 확인하는 과정을 거치지 않는다.

 

따라서 악의적인 이용자가 의도적으로 내부 바이트를 수정하게 되면 다른 값으로 바뀔 수도 있다는 뜻이다.

 

이처럼 readObject()메서드는 실직적으로 숨겨진 또다른 생성자이다. 다른 생성자처럼 validation에 신경써야한다.

이를 해결하기 위해선 커스텀 readObject() 메서드를 만들면 되는데 이는 바이트 스트림을 매개변수로 받는 생성자라고 생각하면 된다. 일반 생성자와 동일하게 유효성 검사를 진행하면 앞서 말한 보안적 결함을 막을 수 있다.

 

커스텀 readObject를 생성한 PositiveNumber 객체

 

 

 

싱글톤 적용 객체 직렬화시

두번째 이슈사항은 싱글톤 객체를 직렬화 했을 때 이다.

일단 간단한 싱글톤 객체를 만들어보았다. 역시 직렬화를 위해 Serializable을 상속받았다.

이 객체를 직렬화했다가 역직렬화하게 되면 다른 객체가 생성되기 때문에 싱글톤이 의미가 없어지게 된다.

 

MySingleton 객체

 

이 문제를 해결할 수 있는 방법은 readResolve() 메서드이다.

MySingleton객체 안에 readResolve()메서드를 만들어서 이미 생성되어있는 인스턴스를 반환하도록 한다.

그러면 readObject메서드 이후 (생성되어있다면) 자동으로 readResolve()메서드를 실행한다.

이러한 방법으로 객체를 바꿔치기할 수 있다.

 

readResolve()를 생성한 MySingleton 객체

 

 

 

 

전체적인 flow

 

 

 

writeObject()이후 대상 바꾸기

readResolve 메서드는 역직렬화시 대상을 바꿔주는 일을 수행한다. 마찬가지로 직렬화 이후 대상을 바꿔주는 일을 수행하는 메서드도 있다. 바로 writeReplace 메서드이다!

 

 

이 메서드는 어디에 이용할 수 있을까?

 

 

 

 

보이지 않는 생성자의 또 다른 해결방안, 직렬화 프록시 패턴

이 메서드를 이용해서 아까 다루었던 보이지 않는 생성자 문제를 해결 할 수 있다.

아까의 PositiveNumber class를 다시 보자.

 

자세히 보면 유효한지 확인하는 것을 모든 생성자마다 해야함을 알 수 있다. (+ readObject메서드에서도)

이러한 작업은 신경써야할 포인트가 많다는 뜻이기도 하다. 이러한 단점을 보완할 수 있는 방법이 바로 직렬화 프록시 패턴을 이용하는 것이다.

 

 

PositiveNumberProxy라는 중첩클래스를 만든다. 이 친구는 직렬화만 전담하는 대변인인것이다.

직렬화를 하기위해 writeObject()메소드가 실행되면, writeReplace직렬화할 객체를 proxy객체로 바꾼다.

그러면 직렬화가 되는 객체는 본래 클래스가 아니라 프록시 클래스가 직렬화 되게 된다.

그리고 이후 직렬화된 상태를 나중에 역직렬화하게 된다면, readObject()메소드가 실행될것이고, 바로 readResolve()메소드가 실행되서 객체를 본 객체로 바꾼다.

러면 유효성 검사를 본래 객체 생성자에서만 하면되므로 코드 관리가 편안해진다.

 

직렬화 프록시 패턴

 

 

 

 


 

 

 

결론

정리해보자면 직렬화/역직렬화 할 때 앞서 말한 것들을 반드시 고려해야 하며 고려하지 않았을시 심각한 문제를 초래할 수 있다고 한다. 사실 직렬화 관련해서 이슈사항은 이 글에서 언급한 것들보다 훨씬 많다고 한다.

그렇기 때문에 직렬화말고 JSON이나 CSV와 같은 모든 플랫폼에 적용되는 형식을 사용하는 것이 바람직하다.

 

그럼 왜 공부한거ㅈ..

#오류에 대해 지적해 주시면 수정하겠습니다.

 

System class

입출력을 하기위해선 운영체제의 도움이 반드시 필요하다. 하지만 자바는 운영체제 상에서 바로 실행되는 것이 아니라 JVM이라는 가상 머신위에서 작동된다. 따라서 직접 운영체제가 제공하는 기능에 접근하기는 힘들다.

JVM

 

 

이러한 기능들을 접근할 수 있게 도와주는게 System class이다!

System class를 이용하면 운영체제의 일부 기능을 이용할 수 있다. 예를 들면 프로그램 종료, 입출력, 시간읽기 등이 있다. System class의 모든 필드와 메소드는 static으로 구현되어 있다.

System class의 일부

System class 내부를 보면 InputStream, PrintStream이라는 객체형태의 in, out, err이 선언되어있다. 바로 이것들을 사용해서 자바는 입출력을 한다!

 

 

 


 

 

InputStream/OutputStream

InputStream이나 OutputStream은

"데이터가 들어오고 나가는 통로의 역할에 대해 규정해 놓은 추상클래스"라고 생각하면 된다.

InputStream class
OutputStream class

 

 

 


 

 

자바의 입출력

기본적으로 자바의 입출력은 Stream 기반이다. 컴퓨터 공학에서 스트림이란 연속적인 데이터의 흐름이나 데이터를 전송하는 소프트웨어 모듈을 의미한다. 다음 그림과 같이 자바는 스트림을 통해 입력/출력을 받게 된다.

책 - 황기태, 『 명품 JAVA Programming 』, 생능출판(2005), 442p

 

Stream의 특징

이러한 Stream은 3가지 대표적인 특징이있는데, 다음과 같다.

  1. 단방향
  2. 기본 단위는 바이트/문자
  3. FIFO구조

 

 

Byte Stream/Char Stream

Stream의 입출력 기본 단위는 바이트나 문자이다. 바이트를 기본단위로 받는 스트림을 Byte Stream, 문자를 기본단위로 받는 스트림을 Char Stream이라 한다.

 

-ByteStream중 입력을 받는 class들은 InputStream 추상클래스를 상속받아 만들어진다. 모두 InputStream로 끝난다.

-ByteStream중 출력을 하는 class들은 OutputStream 추상클래스를 상속받아 만들어진다. 모두 OutputStream로 끝난다.

-CharStream중 입력을 받는 class들은 Reader 추상클래스를 상속받아 만들어진다. 모두 Reader로 끝난다.

-CharStream중 출력을 하는 class들은 Writer 추상클래스를 상속받아 만들어진다. 모두 Writer로 끝난다.

InputStream/OutputStream/Reader/Writer을 상속받는 다양한 종류의 Stream들

 

 

자바의 버퍼입출력

버퍼입출력에 대해서는 조금더 자세히 알아보겠다.

ByteStream계열에는 BufferedInputStream, BufferedOutputStream

CharStream계열에는 BufferedReader, BufferedWriter이 해당된다.

 

입출력은 운영체제 API를 호출하는 방식으로 작동 되는데, 당연히 자주 운영체제 API가 호출될 수록 실행속도가 떨어진다. 그래서 스트림에게 각각 버퍼를 가지게 해서, 한번에 호출해서 가져오는 것이다.

책 - 황기태, 『 명품 JAVA Programming 』, 생능출판(2005), 442p

 

 

Stream Chain

스트림은 서로 연결 될 수 있다. 마치 쿠키를 만드는 시스템과 같다. 컨베이어 벨트 위에있는 밀가루 반죽을 한 파트는 적절한 크기로 자르고 한 파트는 쿠키틀로 모양을 내고 한 파트는 구울 것이다. 스트림도 그와 마찬가지로 입력 혹은 출력값을 내가 원하는 형태로 입력/출력하는 것이다. 스트림은 몇 개라도 연결 될 수 있다.

자바로 코딩테스트하면 맨날 쓰는 문장!

 

 

 


 

 

 

표준입출력과 객체입출력

- 표준입출력

System클래스를 사용하여 하는 입출력을 표준입출력이라 한다. 시스템 클래스를 보면 정수형, 실수형, 문자형, 바이트 등등.. 다양한 자료형을 입출력 하기위한 메서드가 있다.

 

표준입출력
출력을 하기위해 오버로딩된 print 메서드들

 

- 객체입출력

하지만 이세상에 그보다 훨씬 다양한 자료형이 존재한다. 이를테면 우리가 수업시간에 만든 class들이 있겠다. 이러한 객체들을 입출력하는 것을 객체입출력이라 한다. 객체입출력을 하기 위해서는 직렬화/역직렬화를 해야한다. 이에 대해서는 다음글에서 더 자세히 알아보겠다.

 

 

 

 

 

 

(+)

 

PrintStream vs OutputStream에 대해서

https://stackoverflow.com/questions/11372546/printstream-vs-printwriter

 

/* 문제설명 */

가로 길이가 w이고 세로 길이가 h인 2차원 격자 공간이 있다. 이 격자는 아래 그림처럼 왼쪽 아래가 (0,0)이고 오른쪽 위가 (w,h)이다. 이 공간 안의 좌표 (p,q)에 개미 한 마리가 놓여있다. 개미는 오른쪽 위 45도 방향으로 일정한 속력으로 움직이기 시작한다. 처음에 (p,q)에서 출발한 개미는 1시간 후에는 (p+1,q+1)로 옮겨간다. 단, 이 속력으로 움직이다가 경계면에 부딪치면 같은 속력으로 반사되어 움직인다.

위 그림은 6×4 격자에서 처음에 (4,1)에서 출발한 개미가 움직인 길을 보여주고 있다. 처음에 (4,1)에 있는 개미는 2시간 후에 (6,3)에 있으며 8시간 후에 (0,1)에 있다. 만일 그 개미가 처음에 (5,3)에 있었다면 매 시간마다 (6,4), (5,3), (4,2), (3,1)로 움직인다. 

여러분은 크기 w×h인 격자 공간에서 처음에 (p,q)에서 출발하는 개미의 t시간 후의 위치 (x,y)를 계산하여 출력해야 한다. 개미는 절대 지치지 않고 같은 속력으로 이동한다고 가정한다. 

문제에서 w와 h는 자연수이며 범위는 2 ≤ w,h ≤ 40,000이다. 그리고 개미의 초기 위치 p와 q도 자연수이며 범위는 각각 0 < p < w과 0 < q < h이다. 그리고 계산할 시간 t의 범위는 1 ≤ t ≤ 200,000,000이다.

입력

첫줄에는 w와 h가 공백을 사이에 두고 주어진다. 그 다음 줄에는 초기 위치의 좌표값 p와 q가 공백을 사이에 두고 주어진다. 3번째 줄에는 개미가 움직일 시간 t가 주어진다. 

출력

출력은 t 시간 후에 개미의 위치 좌표 (x,y)의 값 x와 y를 공백을 사이에 두고 출력한다. 

 

 

 

 


 

 

 

/* 풀이방법 */

 

대각선으로 움직이는 것은 결국 가로한칸, 세로한칸을 동시에 움직이는 것과 같다!

그리고 높이나 너비로 나누었을때 해당 숫자가 짝수이면 0부터 시작, 홀수이면 벽에서부터 시작한다.

이점을 고려해서 반복문없이 푸는데 성공했으나,

StringBuilder를 사용하지 않아 계속 시간초과가 나서 매우 괴로웠다 ㅠ

(다음 스터디에서는 StringBuilder에 대해 더 공부해봐야겠다.)

                         


 

/* 해답코드 */

package baekjoon;

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

//개미
public class b10158 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int W = Integer.parseInt(st.nextToken());
		int H = Integer.parseInt(st.nextToken());
		
		st = new StringTokenizer(br.readLine());
		int x = Integer.parseInt(st.nextToken());
		int y = Integer.parseInt(st.nextToken());
		int T = Integer.parseInt(br.readLine());
		
		//짝수면 0에서 출발, 홀수면 벽에서 출발
		boolean moveX = (x+T)/W%2==0;
		boolean moveY = (y+T)/H%2==0;
		
		x=(x+T)%W;
		if(!moveX) {
			x=W-x;
		}
		
		y=(y+T)%H;
		if(!moveY) {
			y=H-y;
		}
		StringBuilder sb = new StringBuilder();
		sb.append(x);sb.append(" ");sb.append(y);
		bw.write(sb.toString());
		bw.flush();
		bw.close();
	}

}

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준]1,2,3 더하기  (0) 2021.08.14
[백준]설탕배달  (0) 2021.08.14
[백준]경비원  (0) 2021.08.07
[백준]색종이  (0) 2021.08.07
[백준]수열  (0) 2021.08.07

/* 문제설명 */

동근이는 무인 경비 회사 경비원으로 항상 대기하고 있다가 호출이 들어오면 경비차를 몰고 그 곳으로 달려가야 한다. 동근이가 담당하고 있는 곳은 직사각형 모양의 블록으로 블록 중간을 가로질러 차가 통과할만한 길이 없다. 이 블록 경계에 무인 경비를 의뢰한 상점들이 있다.

예를 들어 가로의 길이가 10, 세로의 길이가 5인 블록의 경계에 무인 경비를 의뢰한 3개의 상점이 있다고 하자. <그림 1>과 같이 이들은 1, 2, 3으로 표시되어 있고, 동근이는 X로 표시한 위치에 있다.

< 그림 1 >

1번 상점에서 호출이 들어 왔을 때 동근이가 블록을 시계방향으로 돌아 이동하면 이동 거리가 12가 된다. 반면 반시계방향으로 돌아 이동하면 이동 거리는 18이 된다. 따라서 동근이가 1번 상점으로 가는 최단 거리는 12가 된다. 마찬가지로 동근이의 위치에서 2번 상점까지의 최단 거리는 6, 3번 상점까지의 최단 거리는 5가 된다.

블록의 크기와 상점의 개수 및 위치 그리고 동근이의 위치가 주어질 때 동근이의 위치와 각 상점 사이의 최단 거리의 합을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 블록의 가로의 길이와 세로의 길이가 차례로 주어진다. 둘째 줄에 상점의 개수가 주어진다. 블록의 가로의 길이와 세로의 길이, 상점의 개수는 모두 100이하의 자연수이다. 이어 한 줄에 하나씩 상점의 위치가 주어진다. 상점의 위치는 두 개의 자연수로 표시된다. 첫째 수는 상점이 위치한 방향을 나타내는데, 1은 블록의 북쪽, 2는 블록의 남쪽, 3은 블록의 서쪽, 4는 블록의 동쪽에 상점이 있음을 의미한다. 둘째 수는 상점이 블록의 북쪽 또는 남쪽에 위치한 경우 블록의 왼쪽 경계로부터의 거리를 나타내고, 상점이 블록의 동쪽 또는 서쪽에 위치한 경우 블록의 위쪽 경계로부터의 거리를 나타낸다. 마지막 줄에는 동근이의 위치가 상점의 위치와 같은 방식으로 주어진다. 상점의 위치나 동근이의 위치는 블록의 꼭짓점이 될 수 없다.

출력

첫째 줄에 동근이의 위치와 각 상점 사이의 최단 거리의 합을 출력한다.

 

 

 

 


 

 

 

/* 풀이방법 */

 

 

 

처음에 상점이나 동근이 위치를 받을 때, switch문을 사용해 좌표로 바꾸어준다.

이 때, 동근이의 방향(동,서,남,북)만 저장해 놓는다.

 

그리고 상점 수만큼 반복문을 돌면서, 

상점의 좌표가 나올 때까지 turnClockwise메서드를 재귀적으로 실행한다.

만약, 이동한 횟수가 X+Y (동근이가 담당하고 있는 곳은 직사각형 모양의 블록의 가로와 세로를 합한 값)를 넘는다면,

최단 거리가 아니므로, 둘레에서 해당 값을 빼준다.

 

이동한 횟수를 전부 더해주면  동근이의 위치와 각 상점 사이의 최단 거리의 합 완성이다.

 

                         

 

 


 

/* 해답코드 */

package baekjoon;

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

//경비원
public class b2564 {

	public static int X = 0;
	public static int Y = 0;
	public static int cnt = 0;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		//블록 사이즈와 상점 수 받기
		X = Integer.parseInt(st.nextToken());
		Y = Integer.parseInt(st.nextToken());
		int T = Integer.parseInt(br.readLine());
		int dongDir = 0;
		
		//상점,동근이 위치 받기(point[T][]가 동근이)
		int[][] point = new int[T+1][2];
		for(int i=0;i<T+1;i++) {
			st = new StringTokenizer(br.readLine());
			int dir = Integer.parseInt(st.nextToken());
			int n = Integer.parseInt(st.nextToken());
			switch(dir) {
			case 1:
				point[i][0]= n;
				point[i][1]= Y;
				break;
			case 2:
				point[i][0]= n;
				point[i][1]= 0;
				break;
			case 3:
				point[i][0]= 0;
				point[i][1]= Y-n;
				break;
			case 4:
				point[i][0]= X;
				point[i][1]= Y-n;
				break;
			}
			if(i==T) {
				dongDir = dir;
			}
		}
		
		int sum = 0;
		for(int i=0;i<T;i++) {
			cnt=0;
			turnClockwise(dongDir,point[T][0],point[T][1],point[i][0],point[i][1]);
			int r = (cnt<(X+Y)?cnt:2*(X+Y)-cnt);
			sum+=r;
			//System.out.println(r);
		}	
		
		System.out.println(sum);
		
	}
	
	public static void turnClockwise(int dir,int x,int y,int tx,int ty) {

		if(x==tx&&y==ty) {
			return;
		}
		cnt++;
		switch(dir) {
			case 3:
				if(y+1==Y)dir=1;
				turnClockwise(dir,x,y+1,tx,ty);
				break;
			case 1:
				if(x+1==X)dir=4;
				turnClockwise(dir,x+1,y,tx,ty);
				break;
			case 4:
				if(y-1==0)dir=2;
				turnClockwise(dir,x,y-1,tx,ty);
				break;
			case 2:
				if(x-1==0)dir=3;
				turnClockwise(dir,x-1,y,tx,ty);
				break;
		}
	
	}

}

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준]설탕배달  (0) 2021.08.14
[백준]개미  (0) 2021.08.08
[백준]색종이  (0) 2021.08.07
[백준]수열  (0) 2021.08.07
[백준]일곱난쟁이  (0) 2021.08.04

/* 문제설명 */

가로, 세로의 크기가 각각 100인 정사각형 모양의 흰색 도화지가 있다. 이 도화지 위에 가로, 세로의 크기가 각각 10인 정사각형 모양의 검은색 색종이를 색종이의 변과 도화지의 변이 평행하도록 붙인다. 이러한 방식으로 색종이를 한 장 또는 여러 장 붙인 후 색종이가 붙은 검은 영역의 넓이를 구하는 프로그램을 작성하시오.

예를 들어 흰색 도화지 위에 세 장의 검은색 색종이를 그림과 같은 모양으로 붙였다면 검은색 영역의 넓이는 260이 된다.

입력

첫째 줄에 색종이의 수가 주어진다. 이어 둘째 줄부터 한 줄에 하나씩 색종이를 붙인 위치가 주어진다. 색종이를 붙인 위치는 두 개의 자연수로 주어지는데 첫 번째 자연수는 색종이의 왼쪽 변과 도화지의 왼쪽 변 사이의 거리이고, 두 번째 자연수는 색종이의 아래쪽 변과 도화지의 아래쪽 변 사이의 거리이다. 색종이의 수는 100 이하이며, 색종이가 도화지 밖으로 나가는 경우는 없다

출력

첫째 줄에 색종이가 붙은 검은 영역의 넓이를 출력한다.

 

 

 

 


 

 

 

/* 풀이법 */

 

 

단순하게 생각해서 100*100 도화지를 만들었다.

입력 받은 색종이 좌표를 이용하여, 색종이 영역은 모두 true로 바꿔준다.

추후 true의 개수만 세면 된다!

                         

 


 

/* 해답코드 */

package baekjoon;

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

//색종이
public class b2563 {
	public static boolean[][] paper = new boolean[100][100];
	public static void main(String[] args) throws NumberFormatException, IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		int T = Integer.parseInt(br.readLine());
		for(int i=0;i<T;i++){
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			
			for(int dx=0;dx<10;dx++) {
				for(int dy=0;dy<10;dy++) {
					paper[y+dy][x+dx]=true;
				}
			}
		}
		
		int size =0 ;
		for(int x=0;x<100;x++){
			for(int y=0;y<100;y++){
				if(paper[y][x])
					size++;
			}
		}
		
		System.out.println(size);
	}

}

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준]개미  (0) 2021.08.08
[백준]경비원  (0) 2021.08.07
[백준]수열  (0) 2021.08.07
[백준]일곱난쟁이  (0) 2021.08.04
[백준]재귀함수가 뭔가요?  (0) 2021.08.03

/* 문제설명 */

0에서부터 9까지의 숫자로 이루어진 N개의 숫자가 나열된 수열이 있다. 그 수열 안에서 연속해서 커지거나(같은 것 포함), 혹은 연속해서 작아지는(같은 것 포함) 수열 중 가장 길이가 긴 것을 찾아내어 그 길이를 출력하는 프로그램을 작성하라. 

예를 들어 수열 1, 2, 2, 4, 4, 5, 7, 7, 2 의 경우에는 1 ≤ 2 ≤ 2 ≤ 4 ≤ 4 ≤ 5 ≤ 7 ≤ 7 이 가장 긴 구간이 되므로 그 길이 8을 출력한다. 수열 4, 1, 3, 3, 2, 2, 9, 2, 3 의 경우에는 3 ≥ 3 ≥ 2 ≥ 2 가 가장 긴 구간이 되므로 그 길이 4를 출력한다. 또 1, 5, 3, 6, 4, 7, 1, 3, 2, 9, 5 의 경우에는 연속해서 커지거나 작아지는 수열의 길이가 3 이상인 경우가 없으므로 2를 출력하여야 한다.

입력

첫째 줄에는 수열의 길이 N이 주어지고, 둘째 줄에는 N개의 숫자가 빈칸을 사이에 두고 주어진다. N은 1 이상 100,000 이하의 정수이다.

출력

첫째 줄에 가장 긴 길이를 출력한다.

 

 

 

 


 

 

 

/* 풀이법 */

 

 

이전 숫자를 beforeNum에 저장한다.

입력을 받은 숫자가 이전 숫자보다 크다면 asc배열에 해당 인덱스의 값을 (이전 인덱스 값+1)로 저장한다.

그리고 desc배열에 해당 인덱스 값을 1로 바꾼다.

입력을 받은 숫자가 이전 숫자보다 작다면 desc배열에 해당 인덱스의 값을 (이전 인덱스 값+1)로 저장한다.

그리고 asc배열에 해당 인덱스 값을 1로 바꾼다.

만약 이전 숫자와 값이 같다면 asc배열과 desc배열 둘 다 (이전 인덱스 값 +1)을 해준다.

 

                         


 

/* 해답코드 */

package baekjoon;

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

public class b2491 {
	public static void main(String[] args) throws IOException {
		BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int[] asc = new int[N];
		int[] desc = new int[N];
		int beforeNum = Integer.parseInt(st.nextToken());
		asc[0]=1; desc[0]=1;
		for(int i=1;i<N;i++) {
			int num = Integer.parseInt(st.nextToken());
			if(num < beforeNum) {
				desc[i] = desc[i-1]+1;
				asc[i] = 1;
			}else if(num > beforeNum) {
				asc[i] = asc[i-1]+1;
				desc[i] = 1;
			}else if(num == beforeNum) {
				asc[i] = asc[i-1]+1;
				desc[i] = desc[i-1]+1;
			}
			beforeNum = num;
		}
		
		int max=0;
		for(int i=0;i<N;i++) {
			if(max<asc[i])
				max=asc[i];
			if(max<desc[i])
				max=desc[i];
		}
		
		System.out.println(max);
	}

}

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준]경비원  (0) 2021.08.07
[백준]색종이  (0) 2021.08.07
[백준]일곱난쟁이  (0) 2021.08.04
[백준]재귀함수가 뭔가요?  (0) 2021.08.03
[백준]하노이 탑  (0) 2021.08.03

+ Recent posts