본문 바로가기
🐣 알고리즘

[프로그래머스] Swift - 오픈 채팅방 (LV.2)

by @Eddy 2023. 6. 23.
728x90

👆문제풀러 가기👆

문제 설명

두 정수 X, Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 ≤ k ≤ 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(단, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다). X, Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다. X, Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다.

예를 들어, X = 3403이고 Y = 13203이라면, X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로 X = 5525이고 Y = 1255이면 X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5가 3개, Y에는 5가 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.)
두 정수 X, Y가 주어졌을 때, X, Y의 짝꿍을 return하는 solution 함수를 완성해주세요.

제한사항

  • record는 다음과 같은 문자열이 담긴 배열이며, 길이는 1 이상 100,000 이하이다.
  • 다음은 record에 담긴 문자열에 대한 설명이다.
    • 모든 유저는 [유저 아이디]로 구분한다.
    • [유저 아이디] 사용자가 [닉네임]으로 채팅방에 입장 - "Enter [유저 아이디] [닉네임]" (ex. "Enter uid1234 Muzi")
    • [유저 아이디] 사용자가 채팅방에서 퇴장 - "Leave [유저 아이디]" (ex. "Leave uid1234")
    • [유저 아이디] 사용자가 닉네임을 [닉네임]으로 변경 - "Change [유저 아이디] [닉네임]" (ex. "Change uid1234 Muzi")
    • 첫 단어는 Enter, Leave, Change 중 하나이다.
    • 각 단어는 공백으로 구분되어 있으며, 알파벳 대문자, 소문자, 숫자로만 이루어져있다.
    • 유저 아이디와 닉네임은 알파벳 대문자, 소문자를 구별한다.
    • 유저 아이디와 닉네임의 길이는 1 이상 10 이하이다.
    • 채팅방에서 나간 유저가 닉네임을 변경하는 등 잘못 된 입력은 주어지지 않는다.

입출력 예

record result
["Enter uid1234 Muzi",
"Enter uid4567 Prodo",
"Leave uid1234",
"Enter uid1234 Prodo",
"Change uid4567 Ryan"]
["Prodo님이 들어왔습니다.",
"Ryan님이 들어왔습니다.",
"Prodo님이 나갔습니다.",
"Prodo님이 들어왔습니다."]

 

풀이 [ 메모리: 58.3mb, 최대시간: 783.13ms ] 

enum Status: String {
    case enter = "enter"
    case leave = "leave"
    case change = "change"
}

struct User {
    var id: String
    var status: Status
}

func solution(_ record:[String]) -> [String] {
    var chatRoom = [String: String]() // 채팅룸 유저아이디, 유저닉네임 기록
    var users = [User]()              // 유저별 입장기록 저장

    // 유저 상태 저장
    for i in 0..<record.count {
        let r = record[i].split(separator: " ").map { String($0) }

        if let status = Status(rawValue: r[0].lowercased()) { // 대소문자 오타 방지
            let uid = r[1]

            switch status {
            case .enter:             // 입장
                users.append(User(id: uid, status: status))
                chatRoom[uid] = r[2] // 닉네임 저장
            case .leave:             // 나감
                users.append(User(id: uid, status: status))
            case .change:
                chatRoom[uid] = r[2] // 닉네임 변경
            default: break
            }
        }
    }

    var result = [String]()

    for user in users {
        let userName = "\(chatRoom[user.id]!)님이"

        switch user.status {
        case .enter: result.append("\(userName) 들어왔습니다.")
        case .leave: result.append("\(userName) 나갔습니다.")
        default: break
        }
    }

    return result
}

추상화 연습을 위해 struct와 enum을 활용해 작성했다.

처음엔 막막했는데, struct를 사용해보니 tuple과 크게 다르지 않아 어렵지 않았다.

lowercased는 Enter, Leave, Change입력 시 대소문자 오타방지를 위함으로,

문제 풀이에서는 불필요한 사항이지만 실제 앱 개발을 고려했을 때, 필요한 코드라고 생각해 입력하게 되었다.

 

풀이 설명

  1. 최종적으로 다른 사람이 유저 닉네임이 어떻게 보이는지 알아야한다.
  2. 유저가 입장, 퇴장할 때 user정보를 기록한다. (user정보 = id, 입장, 퇴장 상태)
  3. 유저가 입장하거나 닉네임을 변경할 때, userID에 따라 닉네임을 create 또는 update한다. (userID = key, name = value)
  4. 2번에서 저장한 정보를 이용해 최종 출력을 확인한다.
반응형

댓글