ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Programmers Lv2) [2021 카카오블라인드] 신규 아이디 추천
    Algorithm/Programmers 2021. 2. 22. 13:38

    출처: programmers.co.kr/learn/courses/30/lessons/72410

    분류: 문자열


    접근방식

    친절하게 단계별로 요구사항을 제시해주고 있기 때문에 주어진 대로 열심히 구현하면 되는 문제였습니다!

    문자열을 다루는 문제이니 만큼 굉장히 다양한 풀이들이 있더라구요. 문자열을 연습하기 아주 좋은 문제였던 것 같아요. 각 단계별로 가능한 다양한 풀이를 생각해보면서 정리해보고자 합니다.

    우선 다른 분들의 풀이를 보면 그냥 solution 함수에 다 때려박아(?)서 구현하신 분도 있고 함수를 나누신 분도 계시고 extension 으로 처리해서 더 깔끔하게 푸신 분들도 계시던 것 같아요. 편한대로 풀면 되겠지만 실전이라면 여기서 너무 시간을 오래 끌지 않도록 익숙하고 빠르게 풀 수 있는 방법으로 우선 풀고 다른 문제에 더 시간을 쏟는 편이 좋을 것 같아요. 작년에 저는 쓸데없이 여기서 시간을 꽤나 많이 버렸던 기억이 있네요... 😭

    단계 1. 소문자 치환

    이건 swift에서 제공해주고 있는 기능이 있어 간단하게 처리가 가능할 것 같아요. 짝꿍인 대문자 치환도 있겠죠?

    lowercased() , uppercased()
    func replaceWithLowercase(_ text: String) -> String {
        return text.lowercased()
    }

     

    단계 2. 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거

    이 부분은 다양한 풀이가 있을 수 있겠는데요, 

    우선 저는 원하는 문자열로 Set을 만들어 필터를 걸어주는 방식을 사용했습니다.

    Set<Character>("0123456789abcdefghijklmnopqrstuvwxyz-_.")
    func removeInValidChacters(_ text: String) -> String {
        let validCharacters = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyz-_.")
        return text.filter { validCharacters.contains($0) }
    }

     

    다른 풀이로 앞서 소문자로 치환해주고 온 다음이기 때문에 문자열인지 or 숫자인지 or  - _ . 인지 확인해주는 or 조건문으로 filter를 걸어주는 방법도 있겠네요.

    text.filter { $0.isLetter || $0.isNumber || "-_.".contains($0) }

     

    단계 3. 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.

    저는 이 부분은 그냥 for문을 돌려서 이전 문자를 저장해뒀다가 "."일 때를 체크해서 문자열을 다시 만들어가는 방식으로 풀어봤습니다.

    func replaceContinouseCommaToOne(_ text: String) -> String {
        var validString = ""
        var previous: Character = " "
        for char in text {
            if char == ".", previous == char {
                continue
            } else {
                previous = char
                validString.append(char)
            }
        }
        return validString
    }

     

    "."이 여러 개 연속된다는 건 ".." 가 있다는 의미이고 이걸 "."로 계속 바꿔나가도 중복을 제거할 수 있습니다.

    while text.contains("..") {
    	text.replacingOccurrences(of: "..", with: ".")
    }

     

    단계 4. 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.

    우선 저는 그냥 처음과 끝이 "." 인지 if문으로 확인해서 제거했습니다.

    func removeCommaAtFirstOrLast(_ text: String) -> String {
        var validText = text
        if validText.first == "." {
            validText.removeFirst()
        }
        if validText.last == "." {
            validText.removeLast()
        }
        return validText
    }

     

    Swift의 String에서는 prefix와 subfix에 관련된 문법도 제공합니다 :)

    if validText.hasSuffix(".") {
    	validText.removeFirst()
    }
    if validText.hasSuffix(".") {
    	validText.removeFirst()
    }

     

    이런 경우는 실제 상황에서도 많이 사용되는 모양이에요. 친절하게도 아예 양 끝을 바로 처리해주는 문법도 제공합니다.

    trimmingCharacters 는 다음과 같이 설명이 되어있습니다 :)

    Returns a new string made by removing from both ends of the String characters contained in a given character set.

     

    func removeCommaAtFirstOrLast(_ text: String) -> String {
        return text.trimmingCharacters(in: ["."])
    }

     

    단계 5. 빈 문자열이라면, new_id에 "a"를 대입합니다.

    이건 뭐 어렵지 않게 가능하겠죠?

    func replaceAIfEmpty(_ text: String) -> String {
        return text.isEmpty ? "a" : text
    }

     

     

    단계 6. 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.

     

    저는 길이가 16자 이상이라면 dropLast를 사용해 15자만 남기도록 해주고 마지막이 "."인지 한 번 더 확인해줬습니다.

    func removeLongString(_ text: String) -> String {
        var validText = text
        if validText.count >= 16 {
            validText = String(validText.dropLast(validText.count - 15))
        }
        if validText.last == "." {
            validText.removeLast()
        }
        return validText
    }

     

    15 번째의 인덱스를 얻어서 서브스크립트로 해줄 수도 있겠네요!

    func removeLongString(_ text: String) -> String {
        var validText = text
        if validText.count >= 16 {
        	let endIndex = text.index(text.startIndex, offsetBy: 15)
    		validText = String(text[text.startIndex..<endIndex])
        }
        if validText.last == "." {
            validText.removeLast()
        }
        return validText
    }

     

     

    단계 7. 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

    while문을 사용해 길이가 3보다 작다면 계속 마지막 글자를 붙여주도록 해줬습니다.

    func repeatLastToThreeLength(_ text: String) -> String {
        var validText = text
        while validText.count < 3 {
            validText.append(validText.last!)
        }
        return validText
    }

     

     

    배운점

    문자열은 꼭 정복하고 익숙해져야 한다 🔥

    너무 시간을 많이 뺏기지 않도록 연습하자.

    댓글

Designed by Tistory.