Os exercícios de prática são exercícios concebidos para permitir que os estudantes resolvam um problema arbitrário, com o objetivo de usarem os conceitos que aprenderam até agora.
Queres adicionar o teu primeiro exercício de prática a um percurso? Consulta a documentação para adicionar exercícios de prática ou vê o nosso vídeo explicativo 👇
Podes criar rapidamente a estrutura de um novo exercício de prática executando os seguintes comandos a partir do diretório raiz do percurso:
bin/fetch-configlet
bin/configlet create --practice-exercise <slug>
Para mais informações, consulta a documentação do configlet create
Os metadados de um exercício de prática são definidos na chave exercises.practice do ficheiro config.json. Os metadados definem o UUID, o slug e muito mais 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 ativamente que um estudante pratique.
strings). Nesses casos, recomendamos escolher alguns bons exercícios que façam as pessoas pensar nesses conceitos de formas interessantes. Por exemplo, exercícios que exijam UTF-8, concatenação de strings, enumeração de carateres, etc., são todos bons exemplos.prerequisitesA chave prerequisites lista os conceitos que um estudante tem de ter concluído para poder aceder a este exercício de prática.
strings, optional-params, implicit-return.loops ou recursion), o maintainer deve escolher a abordagem com que quer desbloquear o exercício, tendo em conta a progressão do estudante ao longo do percurso. Por exemplo, no caso dos ciclos/recursão, pode achar que este exercício é uma boa prática inicial de loops ou que prefere deixá-lo para mais tarde, para ensinar recursão. Também pode recorrer a um analyzer para incentivar o estudante a experimentar uma abordagem alternativa: «Bom trabalho a resolver isto com ciclos. Talvez também gostes de experimentar resolvê-lo com recursão.»Cada exercício de prática tem o seu próprio diretório dentro do diretório exercises/practice do percurso. O nome do diretório do exercício de prática tem de corresponder à propriedade slug do exercício de prática, conforme definido no ficheiro config.json.
Um exercício de prática tem quatro tipos de ficheiros:
Estes ficheiros são apresentados ao estudante para ajudar a explicar o exercício.
.docs/introduction.md: apresenta o contexto e os antecedentes 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 de introdução adicional para acrescentar depois das instruções existentes (opcional).docs/hints.md: fornece pistas ao estudante para o ajudar a desbloquear-se no exercício (opcional)Estes ficheiros não são apresentados ao estudante, mas são usados para definir os metadados do exercício.
.meta/config.json: contém informações de metadados sobre o exercício (obrigatório).meta/design.md: descreve a conceção do exercício (opcional).meta/tests.toml: contém informações sobre os testes implementados (opcional)Estes ficheiros 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: snippet que exemplifica a abordagem (opcional)Estes ficheiros 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: snippet que exemplifica o artigo (opcional)Os ficheiros específicos da linguagem, como os ficheiros de implementação e de testes. Os nomes destes ficheiros são específicos de cada percurso.
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 (example implementation)
├── Isogram.cs (stub implementation)
└── IsogramTests.cs (tests)
.docs/introduction.md
Objetivo: Apresentar ao estudante o contexto e os antecedentes do exercício.
Presença: Obrigatório se o exercício implementar um exercício de Problem Specifications com um ficheiro introduction.md
Se o exercício implementar um exercício de Problem Specifications, o conteúdo deste ficheiro deve corresponder ao ficheiro introduction.md do exercício de Problem Specifications. O configlet tem uma funcionalidade para sincronizar automaticamente o conteúdo deste ficheiro.
Se o exercício não se basear num exercício de Problem Specifications, tem em conta o seguinte:
Damos muito valor a tornar o conteúdo do Exercism seguro para todos e, por isso, muitas vezes pecamos por excesso de cautela ao decidir se uma história é apropriada ou não. Embora tenhamos cuidado com o que fazemos merge, sabemos que é difícil ter consciência do que pode ser visto como problemático. Por isso, partimos sempre do princípio de que estás a agir de boa-fé e fazemos o possível por detetar qualquer problema durante a revisão de forma não confrontacional. Se quiseres verificar uma história connosco, menciona @exercism/leadership e vemo-la juntos. Aqui ficam alguns pontos orientadores:
# 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), podes querer ampliar o ficheiro introduction.md do exercício, por exemplo quando o exercício tem testes implementados que não são abrangidos pelas instruções existentes.
Um percurso que não queira que o Bob suporte 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 ficheiros append devem começar com um cabeçalho H1. Este cabeçalho não é apresentado, mas deve estar presente. O cabeçalho H1 é frequentemente seguido de um cabeçalho H2, que ajuda a separar o conteúdo genérico do conteúdo específico do percurso.
.docs/instructions.md
Objetivo: Fornecer as instruções do exercício.
Presença: Obrigatório
Se o exercício implementar um exercício de Problem Specifications, o conteúdo deste ficheiro deve corresponder ao ficheiro instructions.md do exercício de Problem Specifications (ou ao ficheiro description.md, se não existir um ficheiro instructions.md). O configlet tem uma funcionalidade para sincronizar automaticamente o conteúdo deste ficheiro.
Se o exercício não se basear num exercício de Problem Specifications, tem em conta o seguinte:
Damos muito valor a tornar o conteúdo do Exercism seguro para todos e, por isso, muitas vezes pecamos por excesso de cautela ao decidir se uma história é apropriada ou não. Embora tenhamos cuidado com o que fazemos merge, sabemos que é difícil ter consciência do que pode ser visto como problemático. Por isso, partimos sempre do princípio de que estás a agir de boa-fé e fazemos o possível por detetar qualquer problema durante a revisão de forma não confrontacional. Se quiseres verificar uma história connosco, menciona @exercism/leadership e vemo-la juntos. Aqui ficam alguns pontos orientadores:
# 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), podes querer ampliar o ficheiro instructions.md do exercício, por exemplo quando o exercício tem testes implementados que não são abrangidos 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 ficheiros append devem começar com um cabeçalho H1. Este cabeçalho não é apresentado, mas deve estar presente. O cabeçalho H1 é frequentemente seguido de um cabeçalho H2, que ajuda a separar o conteúdo genérico do conteúdo específico do percurso.
.docs/hints.md
Objetivo: Fornecer pistas ao estudante para o ajudar a desbloquear-se num exercício.
Presença: Opcional
## General.Ver as pistas não será um caminho «recomendado» e vamos desencorajar (suavemente) o seu uso, a não ser que o estudante não consiga avançar sem elas. Por isso, vale a pena ter em conta que o estudante que as lê 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 a conceção do exercício.
Presença: Opcional
Este ficheiro contém informações sobre a conceção do exercício, incluindo coisas como o seu objetivo, os seus objetivos de ensino, o que não ensinar, e mais.
Existe para informar futuros maintainers ou contributors sobre o âmbito e as limitações de um exercício, de modo a evitar a tendência natural para 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 ficheiro contém informações de metadados sobre o exercício:
authors: O(s) nome(s) de utilizador do GitHub do(s) autor(es) do exercício (opcional)
contributors: O(s) nome(s) de utilizador do GitHub do(s) contributor(s) do exercício (opcional)
files: As localizações dos ficheiros usados neste exercício, relativas ao diretório do exercício (obrigatório)
solution: o(s) ficheiro(s) de implementação stub (obrigatório)test: o(s) ficheiro(s) de teste (obrigatório)example: o(s) ficheiro(s) de implementação de exemplo (obrigatório)editor: ficheiros adicionais mostrados como só de leitura no editor (opcional)invalidator: ficheiros que, quando alterados, fazem com que uma solução fique desatualizada (opcional)language_versions Requisitos de versão da linguagem (opcional)blurb: Uma descrição curta deste exercício. O comprimento tem de ser <= 350. O Markdown não é suportado (obrigatório)source: A fonte em que este exercício se baseia (opcional)source_url: O 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. Por predefinição, assume true se não for especificado. (opcional)representer: Informações de metadados relacionadas com a forma como o representer processa este ficheiro (opcional)
version: Um número inteiro para a versão do representer a usar para o exercício (obrigatório se a chave principal estiver presente)icon: O slug do ícone (consulta a lista completa de ícones). Se não for especificado, será usado o slug do exercício (opcional)custom: Quaisquer dados não padrão específicos do exercício. Pode ser usado para personalizar o comportamento das ferramentas do percurso por exercício (opcional)Se alguém for ao mesmo tempo autor e contributor, indica 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"
}
Nota que:
language_versions é uma string de forma livre que os percursos podem usar e interpretar como quiserem.Objetivo: Contém informações sobre os testes implementados.
Presença: Opcional
Este ficheiro contém informações sobre quais testes estão a ser implementados, desde que o exercício tenha testes definidos no seu ficheiro canonical-data.json dentro do repositório problem-specifications.
Existe para ajudar os maintainers a acompanhar quais testes estão implementados e para documentar (opcionalmente) porque é que determinado teste não está implementado. Também pode ser usado para detetar testes não implementados.
A ferramenta configlet trata de atualizar/sincronizar este ficheiro com os dados do repositório problem-specifications através do comando configlet sync. Ao sincronizar, o configlet pergunta, para cada teste não implementado, se deve incluir esse teste 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 ficheiro descreve as abordagens mais comuns para o exercício. Consulta a documentação para mais informações sobre o que deve constar neste ficheiro.
# 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 existe uma introdução de abordagem ou uma abordagem)
Este ficheiro contém informações de metadados sobre as abordagens do exercício:
introduction: O(s) nome(s) de utilizador do GitHub do(s) autor(es) da introdução das abordagens do exercício (opcional)
authors: O(s) nome(s) de utilizador do GitHub do(s) autor(es) da introdução das abordagens do exercício (obrigatório)
contributors: O(s) nome(s) de utilizador do GitHub do(s) contributor(s) 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 tem de ser único tanto dentro do percurso como em todos os percursos, e nunca pode mudarslug: o slug da abordagem, que é uma string em minúsculas, em kebab-case. O slug tem de ser único entre todos os slugs de abordagens do percurso. O comprimento tem de ser <= 255.title: o título da abordagem. O comprimento tem de ser <= 255.blurb: Uma descrição curta desta abordagem. O comprimento tem de ser <= 350. O Markdown não é suportado (obrigatório)authors: O(s) nome(s) de utilizador do GitHub do(s) autor(es) da abordagem do exercício (obrigatório)
contributors: O(s) nome(s) de utilizador do GitHub do(s) contributor(s) da abordagem do exercício (opcional)
tags: Especifica as condições em que uma submissão é associada a uma abordagem. (opcional)
all: Um array de tags que têm de estar todas presentes numa submissão (opcional, a menos que any não tenha elementos)any: Um array de tags das quais pelo menos uma tem de estar presente numa submissão (opcional, a menos que all não tenha elementos)not: nenhuma das tags pode estar presente numa 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 ficheiro contém uma descrição detalhada da abordagem. Consulta a documentação para mais informações sobre o que deve constar neste ficheiro.
# 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: Snippet que exemplifica a abordagem
Presença: Opcional (obrigatório para abordagens)
Este ficheiro contém um pequeno snippet que exemplifica a abordagem. O snippet é mostrado na página dig deeper de um exercício.
O número de linhas tem de ser <= 8.
Consulta a documentação para mais informações sobre o que deve constar neste ficheiro.
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 ficheiro 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 tem de ser único tanto dentro do percurso como em todos os percursos, e nunca pode mudarslug: o slug do artigo, que é uma string em minúsculas, em kebab-case. O slug tem de ser único entre todos os slugs de artigos do percurso. O comprimento tem de ser <= 255.title: o título do artigo. O comprimento tem de ser <= 255.blurb: Uma descrição curta deste artigo. O comprimento tem de ser <= 350. O Markdown não é suportado (obrigatório)authors: O(s) nome(s) de utilizador do GitHub do(s) autor(es) do artigo do exercício (obrigatório)
contributors: O(s) nome(s) de utilizador do GitHub do(s) contributor(s) 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 ficheiro contém uma descrição detalhada da abordagem. Consulta a documentação para mais informações sobre o que deve constar neste ficheiro.
# 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: Snippet que exemplifica a abordagem
Presença: Opcional (obrigatório para artigos)
Este ficheiro contém um pequeno snippet que exemplifica o artigo. O snippet é mostrado na página dig deeper de um exercício.
O número de linhas tem de ser <= 8.
Consulta a documentação para mais informações sobre o que deve constar neste ficheiro.
| 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 ficheiro .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 a correção de uma solução.
Presença: Obrigatório
"files.test" do ficheiro .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 ficheiro .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: Ficheiros adicionais de projeto, de compilação ou de apoio necessários para que os testes possam ser executados.
Presença: Obrigatório se os ficheiros predefinidos não forem suficientes para executar os testes
Algumas linguagens exigem ficheiros adicionais para que os testes sejam executados. Exemplos disso são os ficheiros de projeto do C# e os ficheiros package.json do Node, sem os quais não é possível executar os testes.
Alguns ficheiros não são específicos de exercícios individuais, mas aplicam-se a todos os exercícios. Consulta a documentação para mais informações.
Há uma diferença na forma como a documentação de um exercício é apresentada ao estudante quando este usa o editor no navegador em vez da CLI. Consulta este documento para mais informações.
Cada exercício tem um ícone associado.
Por predefinição, o ícone apresentado é aquele cujo nome corresponde ao slug do exercício.
É possível substituir esta opção especificando a propriedade icon no ficheiro .meta/config.json do exercício.
Se estiveres a implementar um exercício a partir dos metadados do problem-specifications, provavelmente já existe um ícone para esse exercício. Se não, abre uma issue no repositório website-icons.