문제4

배달 앱을 이용하려면 유저는 로그인 → 장바구니에 음식 담기 → 주문 과 같은 순서를 거칩니다. 이를 위해 서버에서는 다음과 같은 일을 합니다.

  1. 로그인: LOGIN 아이디 비밀번호

    • 이미 로그인했다면 거부한다.
    • 아이디와 비밀번호가 유효하면 로그인을 허용한다.
    • 아이디와 비밀번호가 유효하지 않으면(아이디가 없거나 비밀번호가 다른 경우) 로그인을 거부한다.
  2. 장바구니에 음식 담기: ADD 음식아이디

    • 로그인한 유저라면 허용한다.
    • 로그인하지 않았으면 거부한다.
  3. 주문하기: ORDER

    • 장바구니에 담은 음식이 있으면 허용한다. 주문 후에는 장바구니를 비운다.
    • 장바구니에 담은 음식이 없으면 거부한다.
      서버에 저장된 유저 정보 infos와 한 사람의 행동을 담은 배열 actions가 매개변수로 주어질 때, 각 행동이 허용되었으면 true, 거부되었으면 false를 담아 return 하도록 solution 메서드를 완성해주세요.

제한 사항

  • infos의 길이는 1 이상 10 이하입니다.
  • infos의 원소는 아이디 비밀번호 형태입니다.
  • actions의 길이는 1 이상 100 이하입니다.
  • actions의 원소는 다음 형태 중 하나입니다.
    • LOGIN 아이디 비밀번호
    • ADD 음식아이디
    • ORDER
  • infos와 actions 배열에서 주어지는 아이디와 비밀번호는 영문 소문자로만 이루어져 있습니다.
  • actions 배열에서 주어지는 음식아이디는 숫자로만 주어집니다.

스크린샷 2019-11-10 오후 10 11 05
스크린샷 2019-11-10 오후 10 11 36
스크린샷 2019-11-10 오후 10 11 57

풀이

package beautifultask;

import java.util.*;

public class DeliveryProcess {

    public static boolean[] solution(String[] infos, String[] actions) {

        boolean[] answer = new boolean[actions.length];
        Member member = null;

        Map<String, Member> accounts = new HashMap<>();

        // 서버에 저장된 사용자 정보를 해시 Map 객체로 관리합니다.
        // Key 값은 회원 아이디로 회원 객체를 관리합니다.
        for (int i = 0; i < infos.length; i++) {
            String[] memberInfo = infos[i].split(" ");
            accounts.put(memberInfo[0], new Member(memberInfo[0], memberInfo[1]));
        }

        for (int i = 0; i < actions.length; i++) {
            String[] request = actions[i].split(" ");

            switch (request[0]) {
                case "ADD":
                    if (member != null) {
                        member.addFood(request[1]);
                        answer[i] = true;
                    } else {
                        answer[i] = false;
                    }
                    break;

                case "LOGIN":
                    boolean loginResult = getLoginResult(request, member, accounts);
                    if(loginResult) {
                        member = accounts.get(request[1]);
                    }
                    answer[i] = loginResult;
                    break;

                case "ORDER":
                    if(member == null){
                        answer[i] = false;
                    }else{
                       if(member.getCart().size() == 0){
                           answer[i] = false;
                       }else {
                           member.clearCart();
                           answer[i] = true;
                       }
                    }
                    break;

                    default:
                        throw new IllegalStateException("IllegalArgumentException");
            }
        }
        return answer;
    }

    //memberInfo = member 정보가 있습니다.
    public static boolean getLoginResult(String[] request, Member member, Map<String, Member> accounts){

        if(!accounts.containsKey(request[1])){
            return false;
        }

        final Member accountMember = accounts.get(request[1]);

        if(!accountMember.getPassword().equals(request[2])){
            return false;
        }

        if(member != null){
            return false;
        }

        return true;
    }


    public static void main(String[] args) {

        String[] infos = {"kim password", "lee abc"};
        String[] actions = {
                "ADD 30",
                "LOGIN kim abc",
                "LOGIN lee password",
                "LOGIN kim password",
                "LOGIN kim password",
                "ADD 30",
                "ORDER",
                "ORDER",
                "ADD 40",
                "ADD 50"};

        boolean[] result = solution(infos, actions);

        for (boolean answer : result) {
            System.out.println(answer);
        }


    }

}


class Member {

    private String id;
    private String password;
    // HashSet 클래스는 중복을 거르고 담기 때문에 식별자가 유일한 개체만 담습니다.
    private HashSet<String> cart = new HashSet<>();


    public Member(String id, String password) {
        this.id = id;
        this.password = password;
    }


    public void addFood(String foodId) {
        cart.add(foodId);
    }

    public void clearCart() {
        cart.clear();
    }


    public HashSet<String> getCart() {
        return cart;
    }

    public String getPassword() {
        return password;
    }
}

우아한테스크코스 온라인 코딩 테스트 4번 문제는 배달앱 주문과정을 구현하는 것입니다.
위에 나와있는 룰에 기반하여 행동이 들어있는 문자열 타입의 배열을 받아서 허용할지 거부할지 판단하여 boolean 타입의 배열을 리턴하는 것이 핵심입니다.

가장 먼저, 서버에 저장된 회원의 아이디와 패스워드 정보가 들어있는 infos 배열을 각각의 HashMap 클래스를 사용하여 Member 객체의 생성자 로 넣어주어 관리하도록 하였습니다.

for (int i = 0; i < infos.length; i++) {
    String[] memberInfo = infos[i].split(" ");
    accounts.put(memberInfo[0], new Member(memberInfo[0], memberInfo[1]));
}

이 문제를 자세히 살펴보면 행동이 담긴 문자열 배열의 값이 ADD 데이터, LOGIN 데이터, ORDER 데이터 으로 구성되어 있는데 뒤에 나오는 데이터는 공백으로 구분되어 있습니다. 이것을 split() 메서드를 사용하여 공백으로 문자열을 자른 후에 각각의 행동을 처리하도록 swich문을 이용하여 해결하였습니다.

public static boolean getLoginResult(String[] request, Member member, Map<String, Member> accounts){

    if(!accounts.containsKey(request[1])){
        return false;
    }

    final Member accountMember = accounts.get(request[1]);

    if(!accountMember.getPassword().equals(request[2])){
        return false;
    }

    if(member != null){
        return false;
    }

    return true;
}

위의코드는 행동이 LOGIN일때 처리하는 부분입니다.
이미 로그인한 회원이 있으면 false, Map 객체에 containsKey() 메서드로 아이디가 존재하는지 확인하고 없으면 마찬가지로 false, 아이디가 존재하지만 패스워드가 틀리면 false를 리턴하도록 작성하였습니다. 이 세가지 조건을 다 충족하지 않는다면 로그인한 유저가 없거나 아이디, 패스워드가 서버에 저장된 정보랑 일치하는걸로 판단하여 true를 리턴합니다.

그리고 member 객체는 로그인 정보가 들어있는 행동 배열 값이랑 일치하기 때문에 로그인하도록 처리하였습니다.

+ Recent posts