그리디 알고리즘이 다 그런건 아니지만 이 챕터에서 보여준 예제들의 특징은 뭉터기로 잘라내는 법을 찾아내는 것.

import java.util.*;
public class main {
    public static void main(String[] args) {

        Solution s = new Solution();
        System.out.println("GridExample01: "+s.GridExample01(1260));
        System.out.println("GridExample01Guide: "+s.GridExample01Guide(1260));

        System.out.println("GridExample02_01: "+s.GridExample02_01(new int[]{5,8,3}, new int[]{2,4,5,4,6}));
        System.out.println("GridExample02_02: "+s.GridExample02_02(new int[]{5,8,3}, new int[]{2,4,5,4,6}));
        System.out.println("GridExample02Guide: "+s.GridExample02Guide(new int[]{5,8,3}, new int[]{2,4,5,4,6}));
        //02_01과 유사. 한번씩 덧셈을 하지 않고 뭉터기로 덧셈을 할 수 있는 조건을 찾아내는 것이 단축의 핵심
        System.out.println("GridExample02Guide02: "+s.GridExample02Guide(new int[]{5,8,3}, new int[]{2,4,5,4,6}));

        //03은 가이드와 직접 작성했던 것과 유사해서 가이드 생략
        System.out.println("GridExample03 val1: "+s.GridExample03(new int[][]{{3,1,2},{4,1,4}, {2,2,2}}));
        System.out.println("GridExample03 val2: "+s.GridExample03(new int[][]{{7,4,1,8},{3,3,3,4}}));


        System.out.println("GridExample04: "+s.GridExample04(25,5));
        //1씩 빼지 않고 나머지 차를 그대로 빼는 것이 핵심. k > n일 경우 빠지는 것도 중요.
        System.out.println("GridExample04Guide: "+s.GridExample04(25,5));
    }
}
class Solution {
    public int GridExample01(int n) {
        int n500 = n / 500;
        int n100 = (n%500) / 100;
        int n50 = (n%100) / 50;
        int n10 = (n%50) / 10;
        return n500+n100+n50+n10;
    }
    public int GridExample01Guide(int n) {
        int[] coin = new int[]{500,100,50,10};
        int count = 0;
        for(int c : coin) {
            count += n/c;
            n %= c;
        }
        return count;
    }
    public int GridExample02_01(int[] valid, int [] num) {
        Arrays.sort(num);
        int n = valid[0];
        int m = valid[1];
        int k = valid[2];
        int answer = 0;
        //수정부
        int p = 0;
        int first = num[num.length-1];
        int second = num[num.length-2];

        if(k > m)
            return m * first;

        if(k+1 <= m) {
            p = m/(k+1);
            m %= (k+1);
        }
        answer += p * (first * k + second);
        answer += m*first;
        return answer;
    }
    public int GridExample02_02(int[] valid, int [] num) {
        Arrays.sort(num);
        int n = valid[0];
        int m = valid[1];
        int k = valid[2];
        int answer = 0;
        int t = k;
        int i = num.length-1;
        while(m > 0) {
            if(t > 0) {
                answer += num[i];
                t--;
            }
            else {
                t = k;
                answer += num[i-1];
            }
            m--;
        }

        return answer;
    }
    public int GridExample02Guide(int[] valid, int [] num) {
        Arrays.sort(num);
        int answer = 0;
        int m = valid[1];
        int k = valid[2];
        int first = num[num.length-1];
        int second = num[num.length-2];
        while(true) {
            for(int t =0; t<k;t++) {
                if(m == 0)
                    break;
                answer += first;
                m--;
            }
            if(m == 0) {
                break;
            }
            answer += second;
            m--;
        }

        return answer;
    }
    public int GridExample02Guide02(int[] valid, int [] num) {
        Arrays.sort(num);
        int answer=0;
        int m = valid[1];
        int k = valid[2];
        int first = num[num.length-1];
        int second = num[num.length-2];

        int count = m / (k+1) * k;
        count += m % (k+1);
        answer += count * first;
        answer += (m-count) * second;
        return answer;
    }
    public int GridExample03(int[][] cards) {
        int answer = -1;
        for(int[] row : cards)
            Arrays.sort(row);
        for(int i = 0; i<cards.length;++i) {
            if(cards[i][0] > answer)
                answer = cards[i][0];
        }
        return answer;
    }
    public int GridExample04(int n, int k) {
        int answer = 0;

        while(n != 1) {
            if(n % k == 0) {
                n/=k;
                answer++;
            }
            else {
                n--;
                answer++;
            }
        }

        return answer;
    }
    public int GridExample04Guide(int n, int k) {
        int answer = 0;

        int target;
        while(true) {
            target = (n/k)*k;
            answer += (n - target);
            if(n < k) {
                break;
            }
            answer += 1;
            n /= k;
        }
        answer += (n-1);
        return answer;
    }
}
Map<String, Object> lstParam = new HashMap<String, Object>();

Map<String, Object> mapParam;
List<Map<String, Object>> dsBuildList;
List<Map<String, Object>> dsObjList;
List<Map<String, Object>> dsBuildMrtggList;
List<Map<String, Object>> dsPldgList;
List<Map<String, Object>> dsClauseList;
List<Map<String, Object>> dsLoanList;

lstParam.put("mapParam",mapParam);
lstParam.put("dsBuildList",dsBuildList);
lstParam.put("dsObjList",dsObjList);
lstParam.put("dsBuildMrtggList",dsBuildMrtggList);
lstParam.put("dsPldgList",dsPldgList);
lstParam.put("dsClauseList",dsClauseList);
lstParam.put("dsLoanList",dsLoanList);

일반적으로 Mybatis에 Parameter를 넣을 때, 보통 Map<String, Object>, List<Map<String, Object>>와 같은 형태로 집어 넣은 상태를 많이 봤었다.

복수의 List와 Map이 섞인 형태의 Parameter가 필요한 경우가 생길 수 있다.

한 번 Database를 건드릴 때, 일반적으로 하나의 테이블을 각각 Dao를 통해서 건드리게 되는 것이 일반적이지만 insert 도중, 에러가 발생하면 전체 롤백이 필요할 수 있기 때문이다.

다른 방법도 있겠지만 일단 앞에서 개발한 사람 것에 맞추는 것이 일반적이니까...

일단 Object가 최상위 Class 형태니까 위와 같이 하면 List든 Map이든 다 들어간다.

	<insert id="savePreLink" parameterType="java.util.Map">
             DECLARE
                 v_frid	         VARCHAR2(10);  -- 등록자
                 v_chng_val 	 VARCHAR2(10); -- 변경구분						
             BEGIN		    
                 v_frid	         := #{mapParam.FRID};
                 v_chng_val		 := #{mapParam.CHNG_TYPE};
                 
		    BEGIN
                        <foreach item="item" index="key" collection="dsBuildMrtggList" separator="">
                        v_row_03 := v_row_03 + 1;
                        INSERT INTO IF_BEN_HYU_CALC_SECT
                        (
                          SECTCD_NO
                        , SECTCD
                        , SECTMODYN
                        )
                        VALUES
                        (
                          v_row_03
                        , CASE 
                           WHEN #{item.MRTGG_CD} = 'T405' THEN '12'
                           WHEN #{item.MRTGG_CD} = 'U989' THEN '01'
                           WHEN #{item.MRTGG_CD} = 'W990' THEN '01'
                           WHEN #{item.MRTGG_CD} = 'T152' THEN '05'
                           WHEN #{item.MRTGG_CD} = 'T050' THEN '12'
                          END
                        , #{item.NOW_ROWTYPE}
                        );
                        </foreach>
		    END;
            
  ....
		    COMMIT;
		
		    EXCEPTION 
		        WHEN OTHERS THEN
		        	ROLLBACK;
		            RAISE_APPLICATION_ERROR(-20000, 'ERROR - '|| v_step);
		
		END;

	</insert>

코드를 다 올려선 안되기에 일부 삭제가 되었지만 위와 같이 Map에서 Map을 꺼내거나 foreach를 이용하여 List를 사용하는 식으로 사용할 수 있다.

처음엔 이런 내용이 검색해도 안보여서 뭔가 했는데 사실 이렇게 쓰면 안좋아서 쓰는 사람이 없어서 관련 내용이 없었던 것 같다.

this.fnDatasetEsbCall = function (dsData, dsEsbCall)
{
	dsEsbCall.copyData(dsData);
	dsEsbCall.clearData();
	for(var i = 0; i<dsData.rowcount;++i)
	{	
		if(true) {
			
			if(dsData.getColumn(i, "BF_ROWTYPE") == "BF")//"BF" 기존 DB에 존재하던 값을 의미
			{
				if(dsData.getRowType(i) == 4)//값이 변경된 경우. U(업데이트) 처리
				{
					dsEsbCall.addRow();
					dsEsbCall.copyRow(dsEsbCall.rowcount-1, dsData, i);
					dsEsbCall.setColumn(dsEsbCall.rowcount-1, "NOW_ROWTYPE", "U");
					dsEsbCall.setColumn(dsEsbCall.rowcount-1, "BF_ROWTYPE", dsData.getColumn(i, "BF_ROWTYPE"));
				}
				else//기존 값
				{
					dsEsbCall.addRow();
					dsEsbCall.copyRow(dsEsbCall.rowcount-1, dsData, i);
					dsEsbCall.setColumn(dsEsbCall.rowcount-1, "NOW_ROWTYPE", "N");
					dsEsbCall.setColumn(dsEsbCall.rowcount-1, "BF_ROWTYPE", dsData.getColumn(i, "BF_ROWTYPE"));
				}
			}
			else//신규 입력값
			{
				dsEsbCall.addRow();
				dsEsbCall.copyRow(dsEsbCall.rowcount-1, dsData, i);
				dsEsbCall.setColumn(dsEsbCall.rowcount-1, "NOW_ROWTYPE", "I");		
				dsEsbCall.setColumn(dsEsbCall.rowcount-1, "BF_ROWTYPE", dsData.getColumn(i, "BF_ROWTYPE"));
			}
		}
	}
	var delArr = dsData.getDeletedRowset();
	
	//삭제된 행 확인 후,  EsbCall에 추가.
	for(var i = 0; i<dsData.getDeletedRowset().length;++i)
	{
		var delRow = delArr[i];

		if(delRow.includes("BF"))
		{
			dsEsbCall.addRow();
			for(var j = 0; j<dsData.colcount;++j)
			{
				dsEsbCall.setColumn(dsEsbCall.rowcount-1, j, delRow[j]);
			}
			dsEsbCall.setColumn(dsEsbCall.rowcount-1, "NOW_ROWTYPE", "D");
		}
	}
	if(this.dsObjList==dsData) {

		var colArray = new Array("SPOP_1_VAL","SPOP_2_VAL","SPOP_3_VAL","SPOP_4_VAL","SPOP_5_VAL");

		for(var i = 0; i<dsEsbCall.rowcount; ++i) {
			
			var tFront = "BUILD_SN == '"+dsEsbCall.getColumn(i, "BUILD_SN")+"' && PURPS_SN == '"+dsEsbCall.getColumn(i, "PURPS_SN")+"'";
			
			//dsClauseList dataset의 복수의 값을 dsObjList에 넣기위한 조치
			var txt = new Array(tFront + " && SPOP_CD == 'T191'", "BGITDTARIFCAT1" 
							  , tFront + " && SPOP_CD =='T117'", "VGITDTARIFCAT3,GITDTARIFCAT5,GITDTARIFCAT4,GITDTARIFCAT6"
						      , tFront + " && (SPOP_CD == 'T750' || SPOP_CD =='T722')", "GITDTARIF7,GITDTARIF6,BGITDTARIFCAT6"
				         	  , tFront + " && (SPOP_CD == 'T855' || SPOP_CD =='T856')", "GITDTARIFCAT3"
					          , tFront + " && SPOP_CD == 'T559'", "ELAGDDCTAMT"
					          , tFront + " && SPOP_CD == 'T490'", "GITDTARIFCAT16,GITDTARIFCAT17,GITDTARIFCAT18,GITDTARIFCAT19,GITDTARIFCAT15"
					          , tFront + " && SPOP_CD == 'T406'", "RGITDTARIFCAT1"
					          , tFront + " && SPOP_CD == 'T594'", "GITDTARIFCAT10"
					          , tFront + " && SPOP_CD == 'T655'", "GITDTARIFCAT26,GITDTARIFCAT27,GITDTARIFCAT28,GITDTARIFCAT29"
					          );
			for(var j = 0; j<txt.length;j+=2) {
				var t = this.dsClauseList.findRowExpr(txt[j]);
	
				if(t != -1) {
					var insertArr = txt[j+1].split(","); 
					for(k = 0;k<insertArr.length;++k) {
						dsEsbCall.setColumn(i, insertArr[k], this.dsClauseList.getColumn(t2, colArray[k]));
					}
				}			
			}
		}
	}
}

Nexacro에서는 getRowType(n)을 통해 특정 row의 CRUD 상태를 알 수 있다.

그런데 어쩌다보니 이런걸 만들어야 할 필요가 생겼다. 기존 dataset에 deletedRowset을 추가하는 것도 방법이었지만 원본 dataset을 보존해야 할 필요가 있었기에 간략하게 만들었다. 실제 업무와 관련된 부분을 다 지웠더니 좀 너무 이상하게 보일 수 있다. BF가 없어도 되는데 왜 있어야 하느니..

특정 dataset에서 타 dataset의 column에 값을 넣어야 하는데 column명이 서로 다르고 임의로 맞춰넣어야 하기에 

Array로 조건을 묶어서 수정하기 쉽게 진행을 해보았다. 변경이 필요할 경우 한줄씩 바꾸면 되기 때문에 효율적이라 생각했다.

'Web' 카테고리의 다른 글

Nexacro Components 제어 Function  (0) 2020.06.18
Nexacro Div 정렬 Function  (0) 2020.06.18

+ Recent posts