package mok_test.q00;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
Scanner sc = new Scanner(System.in);
int price = sc.nextInt();
System.out.println(sol.solution(price));
}
}
class Solution {
public int solution(int price) {
int answer = 0;
int tsuri = 1000 - price;
int leng = (int)Math.log10(price);
int i;
answer += tsuri / 500;
tsuri %= 500;
answer += tsuri / 100;
tsuri %= 100;
answer += tsuri / 50;
tsuri %= 50;
answer += tsuri / 10;
tsuri %= 10;
answer += tsuri / 5;
tsuri %= 5;
answer += tsuri;
위 코드로 문제는 해결했지만, for문으로 좀더 간단하게 표현할 수 없을까? 라는 생각이 들었다.
그래서 고쳐본게 아래.
int i;
for(i = leng; i >= 0; i--) {
answer += tsuri / 5 * Math.pow(10, i);
tsuri %= (5 * Math.pow(10, i));
answer += tsuri / Math.pow(10, i);
tsuri %= Math.pow(10, i);
}
그런데 이 코드를 돌리니 값이 이상하게 나와서, 내가 생각을 잘못했나? 하고 계속 고민했었다.😫
그래서 여원님과 함께 살펴보면서 디버거를 돌려본 결과, 원인을 찾았다.
tsuri / 5 * Math.pow(10, i)
이 부분의 분모에 괄호를 쳐놓지 않아서, tsuri / 5를 한 값에 Math.pow를 곱해버려서 그런 것.
페어라고 해도 될지 모르겠지만, 개발공부 유경험자 여원님의 리뷰 덕분에 찾아내서 고칠 수 있었다.🥰
Integer[] conv = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Arrays.sort(conv , Collections.reverseOrder());
arr = Arrays.stream(conv).mapToInt(Integer::intValue).toArray();
int배열에서 제일 작은 수를 제거한 배열을 리턴하라길래, 정렬해놓고 제일 작은것만 빼서 복사하면 되겠구나 했는데 웬걸!
테스트는 성공했었는데 제출한건 모조리 틀렸다. 왜지😫😫😫
질문하기를 살펴보니, 배열이 있다고 무조건 sort를 쓰는 습관은 지양하라고 한다.
데이터가 순서를 지켜야 하는 경우가 있어서(예를 들면 월별 수치), 가능하면 쓰지 말라고.
int[] answer = new int[leng - 1];
int min = arr[0];
for (i = 0; i < leng - 1; i++) {
if (arr[i] < min) {
min = arr[i]; //최소로 설정한 값보다 뒤에 나오는 값이 더 작다면, 뒷값을 새 최소값으로 바꿔줘 (최소값 갱신수식)
System.out.println("제일 작은수는: " + min);
String str = Arrays.toString(arr); //최소값이 있는 곳 인덱스 보려고 string으로 변환
String minstr = Integer.toString(min); //String 관련을 보려고 min값도 String으로 변환
// arr2는 최솟값이 항상 맨끝에 오는 배열이다. 즉, 최솟값이 arr[i]번째와 똑같다면 그 i로 보자.
str = str.replaceAll("[^0-9]", "");
if(arr[i] == arr2[arr.length-1]) {
System.out.println("인덱스의 위치는: " + i);
index = i;
// 내가 구하고 싶은건: 배열도 String으로, 최소숫자도 String으로 바꿔서,
// 배열의 i번째 요소 중 최솟값인 곳의 인덱스를 구한다. (sort 안하면 몇번째에 있는지 모르니까)
//그리고 그 인덱스 번호를 통해서, arr의 인덱스번째 요소에다 remove 명령어 쓰고싶음.
System.out.println("제일 작은 수를 string으로 바꾸면: " + minstr);
System.out.println("str은: " + str);
System.out.println("제일 작은 수가 있는 인덱스는: " + str.indexOf(minstr));
str = str.replace(minstr, "");
System.out.println(str);
}
answer[i] = str.charAt(i);
System.out.println(Arrays.toString(answer));
}
}
if (leng == 1) {
answer = new int[]{-1};
}
그래서 이렇게 하려고 했는데, 뭔가 answer[i]에 값도 잘 안 들어가고, 끝도 없이 복잡해진다.
으아ㅏ알너링너라ㅣ 🤯🤯🤯🤯🤯🤯🤯 모르겠어!!!
int countIndex = 0;
for (i = 0; i < leng; i++) {
if (arr[i] == min) {
continue;
}
answer[countIndex++] = arr[i];
}
if (leng == 1) {
answer = new int[]{-1};
}
이 부분이 문제였다!
내가 하고싶었던 건,
일단 arr[i] 중에서 최솟값을 찾아서 min에 넣어주고 싶었고,
-> 첫번째는 성공했다.
최솟값의 위치인 인덱스 i를 찾아서, 배열에서 그 요소만 빼주고 싶었다.
-> i는 구했는데, 배열에서 그 요소만 빼주는건 실패했다. 아무리 생각해도 구현불가!
-> 그래서 다른 방법인 알고리즘을 참고 블로그에서 데려왔다!
이 방법은 처음 ~ 최솟값 위치 전, 최솟값 위치 후~ 끝 까지를 복사하는걸로,
최솟값인 인덱스만 쏙 빼고 복사하겠다는 얘기다.
F9로 고통받던 나날이여 안녕...!! 🥺 가은 매니저님 감사해요 🥺🥺🥺
반복을 시켜야 하는데, 반드시 길이가 중요한게 아닐 때라면 for가 아니라 while을 써보는 것도 좋다!
나중에 런타임 에러가 나는 경우라면, for문의 갯수를 줄일 수는 없는지 고민해보자.
하지만 그게 생각보다 어렵다면, continue나 break를 사용해보자
sout 대신 log를 쓰는게 좋다. 나중 가면 정말 디버깅만 써야해!!
cnt++;
answer = cnt;
if (num == 1) {
break;
}
여기서 if절과 증감연산자의 위치에 따라서 횟수가 1씩 차이난다!!
class Solution {
public int solution(int num) {
int answer = 0;
int cnt = 0;
int i;
long longn = (long) num;
for (i = 0; i < 500; i++) {
if (longn == 1) {
break;
}
if (longn % 2 == 0) {
longn = longn / 2;
} else if (longn % 2 != 0) {
longn = (longn * 3) + 1;
}
cnt++;
answer = cnt;
if (cnt >= 500) {
answer = -1;
}
}
return answer;
}
}
계속 안되다가 되었는데 num이 바로 1을 받았을 때도 계속 for문을 도는게 문제였다.
break를 걸어서 해결했다!
class Solution {
public boolean solution(int x) {
int q = 0;
int div;
int i;
int fisrtx = x;
for (i = (int) Math.log10(x) ; i >= 0; i--) {
div = (int) Math.pow(10, i); //10의 거듭제곱으로 나눠서 각 자리를 돌아보자
q += x / div;
if (fisrtx != (int) Math.pow(10, i)) {
x = x - (q * div);
}
// 몫으로 해당 자리 숫자(한자릿수)만 뽑고 싶어서 -> n에서 몫 * 해당 자릿수만큼을 통채로 빼줬다!
System.out.println("자릿수합: " + q);
System.out.println("나머지는: " + fisrtx % q);
}
return ((fisrtx >= 1 && fisrtx <= 10000) && fisrtx % q == 0);
}
}
위와같이 했더니 와장창창창 틀렸다! 대체 div에 -가 붙어 나오는 이유가 뭐란 말인가!?
-> 이유는 내가 몫을 '뺄셈으로 구하려고 했기 때문' 이었다!
다음 계산의 피젯수를 이전 계산의 나머지로 설정하는 식으로 해야 탈이 없었다!
-> 도연님의 병정개미 코드가 정말 도움이 많이 됐다!
도연님 천재... 천사... 에인절... 빛나는 전공자의 클린코드 8ㅅ8...♥♥♥
class Solution {
public boolean solution(int x) {
int q = 0;
int div;
int i;
int fisrtx = x;
for (i = (int) Math.log10(x); i >= 0; i--) {
div = (int) Math.pow(10, i);
q += x / div;
x %= div;
if (div <= 0) {
break;
}
}
return ((fisrtx >= 1 && fisrtx <= 10000) && fisrtx % q == 0);
}
}
테스트 통과했으니 답도 맞겠지 했는데, 제출시에 계속 틀려서 엄청 고생.
101이나 10의 거듭제곱수 처럼 중간 자리가 0인 경우도 핸들링하는 수식이 아니면,
/ by zero가 되거나 괴상하게 음수가 되어 버리더라.
중간 자릿수들에 0이 있는데 각 자릿수인 x를 뺄셈으로 구하려고 했더니 이렇게 나와버려서,
변수를 하나 선언해서 몫만 다 더하고, 그 아래에는 나머지를 새 피젯수로 사용하는 변수를 선언.
그리고 혹시나 / zero나 음수 문제가 없도록, div <= 0 이면 break 로 for문 탈출!
새벽까지 함께 해주신 동진님께 감사의 말씀을 드린다. 어찌저찌 내 힘으로 풀어냈구나. 🥰🥰
JAVA 알고리즘 풀이를 너무 못해서 도망가고 싶다는 생각을 정말 많이 하는 중.
이대로 괜찮은건지. 좀더 다른 분들처럼 속도를 내고 싶은데. 이해도 구현도 너무 느려 속상🥺🥺🥺🥺
건호님의 자신이 ㅃㄷㄱ이라는 말씀은 기만이야. 진짜 ㅃㄷㄱ 여기있어요😭😭😭😭
매니저님이 진도율이 좋은 걷기반을 경보반 이라고 부르는 경우도 있다고 하셨는데,
어... 음... 결국 경보는커녕 경고수준의 속도로 겨우겨우 걷기반 문제만 꾸역꾸역 끝.
그렇지만 10년 전 교양 찍먹때라면 못했을 걸 지금은 하고 있으니까,
부끄럽지 않게 개발자 커플이 될 수 있도록 어떻게든 달려야 할것.
어차피 원하던 업계에 남으려면 피할 수 없어😤😤😤😤
원빈 멘토님의 몸을 세개로 나누라는 말씀을 이제 실행해야 할 때가 오는구나...🤔