Computer/Coding Test

Excercism - Scale Generator : string 다루기

안녕도라 2025. 2. 6. 15:06

문제요약

  • chromatic scale: 반음계
  • diatonic scale: 온음계

기본음이 주어지면 음계를 출력하는 함수를 완성하라!

https://exercism.org/tracks/csharp/exercises/scale-generator

 

Scale Generator in C# on Exercism

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

exercism.org

 


난이도

Medium


풀이 포인트

  • 문제 해석
  • bb와 Bb를 동일하게
char first = char.ToUpper(tonic[0]);
string upperTonic = first + tonic.Substring(1);	// 1번 인덱스 즉, 2번째 문자

REVIEW

 

우선은 문제 해석에 오래 걸렸다.

음계가 장조(?) #으로 표현되도록 모두 구현했더니,

어느 음계는 b플랫으로 표현되어야 한다는 조건이 있어, 급하게 함수를 추가했다.

 

switch문이 이제 좀 익숙해져서 엄청난 케이스 나열로 장단조 구분을 구현했는데 뭔가 다른 방법이 있으려나?

여튼, 오랜만에 조건별 단계를 깔끔하게 처리해 나간 코드라 후련하다.


CODE

using System;
using System.Collections.Generic;

// chromatic scale: 반음계, 12 음
// diatonic scale : 온음계, 7 음 -> 온음(M), 반음(m), 확장 2도(A)

public static class ScaleGenerator
{
    static string[] pitches = new string[] {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"};

    static string[] pitchesFlat = new string[] {"A","Bb","B","C","Db","D","Eb","E","F","Gb","G","Ab"};

    public static bool checkSharp(string tonic){
        bool isSharp = true;
        switch(tonic)
        {
            case "G":
            case "D":
            case "A":
            case "E":
            case "B":
            case "F#":
            case "e":
            case "b":
            case "f#":
            case "c#":
            case "g#":
            case "d#":
                isSharp = true;
                break;
            case "F":
            case "Bb":
            case "Eb":
            case "Ab":
            case "Db":
            case "Gb":
            case "d":
            case "g":
            case "c":
            case "f":
            case "bb":
            case "eb":
                isSharp = false;
                break; 
        }

        return isSharp;
    }
    
    
    public static string[] Chromatic(string tonic)
    {
        List<string> chromaticScale = new List<string>();
        int tonicIndex = 0;
        
        for(int i = 0; i < 12; i++){
            if(checkSharp(tonic)){
                if(tonic.ToUpper() == pitches[i]) tonicIndex = i;
            }else{
                if(tonic.ToUpper() == pitchesFlat[i]) tonicIndex = i;
            }
            
        }

        while(chromaticScale.Count <12){
            if(tonicIndex >= 12) tonicIndex = 0;
            
            if(checkSharp(tonic)){
                chromaticScale.Add(pitches[tonicIndex]);
            }else{
                chromaticScale.Add(pitchesFlat[tonicIndex]);
            }
            
            tonicIndex++;
        }

        return chromaticScale.ToArray();
    }

    public static string[] Interval(string tonic, string pattern)
    {
        List<string> diatonicScale = new List<string>();
        int tonicIndex = 0;

        char first = char.ToUpper(tonic[0]);
        string upperTonic = first + tonic.Substring(1);

        for(int i = 0; i < 12; i++){
            if(checkSharp(tonic)){
                if(tonic.ToUpper() == pitches[i]) tonicIndex = i;
            }else{
                
                
                if(upperTonic == pitchesFlat[i]) tonicIndex = i;
                Console.WriteLine($"플랫 음계이고 {upperTonic}을 기본음으로 시작하며 인덱스는 {tonicIndex}이다.");
            }
            
        }
        
        diatonicScale.Add(upperTonic);
        
        foreach(char a in pattern)
        {
            switch(a)
            {
                case 'M':
                    tonicIndex+=2;
                    if(tonicIndex >= 12) tonicIndex -=12;
                    
                    if(checkSharp(tonic)){
                        diatonicScale.Add(pitches[tonicIndex]);
                    }else{
                        diatonicScale.Add(pitchesFlat[tonicIndex]);
                    }
            
                    
                    break;
                case 'm':
                    tonicIndex++;
                    if(tonicIndex >= 12) tonicIndex -=12;
                    if(checkSharp(tonic)){
                        diatonicScale.Add(pitches[tonicIndex]);
                    }else{
                        diatonicScale.Add(pitchesFlat[tonicIndex]);
                    }
                    break;
                case 'A':
                    tonicIndex+=3;
                    if(tonicIndex >= 12) tonicIndex -=12;
                    if(checkSharp(tonic)){
                        diatonicScale.Add(pitches[tonicIndex]);
                    }else{
                        diatonicScale.Add(pitchesFlat[tonicIndex]);
                    }
                    break;
                default:
                    break;
            }
        }

        return diatonicScale.ToArray();
    }
}