트랙
/
Crystal
Crystal
/
연습 문제
/
차이타나의 거대한 롤러코스터
차이타나의 거대한 롤러코스터

차이타나의 거대한 롤러코스터

학습 연습 문제

소개

배열은 자주 다루게 되는 자료 구조예요. 그래서 배열을 다루는 데 사용할 수 있는 메서드가 다양하게 있어요. 정렬, 뒤집기, 삽입 등 여러 가지가 포함돼요.

이 메서드 중에는 원본 배열을 수정하는 파괴적인 메서드도 있고, 원본 배열은 그대로 두고 새로운 배열을 반환하는 메서드도 있어요.

다음은 배열을 다룰 때 자주 쓰이는 대표적인 메서드 몇 가지예요.

insert

배열에 원소를 삽입할 때는 insert 메서드를 사용할 수 있어요. 이 메서드는 인덱스와 원소를 인자로 받아요. 원소는 지정한 인덱스에 삽입되고, 나머지 원소는 오른쪽으로 밀려요. 인덱스가 범위를 벗어나면 IndexError가 발생해요.

numbers = [1, 2, 3]
numbers.insert(1, 4)
numbers # => [1, 4, 2, 3]

numbers.insert(5, 5) # => Error: Index out of bounds (IndexError)

delete

배열에서 특정 원소를 삭제하고 싶을 때는 delete 메서드를 사용할 수 있어요. 이 메서드는 원소를 인자로 받아요. 이 메서드는 삭제한 원소를 반환해요. 배열에 그 원소가 없으면 nil을 반환해요.

numbers = [1, 2, 3]
numbers.delete(2) # => 2
numbers           # => [1, 3]

first & last

배열의 첫 번째나 마지막 원소를 가져오고 싶을 때는 first와 last 메서드를 사용할 수 있어요. 이 메서드들은 몇 개의 원소를 반환할지 지정하는 선택적 인자를 받아요. 인덱스 0이나 -1을 사용하거나 범위를 사용하는 것보다 가독성을 높여줄 수 있어요. 배열이 비어 있으면 Enumerable::EmptyError가 발생해요.

numbers = [1, 2, 3]
numbers.first # => 1
numbers.last  # => 3

numbers.first(2) # => [1, 2]
numbers.last(2)  # => [2, 3]

empty_array = [] of Int32
empty_array.last # => Error: Empty enumerable (Enumerable::EmptyError)

reverse

배열을 뒤집고 싶을 때는 reverse 메서드를 사용할 수 있어요. 이 메서드는 원소를 역순으로 담은 새로운 배열을 반환해요. reverse는 새로운 배열을 반환하고 원본 배열은 수정하지 않는다는 점을 기억해 두세요. 원본 배열을 수정하고 싶다면 메서드 이름 끝에 !를 붙여요.

numbers = [1, 2, 3]
numbers.reverse # => [3, 2, 1]
numbers         # => [1, 2, 3]

numbers.reverse! # => [3, 2, 1]
numbers          # => [3, 2, 1]

Concat(+)

append 메서드(<<)는 배열에 객체를 추가하고 싶을 때 유용해요. 하지만 두 배열을 합칠 때는 + 연산자를 사용할 수 있어요. 이 연산자는 두 배열의 원소를 모두 담은 새로운 배열을 반환해요.

[1, 2] + [3, 4] # => [1, 2, 3, 4]

배열에 다른 배열을 append하면, 그 배열은 하나의 원소로 추가돼요.

[1, 2] << [3, 4] # => [1, 2, [3, 4]]

empty?

배열이 비어 있는지 확인하고 싶을 때는 empty? 메서드를 사용할 수 있어요. 이 메서드는 배열이 비어 있으면 true를, 그렇지 않으면 false를 반환해요. 배열의 길이를 0과 비교하는 것보다 가독성을 높여줘요.

[].empty? # => true
[1, 2, 3].empty? # => false

index

배열에서 원소의 인덱스를 가져오고 싶을 때는 index 메서드를 사용할 수 있어요. 이 메서드는 원소를 인자로 받아요. 배열에 그 원소가 없으면 nil을 반환해요.

numbers = [1, 2, 3]
numbers.index(2) # => 1

size

배열의 원소 개수를 알고 싶을 때는 size 메서드를 사용할 수 있어요.

numbers = [1, 2, 3]
numbers.size # => 3

count

배열에 어떤 원소가 몇 번 나타나는지 세고 싶을 때는 count 메서드를 사용할 수 있어요.

fruits = ["apple", "banana", "apple"]
fruits.count("apple")      # => 2
fruits.count("banana")     # => 1
fruits.count("watermelon") # => 0

sort

배열을 정렬하고 싶을 때는 sort 메서드를 사용할 수 있어요. 이 메서드는 정렬된 원소를 담은 새로운 배열을 반환해요. reverse와 마찬가지로 이 메서드도 새로운 배열을 반환하고 원본 배열은 수정하지 않아요.

numbers = [3, 2, 1]
numbers.sort # => [1, 2, 3]
numbers      # => [3, 2, 1]

numbers.sort! # => [1, 2, 3]
numbers       # => [1, 2, 3]

지침

Chaitana는 아주 인기 있는 테마파크를 운영해요. 아름답게 가꾼 부지 한가운데에는 놀이기구가 단 하나뿐이에요. 바로 The Biggest Roller Coaster in the World(TM)예요. 이 하나뿐인 명소인데도 사람들은 세계 곳곳에서 찾아와 Chaitana의 하이퍼코스터를 타려고 몇 시간씩 줄을 서요.

이 놀이기구에는 두 개의 대기열이 있고, 각각은 array로 표현돼요:

  1. 일반 대기열
  2. 익스프레스 대기열(패스트트랙이라고도 불러요) - 돈을 더 내면 우선적으로 탈 수 있는 곳이에요.

공원 손님들을 더 잘 관리할 수 있도록 코드를 작성해 달라는 요청을 받았어요. 손님들(그리고 사장님인 Chaitana!)이 짜증을 내기 전에 다음 함수들을 최대한 빨리 구현해야 해요.

1. 대기열에 사람 추가하기

<express_queue>, <normal_queue>, <ticket_type>, <person_name> 네 개의 인자를 받아서, 해당 인물의 이름이 추가된 알맞은 대기열을 반환하는 ColossalCoaster.add_to_queue 메서드를 정의해요.

  1. <ticket_type>은 Int32이고, 1은 express_queue, 0은 normal_queue를 나타내요.
  2. <person_name>은 각 대기열에 추가할 사람의 이름이에요 (String 타입).
express_queue = ["Tony", "Bruce"]
normal_queue = ["RobotGuy", "WW"]
ColossalCoaster.add_to_queue(express_queue, normal_queue, 1, "RichieRich")
# => ["Tony", "Bruce", "RichieRich"]

2. 내 친구들은 어디에 있을까요?

어떤 사람이 공원에 늦게 도착했는데, 친구들이 기다리고 있는 대기열에 합류하고 싶어 해요. 그런데 친구들이 어디에 서 있는지 전혀 모르고, 전화할 수 있는 신호도 잡히지 않아요.

queue와 friend_name 두 개의 인자를 받아서, 대기열에서 그 사람 이름이 있는 위치를 반환하는 ColossalCoaster.find_my_friend 메서드를 정의해요.

  1. <queue>는 대기열에 서 있는 사람들의 array예요.
  2. <friend_name>은 그 인덱스, 즉 대기열에서의 위치를 찾아야 하는 친구의 이름이에요.
ColossalCoaster.find_my_friend(["Natasha", "Steve", "T'challa", "Wanda", "Rocket"], "Steve")
# => 1

3. 친구들 사이에 끼어도 될까요?

이제 (위의 2번 문제에서) 친구들을 찾았으니, 늦게 도착한 사람은 친구들이 서 있는 자리에 합류하고 싶어 해요. queue, friend_name, person_name 세 개의 인자를 받는 ColossalCoaster.add_with_friends 메서드를 정의해요.

  1. <queue>는 대기열에 서 있는 사람들의 array예요.
  2. <friend_name>은 그 사람을 추가할 위치에 서 있는 친구의 이름이에요.
  3. <person_name>은 해당 인덱스 위치에 추가할 사람의 이름이에요.

늦게 도착한 사람의 이름이 추가된 대기열을 반환해요.

ColossalCoaster.add_with_friends(["Natasha", "Steve", "T'challa", "Wanda", "Rocket"], "Steve", "Bucky")
# => ["Natasha", "Bucky", "Steve", "T'challa", "Wanda", "Rocket"]

4. 대기열의 못된 사람

방금 대기열에서 아주 못된 사람이 밀치고 소리치고 소란을 피우고 있다는 얘기를 들었어요. 그 못된 사람을 나쁜 행동 때문에 쫓아내야 해요!

queue와 person_name 두 개의 인자를 받는 ColossalCoaster.remove_from_queue 메서드를 정의해요.

  1. <queue>는 대기열에 서 있는 사람들의 array예요.
  2. <person_name>은 쫓아내야 하는 사람의 이름이에요.

못된 사람의 이름이 빠진 대기열을 반환해요.

ColossalCoaster.remove_from_queue(["Natasha", "Steve", "Eltran", "Wanda", "Rocket"], "Eltran")
# => ["Natasha", "Steve", "Wanda", "Rocket"]

5. 대기열 목록 정렬하기

관리 목적으로, 주어진 대기열에 있는 모든 이름을 알파벳 순서로 정리해야 해요.

queue(대기열에 서 있는 사람들의 array)를 인자 하나로 받는 ColossalCoaster.sorted_queue 메서드를 정의해요. 이 메서드는 array를 정렬한 복사본을 반환해야 해요.

ColossalCoaster.sorted_queue(["Natasha", "Steve", "Eltran", "Natasha", "Rocket"])
# => ['Eltran', 'Natasha', 'Natasha', 'Rocket', 'Steve']
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Crystal Exercism

차이타나의 거대한 롤러코스터 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Crystal 트랙을 개념 26개연습 문제 142개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.