티스토리 뷰

서론

프로그래머스에서 알고리즘 문제를 IDE환경에서 풀고싶을때가 있다.

하지만 프로그래머스는 웹페이지에서 다이렉트로 코드를 작성하는 방식이며 입력값을 자동으로 넣어준다.

ex) 프로그래머스 L1 붕대감기

그래서인지 백준과 같이 따로 입출력 값을 복붙하는 기능이 없으며 데이터 또한 다음과 같은 형태로 주어진다.

ex) 프로그래머스 L1 붕대감기

따라서 해당 데이터에 대한 입력 변수를 일일이 수기로 작성해야했다.

int bandage[] = {5,1,5};
int health = 30;
int attacks[] = {{2,10}, {9,15}, {10,5}, {11,5}};
int result = 5;

int answer = solution(bandage, health, attacks);

대괄호를 중괄호로 바꾸고 변수를 따로 생성하는 등 생각보다 번거롭다.

나는 주어진 데이터들을 가공하여 프로그래머스의 어떤 문제라도 IntelliJ IDE에서 빠르게 입력을 받아 solution 함수를 호출하도록 만들면 어떨까? 란 생각을 하게되었다.

 

본론

우선 위의 예시 데이터를 통째로 복붙하면 아래와같이 나온다.

bandage	health	attacks	result
[5, 1, 5]	30	[[2, 10], [9, 15], [10, 5], [11, 5]]	5
[3, 2, 7]	20	[[1, 15], [5, 16], [8, 6]]	-1
[4, 2, 7]	20	[[1, 15], [5, 16], [8, 6]]	-1
[1, 1, 1]	5	[[1, 2], [3, 2]]	3

String 변수를 선언하고 " " 사이에 해당 문자열을 복붙하면 \t 와 \n으로 속성을 구분해놓은것을 확인할 수 있다.

String input = "bandage\thealth\tattacks\tresult\n" +
                "[5, 1, 5]\t30\t[[2, 10], [9, 15], [10, 5], [11, 5]]\t5\n" +
                "[3, 2, 7]\t20\t[[1, 15], [5, 16], [8, 6]]\t-1\n" +
                "[4, 2, 7]\t20\t[[1, 15], [5, 16], [8, 6]]\t-1\n" +
                "[1, 1, 1]\t5\t[[1, 2], [3, 2]]\t3";

 

처음 구상은 위의 String 문자열을 통해 입력 변수를 새로 생성하여 solution 함수의 파라미터에 대입하려고했다.

int bandage[] = {5,1,5};
int health = 30;
int attacks[] = {{2,10}, {9,15}, {10,5}, {11,5}};
int result = 5;

int answer = solution(bandage, health, attacks);

하지만  Java에서는 문자열 리터럴("bandage", "health" 등)을 변수명으로 직접 사용할 수 없을 뿐더러 String 문자열로는 입력값의 타입도 알수 없었다.

따라서 리플렉션(Reflection)을 사용해 Method 객체를 생성한 후 solution 함수의 파라미터 이름과 타입을 가져와 그에 맞는 데이터를  동적으로 처리해야한다.

※ 리플렉션(Reflection) : 자바에서 런타임에 클래스의 구조를 분석하고, 그 클래스의 메서드, 필드, 생성자 등을 동적으로 접근하거나 조작할 수 있게 해주는 기능.

 

요약

1. 리플렉션으로 메서드 정보를 가져오기

  • 클래스명.class.getMethods()를 통해 클래스 내 모든 solution 메서드를 가져온다.

2. 문자열 파싱

  • 입력된 문자열을 줄바꿈(\n)과 탭(\t)으로 분리하여 데이터 필드를 추출.
  • 각 필드를 파라미터 타입에 맞게 변환한다. ( int[], double, String, int[][] 등)

3. 동적으로 메서드 호출

  • 추출한 데이터를 적절히 변환한 후, Method.invoke()를 사용하여 리플렉션으로 메서드를 호출한다.

 

소스코드

package com.programmers;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;

public class L1_붕대감기 {

    public static void main(String[] args) throws Exception{

        String input = "bandage\thealth\tattacks\tresult\n" +
                "[5, 1, 5]\t30\t[[2, 10], [9, 15], [10, 5], [11, 5]]\t5\n" +
                "[3, 2, 7]\t20\t[[1, 15], [5, 16], [8, 6]]\t-1\n" +
                "[4, 2, 7]\t20\t[[1, 15], [5, 16], [8, 6]]\t-1\n" +
                "[1, 1, 1]\t5\t[[1, 2], [3, 2]]\t3";
        parseAndCallSolution(L1_붕대감기.class, input);
    }
    
    public static int solution(int[] bandage, int health, int[][] attacks) {
        int answer = 0;
        System.out.println("bandage: " + Arrays.toString(bandage));
        System.out.println("health: " + health);
        System.out.println("attacks: " + Arrays.deepToString(attacks));
        return answer;
    }

    // 문자열을 파싱하여 데이터를 추출하고 solution 메서드를 동적으로 호출하는 함수
    public static void parseAndCallSolution(Class<?> clazz, String input) throws Exception {
        System.out.println("call parseAndCallSolution");
        // 전달된 클래스의 메서드 정보를 리플렉션으로 가져옴
        Method[] methods = clazz.getMethods();

        // 입력 파싱 (첫 번째 줄은 헤더, 이후는 데이터)
        String[] lines = input.split("\n");
        String[] headers = lines[0].split("\t");
        String[] data = lines[1].split("\t");
        System.out.println(Arrays.toString(data));

        // solution 메서드 중 하나를 찾아서 호출하기
        for (Method method : methods) {
            if (method.getName().equals("solution")) {
                Parameter[] parameters = method.getParameters();
                // 파라미터 개수와 일치하는 메서드인지 확인 result 를 빼야하므로 -1
                if (parameters.length == data.length-1) {
                    System.out.println("test");
                    Object[] parsedParams = new Object[parameters.length];

                    for (int i = 0; i < parameters.length; i++) {
                        Class<?> paramType = parameters[i].getType();
                        String field = data[i];

                        // 파라미터 타입에 따라 데이터 변환
                        if (paramType == int[].class) {
                            // int[]로 변환
                            parsedParams[i] = parseIntArray(field);
                        } else if (paramType == int.class) {
                            // int로 변환
                            parsedParams[i] = Integer.parseInt(field);
                        } else if (paramType == long.class) {
                            // long으로 변환
                            parsedParams[i] = Long.parseLong(field);
                        } else if (paramType == long[].class) {
                            // long[]로 변환
                            parsedParams[i] = parseLongArray(field);
                        } else if (paramType == long[][].class) {
                            // long[][]로 변환
                            parsedParams[i] = parseLongMatrix(field);
                        } else if (paramType == double.class) {
                            // double로 변환
                            parsedParams[i] = Double.parseDouble(field);
                        } else if (paramType == int[][].class) {
                            // int[][]로 변환
                            parsedParams[i] = parseIntMatrix(field);
                        } else if (paramType == String.class) {
                            // String으로 변환
                            parsedParams[i] = field;
                        } else if (paramType == String[].class) {
                            // String[]로 변환
                            parsedParams[i] = parseStringArray(field);
                        } else if (paramType == String[][].class) {
                            // String[][]로 변환
                            parsedParams[i] = parseStringMatrix(field);
                        } else if (paramType == Object[].class) {
                            // Object[]로 변환 (예시로 간단히 구현)
                            parsedParams[i] = field.split(", ");
                        } else {
                            // 처리할 수 없는 타입일 때 기본적으로 문자열로 처리
                            parsedParams[i] = field;
                        }
                    }

                    // solution 메서드를 호출하고 결과 출력
                    method.invoke(null, parsedParams);
                    break;
                }
            }
        }
    }

    // 배열 파싱을 위한 헬퍼 함수들
    public static int[] parseIntArray(String input) {
        String cleaned = input.replaceAll("[\\[\\]]", ""); // 대괄호 제거
        String[] parts = cleaned.split(", ");
        int[] arr = new int[parts.length];
        for (int i = 0; i < parts.length; i++) {
            arr[i] = Integer.parseInt(parts[i]);
        }
        return arr;
    }

    public static long[] parseLongArray(String input) {
        String cleaned = input.replaceAll("[\\[\\]]", ""); // 대괄호 제거
        String[] parts = cleaned.split(", ");
        long[] arr = new long[parts.length];
        for (int i = 0; i < parts.length; i++) {
            arr[i] = Long.parseLong(parts[i]);
        }
        return arr;
    }

    public static int[][] parseIntMatrix(String input) {
        String cleaned = input.replaceAll("[\\[\\]]", ""); // 대괄호 제거
        String[] pairs = cleaned.split("], ");
        int[][] arr = new int[pairs.length][2];
        for (int j = 0; j < pairs.length; j++) {
            String[] pair = pairs[j].split(", ");
            arr[j][0] = Integer.parseInt(pair[0]);
            arr[j][1] = Integer.parseInt(pair[1]);
        }
        return arr;
    }

    public static long[][] parseLongMatrix(String input) {
        String cleaned = input.replaceAll("[\\[\\]]", ""); // 대괄호 제거
        String[] pairs = cleaned.split("], ");
        long[][] arr = new long[pairs.length][2];
        for (int j = 0; j < pairs.length; j++) {
            String[] pair = pairs[j].split(", ");
            arr[j][0] = Long.parseLong(pair[0]);
            arr[j][1] = Long.parseLong(pair[1]);
        }
        return arr;
    }

    public static String[] parseStringArray(String input) {
        String cleaned = input.replaceAll("[\\[\\]]", ""); // 대괄호 제거
        return cleaned.split(", ");
    }

    public static String[][] parseStringMatrix(String input) {
        String cleaned = input.replaceAll("[\\[\\]]", ""); // 대괄호 제거
        String[] pairs = cleaned.split("], ");
        String[][] arr = new String[pairs.length][];
        for (int j = 0; j < pairs.length; j++) {
            arr[j] = pairs[j].split(", ");
        }
        return arr;
    }
}

 

결론

조금 편해보자고 열심히 머리를 굴려봤지만 결과물은 위와같이 처참했다.

solution의 파라미터 타입을 동적으로 처리해줄 방법이 없어서 타입별로 if else를 난사해야했다.

또한 Refletion메소드는 일반 메서드보다 호출이 느리고 컴파일 시점에 결정되는게 아니라 런타임에 처리되기 때문에 추가적인 오버해드가 발생한다. 성능이 저하된다는 뜻이다.

=> 걍 수기로 입력하자.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함