현대 그룹에서 만든 Soofteer에서 최근 알고리즘 문제를 풀어봤다. 프로그래머스를 주로 풀면서 느꼈던 차이점은 프로그래머스에서는 입력 값을 직접 받지는 않는 반면에 소프티어에서는 직접 입력 값을 받아서 출력하는식으로 문제를 해결해야 한다.

 

그래서 뭐 하나만 계속 하는것보다는 프로그래머스와 소프티어 둘 다 활용해보면서 입력, 출력 문제도 연습하고, 메서드 파라미터를 활용하여 리턴 값을 가져오는 연습도 해보는 것이 좋다고 느꼈다.

 

평소에 코드 작성 연습을 IntelliJ IDEA에서 했었는데 자동 완성 기능에 익숙해져서 그런지 소프티어 IDE에서만 코드를 작업하는 것이 조금 힘들게 느껴진 부분도 있었다. 예를 들어 IntelliJ에서는 sout 하고 엔터를 치면 System.out.println이 바로 쳐지지만 소프티어 IDE에서는 그렇지 않았다. IDEA에 의존하지 않고 코드를 작성하는 연습이 필요할 것 같다.

 

소프티어에서 Level 2에 해당하는 문제들인 회의실 예약, 전광판, 비밀 메뉴, GBC, 지도 자동 구축, 장애물 인식 프로그램, 8단 변속기, 바이러스, 금고털이를 풀어보면서 느꼈던 점은 같은 Level 2여도... 엄청난 차이가 있는 거 같다.

 

GBC, 회의실 예약 같은 문제는 시간이 생각보다 정말 많이 걸렸다. 출력하는 방법에 미숙하기도 했고, 반복문이 많아지고, 어떤 자료구조를 사용해야 효율적인지 잘 모르겠던 부분이 많았다. 하지만 소프티어의 경우 메모리 제한은 생각보다 넉넉하게 제한하고 있는 것 같아서 메모리가 초과되는 경우는 거의 없었다. 

 

사실 리펙토링도 많이 중요하지만...일단 실행이 되는 것이 우선이기 때문에 코드가 작동되는 것에 먼저 관점을 두고 공부를 해야할 것 같다. Java는 정말...활용도가 엄청난 거 같다. 대신 아는 만큼 더 효율적으로 사용할 수 있다는 것...

 

금고털이

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String[] firstInputData = reader.readLine().split(" ");
        int W = Integer.parseInt(firstInputData[0]);
        int N = Integer.parseInt(firstInputData[1]);

        List<Stone> list = new ArrayList();

        for (int i = 0; i < N; i++) {
            String[] stoneData = reader.readLine().split(" ");
            list.add(new Stone(Integer.parseInt(stoneData[0]), Integer.parseInt(stoneData[1])));
        }

        Collections.sort(list);

        int result = 0;
        int stoneIndex = 0;
        while (true) {
            Stone stone = list.get(stoneIndex);
            if (stone.M < W) {
                W -= stone.M;
                result += stone.M * stone.P;
                stoneIndex++;
                continue;
            }
            result += W * stone.P;
            break;
        }

        System.out.println(result);
    }
}

class Stone implements Comparable<Stone> {
    int M;
    int P;

    public Stone(int M, int P) {
        this.M = M;
        this.P = P;
    }

    @Override
    public int compareTo(Stone obj) {
        return obj.P - this.P;
    }
}

 

바이러스

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer tokenizer = new StringTokenizer(reader.readLine());

        long K = Integer.parseInt(tokenizer.nextToken());
        long P = Integer.parseInt(tokenizer.nextToken());
        int N = Integer.parseInt(tokenizer.nextToken());

        for (int i = 1; i <= N; i++) {
            K = K * P % 1000000007;
        }

        System.out.println(K);
    }
}

 

8단 변속기

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String inputData = reader.readLine();

        if (inputData.equals("1 2 3 4 5 6 7 8")) {
            System.out.println("ascending");
        } else if (inputData.equals("8 7 6 5 4 3 2 1")) {
            System.out.println("descending");
        } else {
            System.out.println("mixed");
        }

        
    }
}

 

장애물 인식 프로그램

import java.util.*;
import java.io.*;


public class Main
{
    static int count = 0;

    public static void main(String args[]) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[][] graph = new int[N][N];
        List<Integer> result = new ArrayList<>();

        for (int i = 0; i < N; i++) {
            String[] data = br.readLine().split("");
            for (int j = 0; j < N; j++) {
                graph[i][j] = Integer.parseInt(data[j]);
            }
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                count = 0;
                if (graph[i][j] == 0) {
                    continue;
                }
                dfs(i, j, graph, N);
                result.add(count);
            }
        }

        Collections.sort(result);
        System.out.println(result.size());
        result.stream().forEach(System.out::println);
    }

    public static void dfs(int i, int j, int[][] graph, int N) {
        if (i < 0 || j < 0 || i >= N || j >= N) {
            return;
        }

        if (graph[i][j] == 0) {
            return;
        }

        if (graph[i][j] == 1) {
            graph[i][j] = 0;
            count++;
            dfs(i, j + 1, graph, N);
            dfs(i, j - 1, graph, N);
            dfs(i + 1, j, graph, N);
            dfs(i - 1, j, graph, N);
        }
    }
}

 

지도 자동 구축

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(reader.readLine());

        int result = getResult(N);

        System.out.println(result * result);
    }

    public static int getResult(int N) {
        if (N == 0) {
            return 2;
        }
        return getResult(N - 1) + (int)Math.pow(2, N - 1);
    }
}

 

GBC

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        
        StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
        int n = Integer.parseInt(tokenizer.nextToken());
        int m = Integer.parseInt(tokenizer.nextToken());

        Section nSection = new Section();
        int before = 0;

        for (int i = 0; i < n; i++) {
            tokenizer = new StringTokenizer(reader.readLine());
            nSection.scope.add(before + Integer.parseInt(tokenizer.nextToken()));
            nSection.speed.add(Integer.parseInt(tokenizer.nextToken()));

            before = nSection.scope.get(i);
        }

        Section mSection = new Section();
        before = 0;
        
        for (int i = 0; i < m; i++) {
            tokenizer = new StringTokenizer(reader.readLine());
            mSection.scope.add(before + Integer.parseInt(tokenizer.nextToken()));
            mSection.speed.add(Integer.parseInt(tokenizer.nextToken()));

            before = mSection.scope.get(i);
        }

        int result = 0;
        before = 0;

        for (int i = 0; i < n; i++) {
            int sectionLimitSpeed = nSection.speed.get(i);
            int sectionMaxSpeed = mSection.getMaxSpeed(before, nSection.scope.get(i));
            result = Math.max(result, sectionMaxSpeed - sectionLimitSpeed);
            before = nSection.scope.get(i) + 1;
        }

        System.out.println(result);
    }
}

class Section {
    List<Integer> scope = new ArrayList<>();
    List<Integer> speed = new ArrayList<>();

    public int getMaxSpeed(int start, int end) {
        int s = 0;

        for (int i = start; i <= end; i++) {
            s = Math.max(s, getSpeed(i));
        }

        return s;
    }

    public int getSpeed(int value) {
        int s = 0;

        for (int i = 0; i < scope.size(); i++) {
            if (value <= scope.get(i)) {
                s = speed.get(i);
                break;
            }
        }

        return s;
    }
}

 

[21년 재직자 대회 예선] 비밀 메뉴

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        
        String[] inputData = reader.readLine().split(" ");
        int M = Integer.parseInt(inputData[0]);
        int N = Integer.parseInt(inputData[1]);
        int K = Integer.parseInt(inputData[2]);

        String[] SecretCode = reader.readLine().split(" ");
        String[] MyCode = reader.readLine().split(" ");

        boolean isSecret = false;

        for (int i = 0; i < MyCode.length; i++) {
            if (MyCode.length - i < SecretCode.length || isSecret) {
                break;
            }

            if (MyCode[i].equals(SecretCode[0])) {
                isSecret = Arrays.equals(Arrays.copyOfRange(MyCode, i, i + SecretCode.length), SecretCode);
            }
        }

        if (isSecret) {
            System.out.println("secret");
        } else {
            System.out.println("normal");
        }
    }
}

 

[21년 재직자 대회 예선] 전광판

import java.util.*;
import java.io.*;


public class Main
{
    private static final List<int[]> digitInfo = new ArrayList<>() {{
        add(new int[]{1, 1, 1, 0, 1, 1, 1});
        add(new int[]{0, 0, 1, 0, 0, 1, 0});
        add(new int[]{1, 0, 1, 1, 1, 0, 1});
        add(new int[]{1, 0, 1, 1, 0, 1, 1});
        add(new int[]{0, 1, 1, 1, 0, 1, 0});
        add(new int[]{1, 1, 0, 1, 0, 1, 1});
        add(new int[]{1, 1, 0, 1, 1, 1, 1});
        add(new int[]{1, 1, 1, 0, 0, 1, 0});
        add(new int[]{1, 1, 1, 1, 1, 1, 1});
        add(new int[]{1, 1, 1, 1, 0, 1, 1});
    }};

    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(reader.readLine());

        for (int i = 0; i < T; i++) {
            StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
            int firstValue = Integer.parseInt(tokenizer.nextToken());
            int secondValue = Integer.parseInt(tokenizer.nextToken());

            System.out.println(testCase(firstValue, secondValue));
        }
    }

    public static int testCase(int firstValue, int secondValue) {
        int result = 0;

        List<Integer> firstValueDigit = getDigitInfo(firstValue);
        List<Integer> secondValueDigit = getDigitInfo(secondValue);

        for (int i = 0; i < 5; i++) {
            result += getChangeCount(firstValueDigit.get(i), secondValueDigit.get(i));
        }

        return result;
    }

    public static int getChangeCount(int x, int y) {
        if (x == -1 && y == -1) {
            return 0;
        }

        if (x == -1) {
            return (int)Arrays.stream(digitInfo.get(y)).filter(data -> data == 1).count();
        }

        if (y == -1) {
            return (int)Arrays.stream(digitInfo.get(x)).filter(data -> data == 1).count();
        }

        int changeCount = 0;
        int[] xInfo = digitInfo.get(x);
        int[] yInfo = digitInfo.get(y);

        for (int i = 0; i < 7; i++) {
            if (xInfo[i] != yInfo[i]) {
                changeCount++;
            }
        }

        return changeCount;
    }

    public static List<Integer> getDigitInfo(int value) {
        List<Integer> info = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            info.add(value / 10000);
            info.add(value % 10000 / 1000);
            info.add(value % 1000 / 100);
            info.add(value % 100 / 10);
            info.add(value % 10);
        }

        int length = String.valueOf(value).length();

        for (int i = 0; i < 5 - length; i++) {
            info.set(i, -1);
        }

        return info;
    }
}

 

[21년 재직자 대회 예선] 회의실 예약

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String[] firstInputData = reader.readLine().split(" ");

        int N = Integer.parseInt(firstInputData[0]);
        int M = Integer.parseInt(firstInputData[1]);

        Map<String, ConferenceRoom> conferenceRoom = new HashMap<String, ConferenceRoom>();

        for (int i = 0; i < N; i++) {
            String name = reader.readLine();
            conferenceRoom.put(name, new ConferenceRoom(name));
        }

        for (int i = 0; i < M; i++) {
            String[] conferenceData = reader.readLine().split(" ");
            String name = conferenceData[0];
            int start = Integer.parseInt(conferenceData[1]);
            int end = Integer.parseInt(conferenceData[2]);

            List<Boolean> currentAvailable = conferenceRoom.get(name).available;
            
            for (int j = start - 9; j <= end - 10; j++) {
                currentAvailable.set(j, false);
            }
            
        }

        List<String> sortedKey = new ArrayList<>(conferenceRoom.keySet());
        Collections.sort(sortedKey);

        for (int i = 0; i < sortedKey.size(); i++) {
            System.out.println("Room " + conferenceRoom.get(sortedKey.get(i)).name + ":");

            ConferenceRoom pickedConferenceRoom = conferenceRoom.get(sortedKey.get(i));
            List<Boolean> currentAvailable = pickedConferenceRoom.available;

            if (!currentAvailable.contains(true)) {
                System.out.println("Not available");
            } else {
                System.out.println(pickedConferenceRoom.getCount() + " available:");
                pickedConferenceRoom.printCurrentAvailable();
            }
            
            if (i != sortedKey.size() - 1) {
                System.out.println("-----");
            }
        }
    }
}

class ConferenceRoom {
    String name;
    List<Boolean> available;
    List<int[]> availableTime;

    public ConferenceRoom(String name) {
        this.name = name;

        available = new ArrayList<Boolean>();

        for (int i = 0; i < 9; i++) {
            available.add(true);
        }

        availableTime = new ArrayList<int[]>();
    }

    public int getCount() {
        int count = 0;
        boolean before = false;

        int start = 0;
        int end = 0;

        for (int i = 0; i < available.size(); i++) {
            if (!before && available.get(i)) {
                start = i + 9;
                before = true;
            } else if (before && !available.get(i)) {
                end = i + 9;
                before = false;
                count++;
                availableTime.add(new int[]{start, end});
            }
        }

        if (before) {
            count++;
            availableTime.add(new int[]{start, 18});
        }

        return count;
    }

    public void printCurrentAvailable() {
        for (int[] a : availableTime) {
            System.out.printf("%02d-%02d\n", a[0], a[1]);
        }
    }
}

 

정답을 맞추기 위해서 풀었던 문제들이 많았기에...코드가 가독성이 많이 떨어집니다... 그냥 기록이라도 해놓기 위해서 올려둔 것이기 때문에 불편해도 어쩔 수 없습니다. 하하하 🤓

 

 

 

문제 설명

어떤 부서의 업무 조직은 완전이진트리 모양이다. 즉, 부서장이 루트이고 부서장 포함 각 직원은 왼쪽과 오른쪽의 부하 직원을 가진다. 부하 직원이 없는 직원을 말단 직원이라고 부른다.

모든 말단 직원은 부서장까지 올라가는 거리가 동일하다. 조직도 트리의 높이는 H이다. 아래는 높이가 1이고 업무가 3개인 조직도를 보여준다.

 

업무는 R일 동안 진행된다. 처음에 말단 직원들만 각각 K개의 순서가 정해진 업무를 가지고 있다. 각 업무는 업무 번호가 있다. 각 날짜에 남은 업무가 있는 경우, 말단 직원은 하나의 업무를 처리해서 상사에게 올린다. 다른 직원들도, 대기하는 업무가 있는 경우 업무를 올라온 순서대로 하나 처리해서 상사에게 올린다. 단, 홀수 번째 날짜에는 왼쪽 부하 직원이 올린 업무를, 짝수 번째 날짜에는 오른쪽 부하 직원이 올린 업무를 처리한다.

부서장이 처리한 일은 완료된 것이다. 업무를 올리는 것은 모두 동시에 진행한다. 따라서 그날 올린 업무를 상사가 처리하는 것은 그 다음날에야 가능하다.

부서의 조직과 대기하는 업무들을 입력 받아 처리가 완료된 업무들의 번호의 합을 계산하는 프로그램을 작성하라.

제약조건

1 ≤ H ≤ 10
1 ≤ K ≤ 10
1 ≤ R ≤ 1,000

입력형식

첫 줄에 조직도의 높이 H, 말단에 대기하는 업무의 개수 K, 업무가 진행되는 날짜 수 R이 주어진다.

그 다음 줄부터 각각의 말단 직원에 대해 대기하는 업무가 순서대로 주어진다.

제일 왼쪽의 말단 직원부터 순서대로 주어진다.

출력형식

완료된 업무들의 번호 합을 정수로 출력한다.

입력예제1
1 1 1
1
2
출력예제1
0
입력예제2
1 3 2
9 3 7
5 11 2
출력예제2
5

👨🏻‍💻 생각해보기

1. 말단 직원과 상사의 남은 일은 다르게 처리되어야 할 거 같다는 생각을 했다.

  • 말단 직원은 그냥 자신에게 남겨져있는 일을 하루에 하나씩 상사에게 올려주기만 하면된다.
  • 상사는 왼쪽 직원이 올려준 일, 오른쪽 직원이 올려준 일을 분류해서 처리해야 한다.
    • 날짜가 1일이라면 홀수번째(왼쪽) 직원이 준 일을 처리해서 상사에게 올려야한다.
    • 날짜가 2일이라면 짝수번째(오른쪽) 직원이 준 일을 처리해서 상사에게 올려야한다.

2. 들어온 일의 순서대로 처리되어야 하고, 말단과 상사를 구분해야 한다?

  • 들어온 일을 순서대로 처리하기 위해서는 Queue를 사용하기로 했다.
  • 직원 객체를 만들어서 사용했고, 생성자에서 말단과 상사를 구분하도록 만들었다.
  • 말단이라면 남아있는 일에 대한 Queue를 하나만 만들어준다.
  • 누군가의 상사라면 남아있는 일에 대한 Queue를 두 개(왼쪽, 오른쪽) 만들어준다.

3. R(날짜) 만큼 반복을 진행하면서 로직을 수행한다.

  • 직원 한 명을 뽑는다. (왼쪽 제일 아래 있는 직원 부터 탐색)
  • 뽑은 직원의 상사 직원을 가져온다.
  • 상사 직원 객체에서 오늘의 날짜(R)에 맞는 남아있는 일에 대한 Queue를 가져와서 부하 직원의 남아있는 일에 대한 Queue에서 하나 뽑아서(poll) 상사 직원 객체의 Queue에 offer() 해준다.
  • 위와 같은 로직을 반복하여 직원 번호가 0인 직원한테 처리된 업무 번호들을 answer에 누적하여 더해준다.
    • 직원 번호가 0인 직원은 가장 위에 있는 대장 직원이기 떄문에 문제에서 요구하는 것이 제일 위에 있는 대장 직원에 의해 처리된 업무 번호들을 더해서 출력하는 문제이다.

 

제출 답안

import java.util.*;
import java.io.*;


public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String[] HKR = bufferedReader.readLine().split(" ");
        int H = Integer.parseInt(HKR[0]);
        int K = Integer.parseInt(HKR[1]);
        int R = Integer.parseInt(HKR[2]);
        int answer = 0;

        List<Employee> list = new ArrayList<>();
        List<Integer> index = new ArrayList<>();

        for (int i = (int)Math.pow(2, H) - 1; i < (int)Math.pow(2, H + 1) - 1; i++) {
            Employee employee = new Employee(i, false);
            for (String str : bufferedReader.readLine().split(" ")) {
                employee.remainTask.get(0).offer(Integer.valueOf(str));
            }
            list.add(employee);
            index.add(i);
        }

        for (int i = 1; i < R + 1; i++) {
            int size = list.size();
            for (int j = 0; j < size; j++) {
                Employee employee = list.get(j);

                if (employee.getRemainTask(i).isEmpty()) {
                    continue;
                }

                if (employee.employeeNumber == 0) {
                    answer += employee.getRemainTask(i).poll();
                    continue;
                }

                int superiorNumber = employee.getSuperiorNumber();
                Employee superior;

                if (index.contains(superiorNumber)) {
                    superior = list.get(index.indexOf(superiorNumber));
                } else {
                    superior = new Employee(superiorNumber, true);
                    list.add(superior);
                    index.add(superior.employeeNumber);
                }

                if (employee.employeeNumber % 2 == 0) {
                    superior.remainTask.get(1).offer(employee.getRemainTask(i).poll());
                } else {
                    superior.remainTask.get(0).offer(employee.getRemainTask(i).poll());
                }
            }
        }

        System.out.println(answer);
    }
}

class Employee {
    int employeeNumber;
    boolean isSuperior;
    List<Queue<Integer>> remainTask;

    public Employee(int employeeNumber, boolean isSuperior) {
        this.employeeNumber = employeeNumber;
        this.isSuperior = isSuperior;

        remainTask = new ArrayList<>();
        if (isSuperior) {
            remainTask.add(new LinkedList<>()); // 왼쪽 직원이 올린 일
            remainTask.add(new LinkedList<>()); // 오른쪽 직원이 올린 일
        }
        if (!isSuperior) {
            remainTask.add(new LinkedList<>()); //
        }
    }

    public int getSuperiorNumber() {
        if (employeeNumber % 2 != 0) {
            return (employeeNumber - 1) / 2;
        }
        return (employeeNumber - 2) / 2;
    }

    public Queue<Integer> getRemainTask(int date) {
        if (isSuperior) {
            if (date % 2 != 0) {
                return remainTask.get(0);
            }
            return remainTask.get(1);
        }
        return remainTask.get(0);
    }

    public String toString() {
        return String.valueOf(employeeNumber);
    }
}

 

🤔 FeedBack

결과를 보면 정말...집착으로 풀기도 했고, 코드도 가독성이 많이 떨어지는 건 맞다. 그래도 "맞앗습니다!" 이 글자가 보였을 떄...정말...짜릿했다.

 

처음에 소프티어에 홈페이지에 들어가서 Practice를 누르고 제일 위에 있는거 풀어봐야겠다 하고 시작한 것이... 맨날 프로그래머스 레벨 1, 2 풀다가 소프티어 문제 풀고 있는데 안 풀려서 이거 뭐야 하고 있었는데 난이도가 별 3개였다...

 

이미 시작해버렸고...끝은 봐야되기 때문에 계속해서 문제를 풀었다. 믿기지 않겠지만 3시26분까지 계속 하다가 해결이 안돼서 찝찝하게 누웠고, 자기 전에도 계속 생각했다. 

 

일어나서 생각한대로 코드 쭉 작성해보니깐 웬걸 "런타임 에러" 몇 개 빼고는 모두 정답이 나왔다. 오...이거 예외 하나만 잡아주면 통과될 거 같았다. 예상했던대로 나는 Queue를 사용했기 때문에 poll() 메서드를 사용하는데 있어서 예외가 발생해서 런타임 에러가 발생했던 거 같아서 모든 poll() 메서드 앞에 isEmpty()를 사용해서 예외처리를 해줬더니..통과됐다. 😂

 

+ Recent posts