프로그래머스 lv.0 문자열 밀기 / 저주의 숫자3

hyerin·2023년 4월 10일
0

🌱 1. 문자열 밀기

문제 : 문자열 "hello"에서 각 문자를 오른쪽으로 이동시킨다. 매개변수가 A,B로 주어질 때 A가 밀어서 B가 될수 있으면, 밀어야 되는 최소 횟수를 반환한다. A가 아무리 밀어도 B가 될 수 없으면 -1을 반환한다.

한글풀이
1. A,B가 일치하면 0을 리턴한다(얼리리턴)
2. A의 가장 오른쪽 문자를 맨 앞으로 붙인다.
3. 2번을 반복하며 B와 일치하는지 찾는다.
4. 일치하면 그 횟수를 반환한다.
5. 불가능하다면 -1을 반환한다.

가장 어려웠던 점은 문자열을 수정하는 작업이었다. 가장 뒤의 문자를 가장 앞으로 붙여와야 하는데, 문자열은 일부 수정이 불가능하므로 배열 메소드(unshift, pop, slice)를 써서 풀어야 한다.
배열 메소드들에 대한 제대로 된 이해가 필요한 문제였다.

🍀 첫번째 풀이

function solution(A,B){
  //얼리리턴
	if(A === B) 
    return 0;
  //A를 배열로 만들기 (디스트럭쳐)
    const Aarr = [...A]
   //반복문 돌리기 . Aarr의 가장 뒤의 요소를 pop해서
   //가장 앞에다 붙이기
    for(let i = 0 ; i< A.length; i++){
    Aarr.unshift(Aarr.pop())
    A = Aarr.join('');
    if(A === B) return i+1;
    }
  //앞에서 안나오면 -1리턴
    return -1;
}

배열메소드 unshift와 pop은 원본 배열을 변경한다. 변경된 배열을 반환한고 싶다면 수정된 원본 배열(Aarr)을 받아야지, 변수에 할당하면 안된다.

🍀 두번째 풀이

function solution(A,B){
  if(A === B)
    return 0; //얼리리턴
//for 반복문을 사용.
//뒤 알파벳을 앞에다 붙인다. 총횟수는 총길이가 된다.
//i는 인덱스이자 횟수(index+1)로 활용한다.
//진행하다가 같으면 횟수를 반환한다.
  for(let i = 0; i < A.length; i++){
    A = A.slice(-1) + A.slice(0,-1);
    if(A === B) return i +1;
    
  }
  //안되면 -1을 반환한다. 
  return -1;
}

배열 메소드인 slice에는 인수가 두개가 아닌 하나가 들어갈 수도 있다. slice(a)의 경우 a인덱스부터 끝까지 자른 새 배열을 반환하며 slice(-a)의 경우 끝에서 a개 자른 배열을 반환한다.

//slice에 인수가 하나 들어갔을 때 
let arr = [1,2,3,4,5];
console.log(arr.slice(-3)); //[3,4,5]
console.log(arr.slice(2)); //[3,4,5]

같은 하나의 인수지만 양수와 음수일 때 반환값이 다른 메소드라는 것을 생각하자!

다른 사람 풀이중 신기한 풀이를 가져왔다. indexOf는 인수의 문자열을 찾고 있으면 그 인덱스를 , 없으면 -1를 반환한다. 이 분은 이를 이용해서 간단하게 풀었다.

let solution = (a,b) => (b+b).indexOf(a)

🌱 2. 저주의 숫자 3

문제 : 3x 마을 사람들은 3을 저주의 숫자라고 생각하기 때문에 3의 배수와 숫자 3을 사용하지 않습니다. 3x 마을 사람들의 숫자는 다음과 같습니다. 인수로 n을 주었을때 3x마을에서 n을 어떻게 쓰는지 구하시오.

1 => 1 | 6 => 8
2 => 2 | 7 => 10
3 => 4 | 8 => 11
4 => 5 | 9 => 14
5 => 7 | 10 => 16

이 문제에서 주의할 점은 3의 배수뿐만 아니라 3이 들어간 모든 숫자를 건너 뛰어야 한다는 점이다. 13,30 등 3이 들어간 숫자면 모두 건너 뛰어야 한다.

바로 이 '건너뛴다'는 키워드가 풀이 포인트이다. 숫자는 순서대로 1씩 증가하면서, 3의 배수거나 3이 들어가 있을 때 그 숫자에서 +1을 해주면 된다.

33처럼 3의 배수이자 3이 들어가 있는 숫자더라도 +1을 해주면 된다. 이 말은 즉슨 2가지 조건

  1. 3의 배수
  2. 3이 들어있는 수

를 하나라도 만족하면 +1을 해주는 것이다. 그 다음숫자도 계속 이 조건을 검사해야 하기 때문에 반복 횟수가 정해진 for문보다 반복 횟수를 정하지 않는 while문을 쓰는 것이 적합하다.

하지만 조건에 만족했을 때 숫자를 건너뛰는 것과 별개로 지속적으로 숫자를 늘려줘야 하므로 for문을 같이 사용한다.

function solution(n) {
    let count = 0;
  //for문으로 n이 될 때까지 반복문으로 돌린다. 
    for(let i = 1 ; i <= n ; i++){
        count++;
  //조건에 맞으면 count를 증가시킨다. 
        while(count% 3 === 0 || count.toString().includes('3')){         count++;
              
              }
    }
    return count;
}

최근 이런 문제를 풀다 느낀건데, for문의 i를 단순히 반복횟수가 아닌 리턴 값이나, 하나의 조건으로 활용을 하는 경우가 많은 것 같다.

profile
글쓰기의 시작은 나를 위해, 끝은 읽는 당신을 위해

0개의 댓글