Exercícios de prática são exercícios criados para que os estudantes resolvam um problema arbitrário, com o objetivo de que usem os conceitos que aprenderam até agora.
Quer adicionar seu primeiro exercício de prática a uma trilha? Confira a documentação de Adicionar exercício de prática ou assista ao nosso vídeo explicativo 👇
Você pode criar rapidamente a estrutura de um novo exercício de prática rodando os comandos a seguir a partir do diretório raiz da trilha:
bin/fetch-configlet
bin/configlet create --practice-exercise <slug>
Para mais informações, confira a documentação do configlet create
Os metadados de um exercício de prática são definidos na chave exercises.practice do arquivo config.json. Os metadados definem o UUID, o slug e outras informações do exercício.
{
"exercises": {
"practice": [
{
"uuid": "8ba15933-29a2-49b1-a9ce-70474bad3007",
"slug": "leap",
"name": "Leap",
"practices": ["if-statements", "numbers", "operator-precedence"],
"prerequisites": ["if-statements", "numbers"],
"difficulty": 1
}
]
}
}
practicesA chave practices deve listar os slugs dos Conceitos que este exercício de prática permite que um estudante pratique ativamente.
strings). Nesses casos, recomendamos escolher alguns bons exercícios que façam as pessoas pensarem nesses Conceitos de formas interessantes. Por exemplo, exercícios que exigem UTF-8, concatenação de strings, enumeração de caracteres etc. seriam todos bons exemplos.prerequisitesA chave prerequisites lista os Conceitos que um estudante precisa ter concluído para acessar este exercício de prática.
strings, optional-params, implicit-return.loops ou recursion), o mantenedor deve escolher a abordagem com a qual prefere desbloquear o exercício, considerando a jornada do estudante pela trilha. Por exemplo, no caso de loops/recursão, ele pode achar que este exercício é uma boa prática inicial de loops ou que prefere deixá-lo mais para frente para ensinar recursão. Ele também pode usar um analisador para sugerir ao estudante que tente uma abordagem alternativa: "Bom trabalho resolvendo com loops. Você também pode gostar de tentar resolver usando recursão."Cada exercício de prática tem seu próprio diretório dentro do diretório exercises/practice da trilha. O nome do diretório do exercício de prática deve corresponder à propriedade slug do exercício de prática, conforme definido no arquivo config.json.
Um exercício de prática tem quatro tipos de arquivos:
Esses arquivos são apresentados ao estudante para ajudar a explicar o exercício.
.docs/introduction.md: apresenta o cenário e o contexto do exercício (opcional).docs/introduction.append.md: texto de introdução adicional para acrescentar depois da introdução existente (opcional).docs/instructions.md: fornece as instruções do exercício (obrigatório).docs/instructions.append.md: texto adicional para acrescentar depois das instruções existentes (opcional).docs/hints.md: fornece dicas para ajudar o estudante a se desbloquear no exercício (opcional)Esses arquivos não são apresentados ao estudante, mas usados para definir metadados do exercício.
.meta/config.json: contém informações de metadados sobre o exercício (obrigatório).meta/design.md: descreve o design do exercício (opcional).meta/tests.toml: contém informações sobre quais testes estão implementados (opcional)Esses arquivos descrevem abordagens para o exercício.
.approaches/introduction.md: introdução às abordagens mais comuns para o exercício (opcional).approaches/config.json: metadados das abordagens (opcional).approaches/<approach-slug>/content.md: descrição da abordagem (opcional).approaches/<approach-slug>/snippet.txt: trecho que mostra a abordagem (opcional)Esses arquivos descrevem artigos para o exercício.
.articles/config.json: metadados dos artigos (opcional).articles/<article-slug>/content.md: descrição do artigo (opcional).articles/<article-slug>/snippet.md: trecho que mostra o artigo (opcional)Os arquivos específicos da linguagem, como os arquivos de implementação e de teste. Os nomes desses arquivos variam conforme a trilha.
exercises
└── practice
└── isogram
├── .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
| ├── tests.toml
| └── Example.cs (implementação de exemplo)
├── Isogram.cs (implementação stub)
└── IsogramTests.cs (testes)
.docs/introduction.md
Objetivo: Apresentar ao estudante o cenário e o contexto do exercício.
Presença: Obrigatório se o exercício implementa um Exercício de Problem Specifications com um arquivo introduction.md
Se o exercício implementa um Exercício de Problem Specifications, o conteúdo deste arquivo deve corresponder ao arquivo introduction.md do Exercício de Problem Specifications. O configlet tem uma funcionalidade para sincronizar automaticamente o conteúdo deste arquivo.
Se o exercício não for baseado em um Exercício de Problem Specifications, considere o seguinte:
Damos muito valor a tornar o conteúdo do Exercism seguro para todo mundo e, por isso, muitas vezes pecamos pelo excesso de cautela ao decidir se uma história é apropriada ou não. Embora sejamos cuidadosos com o que fazemos merge, sabemos que é difícil ter consciência do que pode ser visto como problemático. Por isso, sempre presumimos que você está agindo de boa-fé e fazemos o possível para identificar qualquer problema na revisão de forma não confrontadora. Se quiser verificar uma história com a gente, mencione @exercism/leadership e vamos analisá-la juntos. Aqui vão alguns pontos norteadores:
# Introduction
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
.docs/introduction.append.md
Objetivo: Texto de introdução adicional para acrescentar depois da introdução existente.
Presença: Opcional
Em alguns casos (raros), você pode querer ampliar o arquivo introduction.md do exercício, por exemplo quando o exercício implementa testes que não são cobertos pelas instruções existentes.
Uma trilha que não quer que o Bob aceite mensagens não ASCII pode acrescentar o seguinte:
# Introduction append
## Note
As part of his teenage rebellion, Bob has decided to only communicate using ASCII.
Os arquivos de append devem começar com um cabeçalho H1. Esse cabeçalho não é exibido, mas ainda assim deve estar presente. O cabeçalho H1 geralmente é seguido por um cabeçalho H2, que ajuda a separar o conteúdo genérico do conteúdo específico da trilha.
.docs/instructions.md
Objetivo: Fornecer as instruções do exercício.
Presença: Obrigatório
Se o exercício implementa um Exercício de Problem Specifications, o conteúdo deste arquivo deve corresponder ao arquivo instructions.md do Exercício de Problem Specifications (ou ao arquivo description.md, se não houver um arquivo instructions.md). O configlet tem uma funcionalidade para sincronizar automaticamente o conteúdo deste arquivo.
Se o exercício não for baseado em um Exercício de Problem Specifications, considere o seguinte:
Damos muito valor a tornar o conteúdo do Exercism seguro para todo mundo e, por isso, muitas vezes pecamos pelo excesso de cautela ao decidir se uma história é apropriada ou não. Embora sejamos cuidadosos com o que fazemos merge, sabemos que é difícil ter consciência do que pode ser visto como problemático. Por isso, sempre presumimos que você está agindo de boa-fé e fazemos o possível para identificar qualquer problema na revisão de forma não confrontadora. Se quiser verificar uma história com a gente, mencione @exercism/leadership e vamos analisá-la juntos. Aqui vão alguns pontos norteadores:
# Instructions
Bob answers 'Sure.' if you ask him a question, such as "How are you?".
He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
He says 'Fine. Be that way!' if you address him without actually saying anything.
He answers 'Whatever.' to anything else.
.docs/instructions.append.md
Objetivo: Texto de instruções adicional para acrescentar depois das instruções existentes.
Presença: Opcional
Em alguns casos (raros), você pode querer ampliar o arquivo instructions.md do exercício, por exemplo quando o exercício implementa testes que não são cobertos pelas instruções existentes.
# Instructions append
## Note
Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
Os arquivos de append devem começar com um cabeçalho H1. Esse cabeçalho não é exibido, mas ainda assim deve estar presente. O cabeçalho H1 geralmente é seguido por um cabeçalho H2, que ajuda a separar o conteúdo genérico do conteúdo específico da trilha.
.docs/hints.md
Objetivo: Fornecer dicas para ajudar um estudante a se desbloquear em um exercício.
Presença: Opcional
## General.Ver as dicas não será um caminho "recomendado" e vamos desencorajar (com jeitinho) o uso delas, a menos que o estudante não consiga progredir sem elas. Por isso, vale considerar que o estudante que as lerá estará um pouco confuso/sobrecarregado e talvez frustrado.
## General
- There are many [built-in methods][integers] to simplify working with integers.
[integers]: https://ruby-doc.org/core-2.7.0/Integer.html
Objetivo: Descrever o design do exercício.
Presença: Opcional
Este arquivo contém informações sobre o design do exercício, incluindo coisas como seu objetivo, seus objetivos de ensino, o que não ensinar e mais.
Ele existe para informar futuros mantenedores ou colaboradores sobre o escopo e as limitações de um exercício, a fim de evitar a tendência natural de tornar os exercícios mais complexos com o tempo.
# Design
## Goal
The goal of this exercise is help students practice how to work with strings.
## Notes
This exercise does not contain any error handling tests.
.meta/config.json
Objetivo: Contém informações de metadados sobre o exercício.
Presença: Obrigatório
Este arquivo contém informações de metadados sobre o exercício:
authors: o(s) nome(s) de usuário do GitHub do(s) autor(es) do exercício (opcional)
contributors: o(s) nome(s) de usuário do GitHub do(s) colaborador(es) do exercício (opcional)
files: os locais dos arquivos usados neste exercício, relativos ao diretório do exercício (obrigatório)
solution: o(s) arquivo(s) de implementação stub (obrigatório)test: o(s) arquivo(s) de teste (obrigatório)example: o(s) arquivo(s) de implementação de exemplo (obrigatório)editor: arquivos adicionais exibidos como somente leitura no editor (opcional)invalidator: arquivos que, quando alterados, fazem uma solução ficar desatualizada (opcional)language_versions: requisitos de versão da linguagem (opcional)blurb: uma descrição curta deste exercício. O comprimento deve ser <= 350. Markdown não é suportado (obrigatório)source: a fonte em que este exercício se baseia (opcional)source_url: a URL da fonte em que este exercício se baseia (opcional)test_runner: indica se as soluções deste exercício devem ser testadas no test runner. Assume true por padrão, se não for especificado. (opcional)representer: informações de metadados relacionadas a como o representer processa este arquivo (opcional)
version: um inteiro para a versão do representer a usar no exercício (obrigatório se a chave pai estiver presente)icon: o slug do ícone (veja a lista completa de ícones). Se não for especificado, o slug do exercício será usado (opcional)custom: quaisquer dados não padrão específicos do exercício. Pode ser usado para personalizar o comportamento das ferramentas da trilha por exercício (opcional)Se alguém for ao mesmo tempo autor e colaborador, liste essa pessoa apenas como autor.
{
"authors": ["FSharpForever"],
"files": {
"solution": ["Bob.fs"],
"test": ["BobTests.fs"],
"example": [".meta/Example.fs"]
},
"blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited"
}
Observe que:
language_versions é uma string de formato livre que as trilhas podem usar e interpretar como quiserem.Objetivo: Contém informações sobre quais testes estão implementados.
Presença: Opcional
Este arquivo contém informações sobre quais testes estão sendo implementados, desde que o exercício tenha testes definidos em seu arquivo canonical-data.json dentro do repositório problem-specifications.
Ele existe para ajudar os mantenedores a acompanhar quais testes estão implementados e para (opcionalmente) documentar por que um determinado teste não foi implementado. Ele também pode ser usado para detectar testes não implementados.
A ferramenta configlet cuida de atualizar/sincronizar este arquivo com os dados do repositório problem-specifications por meio do comando configlet sync. Ao sincronizar, o configlet pergunta, para cada teste não implementado, se aquele teste deve ser incluído ou não.
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.
[3e5c30a8-87e2-4845-a815-a49671ade970]
description = "empty strand"
[a0ea42a6-06d9-4ac6-828c-7ccaccf98fec]
description = "can count one nucleotide in single-character input"
[eca0d565-ed8c-43e7-9033-6cefbf5115b5]
description = "strand with repeated nucleotide"
[40a45eac-c83f-4740-901a-20b22d15a39f]
description = "strand with multiple nucleotides"
[b4c47851-ee9e-4b0a-be70-a86e343bd851]
description = "strand with invalid nucleotides"
include = false
comment = "error handling omitted on purpose"
.approaches/introduction.md
Objetivo: Introdução às abordagens mais comuns para o exercício
Presença: Opcional
Este arquivo descreve as abordagens mais comuns para o exercício. Confira a documentação para mais informações sobre o que deve constar neste arquivo.
# 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
Objetivo: Metadados das abordagens
Presença: Opcional (obrigatório quando existem uma introdução de abordagem ou uma abordagem)
Este arquivo contém informações de metadados sobre as abordagens do exercício:
introduction: o(s) nome(s) de usuário do GitHub do(s) autor(es) da introdução das abordagens do exercício (opcional)
authors: o(s) nome(s) de usuário do GitHub do(s) autor(es) da introdução das abordagens do exercício (obrigatório)
contributors: o(s) nome(s) de usuário do GitHub do(s) colaborador(es) da introdução das abordagens do exercício (opcional)
approaches: um array que lista as abordagens detalhadas (opcional)
uuid: um UUID V4 que identifica a abordagem de forma única. O UUID deve ser único tanto dentro da trilha quanto em todas as trilhas, e nunca deve mudarslug: o slug da abordagem, que é uma string em letras minúsculas no formato kebab-case. O slug deve ser único entre todos os slugs de abordagem da trilha. O comprimento deve ser <= 255.title: o título da abordagem. O comprimento deve ser <= 255.blurb: uma descrição curta desta abordagem. O comprimento deve ser <= 350. Markdown não é suportado (obrigatório)authors: o(s) nome(s) de usuário do GitHub do(s) autor(es) da abordagem do exercício (obrigatório)
contributors: o(s) nome(s) de usuário do GitHub do(s) colaborador(es) da abordagem do exercício (opcional)
tags: especifique as condições para quando uma submissão é vinculada a uma abordagem. (opcional)
all: um array de tags que devem estar todas presentes em uma submissão (opcional, a menos que any não tenha elementos)any: um array de tags das quais pelo menos uma deve estar presente em uma submissão (opcional, a menos que all não tenha elementos)not: nenhuma das tags deve estar presente em uma submissão (opcional){
"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
Objetivo: Descrição detalhada da abordagem
Presença: Opcional (obrigatório para abordagens)
Este arquivo contém uma descrição detalhada da abordagem. Confira a documentação para mais informações sobre o que deve constar neste arquivo.
# 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
Objetivo: Trecho que mostra a abordagem
Presença: Opcional (obrigatório para abordagens)
Este arquivo contém um pequeno trecho que mostra a abordagem. O trecho é exibido na página Dig Deeper de um exercício.
O número de linhas deve ser <= 8.
Confira a documentação para mais informações sobre o que deve constar neste arquivo.
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
Objetivo: Metadados dos artigos
Presença: Opcional (obrigatório quando existe um artigo)
Este arquivo contém informações de metadados sobre os artigos do exercício:
articles: um array que lista os artigos detalhados (opcional)
uuid: um UUID V4 que identifica o artigo de forma única. O UUID deve ser único tanto dentro da trilha quanto em todas as trilhas, e nunca deve mudarslug: o slug do artigo, que é uma string em letras minúsculas no formato kebab-case. O slug deve ser único entre todos os slugs de artigo da trilha. O comprimento deve ser <= 255.title: o título do artigo. O comprimento deve ser <= 255.blurb: uma descrição curta deste artigo. O comprimento deve ser <= 350. Markdown não é suportado (obrigatório)authors: o(s) nome(s) de usuário do GitHub do(s) autor(es) do artigo do exercício (obrigatório)
contributors: o(s) nome(s) de usuário do GitHub do(s) colaborador(es) do artigo do exercício (opcional)
{
"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
Objetivo: Descrição detalhada da abordagem
Presença: Opcional (obrigatório para abordagens)
Este arquivo contém uma descrição detalhada da abordagem. Confira a documentação para mais informações sobre o que deve constar neste arquivo.
# 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
Objetivo: Trecho que mostra a abordagem
Presença: Opcional (obrigatório para artigos)
Este arquivo contém um pequeno trecho que mostra o artigo. O trecho é exibido na página Dig Deeper de um exercício.
O número de linhas deve ser <= 8.
Confira a documentação para mais informações sobre o que deve constar neste arquivo.
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
Objetivo: Fornecer um ponto de partida para os estudantes.
Presença: Obrigatório
"files.solution" do arquivo .meta/config.json.using System;
public static class Isogram
{
public static bool IsIsogram(string word)
{
throw new NotImplementedException("You need to implement this function.");
}
}
Objetivo: Verificar se uma solução está correta.
Presença: Obrigatório
"files.test" do arquivo .meta/config.json.using Xunit;
public class IsogramTest
{
[Fact]
public void Empty_string() =>
Assert.True(Isogram.IsIsogram(""));
[Fact(Skip = "Remove this Skip property to run this test")]
public void Isogram_with_only_lower_case_characters() =>
Assert.True(Isogram.IsIsogram("isogram"));
[Fact(Skip = "Remove this Skip property to run this test")]
public void Word_with_one_duplicated_character() =>
Assert.False(Isogram.IsIsogram("eleven"));
}
Objetivo: Fornecer uma implementação de exemplo que passa em todos os testes.
Presença: Obrigatório
"files.example" do arquivo .meta/config.json.using System.Linq;
public static class Isogram
{
public static bool IsIsogram(string word)
{
var lowerCaseLetters = word.ToLower().Where(char.IsLetter).ToList();
return lowerCaseLetters.Distinct().Count() == lowerCaseLetters.Count;
}
}
Objetivo: Arquivos adicionais de projeto, de build ou de apoio necessários para que os testes possam rodar.
Presença: Obrigatório se os arquivos padrão não forem suficientes para rodar os testes
Algumas linguagens exigem arquivos adicionais para que os testes rodem. Exemplos disso são os arquivos de projeto do C# e os arquivos package.json do Node, sem os quais não será possível rodar os testes.
Alguns arquivos não são específicos de exercícios individuais, mas se aplicam a todos os exercícios. Confira a documentação para mais informações.
Há uma diferença na forma como a documentação do exercício é apresentada ao estudante ao usar o editor no navegador versus usar a CLI. Veja este documento para mais informações.
Cada exercício tem um ícone correspondente.
Por padrão, o ícone exibido é aquele cujo nome corresponde ao slug do exercício.
É possível substituir isso especificando a propriedade icon no arquivo .meta/config.json do exercício.
Se você está implementando um exercício a partir dos metadados do problem-specifications, provavelmente já existe um ícone para esse exercício. Se não houver, por favor abra uma issue no repositório website-icons.