ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [알고리즘/자바스크립트] 배열의 값으로 수량 체크하기 (Help the bookseller!)
    Algorithm 2019. 3. 3. 21:31

    -해당 문제는 codewars사이트의 level6 문제입니다. (1~8단계 중 8단계가 가장 쉬운 레벨)-



    [문제] A bookseller has lots of books classified in 26 categories labeled A, B, ... Z. Each book has a code c of 3, 4, 5 or more capitals letters. The 1st letter of a code is the capital letter of the book category. In the bookseller's stocklist each code c is followed by a space and by a positive integer n (int n >= 0) which indicates the quantity of books of this code in stock.


    For example an extract of one of the stocklists could be:


    L = {"ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"}.

    or

    L = ["ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"] or ....


    You will be given a stocklist (e.g. : L) and a list of categories in capital letters e.g :


    M = {"A", "B", "C", "W"}

    or

    M = ["A", "B", "C", "W"] or ...

    and your task is to find all the books of L with codes belonging to each category of M and to sum their quantity according to each category.


    For the lists L and M of example you have to return the string (in Haskell/Clojure a list of pairs):


    (A : 20) - (B : 114) - (C : 50) - (W : 0)


    where A, B, C, W are the categories, 20 is the sum of the unique book of category A, 114 the sum corresponding to "BKWRK" and "BTSQZ", 50 corresponding to "CDXEF" and 0 to category 'W' since there are no code beginning with W.


    If L or M are empty return string is "" (Clojure should return an empty array instead).


    Note:

    In the result codes and their values are in the same order as in M.




    [해석] 어떤 책 판매원은 책을 A~Z 사이의 알파벳 3자 이상으로 이루어진 코드 c를 붙여서 분류하였다. 이 c 코드의 첫번째 글자는 바로 책 제목 첫글자의 대문자이다. 이 서점의 재고 리스트는 c코드와 공백, 그리고 서적 수량을 의미하는 숫자로 이루어진 배열이다. 재고 수량은 0보다 큰 정수로만 이루어져있다.


    L = ["ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"]


    이제 우리에게는 위의 재고리스트와 함께 대문자 리스트가 주어질 것이다.


    M = ["A", "B", "C", "W"] 


    우리의 임무는 대문자 리스트에 있는 대문자로 코드가 시작되는 책들의 수량을 카테고리별로 각각 합산하여 다음과 같은 형태의 string으로 만드는 것이다.


    (A : 20) - (B : 114) - (C : 50) - (W : 0)


    만약에 대문자 리스트나 재고 리스트가 공백이라면 ""를 리턴해야한다.




    function stockList(listOfArt, listOfCat){
    	if(listOfArt.length === 0 || listOfCat.length === 0) 
    		return ''
    	var list = listOfArt.reduce((av, cv, i, arr) => {
    		listOfCat.forEach((alp) => {
    			var num = Number(cv.substring(cv.indexOf(' ')+1))
    			if(cv.indexOf(alp) == 0 && ! (alp in av)) {
    				av[alp] = num
    			} else if(cv.indexOf(alp) == 0 && alp in av) {
    				av[alp] += num
    			} else if (cv.indexOf(alp) < 0 && ! (alp in av)) {
    				av[alp] = 0
    			}
    		})
    		return av
    	}, {})
    	var result = ''
    	for(var i=0; i<listOfCat.length; i++) {
    		result += '('
    		result += listOfCat[i] + ' : ' +list[listOfCat[i]]
    		result += ') - '
    	}
    	return result.substring(0, result.length-3)
    }


    역시나 또 복잡하게 문제를 푼 나...

    언제쯤이면 나도 5줄로 깔끔하게 끝나는 코드를 쓸 수 있을지ㅜㅜ


    1. 일단 먼저 listOfArt와 listOfCat의 길이가 0이면 ""를 리턴한다.
    2. listOfArt에 reduce() 메소드를 사용하여 객체를 만들어주려고 한다. 초기값에 {}를 넣어준다.
    3. listOfCat 배열을 forEach문으로 반복하여 각각의 알파벳이 listOfArt에 있는 책 코드명에서 첫번째 index 지점에서 발견되는지를 판단해준다.
      • num 변수는 공백을 기준으로 잘라서 숫자만 추출한 후 Number 타입으로 변환해준 값이다. 즉, 책의 수량을 담는 변수이다.
    4. 만약에 알파벳이 첫번째 글자로 있으면 av에 알파벳을 키값으로 하여 책의 수량을 넣어준다.
    5. 이미 객체로 만들어진 알파벳이 또 나오면 해당 섹션에 값을 더해준다.
    6. 만약에 해당 코드의 책이 없다면 0을 넣어준다.


    이렇게 책의 재고 리스트가 객체형태로 만들어지면 

    (A : 20) - (B : 114) 

    이러한 형태의 string으로 만들어줘야 하는데 

    처음에 생각한 방법은 빈 string을 선언하고 누적해서 더해주는 방법이었다.


    그런데 이 방법을 쓰면 

    (A : 20) - (B : 114) - 

    이렇게 마지막 요소에도 ' - '값이 추가되어

    substring으로 마지막 3글자를 제외해주어야 한다.



    function stockList(listOfArt, listOfCat){
    	if(listOfArt.length === 0 || listOfCat.length === 0) 
    		return ''
    	var list = listOfArt.reduce((av, cv, i, arr) => {
    		listOfCat.forEach((alp) => {
    			var num = Number(cv.substring(cv.indexOf(' ')+1))
    			if(cv.indexOf(alp) == 0 && ! (alp in av)) {
    				av[alp] = num
    			} else if(cv.indexOf(alp) == 0 && alp in av) {
    				av[alp] += num
    			} else if (cv.indexOf(alp) < 0 && ! (alp in av)) {
    				av[alp] = 0
    			}
    		})
    		return av
    	}, {})
    	
    	listOfCat.forEach((v, i) => {
    		listOfCat.splice(i, 1, '('+v+' : '+list[v]+')')
    	})
    	return listOfCat.join(' - ')
    }


    그래서 생각한 방법은 위와 같다.


    배열에 splice로 알파벳과 숫자를 각각 (A : 20)의 형태로 넣은 후

    배열 요소들을 ' - ' 와 함께 join()시키는 방법이다.





    반응형

    COMMENT