#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int originalNumber = n;
int count = 0;
do {
int a = n % 10;
int b = (n / 10 + n % 10) % 10;
n = a * 10 + b;
count++;
} while (n != originalNumber);
cout << count;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int* numbers = new int[n];
int* dp = new int[n]; //i까지의 최장 증가하는 수열의 길이를 저장하는 배열
for (int i = 0; i < n; i++) {
cin >> numbers[i];
}
dp[0] = 0;
for (int i = 0; i < n; i++) {
int maxBeforeI = 0; //i 전까지 최장 증가하는 수열의 길이를 저장할 변수
for (int j = 0; j < i; j++) { //i 전까지
if (numbers[i] > numbers[j]) { //'증가하는' 조건을 만족하면서
if (dp[j] > maxBeforeI) //더 긴 수열이 발견되면
maxBeforeI = dp[j]; //업데이트
}
}
dp[i] = maxBeforeI + 1; // i 전까지를 구했으니까 나 자신 i를 더해줘야 한다.
}
int maxDp = 0;
for (int i = 0; i < n; i++) {
if (dp[i] > maxDp)
maxDp = dp[i];
}
cout << maxDp << endl;
return 0;
}
OutputStream도 마찬가지로 추상클래스이고 Closeable의 구현 클래스인 것을 볼 수 있다. 한 가지 다른 것은 Flushable의 구현 클래스라는 것이다. 뒤에서 배우겠지만 출력 스트림은 flush를 해줘야 한다.
InputStream의 주요 메소드
int available()
읽을 수 있는 바이트의 개수 반환.
void close()
입력 스트림을 닫는다.
abstract int read()
한 바이트를 읽고 그 읽은 것을 int로 리턴한다.
int read(byte[] b)
1바이트씩 읽어 배열에 집어넣고 몇 바이트 읽었는지 반환
데이터 읽을 게 있는지 없는지 체크하려면 available() 메소드를 사용한다. 헷갈릴 수도 있는데 이 메소드는 boolean 타입이 아니다. 기억해 두자.
InputStream객체.available() 해보고 0보다 클 경우에만 읽으면 된다.
read() 메소드가 특이한 것은 1byte를 읽어서 int 타입으로 반환한다는 것이다. int는 4바이트이다. 즉, 앞쪽 3바이트는 사용을 안 한다는 것이다. read() 메소드는 1바이트를 읽어서 읽은 내용을 반환하는데 int 타입으로 반환한다는 것 잊지 말자.
read() 메소드는 만약 더 이상 읽을 것이 없으면 -1을 반환한다. -1을 반환하기 위해서 read() 메소드의 반환 타입이 int 타입인 것이다.
OutputStream의 주요 메소드
void close()
출력 스트림을 닫는다.
void flush()
버퍼를 비운다.
abstract void write(int b)
b를 바이트로 변환해서 1바이트를 쓴다.
void write(byte[] b)
바이트 배열 b를 쓴다.
flush()라는 것은 InputStream에는 없고 출력 스트림에만 있는 메소드이다. flush는 뭘까?
대부분의 운영체제나 JVM은 read(입력), write(출력)를 효율적으로 하기 위해서 버퍼를 사용한다.
컴퓨터가 처리하는 속도와 출력장치가 출력하는 속도를 비교하면 출력장치가 출력하는 속도가 훨씬 느리다.
예를 들어 출력 장치가 모니터라고 하자.
컴퓨터의 처리와 모니터가 출력하는 것은 속도 차이가 나기 때문에 출력을 효율적으로 하기 위해서 일단 버퍼에 써서 모아놨다가 나중에 한꺼번에 출력(write)을 한다.
System.in, System.out, System.err은 각각 표준 입력, 표준 출력, 표준 오류 장치이다. 표준 장치들은 시스템에서 바로 쓰기 때문에 효율적으로 사용하는 것이 좋으므로 버퍼를 사용한다. 따라서 내가 System.out.write(b) 하면 모니터에 바로 b가 나타나는 것이 아니라 버퍼에 모아둔다.
그 이후에 계속 써도 일단 버퍼에 쓴다. 그러고 나서 버퍼가 꽉 차면 그제서야 모니터에 출력한다.
그런데 나는 아직 버퍼가 꽉 차지는 않았지만 지금 바로 실제로 모니터에 출력을 하고 싶다면 그 때 사용하는 것이 flush 메소드이다. 그러면 버퍼에 있는 내용을 비우고 모니터에 바로 출력한다.
그런데 close() 메소드에는 flush()의 기능이 있어서 close()를 하면 자동으로 flush()가 된다. 더 이상 이 스트림 객체를 안 쓴다는 것이므로 끝내기 전에 버퍼에 있던 내용들은 출력하고 끝내야 하기 때문이다.
write() 메소드는 read() 메소드와 마찬가지로 1byte를 쓰지만 매개변수는 int 타입이다. 인자로 int 타입을 받아서 byte 타입으로 변환해서 1바이트를 쓴다.
import java.io.IOException;
public class IOStreamDemo {
public static void main(String[] args) throws IOException {
int b, len = 0;
int ba[] = new int[100];
System.out.println("---입력 스트림---");
while ((b = System.in.read()) != '\n') {
System.out.printf("%c(%d)", (char)b, b);
ba[len++] = b;
}
System.out.println("\n\n---출력 스트림---");
for(int i = 0; i < len; i++)
System.out.write(ba[i]);
System.out.flush();
}
}
public static void main(String[] args) 뒤에 throws IOException이라고 예외 처리를 한 것을 볼 수 있는데
입출력 장치를 이용할 때에는 거의 IOException이 일어나기 때문에 반드시 예외 처리를 해 줘야 한다.
예외처리를 해주지 않으면 다음과 같이 컴파일 에러가 난다. 따라서 예외 처리는 선택이 아니라 필수이다.
예외처리를 해주지 않으면 컴파일 에러가 남
이 글은 예외처리 글이 아니라서 예외처리를 자세히 설명하면 너무 산으로 갈 것 같아서 예외처리는 따로 설명을 하겠다.
아무튼 입출력을 할 때에는 무조건 IOException에 대한 예외 처리를 해줘야 한다는 것이다.
이 코드에서는 InputStream, OutputStream 객체를 따로 만들지는 않았고 표준 입력 장치인 System.in과 표준 출력 장치인 System.out을 사용했다. 키보드로부터 입력을 받고 모니터에 출력을 하겠다는 것이다.
while문을 돌면서 키보드로부터 1바이트를 읽어서 ba 배열에 저장한다.
여기에서 주목해야 할 것은 1바이트를 읽어서 b에 저장하는데 b는 int 타입이라는 것이다.
잊지 말자 read() 메소드는 1바이트를 읽어서 int를 리턴한다.
그렇게 읽은 것은 ba 배열에 저장하고 나중에 write 메소드로 모니터에 출력한다.
마지막에 System.out.flush()를 해준다. flush()를 해주지 않으면 모니터에 출력이 안 될 수도 있다.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
ArrayList<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
for(int i = 0; i < n; i++) {
set.add(in.next());
}
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
list.add(iterator.next());
}
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if(o1.length() != o2.length())
return o1.length() - o2.length();
else
return o1.compareTo(o2);
}
});
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
HashSet을 List로 바꿀 수 있는 방법을 다시 공부해야겠다. 컬렉션 배웠던거 다시 복습해야지
#include <iostream>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
int numerator = 1; //분자
int denominator = 1; //분모
for (int i = n; i > n - k; i--) {
numerator *= i;
}
for (int i = k; i >= 1; i--) {
denominator *= i;
}
cout << numerator / denominator;
return 0;
}
#include <iostream>
#include <tuple>
using namespace std;
int main() {
int n;
cin >> n;
int count = 0;
for (int i = 1; i <= n; i++) {
if (i < 100) {
count++;
}
else if (i < 1000){
int a, b, c;
a = i / 100;
b = i / 10 % 10;
c = i % 10;
if (a - b == b - c) count++;
}
}
cout << count << endl;
return 0;
}