Computer/Coding Test

Excercism - Squeaky Clean : 문자열, 아스키코드, 이모지, 숫자 구분 등

안녕도라 2025. 2. 6. 16:39

문제요약

문자가 주어지면, 특정 규칙을 적용해 다듬어라!

 

https://exercism.org/tracks/csharp/exercises/squeaky-clean

 

Squeaky Clean in C# on Exercism

Can you solve Squeaky Clean in C#? Improve your C# skills with support from our world-class team of mentors.

exercism.org


난이도

Learning Excercise


풀이 포인트

  • 그리스 문자 판별
// char 형은 16비트 정수형이다. 대소 비교로 그리스어 범위 한정할 수 있다.
c >= 'α' && c <= 'ω'
  • 이모지 판별
// IsLetter: 유니코드 문자 범주에 포함되는지 판단.
// 정확하게는 모르겠으나 이걸로 이모지는 탈락시킬 수 있었다.
char.IsLetter(a);
  • 케밥케이스 → 카멜케이스 변경
// 케밥 케이스
do-re-mi-fa-sol

// 카멜 케이스
doReMiFaSol
  • StringBuilder 활용

https://machineboy0.tistory.com/341

 

C# 문자 형식 char, 문자열 형식 string, String Builder

Char 형char 형식은 Integer Type(정수 형식)에 속한다.하지만 수가 아닌 '가', '나',' 다', 'a', 'b', 'c' 와 같은 문자 데이터를 다룬다.2 byte(16 bit)크기로, 텍스트의 가장 작은 요소를 나타낸다.UTF-16 Unicode를

machineboy0.tistory.com


REVIEW

 

이모지 판별과 그리스어 판별을 어떻게 하는지 구글링을 하는데 시간이 많이 걸렸다.

결국 모범 답안을 참고했는데 IsLetter()로 분간되는 유니코드 문자 범위엔 이모지가 포함되지 않는듯 하다.

근데 또 검색해보면 이모지 또한 유니코드라고 하고 이건 좀 더 찾아봐야 한다.

 

그리고 늘 문자를 아스키코드로 변환한 뒤, 대소 비교나, 범위 한정에 사용해야 한다고 생각해버리는데,

풀어 말해, A는 96임을 알고 있어야 한다고 생각하는데 'A' char형으로 대소 비교 해버리면 된다는 것 잊지 말기..

 

그리고 케밥케이스라는 것은 처음 접했는데, 

나는 Split 함수를 활용해 '-'기준으로 나눈뒤, 단어의 첫 글자를 대문자로 변환해 다시 연결하는 식으로 구현했지만,

모범 풀이를 보니 isAfterDash라는 flag값을 하나 두고 이를 껐다 키며 문자를 조합하더라.

머리 좋은 것 같다. 

 

그리고 차차 Linq도 익숙해져 나가야 한다..


CODE

using System;
using System.Text;

public static class Identifier
{
    // 그리스어 문자 판별 (대소문자 모두 포함)
    public static bool IsGreekLetter(char c)
    {
        return (c >= 'α' && c <= 'ω');
    }

    public static string Clean(string identifier)
    {
        // 입력이 빈 문자열이면 바로 반환
        if (string.IsNullOrEmpty(identifier)) return "";

        StringBuilder sb = new StringBuilder();

        foreach (char a in identifier)
        {
            if (a == ' ')
            {
                sb.Append('_'); // 공백 → '_'
            }
            else if (a == '\0')
            {
                sb.Append("CTRL"); // NULL 문자 → "CTRL"
            }
            else if (IsGreekLetter(a))
            {
                continue; // 그리스어 제거
            }
            else if (char.IsLetter(a) || a == '-')
            {
                sb.Append(a);
            }
            else
            {
                continue;
            }
        }

        // '-'로 나눈 배열에서 빈 문자열 제외
        string[] kebab = sb.ToString().Split('-');

        // 첫 번째 단어는 그대로
        string answer = kebab[0];
        Console.WriteLine(sb.ToString());
        Console.WriteLine(kebab[0]);

        // 두 번째 단어부터 첫 글자 대문자로 변환
        for (int i = 1; i < kebab.Length; i++)
        {
            char first = char.ToUpperInvariant(kebab[i][0]);
            answer += first + kebab[i].Substring(1);
        }

        return answer;
    }
}
using System.Text;
public static class Identifier
{
    private static bool IsGreekLowercase(char c) => (c >= 'α' && c <= 'ω');
    
    public static string Clean(string identifier)
    {
        var stringBuilder = new StringBuilder();
        var isAfterDash = false;
        foreach (var c in identifier)
        {
            stringBuilder.Append(c switch
            {
                _ when IsGreekLowercase(c) => default,
                _ when isAfterDash => char.ToUpperInvariant(c),
                _ when char.IsWhiteSpace(c) => '_',
                _ when char.IsControl(c) => "CTRL",
                _ when char.IsLetter(c) => c,
                _ => default,
            });
            isAfterDash = c.Equals('-');
        }
        return stringBuilder.ToString();
    }
}