개발이 하고싶니?
[프로그래머스 입문]각도기, 배열의 평균값, 피자 나눠 먹기(3),배열 뒤집기, 문자열뒤집기(자바) 본문
나는 그동안 제로베이스에서 중간중간 코딩테스트를 맛보기로 접해왔다.
코딩테스트에 'ㅋ'도 모르는 나는 한 문제를 푸는데 기본 1일~4일 걸렸고(책이나 서치 하지 않고 혼자서는 작성을 못해서 매번 함수를 어떻게 쓰는지,해당 메서드를 쓸 수 있는 게 맞는지, 이럴 땐 어떤 함수나 자료구조를 쓰는지 찾아보고 구현하거나에러가 발생했을 때는 왜 에러가 난 건지 오픈카톡방에 물어보거나아예 아이디어가 떠오르지않아 못 푸는 문제가 나왔을 땐 구글링으로 코드분석을 하여 해결했다.)
그마저도 IDE로 돌려본 후 코드를 붙여 넣기 해서 제출했었다.
그런데 이번 코딩테스트는 달라도 너무 달랐다.
프로그래머스랑 연계되어서 진행했고, 5문제당 3시간으로 시간제한이 있었다.
연습 삼아 IDE 도움을 받지 않고 진행했더니 결과는 10문제 중 2문제 정답..........
이게 맞는건가 현타가 세게 왔다. 공부를 안 해왔던 게 아닌데 이렇게까지 심하다고? 어이도 없고
너무너무너무 처참했다👤
시간은 1~4일에 하나 풀어왔으니 당연히 모자랐고
IDE가 없어서 작성한 코드에 오타가 있는지 오류가 있는지 메서드가 어떤 게 있었는지
해당 메서드를 여기서 쓸 수 있는지 없는지 매번 IDE가 친절하게 표시해 주고 알려줘서
그나마 코드를 이어나갔었는데 슬프게도 이번에 나는 아무것도 모르는
그냥 컴퓨터 앞에 앉은 코딩 신생아였다....👶(기초정도의 문제 같았는데)
그동안 풀어봤던 거에 비하면 분명히 그리 어려운 문제도 아니어서 문제 읽을 때까지만 해도
이렇게 저렇게 하면 되겠다 싶었는데 현실은 생각대로 되지 않았다.
문자열을 뒤집는데 왜 뒤집어지는 거에 그치지 않고 거울처럼 출력이 되는지...
왜 내가 원하는 답의 근처만 돌고 있는지
제대로 쓴 것 같은데 수정에 수정을 해도 왜 에러가 추가로 생기기만 하고 잡히지 않는 건지
그렇게 나 자신의 수준을 확실히 느꼈다.(모든 문제를 if문과 for문으로만 해결 보려 하고 그걸 못쓰거나 그게 막히면 바보가 되는 수준)
그리고 생각했다. 지금 이런 문제 풀 때가 아니라 입문부터 기초부터 그렇게 올라가야겠다고....
뒤집지도 못하면서 일어나서 걷는 게 당연히 안되는 건데 일어나서 걷겠다고 며칠을 허비하지 말자고
추가로 욕심은 과감히 버리기로 했다.
입문부터 차근차근 풀다가 기억해야 하는 것들이 나오면 분석하고 기록해 놓자
그렇게 처음부터 시작하자🔥🔥🔥🔥🔥🔥🔥
🔒각도기
나는 if문을 사용해서 범위를 나눴고, 해당 범위의 값이 들어오면 그에 맞는 답이 출력될 수 있게 answer을 잡아주었다.
그런데 제출하고 다른 사람들의 코드를 확인해 보니 삼항연산자를 활용한 코드가 있었다.
저거 나도 아는 건데.... 배운 건데.... 공부한 건데.... 왜 생각이 안 나는 걸까? 아니 생각이 났으면 내가 작성은 할 수 있었을까?
그래서 이 문제를 포스팅에 넣기로 했다.
우선 여러 코드와 댓글을 확인하다가 망치로 얻어맞은 것 같은 댓글이 있었다.
맞다.
실전 코딩테스트였다면 저렇게 쓸데없이 타이핑할 시간은 없을 텐데.
0 <angle&& -> 문제에서 '0 <angle <=180'이라고 범위가 지정되어 있어서 작성할 필요 X
90 <angle&& -> else if에서 'angle==90'으로 잡아놨기 때문에 중복작성
이런 부분도 신경 써야겠다.
🔑 다른 코드 풀이 & 분석
이제 삼항연산자를 사용하여 작성한 코드를 살펴보자!
class Solution {
public int solution(int angle){
return angle == 180 ? 4 : angle < 90 ? 1 : angle == 90 ? 2 : angle > 90 ? 3 : 0;
}
}
return 반환해
angle == 180 ?
각도가 180과 같다면? 4
angle < 90 ?
각도가 90보다 작다면? 1
angle == 90 ?
각도가 90도와 같다면? 2
angle > 90 ?
각도가 90도보다 크다면? 3
아니면 0
이렇게도 작성하는 방법이 있는데 정말 생각이 안 났다.
처음 보자마자 정말 오!!!!! 가 절로 나왔는데
댓글에서는 "실무에서 이렇게 쓰면 안 된다" ||"가독성이 떨어진다"라는 말이 많은 거 보니 우선은 코테같이 시간 싸움인 곳에서만 쓰거나 길지 않은, 짧게 나오는 경우 쓰는 습관을 들여야겠다.
기억하자 짧은 if문 대신 삼항연산자를 활용할 수도 있다!
삼항연산자 삼항연산자 삼항연산자!!!!! 삼항연산자아아아악!!!!!!!!!
🔒배열의 평균값
역시나 for문 밖에 모르는 나는 오늘도 여러 번 for문을 써 내려갔다.
이 문제를 해결하고 다른 사람의 Stream 코드를 봤는데 Stream을 생각했다는 것과
서치 하지 않고, 생각한 대로 막힘없이 코드를 작성할 수 있다는 게 그렇게나 부러웠다.
솔직히 나는 Stream을 배우긴 했어도 쓰라면 딱 'Stream.' 까지만 쓸 수 있다😂😂😂
(아 ()가 없네? 그마저도 틀림.... )
그 뒤에 어떤 메서드를 써야 하는지 잘 모른다. 이다음 문제도 Stream을 적용할 수 있고
그다음문제도 Stream을 적용할 수 있었는데 항상 풀고 다른 사람의 풀이를 본 후에야 아~? 오! 만 나왔다.
나도 혼자서 작성할 수 있게 따라 쓰고 또 따라 쓰자!
그렇기 때문에 다른 사람 코드에 Stream이 적용된 문제는 다 포스팅에 넣어보겠다.
다른 사람의 코드를 분석하자면
🔑 다른 코드 풀이 & 분석
import java.util.Arrays;
class Solution {
public double solution(int [] numbers){
return Arrays.stream(numbers).average().orElse(0);
}
}
다시 봐도 짧고 간결하다... 멋있다.
아예 return 값으로 바로 출력되게 작성할 수 있다.
Arrays.stream(변수명) 는 배열 (변수명)을 stream으로 변환( Arrays->Stream )하는 역할을 함.
// () 비어있지 않고 변수명을 넣어줌
.average() 평균 구하는 메서드
//() 안이 비어있음.
.orElse(n) 값이 존재하지 않을 경우 or 주어진 값이 null인 경우에 기본값으로 n을 반환하는 역할을 함
**n을 문자로 작성할 경우 ClassCastException 에러발생!!! 이 경우에는 double대신 object 타입을 사용하여 다 둘 수 있지만 형변환이 필요할 수도 있음.
🔒피자 나눠 먹기(3)
🔑 다른 코드 풀이 & 분석
class Solution {
public int solution(int slice, int n){
return n % slice > 0 ? n/slice+1 : n/slice;
}
}
반환해 return
n을 slice로 나눈 나머지가 0보다 크니?
n % slice > 0
맞다면
n/slice+1
아니라면
n/slice
ㅋㅋㅋㅋㅋㅋㅋ아 또 삼항연산자다!!!!!!!!!
난 결국 생각을 못했던거다....ㅎ
아니 위에 문제가 지나간 지 1시간도 안 지났던 것 같은데...
이렇게 생각이 안 나네... 문제를 해결하는 센스가 왜 이러지?
아무튼 이번 문제는 그래도 나름 괜찮았던 것 같다.
삼항연산자가 생각이 나서 적용했다면 정말 뿌듯했을 텐데 그게 하나 아쉬운 문제였다.
🔒배열 뒤집기
🔑 다른 코드 풀이 & 분석
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Arrays;
class Solution {
public int [] solution(int [] numList) {
List <Integer> list = Array.stream(numList).boxed().collect(collectors.toList());
Collections.reverse(list);
return list.stream().mapToInt(Integer::intValue).toArray();
Array.stream(변수명) 배열 변수명을 스트림으로 변환함.
List<Integer> list
.boxed() 기본 자료형의 스트림을 해당하는 래퍼 클래스의 박싱 된 스트림으로 변환 IntStrem -> Stream<Integer>
// 박싱은 기본 자료형을 해당하는 래퍼클래스로 변환하는 과정. ex) int ->Integer / double -> Double
.collect() 최종 연산 중 하나, 스트림의 요소들을 어떤 형태로 수집할지를 지정.
//.collect() 는 Collectors.~ 랑 같이 사용하는 듯?
Collectors.toList() 스트림의 요소들을 List로 수집하는 역할.
Collections.reverse(list) 리스트를 뒤집음.
list.stream() 리스트를 스트림으로 변환
.mapToInt(Integer::intValue) 각 요소를 int로 매핑함.
// Integer::intValue는 Integer를 int로 변환하는 메서드 레퍼런스
.toArray() 스트림의 요소들을 배열로 변환함.
Stream 찢었다.
진짜 나도 꼭 잘 쓰게 만들어야지!!!!
또 다른 코드
class Solution {
public int[] solution(int[] numList) {
int length = numList.length;
for(int i =0; i < length / 2; i++)
{
int temp = numList[i];
numList[i] = numList{length - i -1];
numList[length - i - 1] = temp;
}
return numList;
같은 for문이지만 나는 배열 전체를 뒤에서부터 꺼내 넣어준 걸 출력했다면, 이 코드는 다른 배열을 생성하지 않고
배열길이의 반까지만 for문을 돌리고 임의로 한 공간을 만들어 0번 인덱스의 값을 넣어준 후
0번 인덱스가 있던 자리에 끝 인덱스를 넣어주고 공간에 넣어놓았던 0번 인덱스였던 값을 끝인덱스 위치에 넣는 코드다
그렇게 되면 배열 중간까지 갔을 때 모든 인덱스들이 거꾸로 뒤집혀있으니까!
이것도 강의에서 많이 보던 방식인데 전혀 생각이 나지 않았다.
뭐 계속 이렇게 하다 보면 나도 문제를 봤을 때 한 가지 방식이 아닌 여러 방식이 생각나지 않을까?
🔒문자열 뒤집기
문자열 뒤집기는 무조건!!!! 무조건! 꼭!!!!!! 포스팅해야겠다 생각했다.
요번 멘털이 털린 테스트에서 문자열 뒤집기 때문에 두 시간을 허비해 놓고도 못 맞췄다.
그 문제는 잘라내서 버려야 하는 글자도 있었고, 배열식으로 인덱스 순서는 그대로인데 그 안에 문자열만 뒤집는 거였다.
split 함수를 사용하여 시도했으나 정말이지 결과가 너무 어이없었다. (또다시 그렇게 만들어보라면 못 만들 정도...)
수정의 수정을 거치다 보니 의도하지 않은 거울에 반사된 모양으로 이상하게 출력이 됐다.
일단 문자열 뒤집기는 내선에서 끝낼 수 없는 걸 알기에 기초부터 배워야겠다 생각했고 우선 바로 서치에 들어갔다.
아무래도 입문문제라 그런지 되게 간결하게 풀 수 있는 방법들이 있었다.
그중 StringBuffer를 사용해서 작성하는 방법이 있어서 따라 해봤다.
그리고는 다른 사람들의 더 다양한 코드를 살펴보았다.
🔑 다른 코드 풀이 & 분석
import java.util.*;
class Solution {
public String solution(String my_string) {
StringBuilder 객체 sb 생성
StringBuilder sb = new StringBuilder();
sb에 문자열 추가
sb.append(my_string);
.reverse() 사용하여 문자열 뒤집기
sb.reverse();
.toString() 사용하여 문자열로 변환
return sb.toString();
**여기서 또다시 문자열로 변환시켜 주는 이유는 StingBuilder는 가변적인 문자열을 나타내는 클래스이고, 사용하면서 발생한 변경은 내부 버퍼에만 적용되어 실제 문자열로 얻으려면 toString을 호출하여 변환해야 함.
}
}
이 코드는 StringBuilder를 사용했다.
왜 buffer를 사용하지 않았을까.... 흠.
StringBuilder와 StringBuffer는 뭐가 다른 거지?
- 공통점 : 둘 다 가변적인 문자열을 처리하는 클래스
- 차이점 :
- 가변성 - Builder: 스레드 안전성이 보장되지 않음/ Buffer: 여러 스레드에서 동시에 수정되더라도 안전하게 동작함.
- 성능 - Builder: 단일 스레드환경에서 사용할 때 더 빠른 성능을 제공/ Buffer: 동기화 작업이 추가되어 성능이 떨어짐.
최근에는 StringBuilder를 더 선호(동기화를 지원하지 않기 때문에 성능상 이점이 있음. 상황에 따라 사용하는 클래스가 달라지겠지만 대부분의 상황에서는 Builder를 선호)
이렇게 찾아보다 보니 이거.. 배운 거였네;;;; 강의에서 분명 들은 기억이 났다.
또 다른 코드
class Solution {
public String solution(String my_String) {
return new StringBuilder(my_String).reverse().toString();
}
}
new StringBuilder(my_String)
.reverse()
.toString()
이 코드도 Builder를 썼다.
그리고는 한 번에 return값으로 잡아 출력했다.
코드 분석을 위해서 쪼개다 보니 위에 코드랑 결국에는 똑같은 코드인데 한 줄 버전인 거다!!!!!
StringBuilder sb = new StringBuilder(); 객체를 sb라는 이름으로 생성해서 sb.~ sb.~ 하지 않고
new StringBuilder(my_String) 객체를 생성한 곳에.~.~ 바로 붙여서 return에 바로 출력!
제발 이렇게 쉬운 것부터 여러 번 차곡차곡 경험을 쌓아나가
나중에 어려운 문제들을 만났을 때 이 자잘한 것들이 떠올라 부분 부분 적용할 수 있게 되었으면 좋겠다.
입문문제이기 때문에 10개 정도는 하고 싶었는데 시간은 왜 이렇게 빠르게 흐르는지...
공부할 때는 천천히 흘러줘라... 제발 일할 때만 빠르게 흘러가줘🙏
'스터디 . 코테 해체하기' 카테고리의 다른 글
[프로그래머스] K번째수 (Java) (0) | 2024.02.06 |
---|---|
[백준 11725번] 트리의 부모찾기(자바) (0) | 2024.02.02 |
[백준 2830번] 행성X3 (자바) (3) | 2024.01.25 |