요즘 카카오톡 봇을 통해
쉬운 편의 알고리즘과 JavaScript에 대해서 공부할 수 있었다.
카카오톡 봇 정도는 꽤 재미 있게 JS를 익힐 수 있는 토이 프로젝트였던 것 같다
각설하고 오늘 공부했던걸 적어보자면
로또번호 생성 기능을 구현해보고 싶었는데
중복수 처리가 어려웠었다.
배열에서의 중복수 처리 문제
예를 들어 1부터 45까지의 난수를 생성한 배열까지는 너무나도 쉬웠지만
(Math에서 random()을 이용하면 되었고, 자연수 처리는 parseInt를 써도 되고 Math.floor()를 사용해도 되었다.
중복수라는게 처리하기가 난감했다.
생성된 난수에 1을 더해서 중복을 피하기(?)
예를 들어서 다른 사람의 알고리즘을 참조했을 때에는
난수를 생성했을 때 이미 배열에 들어가 있는 항목들과 비교해서 그 값이 같다면
방금 생성된 난수에 +1을 해서 중복을 피하는 형식이었다.
하지만 이 로직에는 치명적인 문제가 있다.
1. 45가 중복으로 나올 경우 46이 출력되어 내가 의도한 방향에서 어긋나게 설계되어버린다.
2. 위 방법으로도 중복을 피할 수 없다. 극히 낮은 확률이지만 1부터 46미만의 실수에서 정수 중에 똑같이 44가 나왔다면 혹은 44가 나오고 45가 나온다면?
이런 경우를 생각해보았을 때 result++ 은 근본적인 해결책이 아닌 미봉책일 뿐이었다.
프로그래밍에서 의도한 대로 프로그램이 돌아가지 않는 것은 정말 치명적이라고 생각한다.
일단 구현되면 되었지라는 마인드로 공부했다가 처절하게 깨졌던 몇달 전의 내 모습을 생각해보며 고민을 하면서 두시간쯤 흘렀을까
아주 간단한 해결책이 있었다.
그 전에 겪었던 시행착오에 대해서 하나 더 적어보려고 한다.
if( a.indexOf(b) == -1)
다른 어떤 분의 해석 중에서는 포함되지 않으면
배열에 push를 하지 않고 넘어가도록 코드를 짜셨다.
여기에서 내가 원하는 답에 가장 근접하게 되었다.
위의 코드를 그대로 가져오게 되었을 때 가장 큰 문제가 있었다면
초기 코드는 for문을 선언할 때 변수 i를 선언한 후 6번까지만 반복하도록 짰었는데
위 코드를 이용해서 바로 넘겨버리면
로또 번호인데 번호가 5개 혹은 4개만 출력되는 사태가 일어나는 것이었다.
그래서 밑의 코드로 완성이 되었고 의도한 대로 잘 동작하게 되었다.
/**
로또 번호 사이트를 크롤링해서 그 정보들을 조합해내 최신 번호를 알려주는 기능을 가지고 있습니다.
작성자 : 이민재(Minjae Lee)
최종수정일 : 2022.10.30
**/
const scriptName = "로또";
// 현재의 날짜와 각종 시간 정보를 얻어와서
// 실제 로또 복권을 받는 듯한 느낌에 조금이라도 더 근접하게 하고 싶었다.
let today = new Date();
let dayOfWeek = new Array("(일)", "(월)", "(화)", "(수)", "(목)", "(금)", "(토)");
let year = today.getFullYear();
let month = ('0' + (today.getMonth() + 1)).slice(-2);
let day = ('0' + today.getDate()).slice(-2);
let dateString1 = year + '-' + month + '-' + day;
let now_hour = today.getHours();
let now_minute = today.getMinutes();
let now_sec = today.getSeconds();
let dateString2 = now_hour + ':' + now_minute + ':' + now_sec;
function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) {
if( msg == "!로또생성" || msg == "!로또뽑기" ) {
replier.reply(sender + `님!
${lottoGenerator()}
행복이 깃들길 바래요 :)`);
}
}
function lottoGenerator(){
let message = `민재복권
Lotto 6/45
발급일 : ${dateString1} ${getTodayLabel()} ${dateString2}
${generateRandomString(16)}
-------------------------------------
A 자 동 ${lottoRandomSixNumber()}
B 자 동 ${lottoRandomSixNumber()}
C 자 동 ${lottoRandomSixNumber()}
D 자 동 ${lottoRandomSixNumber()}
E 자 동 ${lottoRandomSixNumber()}
-------------------------------------
`
return message;
}
// 요일을 한글로 출력하는 함수입니다.
function getTodayLabel(){
let dow = new Date().getDay();
let todayLabel = dayOfWeek[dow];
return todayLabel;
}
// 고유 번호 16자리를 출력하는 함수입니다.
const generateRandomString = (num) => {
const characters ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
const charactersLength = characters.length;
for (let i = 0; i < num; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
// 랜덤한 6개의 숫자를 배열에 넣고 그 배열을 오름차순으로 정렬한 후,
// 그 배열을 문자열화시켜 리턴하는 함수입니다.
function lottoRandomSixNumber(){
let lottoNumber = [];
for(let i = 0; i<6; i++){
let lotto = Math.floor((Math.random()*45)+1);
if(lottoNumber.indexOf(lotto)==-1){
lottoNumber.push(lotto);
}else{
i--
// 이 부분을 생각해내는게 그렇게 오래 걸렸었다. 중복수가 걸렸다면
// i를 +- = 0으로 만들어 진행을 계속해서 시키면 되는 문제였다.
}
}
lottoNumber.sort(function(a, b) {
if(a > b) return 1;
if(a === b) return 0;
if(a < b) return -1;
});
return `${lottoNumber[0]} ${lottoNumber[1]} ${lottoNumber[2]} ${lottoNumber[3]} ${lottoNumber[4]} ${lottoNumber[5]} `
}
/* 사용 결과
Q : !로또뽑기
A : 이민재님!
민재복권
Lotto 6/45
발급일 : 2022-10-30 (일) 14:12:20
VQWSpTZJ12SSE4iQ
----------------------------------
A 자 동 2 12 14 17 36 40
B 자 동 2 3 8 19 22 36
C 자 동 2 29 33 34 35 42
D 자 동 6 13 18 19 29 43
E 자 동 8 9 14 19 37 42
----------------------------------
행복이 깃들길 바래요 :)
*/
'코딩이야기 > JavaScript' 카테고리의 다른 글
[JavaScript] 카카오톡봇 가지고 놀면서 공부한 사실(3편) 구글 날씨 가져오기, 날씨 알림봇 (0) | 2023.02.02 |
---|---|
[Javascript] class와 상속의 사용 예제 (0) | 2023.01.20 |
[let, const] const에 객체를 담았을 때 (0) | 2023.01.20 |
[JavaScript] 주어진 수 n 이하의 모든 짝수의 합을 구하는 여러가지 방법 (0) | 2022.11.11 |
[Javascript] 카카오톡 봇 가지고 놀면서 공부한 사실들(1) (0) | 2022.08.06 |