개념 연습 문제는 특정 (프로그래밍) 개념을 가르치기 위해 설계된 연습 문제예요. 개념 연습 문제가 가르치는 개념들은 _실러버스_를 이뤄요. 실러버스를 설계하는 방법에 대한 더 자세한 내용은 실러버스 문서를 확인해 봐요.
트랙의 루트 디렉터리에서 다음 명령을 실행하면 새 개념 연습 문제의 뼈대를 빠르게 만들 수 있어요:
bin/fetch-configlet
bin/configlet create --concept-exercise <slug>
더 자세한 내용은 configlet create 문서를 확인해 봐요
개념 연습 문제의 메타데이터는 config.json 파일의 exercises.concept 키에 정의돼요. 이 메타데이터는 연습 문제의 UUID, slug 등을 정의해요.
{
"exercises": {
"concept": [
{
"uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
"slug": "cars-assemble",
"name": "Cars, Assemble!",
"concepts": ["if-statements", "numbers"],
"prerequisites": ["basics"]
}
]
}
}
각 개념 연습 문제는 트랙의 exercises/concept 디렉터리 안에 자신만의 디렉터리를 가져요. 개념 연습 문제 디렉터리의 이름은 config.json 파일에 정의된 대로 개념 연습 문제의 slug 속성과 일치해야 해요.
개념 연습 문제에는 네 가지 종류의 파일이 있어요:
이 파일들은 연습 문제를 설명하는 데 도움을 주기 위해 학생에게 제공돼요.
.docs/introduction.md: 연습 문제가 학생에게 가르치는 개념을 소개해요 (필수).docs/instructions.md: 연습 문제에 대한 지침을 제공해요 (필수).docs/hints.md: 학생이 연습 문제에서 막혔을 때 스스로 벗어날 수 있도록 힌트를 제공해요 (필수)이 파일들은 학생에게 제공되지 않고, 연습 문제의 메타데이터를 정의하는 데 사용돼요.
.meta/config.json: 연습 문제에 대한 메타 정보를 담고 있어요 (필수).meta/design.md: 연습 문제의 설계를 설명해요 (필수)이 파일들은 연습 문제에 대한 접근법을 설명해요.
.approaches/introduction.md: 연습 문제에서 가장 흔한 접근법을 소개해요 (선택).approaches/config.json: 접근법의 메타데이터예요 (선택).approaches/<approach-slug>/content.md: 접근법에 대한 설명이에요 (선택).approaches/<approach-slug>/snippet.txt: 접근법을 보여 주는 스니펫이에요 (선택)이 파일들은 연습 문제에 대한 아티클을 설명해요.
.articles/config.json: 아티클의 메타데이터예요 (선택).articles/<article-slug>/content.md: 아티클에 대한 설명이에요 (선택).articles/<article-slug>/snippet.md: 아티클을 보여 주는 스니펫이에요 (선택)구현 파일과 테스트 파일처럼 언어에 특화된 파일이에요. 이 파일들의 이름은 트랙마다 달라요.
exercises
└── concept
└── cars-assemble
├── .approaches
| ├── for-loop
| | ├── content.md
| | └── snippet.txt
| ├── config.json
| └── introduction.md
├── .articles
| ├── performance
| | ├── content.md
| | └── snippet.md
| └── config.json
├── .docs
| ├── introduction.md
| ├── instructions.md
| └── hints.md
├── .meta
| ├── config.json
| ├── design.md
| └── Exemplar.cs (exemplar implementation)
├── CarsAssemble.cs (stub implementation)
└── CarsAssemblyTests.cs (tests)
우리는 새 연습 문제에 "낙관적 병합" 접근법을 선호해요. 트랙은 연습 문제를 "작업 중" 상태로 개발할 수 있어요. configlet을 통과하고 병합할 수 있게 해 주는 최소 유효 상태는 다음과 같아요:
config.json에 유효한 항목이 있고, status가 wip로 설정돼 있어요..meta/config.json 파일이 있어요.docs/introduction.md.docs/instructions.md.docs/hints.md.docs/introduction.md
목적: 연습 문제가 학생에게 가르치는 개념을 소개해요.
포함 여부: 필수
about.md 문서에 남겨 둬요.예를 들어, "strings" 연습 문제의 소개에서는 문자열을 그저 "유니코드 문자의 나열" 또는 "바이트의 연속"이라고 설명하고, 사용자에게 문자열을 만드는 방법을 알려 주고, 문자열을 조작하는 데 쓸 수 있는 메서드가 있다고 설명할 수 있어요. 학생이 연습 문제를 풀기 위해 더 미묘한 세부 사항까지 이해할 필요가 없다면, 이런 짧은 설명(문법 예시와 함께)만으로도 학생이 연습 문제를 풀기에 충분해요.
# Introduction
There are two primary ways to assign objects to names in Ruby - using variables or constants. Variables are always written in snake case. A variable can reference different objects over its lifetime. For example, `my_first_variable` can be defined and redefined many times using the `=` operator:
```ruby
my_first_variable = 1
my_first_variable = "Some string"
my_first_variable = SomeComplexObject.new
```
.docs/introduction.md.tpl
목적: introduction.md 파일을 생성하는 데 사용하는 템플릿이에요.
포함 여부: 선택
introduction.md 문서는 연습 문제의 개념을 학생에게 소개해요. 각 개념에는 자신만의 introduction.md 문서도 있는데, 이는 연습 문제 맥락 밖에서는 표시되지 않아요.
개념의 소개를 연습 문제의 소개에 그대로 포함해야 한다면, introduction.md.tpl 파일을 사용할 수 있어요. 이 파일에서는 자리 표시자 %{concept:<concept-slug>}를 통해 개념 소개를 참조할 수 있어요.
configlet은 템플릿 파일로부터 introduction.md 파일을 생성할 수 있어요. 생성된 파일에서는 개념 자리 표시자가 해당 개념의 introduction 내용으로 바뀌어요.
Exercism 웹사이트는 introduction.md 문서만 알고 있어요. 템플릿 파일을 사용할 때 introduction.md를 생성하는 것은 트랙의 책임이에요.
트랙은 연습 문제마다 템플릿을 사용할지 여부를 결정할 수 있어요. 경우에 따라서는 개념의 소개를 그대로 쓰는 것이 최선이 아닐 수도 있어요. 항상 학생에게 가장 좋은 학습 경험을 제공하는 쪽을 선택해요.
# Introduction
%{concept:variables}
.docs/instructions.md
목적: 연습 문제에 대한 지침을 제공해요.
포함 여부: 필수
이 파일은 두 부분으로 나뉘어요.
각 과제는 다음 기준을 따라야 해요:
## 1. Do X, ## 2. Do Y).## 1. Check if an appointment has already passed).Implement method X(...) that takes an A and returns a Z),우리는 Exercism의 콘텐츠를 모든 사람에게 안전하게 만드는 것을 매우 중요하게 생각해요. 그래서 이야기가 적절한지 판단할 때는 신중한 쪽을 택해요. 병합할 내용을 검토할 때도 조심하지만, 무엇이 문제로 보일지는 알아채기 어렵다는 점을 잘 알고 있어요. 그래서 항상 여러분이 선의로 행동한다고 믿고, 검토 과정에서 문제를 비난하지 않는 방식으로 찾아내려고 노력해요. 이야기를 우리와 함께 점검하고 싶다면 @exercism/leadership을 멘션해 주세요. 함께 살펴볼게요. 몇 가지 지침은 다음과 같아요:
# Instructions
In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book.
## 1. Calculate the remaining oven time in minutes
Define the `Lasagna#remaining_minutes_in_oven` method that takes the actual minutes the lasagna has been in the oven as a parameter and returns how many minutes the lasagna still has to remain in the oven, based on the expected oven time in minutes from the previous task.
```ruby
lasagna = Lasagna.new
lasagna.remaining_minutes_in_oven(30)
# => 10
```
.docs/hints.md
목적: 학생이 연습 문제에서 막혔을 때 스스로 벗어날 수 있도록 힌트를 제공해요.
포함 여부: 필수
## General 제목 아래에 Markdown 목록으로 나타낼 수 있어요.instructions.md의 해당 과제 제목과 일치하는 제목 아래에 Markdown 목록으로 나타내야 해요 (예: ## 2. Do Y).## 2. Check if a book can be borrowed).Implement the 'canBorrowBook' function to check if a book can be borrowed. The function takes a book as its parameter and returns `true` if the book has not already been borrowed; otherwise, return `false`).힌트를 보는 것은 "권장" 경로가 아니며, 학생이 힌트 없이는 진행할 수 없을 때를 제외하면 (부드럽게) 사용을 말려요. 그러니 힌트를 읽는 학생은 다소 혼란스럽거나 압도당하고, 어쩌면 답답함을 느낄 수 있다는 점을 염두에 두면 좋아요.
# Hints
## General
- You need to define a [constant][constant] which should contain the [integer][integers] value specified in the recipe.
## 1. Calculate the remaining oven time in minutes
- You need to define a [method][methods] with a single parameter for the actual time so far.
[constants]: https://www.rubyguides.com/2017/07/ruby-constants/
[integers]: https://ruby-doc.org/core-2.7.0/Integer.html
[methods]: https://launchschool.com/books/ruby/read/methods
목적: 연습 문제의 설계를 설명해요.
포함 여부: 필수
이 파일은 연습 문제의 설계에 대한 정보를 담고 있어요. 여기에는 목표, 교육 목표, 가르치지 말아야 할 것 등이 포함돼요. 이 정보는 연습 문제에 해당하는 GitHub 이슈에서 가져올 수 있어요.
이 파일은 향후 메인테이너나 기여자에게 연습 문제의 범위와 한계를 알려 주기 위해 존재해요. 시간이 지나면서 연습 문제가 점점 복잡해지는 자연스러운 흐름을 피하기 위해서예요.
# Design
## Goal
The goal of this exercise is to teach the student the basics of programming in Ruby.
## Learning objectives
- Know what a variable is.
- Know how to define a variable.
- Know how to update a variable.
## Out of scope
- Memory and performance characteristics.
- Method overloads.
## Concepts
The Concepts this exercise unlocks are:
- `basics`: know what a variable is; know how to define a variable; know how to update a variable.
## Prerequisites
There are no prerequisites.
.meta/config.json
목적: 연습 문제에 대한 메타 정보를 담고 있어요.
포함 여부: 필수
이 파일은 연습 문제에 대한 메타 정보를 담고 있어요:
authors: 연습 문제 작성자의 GitHub 사용자 이름이에요 (필수)
contributors: 연습 문제 기여자의 GitHub 사용자 이름이에요 (선택)
forked_from: 어느 연습 문제에서 포크했는지예요 (연습 문제를 포크한 경우 필수)files: 이 연습 문제에서 사용하는 파일의 위치예요. 연습 문제 디렉터리를 기준으로 한 상대 경로예요 (필수)
language_versions: 언어 버전 요구 사항이에요 (선택)blurb: 이 연습 문제에 대한 짧은 설명이에요. 길이는 350 이하여야 해요. Markdown은 지원되지 않아요 (필수)source: 이 연습 문제가 기반으로 한 출처예요 (선택)source_url: 이 연습 문제가 기반으로 한 출처의 URL이에요 (선택)representer: representer가 이 파일을 처리하는 방식과 관련된 메타 정보예요 (선택)
version: 연습 문제에 사용할 representer 버전을 나타내는 정수예요 (상위 키가 있으면 필수)icon: 아이콘의 slug예요 (전체 아이콘 목록을 참고해요). 지정하지 않으면 연습 문제의 slug가 사용돼요 (선택)custom: 연습 문제별 비표준 데이터예요. 연습 문제마다 트랙 도구의 동작을 사용자 정의하는 데 쓸 수 있어요 (선택)어떤 사람이 작성자이_면서_ 기여자라면, 작성자로만 표시해요.
{
"authors": ["FSharpForever"],
"files": {
"solution": ["Lasagna.fs"],
"test": ["LasagnaTests.fs"],
"exemplar": [".meta/Exemplar.fs"]
},
"blurb": "Learn the basics of F# by cooking Lucian's Luscious Lasagna"
}
사용자 FSharpForever가 F# 트랙을 위해 log-levels라는 연습 문제를 작성했다고 가정해요. PythonProfessor가 이 연습 문제를 Python 트랙에 맞게 각색해요. 나중에 사용자 GladToHelp가 연습 문제를 개선해요.
{
"authors": ["PythonProfessor"],
"contributors": ["GladToHelp"],
"files": {
"solution": ["log_levels.py"],
"test": ["log_levels_test.py"],
"exemplar": [".meta/exemplar.py"],
"editor": ["test_helper.py"]
},
"forked_from": ["fsharp/log-levels"],
"language_versions": ">=3.7",
"blurb": "Learn how to work with strings by processing log lines.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Log_file",
"representer": {
"version": 2
},
"icon": "logs",
"custom": {
"parallel": true
}
}
다음 사항에 유의해요:
forked_from이 올바른지만 확인해요.language_versions는 자유 형식 문자열이며, 트랙에서 자유롭게 사용하고 해석할 수 있어요..approaches/introduction.md
목적: 연습 문제에서 가장 흔한 접근법을 소개해요
포함 여부: 선택
이 파일은 연습 문제에서 가장 흔한 접근법을 설명해요. 이 파일에 무엇을 넣어야 하는지 더 자세히 알고 싶다면 문서를 확인해 봐요.
# Introduction
The key to this exercise is to deal with C# strings being immutable, which means that a `string`'s value cannot be changed.
Therefore, to reverse a string you'll need to create a _new_ `string`.
## Using LINQ
```csharp
public static string Reverse(string input)
{
return new string(input.Reverse().ToArray());
}
```
For more information, check the [LINQ approach][approach-linq].
## Which approach to use?
If readability is your primary concern (and it usually should be), the LINQ-based approach is hard to beat.
.approaches/config.json
목적: 접근법의 메타데이터예요
포함 여부: 선택 (접근법 소개나 접근법이 있으면 필수)
이 파일은 연습 문제의 접근법에 대한 메타 정보를 담고 있어요:
introduction: 연습 문제 접근법 소개의 작성자 GitHub 사용자 이름이에요 (선택)
authors: 연습 문제 접근법 소개의 작성자 GitHub 사용자 이름이에요 (필수)
contributors: 연습 문제 접근법 소개의 기여자 GitHub 사용자 이름이에요 (선택)
approaches: 자세한 접근법을 나열한 배열이에요 (선택)
uuid: 접근법을 고유하게 식별하는 V4 UUID예요. UUID는 트랙 안에서도, 모든 트랙을 통틀어서도 고유해야 하며, 절대 바뀌어서는 안 돼요slug: 접근법의 slug로, 소문자 kebab-case 문자열이에요. slug는 트랙 안의 모든 접근법 slug 중에서 고유해야 해요. 길이는 255 이하여야 해요.title: 접근법의 제목이에요. 길이는 255 이하여야 해요.blurb: 이 접근법에 대한 짧은 설명이에요. 길이는 350 이하여야 해요. Markdown은 지원되지 않아요 (필수)authors: 연습 문제 접근법의 작성자 GitHub 사용자 이름이에요 (필수)
contributors: 연습 문제 접근법의 기여자 GitHub 사용자 이름이에요 (선택)
tags: 제출물이 접근법에 연결되는 조건을 지정해요. (선택)
all: 제출물에 모두 있어야 하는 태그의 배열이에요 (선택이지만, any에 요소가 없으면 필수예요)any: 제출물에 최소 하나는 있어야 하는 태그의 배열이에요 (선택이지만, all에 요소가 없으면 필수예요)not: 제출물에 있어서는 안 되는 태그들이에요 (선택){
"introduction": {
"authors": ["erikschierboom"]
},
"approaches": [
{
"uuid": "448fb2b4-18ab-4e55-aa54-ad4ed6d5f7f6",
"slug": "span",
"title": "Use Span<T>",
"blurb": "Use Span<T> to efficiently reverse a string.",
"authors": ["erikschierboom"]
}
]
}
.approaches/<approach-slug>/content.md
목적: 접근법에 대한 자세한 설명이에요
포함 여부: 선택 (접근법에는 필수)
이 파일은 접근법에 대한 자세한 설명을 담고 있어요. 이 파일에 무엇을 넣어야 하는지 더 자세히 알고 싶다면 문서를 확인해 봐요.
# Span
```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```
This `Span<T>` approach uses a `for` loop.
.approaches/<approach-slug>/snippet.txt
목적: 접근법을 보여 주는 스니펫이에요
포함 여부: 선택 (접근법에는 필수)
이 파일은 접근법을 보여 주는 작은 스니펫을 담고 있어요. 스니펫은 연습 문제의 dig deeper 페이지에 표시돼요.
줄 수는 8 이하여야 해요.
이 파일에 무엇을 넣어야 하는지 더 자세히 알고 싶다면 문서를 확인해 봐요.
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
.article/config.json
목적: 아티클의 메타데이터예요
포함 여부: 선택 (아티클이 있으면 필수)
이 파일은 연습 문제의 아티클에 대한 메타 정보를 담고 있어요:
articles: 자세한 아티클을 나열한 배열이에요 (선택)
uuid: 아티클을 고유하게 식별하는 V4 UUID예요. UUID는 트랙 안에서도, 모든 트랙을 통틀어서도 고유해야 하며, 절대 바뀌어서는 안 돼요slug: 아티클의 slug로, 소문자 kebab-case 문자열이에요. slug는 트랙 안의 모든 아티클 slug 중에서 고유해야 해요. 길이는 255 이하여야 해요.title: 아티클의 제목이에요. 길이는 255 이하여야 해요.blurb: 이 아티클에 대한 짧은 설명이에요. 길이는 350 이하여야 해요. Markdown은 지원되지 않아요 (필수)authors: 연습 문제 아티클의 작성자 GitHub 사용자 이름이에요 (필수)
contributors: 연습 문제 아티클의 기여자 GitHub 사용자 이름이에요 (선택)
{
"articles": [
{
"uuid": "6db71962-62d5-448b-a980-c20ae41013ed",
"slug": "performance",
"title": "Optimizing performance",
"blurb": "Explore how to most efficiently reverse a string and what the trade-offs are.",
"authors": ["erikschierboom"]
}
]
}
.articles/<article-slug>/content.md
목적: 접근법에 대한 자세한 설명이에요
포함 여부: 선택 (접근법에는 필수)
이 파일은 접근법에 대한 자세한 설명을 담고 있어요. 이 파일에 무엇을 넣어야 하는지 더 자세히 알고 싶다면 문서를 확인해 봐요.
# Performance
In this document, we'll find out which approach is the most performant one.
## Benchmark results
| Method | Mean | Error | StdDev | Median | Allocated |
| -----: | --------: | --------: | --------: | --------: | --------: |
| Linq | 29.133 ns | 0.5865 ns | 0.5486 ns | 28.984 ns | 80 B |
| Array | 4.806 ns | 0.4999 ns | 1.4739 ns | 3.967 ns | - |
.articles/<article-slug>/snippet.txt
목적: 접근법을 보여 주는 스니펫이에요
포함 여부: 선택 (아티클에는 필수)
이 파일은 아티클을 보여 주는 작은 스니펫을 담고 있어요. 스니펫은 연습 문제의 dig deeper 페이지에 표시돼요.
줄 수는 8 이하여야 해요.
이 파일에 무엇을 넣어야 하는지 더 자세히 알고 싶다면 문서를 확인해 봐요.
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
목적: 학생에게 시작점을 제공해요.
포함 여부: 필수
.meta/config.json 파일의 "files.solution" 키에 지정해야 해요.class Lasagna
def remaining_minutes_in_oven(actual_minutes_in_oven)
raise NotImplementedError, 'Please implement the Lasagna#remaining_minutes_in_oven method'
end
def preparation_time_in_minutes(layers)
raise NotImplementedError, 'Please implement the Lasagna#preparation_time_in_minutes method'
end
end
목적: 풀이의 정확성을 검증해요.
포함 여부: 필수
instructions.md 파일의 예시를 사용해서는 안 돼요..meta/config.json 파일의 "files.test" 키에 지정해야 해요.require 'minitest/autorun'
require_relative 'lasagna'
class LasagnaTest < Minitest::Test
def test_remaining_minutes_in_oven
assert_equal 15, Lasagna.new.remaining_minutes_in_oven(25)
end
def test_preparation_time_in_minutes_with_one_layer
assert_equal 2, Lasagna.new.preparation_time_in_minutes(1)
end
def test_preparation_time_in_minutes_with_multiple_layers
assert_equal 8, Lasagna.new.preparation_time_in_minutes(4)
end
end
목적: 학생이 목표로 삼아야 할 구현을 제공해요.
포함 여부: 필수
.meta/config.json 파일의 "files.exemplar" 키에 지정해야 해요.class Lasagna
EXPECTED_MINUTES_IN_OVEN = 40
PREPARATION_MINUTES_PER_LAYER = 2
def remaining_minutes_in_oven(actual_minutes_in_oven)
EXPECTED_MINUTES_IN_OVEN - actual_minutes_in_oven
end
def preparation_time_in_minutes(layers)
layers * PREPARATION_MINUTES_PER_LAYER
end
end
목적: 테스트를 실행할 수 있도록 보장해요.
포함 여부: 기본 파일만으로는 테스트를 실행할 수 없을 때 필수
일부 언어는 테스트를 실행하기 위해 추가 파일이 필요해요. 예를 들어 C#의 프로젝트 파일이나 Node의 package.json 파일이 없으면 테스트를 실행할 수 없어요.
일부 파일은 개별 연습 문제에 특정되지 않고 모든 연습 문제에 적용돼요. 더 자세한 내용은 문서를 확인해 봐요.
개념 연습 문제의 이름은 그 개념이 아니라 이야기/테마를 따라 지어야 해요.
좋은 이름 예시:
Tim from MarketingLucian's Luscious LasagnaCalculator Conundrum허용되지 않는 이름:
Booleans: 이야기 이름이 아니라 개념 이름을 사용했어요Exercise #1: 연습 문제는 이야기/테마가 아니에요큰 변경 없이 연습 문제를 포크할 때는 가능하면 원래 이름을 사용해요.
각 연습 문제에는 _slug_도 있어요. slug는 다음 규칙에 따라 연습 문제 이름을 정규화한 버전이에요:
[a-z0-9-]+)2-fer보다 two-fer)좋은 slug 예시:
tim-from-marketinglucians-luscious-lasagnacalculator-conundrum허용되지 않는 slug:
TIM-FROM-MARKETING: 소문자를 사용하지 않았어요 (즉, tim-from-marketing)TimFromMarketing: kebab-case를 사용하지 않았어요 (즉, tim-from-marketing)floating-point-numbers: 이야기 이름이 아니라 개념 이름을 사용했어요브라우저 편집기를 사용할 때와 CLI를 사용할 때 연습 문제 문서가 학생에게 표시되는 방식에는 차이가 있어요. 더 자세한 내용은 이 문서를 봐요.
각 연습 문제에는 함께 제공되는 아이콘이 있어요.
기본적으로 표시되는 아이콘은 이름이 연습 문제의 slug와 일치하는 아이콘이에요.
연습 문제의 .meta/config.json 파일에 icon 속성을 지정하면 이를 바꿀 수 있어요.
기존 연습 문제를 포크하는 경우라면 그 연습 문제에 맞는 아이콘이 이미 있을 거예요. 없다면 website-icons 저장소에 이슈를 열어 주세요.