반응형

 

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

 

https://programmers.co.kr/learn/courses/30/lessons/12940

 

코딩테스트 연습 - 최대공약수와 최소공배수

두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의

programmers.co.kr

 

 

 

 

 

내 풀이는 이렇다.

 

 

** Javascript

 

function greatestCommonDivisor(x, y) {
    return y ? greatestCommonDivisor(y, x % y) : x;
}

function leastCommonMultiple(x, y) {
    return x * y / greatestCommonDivisor(x, y);
}

function solution(n, m) {
    return [greatestCommonDivisor(n, m), leastCommonMultiple(n, m)];
}

 

 

다른 사람 풀이 중 진짜로 이게 머선129 외친 풀이를 가져와 봤다.

 

// 문제가 개편되었습니다. 이로 인해 함수 구성이나 테스트케이스가 변경되어, 과거의 코드는 동작하지 않을 수 있습니다.
// 새로운 함수 구성을 적용하려면 [코드 초기화] 버튼을 누르세요. 단, [코드 초기화] 버튼을 누르면 작성 중인 코드는 사라집니다.
function gcdlcm(a, b) {
    var r;
    for(var ab= a * b; r = a % b; a = b, b = r){}
    return [b, ab / b];
}

 

 

 

** Java

 

class Solution {
    public int[] solution(int n, int m) {
        int[] answer = new int[2];
        answer[0] = getGCD(n, m);
        answer[1] = getLCM(n, m);
        return answer;
    }
    
    private int getGCD(int x, int y) {
        return (y > 0) ? getGCD(y, x % y) : x;
    }
    private int getLCM(int x, int y) {
        return x * y / getGCD(x, y);
    }
}

 

 

 

** Python

 

def getGCD(a, b):
    return getGCD(b, a % b) if b > 0 else a

def getLCM(a, b):
    return a * b / getGCD(a, b)

def solution(n, m):
    return [getGCD(n, m), getLCM(n, m)]

 

 

python 의 경우 다른 사람 풀이 중에 참고할 만한 풀이를 가져왔다.

 

def solution(n, m):
    gcd = lambda a,b : b if not a%b else gcd(b, a%b)
    lcm = lambda a,b : a*b//gcd(a,b)
    return [gcd(n, m), lcm(n, m)]

 

 

 

 

** 풀이 설명

 

 

임의의 두 수의 최소공배수와 최대공약수를 구한다면

 

어릴 때 대부분 이렇게 구했을 것이다.

 

 

여기서 빨간색 박스 내 숫자들의 곱이 최대공약수이고

 

파란색 박스 내 숫자들의 곱이 최소공배수가 된다.

 

 

출처: https://www.w3resource.com/javascript-exercises/javascript-math-exercise-10.php

 

그림으로 쉽게 다시 설명하면 두 수의 합집합이 최소공배수이고 교집합이 최대공약수이다.

 

만약 덧셈이라면 a,b 합집합 =  a 집합 + b 집합 - (a, b 교집합) 이겠지만

 

제곱근 같이 곱셈의 경우 a,b 합집합 = a 집합 * b 집합 / (a, b 교집합) 이렇게 된다.

 

따라서 최대공약수를 먼저 구하고 나서 두 수의 곱 / 최대공약수 로 최소공배수를 구하면 된다.

 

 

나는 이 블로그를 가장 많이 참고했다. https://velog.io/@jakeseo_me/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0-6-%EC%88%98%ED%95%99-%EB%82%98%EB%A8%B8%EC%A7%80-%EC%97%B0%EC%82%B0-%EC%B5%9C%EB%8C%80-%EA%B3%B5%EC%95%BD%EC%88%98

 

자바스크립트로 알고리즘 정리하기 #6 수학1 (나머지 연산, 최대 공약수)

나머지연산 최대공약수 최소공배수 개념

velog.io

 

 

풀이에 달린 댓글들을 보니 유클리드 호제법이 언급되었는데 위 블로그에 유클리드 호제법에 관한 설명도 있다.

내 풀이에서 최대공약수도 유클리드 호제법을 이용한 것이다.

 

 

유클리드 호제법의 기본 원리는 a를 b로 나눈 나머지를 r이라고 했을 때, GCD(a, b) = GCD(b, r)과 같다는 것이다.
r이 0이라면, 그 때의 b가 최대공약수이다.

a = 24, b = 16을 가정하면, GCD(24, 16) = GCD(16, 8) = GCD(8, 0)
GCD = 8

 

GCD(a, b) = GCD(b, a % b)

 

 

 

위 규칙에 따라 함수를 만들면 다음과 같이 된다.

 

// javascript

let getGCD = (a, b) => (b > 0 ? getGCD(b, a % b) : a);
// java
public static int gcd(int p, int q) {
    if (q == 0) return p;
    return gcd(q, p % q);
}

 

 

 

 

위키피디에서는 유클리드 호제 최대공약수 알고리즘도 설명해주고 있다.

 

1. 입력으로 두 수 m,n(m>n)이 들어온다.
2. n이 0이라면, m을 출력하고 알고리즘을 종료한다.
3. m이 n으로 나누어 떨어지면, n을 출력하고 알고리즘을 종료한다.
4. 그렇지 않으면, m을 n으로 나눈 나머지를 새롭게 m에 대입하고, m과 n을 바꾸고 3번으로 돌아온다.

 

https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95

 

유클리드 호제법 - 위키백과, 우리 모두의 백과사전

유클리드 호제법(-互除法, Euclidean algorithm) 또는 유클리드 알고리즘은 2개의 자연수 또는 정식(整式)의 최대공약수를 구하는 알고리즘의 하나이다. 호제법이란 말은 두 수가 서로(互) 상대방 수를

ko.wikipedia.org

 

반응형
반응형

 

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

 

 

 

** Javascript

 

 

문제를 보고 ASCII CODE로 shift 해야 한다는 걸 직감했다

 

그래서 구글링 해봤더니 Caeser Cipher 라는 게 있었다. 이게 문제 제목에서 가리킨 시저 암호였다.

 

 

처음 소스는 이랬다. (하지만 제출은 안 했다. 갓택오버플로우 베낀 소스여서)

 

1)

function solution(s, k) {
    var n = 26; // alphabet letters amount
    if (k < 0) {
        return caesarCipher(s, k + n);
    }
    return s.split('')
        .map((c) => {
            if (c.match(/[a-z]/i)) {
                const code = c.charCodeAt();
                const shift = code >= 65 && code <= 90 ? 65 : code >= 97 && code <= 122 ? 97 : 0;
                return String.fromCharCode(((code - shift + k) % n) + shift);
            }
            return c;
        }).join('');
}

 

 

정리하여 제출한 소스는 다음과 같다. 하지만 너무나 마음에 안듦

 

 

2)

 

function solution(s, n) {
    const alphabet = 26;
    const answer = s.split("").reduce((acc, curr) => {
        const asciiCode = curr.charCodeAt();
        if (asciiCode === 31 || asciiCode === 32) return acc + curr;
        const shift = (asciiCode >= 65 && asciiCode <= 90) ? 65
            : (asciiCode >= 97 && asciiCode <= 122) ? 97 : 0; 
        return acc + String.fromCharCode((asciiCode - shift + n) % alphabet + shift);
    }, "");
    return answer;
}

 

 

 

추천을 많이 받은 풀이 중 가장 깔끔한 것은 아래 풀이다.

아스키 코드 변환 함수를 사용하지 않고도 풀 수 있었다.

 

function solution(s, n) {
    var upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var lower = "abcdefghijklmnopqrstuvwxyz";
    var answer= '';

    for(var i =0; i <s.length; i++){
        var text = s[i];
        if(text == ' ') {
            answer += ' '; 
            continue;
        }
        var textArr = upper.includes(text) ? upper : lower;
        var index = textArr.indexOf(text)+n;
        if(index >= textArr.length) index -= textArr.length;
        answer += textArr[index];
    }
    return answer;
}

 

 

3)

위 풀이를 참고하여 다시 작성한 풀이는 아래와 같다.

 

function solution(s, n) {
    const lower = "abcdefghijklmnopqrstuvwxyz";
    const upper = lower.toUpperCase();
    
    return Array.from(s).reduce((acc, curr) => {
        if(curr === " ") return acc += curr;
        if(lower.indexOf(curr) > -1) acc += lower[(lower.indexOf(curr) + n) % 26];
        if(upper.indexOf(curr) > -1) acc += upper[(upper.indexOf(curr) + n) % 26];
        return acc;
    }, "");
}

 

 

 

 

** Java

 

 

java에서는 아스키코드를 이용하지 않고 풀어봤다.

 

class Solution {
    public String solution(String s, int n) {
        String lowerCases = "abcdefghijklmnopqrstuvwxyz";
        String upperCases = lowerCases.toUpperCase();
        String[] strArr = s.split("");
        StringBuilder sb = new StringBuilder();
        for (String str : strArr) {
            if (str.equals(" ")) {
                sb.append(str);
                continue;
            }
            if (lowerCases.indexOf(str) > -1) {
                sb.append(lowerCases.charAt((lowerCases.indexOf(str) + n) % 26));
            }
            if (upperCases.indexOf(str) > -1) {
                sb.append(upperCases.charAt((upperCases.indexOf(str) + n) % 26));
            }
        }
        return sb.toString();
    }
}

 

String에서 [인덱스] 로 가져오질 못해서 .charAt(인덱스)을 사용하였다.

그리고 문자열 가공을 편하게 하기 위해 처음부터 StringBuilder를 이용하였다.

 

 

 

추천 풀이를 보면

 

class Caesar {
    String caesar(String s, int n) {
        String result = "";
    n = n % 26;
    for (int i = 0; i < s.length(); i++) {
      char ch = s.charAt(i);
      if (Character.isLowerCase(ch)) {
        ch = (char) ((ch - 'a' + n) % 26 + 'a');
      } else if (Character.isUpperCase(ch)) {
        ch = (char) ((ch - 'A' + n) % 26 + 'A');
      }
      result += ch;
    }
        return result;
    }

    public static void main(String[] args) {
        Caesar c = new Caesar();
        System.out.println("s는 'a B z', n은 4인 경우: " + c.caesar("a B z", 4));
    }
}

 

여기서 ch - 'a' 와 ch - 'A' 가 있는데 위 자바스크립트 풀이에서 shift 값을 소문자, 대문자 여부를 따져 65, 97 값을 만들어주는 것과 같은 방법인 것 같다.

java에서는 따로 ascii 코드 변환 함수를 쓰지 않고 char끼리 바로 덧셈, 뺄셈으로 구하는 것 같다.

ascii 코드 -> char는 char 캐스팅으로 끝내고 말이다.

 

 

 

 

다른 풀이의 경우 생경한 메소드를 사용했다.

 

class Caesar {
    public String caesar(String s, int _n) {
        return s.chars().map(c -> {
            int n = _n % 26;
            if (c >= 'a' && c <= 'z') {
                return 'a' + (c - 'a' + n) % 26;
            } else if (c >= 'A' && c <= 'Z') {
                return 'A' + (c - 'A' + n) % 26;
            } else {
                return c;
            }
        }).mapToObj(c -> String.valueOf((char)c))
        .reduce((a, b) -> a + b).orElse("");
    }

    public static void main(String[] args) {
        Caesar c = new Caesar();
        System.out.println("s는 'a B z', n은 4인 경우: " + c.caesar("a B z", 4));
    }
}

 

String -> char -> int -> char -> String 되고 있다. 이를 위해 mapToObj 를 함께 사용하였다.

 

mapToObj 말고도 mapToDouble, mapToLong, mapToInt 등이 있다.

 

 

 

 

위 예시를 보면 mapToObj에 대해 더 쉽게 알 수 있다.

출처: https://dev-kani.tistory.com/32

 

[Stream API] 중간 연산 - map 메서드

개념 스트림은 파라미터로 제공되는 함수( Function 관련된 함수형 인터페이스)를 적용해서 기존 요소를 새로운 요소로 매핑시키는 map 이라는 메서드를 제공한다. 기존 값을 변경한다는 개념보다

dev-kani.tistory.com

 

 

 

 

 

 

** Python

 

 

 

python 도 거의 같은 식으로 풀었다.

 

lower = 'abcdefghijklmnopqrstuvwxyz'
upper = lower.upper()

def solution(s, n):
    answer = ''
    for i in list(s):
        if lower.find(i) > -1:
            answer += lower[(lower.find(i) + n) % 26]
        elif upper.find(i) > -1:
            answer += upper[(upper.find(i) + n) % 26]
        else:
            answer += i
    return answer

 

 

추천을 많이 받은 풀이 중 ascii 코드를 이용한 풀이는 아래와 같다.

 

# 문제가 개편되었습니다. 이로 인해 함수 구성이나 테스트케이스가 변경되어, 과거의 코드는 동작하지 않을 수 있습니다.
# 새로운 함수 구성을 적용하려면 [코드 초기화] 버튼을 누르세요. 단, [코드 초기화] 버튼을 누르면 작성 중인 코드는 사라집니다.
def caesar(s, n):
    s = list(s)
    for i in range(len(s)):
        if s[i].isupper():
            s[i]=chr((ord(s[i])-ord('A')+ n)%26+ord('A'))
        elif s[i].islower():
            s[i]=chr((ord(s[i])-ord('a')+ n)%26+ord('a'))

    return "".join(s)
    # 주어진 문장을 암호화하여 반환하세요.


# 실행을 위한 테스트코드입니다.
print('s는 "a B z", n은 4인 경우: ' + caesar("a B z", 4))

 

 

python 내장함수를 잘 모르는데 isupper() 와 islower()를 이용했다면 더 쉬웠을 것 같긴 하다.

 

그리고 내장함수 중 ord 는 문자열을 아스키코드화 시켜주는 것이고 chr은 아스키코드를 문자열로 변환해주는 것 같다.

반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

 

 

 

 

** Javascript

 

 

나의 풀이다.

(프로그래머스 풀다 보니 reduce에 대해 호기심이 생겨 level1 에서 reduce를 엄청 사용하기 시작하였다.)

 

function solution(arr) {
    return arr.reduce((acc, curr) => acc + curr) / arr.length;
}

 

 

 

** Java

 

 

java는 그냥 for문을 돌렸다. for문이 가장 빠르다고 매번 갓택오버플로우에서 얘기가 나왔기에

 

class Solution {
    public double solution(int[] arr) {
        double answer = 0;
        for (int i = 0; i < arr.length; i++) {
            answer += arr[i];
        }
        return answer / arr.length;
    }
}

 

 

다른 사람들 풀이 보면 null 체크도 해줬다. 나는 그럼 for문 형태를 변형하겠다.

 

class Solution {
    public double solution(int[] arr) {
        if (arr == null || arr.length == 0) return Double.valueOf(0);
        double sum = 0;
        for (int number : arr) {
            sum += number;
        }
        return sum / arr.length;
    }
}

 

arr 이 비어있거나 null 일 경우 바로 0으로 빠지도록 한다. 알다시피 0으로 나누는 건 안되기 때문.

반응형
반응형

 

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

 

 

 

** Javascript

 

 

1) 나의 첫번째 풀이는 이렇다.

 

function solution(x) {
    const arrX = `${x}`.split("").map((n) => parseInt(n));
    let sum = 0;
    for (const num of arrX) {
        sum += num;
    }
    
    return !(x % sum);
}

 

 

2) reduce 를 좋아하는 지금의 나

 

function solution(x) {
    return !( x % `${x}`.split("").reduce((acc, curr) => {
        acc += parseInt(curr);
        return acc;
    }, 0));
}

 

욕심을 버리고 가독성 있게 정리하면

 

function solution(x) {
    const sum = `${x}`.split("").reduce((acc, curr) => {
        acc += parseInt(curr);
        return acc;
    }, 0);
    return !( x % sum);
}

 

이렇게 된다.

 

 

다른 사람들의 풀이를 보면

 

// 문제가 개편되었습니다. 이로 인해 함수 구성이나 테스트케이스가 변경되어, 과거의 코드는 동작하지 않을 수 있습니다.
// 새로운 함수 구성을 적용하려면 [코드 초기화] 버튼을 누르세요. 단, [코드 초기화] 버튼을 누르면 작성 중인 코드는 사라집니다.
function Harshad(n){
  return !(n % (n + "").split("").reduce((a, b) => +b + +a ));
}

// 아래는 테스트로 출력해 보기 위한 코드입니다.
console.log(Harshad(148))

 

reduce 안 람다 함수를 더 알아봐야겠다.

 

 

하지만 숫자를 string array 를 바꿔서 푸는 것은 아무래도 효율이 떨어진다고 한다.

 

아래는 속도를 우선시 한 사람의 풀이다.

 

function solution(x) {
    let num = x;
    let sum = 0;
    do {
        sum += x % 10;
        x = Math.floor(x / 10);
    } while (x > 0);

    return !(num % sum);
}

 

 

그리고 재귀함수의 달인의 풀이다.

 

function solution(x, i = 0, sum = 0) {
    return String(x).length === i ? x % sum === 0 : solution(x, i + 1, sum + String(x)[i] * 1);
}

 

 

속도는 느리지만 처음 보는 함수가 있어 가져온 풀이다.

 

function solution(x) {
    return x % eval([ ...x.toString() ].join("+")) ? false : true;
}

 

 

 

** Java

 

 

 

javascript 로는 string 으로 바꿔서 풀었는데 형변환의 경우 시간이 오래 걸린다고 해서 java는 정수로만 해결했다.

 

 

class Solution {
    public boolean solution(int x) {
        int divisor = 0;
        int newX = x;
        while (newX > 0) {
            divisor += newX % 10;
            newX /= 10;
        }
        return x % divisor == 0;
    }
}

 

javascript 의 경우 숫자 형태를 정해주지 못해서 parseInt 를 해야 하는데 java의 경우 int 형으로 바로 선언하니까 편했다.

 

계속 나눠도 몫만 newX에 담긴다.

 

 

숫자로 계산하여 푼 경우 거의 동일하게 푼 것 같다.

 

 

** Python 의 경우 divmod() 함수를 한 번 이용해 보자

 

divmod 는 몫과 나머지를 (몫, 나머지)의 튜플 형태로 return 해주는 python 내장함수이다.

 

x = divmod(a, b)

 

x 값으로 (a // b, a % b) 가 리턴된다.

반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

 

 

 

** Javascript

 

 

1) 나의 첫번째 풀이는 이렇다.

function solution(phone_number) {
    if (phone_number.length === 4) {
        return phone_number;
    } else {
        const numbers = phone_number.replace(/(\d)(\d{4}$)/, "$1-$2").split("-");
        let mask = "";
        for (var i=0; i<numbers[0].length; i++) {
            mask += "*";
        }

        return `${mask}${numbers[1]}`;   
    }
}

 

 

 

 

2) reduce 를 좋아하게 된 지금의 나의 풀이는 이렇다.

function solution(phone_number) {
    return phone_number
        .split("")
        .reduce((acc, curr, index) =>
            (index < phone_number.length - 4) ? acc + "*" : acc + curr, "");
}

 

 

 

3) map 과 join 을 이용해도 된다.

 

function solution(phone_number) {
    return phone_number
        .split("")
        .map((number, index) => (index < phone_number.length - 4) ? "*" : number)
        .join("");
}

 

 

 

추천을 가장 많이 받은 풀이는 정규표현식의 달인의 풀이다.

// 문제가 개편되었습니다. 이로 인해 함수 구성이나 테스트케이스가 변경되어, 과거의 코드는 동작하지 않을 수 있습니다.
// 새로운 함수 구성을 적용하려면 [코드 초기화] 버튼을 누르세요. 단, [코드 초기화] 버튼을 누르면 작성 중인 코드는 사라집니다.
function hide_numbers(s) {
  return s.replace(/\d(?=\d{4})/g, "*");
}

// 아래는 테스트로 출력해 보기 위한 코드입니다.
console.log("결과 : " + hide_numbers('01033334444'));

 

내가 바라던 풀이이긴 했는데 나는 아직 정규식에 미숙하다.

 

 

 

 

그 다음으로 추천을 많이 받은 풀이는 repeat 함수를 이용한 풀이다.

// 문제가 개편되었습니다. 이로 인해 함수 구성이나 테스트케이스가 변경되어, 과거의 코드는 동작하지 않을 수 있습니다.
// 새로운 함수 구성을 적용하려면 [코드 초기화] 버튼을 누르세요. 단, [코드 초기화] 버튼을 누르면 작성 중인 코드는 사라집니다.
function hide_numbers(s){
  var result = "*".repeat(s.length - 4) + s.slice(-4);
  //함수를 완성해주세요

  return result;
}

// 아래는 테스트로 출력해 보기 위한 코드입니다.
console.log("결과 : " + hide_numbers('01033334444'));

 

 

slice 안에 음수를 넣으면 뒤에서부터 숫자를 세는 것으로 알고 있다.

 

 

 

** Java

 

1) 첫번째로 제출한 풀이다

 

import java.util.stream.IntStream;

class Solution {
    public String solution(String phone_number) {
        StringBuilder answer = new StringBuilder();
        
        IntStream.range(0, phone_number.length() - 4).forEach((i) -> answer.append("*"));
        answer.append(phone_number.substring(phone_number.length() - 4, phone_number.length()));

        return answer.toString();
    }
}

 

직사각형 별찍기 문제에서 본 IntStream 과 StringBuilder를 활용하였다.

 

그런데 이 식은 시간이 엄청엄청 오래 걸린다.

 

 

2) 다시 바꿔 본 풀이다.

 

class Solution {
    public String solution(String phone_number) {
        StringBuilder answer = new StringBuilder();

        for (int i = 0; i < phone_number.length(); i++) {
            if (i >= phone_number.length() - 4) {
                answer.append(phone_number.charAt(i));
            } else {
                answer.append("*");   
            }
        }
        return answer.toString();
    }
}

 

이렇게 하면 속도는 확 줄어든다.

 

String.chartAt(인덱스) 는 문자열에서 인덱스가 가리키는 값을 알려준다.

 

 

 

 

3) 이 풀이도 가능하다. 그런데 속도는 두번째 풀이가 훨씬 더 빠르다.

 

import java.util.stream.IntStream;

class Solution {
    public String solution(String phone_number) {        
        StringBuilder answer = new StringBuilder(phone_number);
        
        for (int i = 0; i < phone_number.length() - 4; i++) {
            answer.replace(i, i + 1, "*");
        }
        
        return answer.toString();
    }
}

 

 

 

추천을 많이 받은 다른 사람들의 풀이들을 살펴보면

 

 

class Solution {
  public String solution(String phone_number) {
     char[] ch = phone_number.toCharArray();
     for(int i = 0; i < ch.length - 4; i ++){
         ch[i] = '*';
     }
     return String.valueOf(ch);
  }
}

 

이 풀이는 문자열(String)을 문자 배열(char형 배열)로 만든 뒤 값을 변경하고 나서 다시 문자열로 합쳐주는 것이다.

 

String.toCharArray() : String(문자열)을 char형 배열로 바꾼다.

 

String.valueOf(char) 로 char형 배열을 합쳐서 하나의 String(문자열)로 만듦

 

new String(char) 와 기능은 같다.

 

 

참고:

https://velog.io/@uhan2/java-String.toCharArray-%EC%82%AC%EC%9A%A9%EB%B2%95

 

[Java] - String.toCharArray() 사용법

How to Use - String.toCharArray()

velog.io

 

 

 

 

정규표현식의 달인이라면 프로그램 언어 상관없이 한 줄로 끝낼 수 있다.

 

class Solution {
  public String solution(String phone_number) {
    return phone_number.replaceAll(".(?=.{4})", "*");
  }
}
반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

 

 

 

행렬의 덧셈은 행의 개수와 열의 개수가 같은 것끼리만 가능하다.

 

 

 

** Javascript

 

나의 풀이는 이렇다.

 

function solution(arr1, arr2) {
    return arr1.map((col, idx1) => col.map((row, idx2) => row + arr2[idx1][idx2]));
}

 

당시 javascript 의 다양한 기능들을 몰라서 map만 이용하여 이렇게 풀었다. 그런데 나 말고 다른 사람들도 생각이 비슷했던 것 같다.

 

근데 정확히는 col 과 row 위치가 바뀌어야 한다 ㅎㅎ

 

 

** Java

 

나의 풀이는 이렇다.

 

class Solution {
    public int[][] solution(int[][] arr1, int[][] arr2) {
        int[][] answer = new int[arr1.length][arr1[0].length];
        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr1[i].length; j++) {
                answer[i][j] = arr1[i][j] + arr2[i][j];
            }
        }
        return answer;
    }
}

 

 

arr1[0].length 를 쓴 부분이 찝찝했다.

 

그런데 문제 제출 후 다른 사람들의 풀이를 보니 다 같은 생각이었던 것 같다. 추천을 두번째로 많이 받은 풀이는 내것과 거의 같았고 가장 많이 추천을 받은 풀이도 결국 arr1[0].length 를 사용하였다.

 

 

반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

문제는 이렇다.

 

 

 

 

** Javascript

 

 

내 풀이는 이렇다.

 

function solution(n) {
    const sqrt = Math.sqrt(n) % 1 === 0 ? Math.sqrt(n) : -1;
    return sqrt === -1 ? sqrt : Math.pow(sqrt + 1, 2);
}

 

 

사실 온전한 내 실력으로 풀지는 않았고 루트를 씌웠을 때 결과값이 정수인지 아닌지 가리는 방법을 갓택오버플로우에서 찾았다.

 

 

https://stackoverflow.com/questions/30919111/whats-the-best-way-in-javascript-to-test-if-a-given-parameter-is-a-square-numbe

 

What's the best way in JavaScript to test if a given parameter is a square number?

I created a function that will test to see if a given parameter is a square number. Read about square numbers here: https://en.wikipedia.org/?title=Square_number If the number is a square number...

stackoverflow.com

 

 

위 주소에서

 

var isSquare = function (n) {
    return Math.sqrt(n) % 1 === 0;
};

 

이 식을 활용했다. 루트 씌운 값을 1로 나눴을 때도 나머지가 없는 경우를 골라내는 것이다.

 

javascript 에서 Math.sqrt(숫자) 는 숫자에 루트를 씌운 것이고

Math.pow(숫자, 지수) 는 숫자^지수 이다.

 

 

 

 

 

(2021-08-09 추가)

 

** Java

 

 

import java.lang.Math;

class Solution {
    public long solution(double n) {
        double sqrt = Math.sqrt(n);
        return (sqrt - Math.floor(sqrt)) == 0 ? (long) Math.pow(sqrt + 1, 2) : -1;
    }
}

 

 

Java 의 경우 perfect square root 를 찾는 방법을 구글링 해봤더니 아래 방법을 쓰는 방법이 나왔다

 

    static boolean checkPerfectSquare(double x)  
    { 

	// finding the square root of given number 
	double sq = Math.sqrt(x); 

	/* Math.floor() returns closest integer value, for
	 * example Math.floor of 984.1 is 984, so if the value
	 * of sq is non integer than the below expression would
	 * be non-zero.
	 */
	return ((sq - Math.floor(sq)) == 0); 
    }

출처: https://beginnersbook.com/2019/02/java-program-to-check-if-given-number-is-perfect-square/

 

 

 

Math.sqrt() 와 Math.power() 의 경우 return 타입이 double 이므로 주의해야 한다.

 

 

 

 

추천을 가장 많이 받은 풀이는 아래와 같다.

class Solution {
  public long solution(long n) {
      if (Math.pow((int)Math.sqrt(n), 2) == n) {
            return (long) Math.pow(Math.sqrt(n) + 1, 2);
        }

        return -1;
  }
}

 

 

두 번째로 추천을 많이 받은 풀이인데 이게 가장 내 취향에 맞다.

 

class Solution {
  public long solution(long n) {

    double i = Math.sqrt(n);

    return Math.floor(i) == i ? (long) Math.pow(i + 1, 2) : -1;
  }
}

 

 

 

 

** Python

 

 

그래서 파이썬은 취향에 맞는 풀이로 작성해 보았다.

 

import math

def solution(n):
    sqrt = math.sqrt(n)
    return math.pow(sqrt + 1, 2) if math.floor(sqrt) == sqrt else -1

 

 

 

언어마다 추천을 가장 많이 받은 풀이를 찾아보면 재밌다. 상상도 못한 풀이 방법을 발견할 수 있다.

 

def nextSqure(n):
    sqrt = n ** (1/2)

    if sqrt % 1 == 0:
        return (sqrt + 1) ** 2
    return 'no'

 

 

생각해보면 1/2 제곱이 루트인데 굳이 javascript 나 java나 python이나 math 를 이용할 필요가 있었나 싶다.

허탈하다.

반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

문제의 규칙(?)은 이러하다.

 

 

 

 

 

** Javascript

 

씐난다. 이번에도 풀고 나서 엄청 뿌듯했다.

 

댓글 달린 날짜들 보니까 대부분 7월 초-중순이다. 2021 카카오 문제인 것만 알았는데 생각보다 올라온 지 얼마 안 된 문제였나 보다.

 

 

내 풀이는 이렇다.

 

function solution(s) {
    const numbers = [
        "zero", "one", "two", "three", "four",
        "five", "six", "seven", "eight", "nine"
    ];
    for (const number of numbers) {
        s = s.replace(new RegExp(`${number}`,'g'), numbers.indexOf(number));
    }
    return Number(s);
}

 

 

일단 숫자들을 index대로 배열 안에 나열해놓았다.

그래서 numbers.indexOf("zero") 하면 0 나오고 numbers.indexOf("seven") 하면 7이 나올 수 있도록!

 

 

시간이 조금 걸렸던 부분은 replace 함수 안에 넣을 정규식 부분이었는데

나는 비교할 문자열이 변수로 들어가 있어서 /숫자문자열/g 이걸 넣을 수가 없었다.

 

 

// <- 이 안에 들어가면 백틱(`)도 소용이 없다.

 

문자열 전체 비교를 하려면 /g 글로벌 조건을 걸어야 하기 때문에 방법을 찾아내는 데 조금 걸렸다.

 

 

javascript replace regular expression constructor 이렇게 찾다가 얻어걸린 RegExp!

 

 

https://developer.mozilla.org/ko/docs/orphaned/Web/JavaScript/Reference/Global_Objects/RegExp

 

RegExp | MDN

RegExp 생성자는 패턴을 사용해 텍스트를 판별할 때 사용합니다.

developer.mozilla.org

 

 

제가 원한 건 이 설명이었죠

 

RegExp.prototype.global (en-US)정규 표현식이 문자열 내에서 가능한 모든 경우에 일치하는지, 아니면 최초에 대해서만 일치하는지 나타냅니다.

 

 

그래서 저 하이퍼링크를 타고 들어간 게 아래 사이트다.

 

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global

 

RegExp.prototype.global - JavaScript | MDN

The global property indicates whether or not the "g" flag is used with the regular expression. global is a read-only property of an individual regular expression instance.

developer.mozilla.org

 

 

 

모질라의 데모 소스를 보면

 

const regex1 = new RegExp('foo', 'g');

console.log(regex1.global);
// expected output: true

const regex2 = new RegExp('bar', 'i');

console.log(regex2.global);
// expected output: false

 

이렇게!! g를!! 쓸 수 있다!!!

 

 

 

예시를 더 보면

 

 

replace 에 어떻게 적용해야 하는지까지도 친절하게 알려준다!

 

 

추천이 가장 많은 다른 풀이를 보면

function solution(s) {
    let numbers = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
    var answer = s;

    for(let i=0; i< numbers.length; i++) {
        let arr = answer.split(numbers[i]);
        answer = arr.join(i);
    }

    return Number(answer);
}

 

여기도 배열의 인덱스 특성을 활용하였는데 굳이 정규식을 쓰지 않아도 되는 참신한 방법이었다.

 

 

s 에 포함되어 있는 문자열로 split을 하면 문자열 전후로 s 가 분리되면서 배열 형태로 리턴된다.

 

그리고 그 과정에서 포함되어있던 문자열은 자연스럽게 제거된다.

 

문자열 대신 index를 넣어 join 하면 끝인데

 

결과적으로 문자열이 숫자로 자연스럽게 치환되어 보인다.

 

 

 

 

세상에 머리 좋은 사람들은 많다.

 

 

 

접근성을 길러야겠다. 같은 문제도 더 쉽게 풀 수 있는 방법으로

반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

문제는 이렇다.

 

 

 

** Javascript

 

javascript 의 sort 와 reverse 함수를 아직 제대로 이해하지 못해서 내 코드는 상대적으로 긴 편이다.

sort 와 reverse 는 기본적으로 문자열을 정렬해준다. 그런데 대소문자까지 가려줄 줄은 생각도 못했다.

 

다른 사람들의 풀이를 보면 sort 는 기본적으로 대문자-알파벳순>소문자-알파벳순 이렇게 정렬해주고 reverse 는 문자 그대로 뒤집어주는 것 같다.

 

나의 풀이다.

 

function solution(s) {
    
    let lowerCaseArr = Array
        .from(s)
        .filter((str) => str === str.toLowerCase())
        .sort().reverse();
    let upperCaseArr = Array
        .from(s)
        .filter((str) => str === str.toUpperCase())
        .sort().reverse();
    return lowerCaseArr.join("") + upperCaseArr.join("")  
}

 

굳이 대소문자를 나눌 필요가 없었다.

 

function solution(s) {
    return Array.from(s).sort().reverse().join("");
}

 

 

이렇게 했어도 그냥 통과다.

 

 

추천을 가장 많이 받은 풀이는 split 함수를 이용했다.

 

function solution(s) {
    return s.split("").sort().reverse().join("");
}

 

 

 

** Java (2021-09-07 추가)

 

내림차순이라 -1을 곱해줬다

 

import java.util.*;
class Solution {
    public String solution(String s) {
        String[] strings = s.split("");
        Collections.sort(Arrays.asList(strings), new Comparator<String>() {
            public int compare(String s1, String s2) {
                return s1.compareTo(s2) * -1;
            } 
        });
        return String.join("", strings);
    }
}

 

 

 

추천 1등 풀이는 StringBuilder를 써줬다. StringBuilder 에는 내장함수로 reverse() 가 있다.

 

javascript와 이럴 때는 또 굉장히 유사하다.

 

import java.util.*;
class Solution {
    public String solution(String s) {
        char[] sol = s.toCharArray();
        Arrays.sort(sol);
        return new StringBuilder(new String(sol)).reverse().toString();
    }
}

 

 

 

** Python (2021-09-07 추가)

 

def solution(s):
    r = sorted(list(s),reverse = True)
    return "".join(r)
반응형
반응형

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

 

 

 

문제는 이렇다.

 

 

 

 

 

** Javascript

 

function solution(strings, n) {
    return strings.sort((a, b) => a[n].localeCompare(b[n]) || a.localeCompare(b));
}

 

문제 풀다보면 javascript 능력자들의 코드들을 볼 수 있는데 드디어 나도!!! 한 줄의 간지를 드디어 해봤다!

 

다른 사람 풀이 중에 내 풀이랑 같은 건 아직 없는 것 같다!  ^_____________________________^

 

 

localeCompare 도 이번에 처음 알았다.

 

 

String.prototype.localeCompare()
The localeCompare() 메서드는 기준 문자열과 비교했을 때 비교 대상 문자열이 정렬상 전에 오는지, 후에 오는지 혹은 같은 순서에 배치되는지를 알려주는 숫자를 리턴합니다.

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

 

String.prototype.localeCompare() | MDN

The localeCompare() 메서드는 기준 문자열과 비교했을 때 비교 대상 문자열이 정렬상 전에 오는지, 후에 오는지 혹은 같은 순서에 배치되는지를 알려주는 숫자를 리턴합니다.

developer.mozilla.org

 

 

추가적으로 설명을 보태면 알파벳이 locale 를 구분하여 전후관계를 알려준다.

 

 

예시로 콘솔창에

 

let a = ["가", "희", "넘", "고", "루"];
a.sort((a, b) => a.localeCompare(b));
console.log(a);

 

를 작성하면

 

["가", "고", "넘", "루", "희"] 로 정렬된 것을 볼 수 있다.

 

주의할 점은 공백이 있는 경우 공백도 고려되어 정렬된다. 그래서 글자 자체만 비교해야 한다면 공백 제거를 한 뒤에 사용하는 것이 좋다.

 

 

** Java (2021-09-07 추가)

 

import java.util.*;
class Solution {
    public String[] solution(String[] strings, int n) {
        Collections.sort(Arrays.asList(strings), new Comparator<String>() {
            public int compare(String s1, String s2) {
                if (Objects.equals(0, s1.split("")[n].compareTo(s2.split("")[n]))) {
                    return s1.compareTo(s2);
                }
                return s1.split("")[n].compareTo(s2.split("")[n]);
            } 
        });
        return strings;
    }
}

 

 

 

** Python (2021-09-07 추가)

 

 

cmp_to_key 한 번 써봄

 

from functools import cmp_to_key

def solution(strings, n):
    def string_compare(s1, s2):
        if s1[n] == s2[n]:
            if s1 > s2:
                return 1
            elif s1 == s2:
                return 0
            else:
                return -1
            return s1 - s2
        else:
            if s1[n] > s2[n]:
                return 1
            elif s1[n] == s2[n]:
                return 0
            else:
                return -1
    return sorted(strings, key = cmp_to_key(string_compare))
반응형

+ Recent posts