순열, 조합, 최대공약수

YoungJoon Suh·2022년 4월 4일

n개 중에서 일부만 선택하여 나열하는 것, 순열은 순서를 지키며 나열해야 합니다.
[A,B,D]와 [A,D,B] 두 경우 나열하는 순서가 다르므로 서로 다른 경우로 파악해야 한다.
조합은 순열과 달리 순서를 고려하지 않습니다. 만약 순열처럼 순서를 생각하여 경우의 수를 샌다면, 조합으로써 올바르지 않을 겁니다.

순열: 새로운 치킨 소스 레시피
개업 이래로 항상 승승장구하는 '승승장구 치킨집'의 비결은 소스에 있다. 수많은 타사 브랜드 치킨집들이 승승장구 치킨집의 소스 비결을 알아내려고 했으나 빈번히 포기했다.
그 이유는 5대째 내려오는 '비밀의 승승장구 치킨 소스 비율 레시피'는 70억 인구 중 사장님만 알고 있기 때문이다. 최근, 누리꾼 사이에서 이 레시피의 일부분을 발췌했다는 소문을 듣게 되었다.
그 소문은 다음과 같다.

N 가지의 재료 중에 단 M 가지만을 사용하여 조합한 모든 경우의 수 중 하나이다.
재료는 0과 1로만 이루어진 숫자로 암호화가 되어 있고, 항상 1로 시작하며 복호화를 할 수 없다.
단, 0이 3개 이상인 재료는 상한 재료이기 때문에 제외한다.
재료의 순서에 따라 맛이 달라지기 때문에, 재료를 넣는 순서가 다르다면 다른 레시피이다.
이 소문을 참고하여 '비밀의 승승장구 치킨 소스'가 될 수 있는 경우의 수를 모두 반환하는 함수를 작성하세요.

function newChickenRecipe(stuffArr, choiceNum) {
// TODO: 여기에 코드를 작성하세요.
let freshArr = stuffArr.filter(el => String(el).slice(-3) !== "000");
const recur = function(arr, choiceNum) {
let result = [];
if(choiceNum === 1) return arr.map(hand => [hand]);
arr.forEach((hand, idx, arr) => {
const fixer = hand;
const restArr = arr.filter((_, index) => index !== idx);
const permutationArr = recur(restArr, choiceNum - 1);
const combineFixer = permutationArr.map(hand => [fixer, ...hand]);
result.push(...combineFixer);
});
return result;
};
return recur(freshArr, choiceNum);
}

조합: 블랙잭은 지겨워
평범한 블랙잭 게임에서 수시로 패배하자 흥미가 떨어진 김코딩은 박타짜에게 게임룰을 변형하여 새로운 카드 놀이를 해 볼 것을 제안합니다.
새로운 룰은 다음과 같습니다.

  1. 숫자로 이루어진 카드를 여러 장 받습니다.
  2. 3장씩 카드를 고르고, 3장에 적힌 숫자들의 합이 소수인지 확인합니다.
  3. 받아든 카드로 만들 수 있는 소수의 개수가 많은 사람이 이기게 됩니다.
    예로, [1, 2, 3, 4]라는 카드를 받았을 때 만들 수 있는 숫자는 6, 7, 8, 9이고, 소수는 7 하나이기 때문에 가지고 있는 소수의 개수는 1개입니다.
    [2, 3, 4, 8, 13]라는 카드를 받았을 때 만들 수 있는 숫자는 9, 13, 18, 14, 19, 23, 15, 20, 24, 25이고, 소수는 13, 19, 23 총 3개이기 때문에 가지고 있는 소수의 개수는 3개입니다.

게임을 진행하기 전에 소수에 대해 아무런 지식이 없는 박타짜는 게임을 며칠 미룬 뒤, 게임의 룰을 따르는 함수를 만들기로 했습니다.
소수에 약한 박타짜를 도와 여러 장의 카드 중 세 장씩 조합해 소수가 되는 경우의 수를 리턴하는 함수를 완성해 주세요.

function boringBlackjack(cards) {
// TODO: 여기에 코드를 작성합니다.
const isPrime = (num) => {
if(num % 2 === 0) return false;
let sqrt = Math.floor(Math.sqrt(num));
for(let i = 3; i <= sqrt; i += 2) {
if(num % i === 0) {
return false;
}
}
return true;
};
let cnt = 0;
for(let i = 0; i < cards.length-2; i++) {
for(let j = i+1; j < cards.length-1; j++) {
for(let k = j+1; k < cards.length; k++) {
if(isPrime(cards[i]+cards[j]+cards[k])) {
cnt += 1;
}
}
}
}
return cnt;
}

최대공약수: 두 수로 공통으로 나누어 떨어지는 수 중 가장 큰 수.
function gcd(M, N) { // M이 N보다 큰 수일 경우
return (M % N) === 0 ? N : gcd(N, M % N);
}

profile
저는 서영준 입니다.

0개의 댓글