Los ejercicios de práctica son ejercicios diseñados para que los estudiantes resuelvan un problema arbitrario, con el objetivo de que apliquen los conceptos que han aprendido hasta ahora.
¿Te interesa agregar tu primer ejercicio de práctica a un track? Consulta la documentación para agregar un ejercicio de práctica o mira nuestro video explicativo 👇
Puedes generar rápidamente la estructura de un nuevo ejercicio de práctica ejecutando los siguientes comandos desde el directorio raíz del track:
bin/fetch-configlet
bin/configlet create --practice-exercise <slug>
Para más información, consulta la documentación de configlet create
Los metadatos de un ejercicio de práctica se definen en la clave exercises.practice del archivo config.json. Los metadatos definen el UUID del ejercicio, su slug y más.
{
"exercises": {
"practice": [
{
"uuid": "8ba15933-29a2-49b1-a9ce-70474bad3007",
"slug": "leap",
"name": "Leap",
"practices": ["if-statements", "numbers", "operator-precedence"],
"prerequisites": ["if-statements", "numbers"],
"difficulty": 1
}
]
}
}
practicesLa clave practices debe enumerar los slugs de los conceptos que este ejercicio de práctica permite practicar activamente a un estudiante.
strings). En esos casos recomendamos elegir unos cuantos ejercicios buenos que hagan que las personas piensen en esos conceptos de maneras interesantes. Por ejemplo, los ejercicios que requieren UTF-8, concatenación de strings, enumeración de caracteres, etc., serían todos buenos ejemplos.prerequisitesLa clave prerequisites enumera los conceptos que un estudiante debe haber completado para poder acceder a este ejercicio de práctica.
strings, optional-params e implicit-return.loops o recursion), el mantenedor debe elegir el enfoque con el que quiera desbloquear el ejercicio, teniendo en cuenta el recorrido del estudiante por el track. Por ejemplo, en el caso de loops/recursion, podría pensar que este ejercicio es una buena práctica temprana de loops o que preferiría dejarlo para más adelante y así enseñar recursión. También puede usar un analizador para invitar al estudiante a probar un enfoque alternativo: «Buen trabajo resolviéndolo con bucles. También podrías intentar resolverlo usando Recursión».Cada ejercicio de práctica tiene su propio directorio dentro del directorio exercises/practice del track. El nombre del directorio del ejercicio de práctica debe coincidir con la propiedad slug del ejercicio, tal como se define en el archivo config.json.
Un ejercicio de práctica tiene cuatro tipos de archivos:
Estos archivos se presentan al estudiante para ayudar a explicar el ejercicio.
.docs/introduction.md: presenta el contexto y los antecedentes del ejercicio (opcional).docs/introduction.append.md: texto de introducción adicional que se agrega después de la introducción existente (opcional).docs/instructions.md: proporciona las instrucciones del ejercicio (obligatorio).docs/instructions.append.md: texto de introducción adicional que se agrega después de las instrucciones existentes (opcional).docs/hints.md: proporciona pistas al estudiante para ayudarlo a desbloquearse en el ejercicio (opcional)Estos archivos no se presentan al estudiante, sino que se usan para definir los metadatos del ejercicio.
.meta/config.json: contiene información meta del ejercicio (obligatorio).meta/design.md: describe el diseño del ejercicio (opcional).meta/tests.toml: contiene información sobre qué tests están implementados (opcional)Estos archivos describen enfoques para el ejercicio.
.approaches/introduction.md: introducción a los enfoques más comunes para el ejercicio (opcional).approaches/config.json: metadatos de los enfoques (opcional).approaches/<approach-slug>/content.md: descripción del enfoque (opcional).approaches/<approach-slug>/snippet.txt: fragmento que muestra el enfoque (opcional)Estos archivos describen artículos para el ejercicio.
.articles/config.json: metadatos de los artículos (opcional).articles/<article-slug>/content.md: descripción del artículo (opcional).articles/<article-slug>/snippet.md: fragmento que muestra el artículo (opcional)Los archivos específicos del lenguaje, como los archivos de implementación y de tests. Los nombres de estos archivos son específicos de cada track.
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 (implementación de ejemplo)
├── Isogram.cs (implementación stub)
└── IsogramTests.cs (tests)
.docs/introduction.md
Propósito: Presentar al estudiante el contexto y los antecedentes del ejercicio.
Presencia: Obligatorio si el ejercicio implementa un ejercicio de Problem Specifications que tenga un archivo introduction.md
Si el ejercicio implementa un ejercicio de Problem Specifications, el contenido de este archivo debe coincidir con el archivo introduction.md de ese ejercicio de Problem Specifications. configlet tiene una funcionalidad para sincronizar el contenido de este archivo automáticamente.
Si el ejercicio no se basa en un ejercicio de Problem Specifications, ten en cuenta lo siguiente:
Valoramos mucho que el contenido de Exercism sea seguro para todas las personas, así que a menudo nos inclinamos por la cautela al decidir si una historia es apropiada o no. Aunque somos cuidadosos con lo que fusionamos, entendemos que es difícil darse cuenta de lo que puede resultar problemático, así que siempre asumiremos que actúas de buena fe y haremos lo posible por detectar cualquier problema durante la revisión de una manera no confrontativa. Si quieres revisar una historia con nosotros, menciona a @exercism/leadership y la veremos juntos. Estos son algunos puntos que te pueden guiar:
# Introduction
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
.docs/introduction.append.md
Propósito: Texto de introducción adicional que se agrega después de la introducción existente.
Presencia: Opcional
En algunos casos (poco frecuentes), es posible que quieras ampliar el archivo introduction.md del ejercicio, por ejemplo cuando el ejercicio ha implementado tests que no están cubiertos por las instrucciones existentes.
Un track que no quiera que Bob admita mensajes que no sean ASCII podría agregar lo siguiente:
# Introduction append
## Note
As part of his teenage rebellion, Bob has decided to only communicate using ASCII.
Los archivos append deben empezar con un encabezado H1. Este encabezado no se muestra, pero debe estar presente de todos modos. Al encabezado H1 suele seguirle un encabezado H2, que ayuda a separar el contenido genérico del contenido específico del track.
.docs/instructions.md
Propósito: Proporcionar las instrucciones del ejercicio.
Presencia: Obligatorio
Si el ejercicio implementa un ejercicio de Problem Specifications, el contenido de este archivo debe coincidir con el archivo instructions.md de ese ejercicio de Problem Specifications (o con el archivo description.md si no hay un archivo instructions.md). configlet tiene una funcionalidad para sincronizar el contenido de este archivo automáticamente.
Si el ejercicio no se basa en un ejercicio de Problem Specifications, ten en cuenta lo siguiente:
Valoramos mucho que el contenido de Exercism sea seguro para todas las personas, así que a menudo nos inclinamos por la cautela al decidir si una historia es apropiada o no. Aunque somos cuidadosos con lo que fusionamos, entendemos que es difícil darse cuenta de lo que puede resultar problemático, así que siempre asumiremos que actúas de buena fe y haremos lo posible por detectar cualquier problema durante la revisión de una manera no confrontativa. Si quieres revisar una historia con nosotros, menciona a @exercism/leadership y la veremos juntos. Estos son algunos puntos que te pueden guiar:
# 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
Propósito: Texto de instrucciones adicional que se agrega después de las instrucciones existentes.
Presencia: Opcional
En algunos casos (poco frecuentes), es posible que quieras ampliar el archivo instructions.md del ejercicio, por ejemplo cuando el ejercicio ha implementado tests que no están cubiertos por las instrucciones 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.
Los archivos append deben empezar con un encabezado H1. Este encabezado no se muestra, pero debe estar presente de todos modos. Al encabezado H1 suele seguirle un encabezado H2, que ayuda a separar el contenido genérico del contenido específico del track.
.docs/hints.md
Propósito: Proporcionar pistas al estudiante para ayudarlo a desbloquearse en un ejercicio.
Presencia: Opcional
## General.Ver las pistas no será un camino «recomendado» y lo desaconsejaremos (con suavidad) a menos que el estudiante no pueda avanzar sin ellas. Por eso vale la pena tener en cuenta que el estudiante que las lea estará algo confundido o abrumado, y quizá 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
Propósito: Describir el diseño del ejercicio.
Presencia: Opcional
Este archivo contiene información sobre el diseño del ejercicio, que incluye cosas como su objetivo, sus metas de enseñanza, lo que no se debe enseñar y más.
Existe para informar a futuros mantenedores o colaboradores sobre el alcance y las limitaciones de un ejercicio, y así evitar la tendencia natural a que los ejercicios se vuelvan más complejos con el tiempo.
# 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
Propósito: Contiene información meta del ejercicio.
Presencia: Obligatorio
Este archivo contiene información meta del ejercicio:
authors: el o los nombres de usuario de GitHub del autor o los autores del ejercicio (opcional)
contributors: el o los nombres de usuario de GitHub del colaborador o los colaboradores del ejercicio (opcional)
files: las ubicaciones de los archivos usados en este ejercicio, relativas al directorio del ejercicio (obligatorio)
solution: el o los archivos de implementación stub (obligatorio)test: el o los archivos de tests (obligatorio)example: el o los archivos de implementación de ejemplo (obligatorio)editor: archivos adicionales que se muestran como solo lectura en el editor (opcional)invalidator: archivos que, al cambiar, hacen que una solución quede desactualizada (opcional)language_versions: requisitos de versión del lenguaje (opcional)blurb: una descripción breve de este ejercicio. Su longitud debe ser <= 350. No se admite Markdown (obligatorio)source: la fuente en la que se basa este ejercicio (opcional)source_url: la URL de la fuente en la que se basa este ejercicio (opcional)test_runner: indica si las soluciones de este ejercicio deben probarse en el ejecutor de tests. Si no se especifica, su valor predeterminado es true. (opcional)representer: información meta relacionada con cómo el representador procesa este archivo (opcional)
version: un número entero con la versión del representador que se usará para el ejercicio (obligatorio si la clave padre está presente)icon: el slug del icono (consulta la lista completa de iconos). Si no se especifica, se usará el slug del ejercicio (opcional)custom: cualquier dato no estándar específico del ejercicio. Se puede usar para personalizar el comportamiento de las herramientas del track para cada ejercicio (opcional)Si alguien es autor y colaborador a la vez, inclúyelo solo 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"
}
Ten en cuenta que:
language_versions es una cadena de formato libre que cada track puede usar e interpretar como quiera.Propósito: Contiene información sobre qué tests están implementados.
Presencia: Opcional
Este archivo contiene información sobre qué tests se están implementando, siempre que el ejercicio tenga tests definidos en su archivo canonical-data.json dentro del repositorio problem-specifications.
Existe para ayudar a los mantenedores a llevar un registro de qué tests están implementados y para documentar (de forma opcional) por qué cierto test no lo está. También se puede usar para detectar tests sin implementar.
La herramienta configlet se encarga de actualizar y sincronizar este archivo con los datos del repositorio problem-specifications mediante el comando configlet sync. Al sincronizar, configlet preguntará, para cada test sin implementar, si se debe incluir o no.
# 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
Propósito: Introducción a los enfoques más comunes para el ejercicio
Presencia: Opcional
Este archivo describe los enfoques más comunes para el ejercicio. Consulta la documentación para más información sobre qué debe incluir este archivo.
# 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
Propósito: Metadatos de los enfoques
Presencia: Opcional (obligatorio cuando existe una introducción de enfoques o un enfoque)
Este archivo contiene información meta sobre los enfoques del ejercicio:
introduction: el o los nombres de usuario de GitHub del autor o los autores de la introducción de enfoques del ejercicio (opcional)
authors: el o los nombres de usuario de GitHub del autor o los autores de la introducción de enfoques del ejercicio (obligatorio)
contributors: el o los nombres de usuario de GitHub del colaborador o los colaboradores de la introducción de enfoques del ejercicio (opcional)
approaches: un array que enumera los enfoques detallados (opcional)
uuid: un UUID V4 que identifica el enfoque de forma única. El UUID debe ser único tanto dentro del track como en todos los tracks, y nunca debe cambiarslug: el slug del enfoque, que es una cadena en minúsculas y en kebab-case. El slug debe ser único entre todos los slugs de enfoques del track. Su longitud debe ser <= 255.title: el título del enfoque. Su longitud debe ser <= 255.blurb: una descripción breve de este enfoque. Su longitud debe ser <= 350. No se admite Markdown (obligatorio)authors: el o los nombres de usuario de GitHub del autor o los autores del enfoque del ejercicio (obligatorio)
contributors: el o los nombres de usuario de GitHub del colaborador o los colaboradores del enfoque del ejercicio (opcional)
tags: especifica las condiciones para que un envío se vincule a un enfoque. (opcional)
all: un array de etiquetas que deben estar todas presentes en un envío (opcional, a menos que any no tenga elementos)any: un array de etiquetas de las cuales al menos una debe estar presente en un envío (opcional, a menos que all no tenga elementos)not: ninguna de las etiquetas debe estar presente en un enví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
Propósito: Descripción detallada del enfoque
Presencia: Opcional (obligatorio para los enfoques)
Este archivo contiene una descripción detallada del enfoque. Consulta la documentación para más información sobre qué debe incluir este archivo.
# 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
Propósito: Fragmento que muestra el enfoque
Presencia: Opcional (obligatorio para los enfoques)
Este archivo contiene un fragmento pequeño que muestra el enfoque. El fragmento se muestra en la página Dig Deeper de un ejercicio.
Su número de líneas debe ser <= 8.
Consulta la documentación para más información sobre qué debe incluir este archivo.
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
Propósito: Metadatos de los artículos
Presencia: Opcional (obligatorio cuando existe un artículo)
Este archivo contiene información meta sobre los artículos del ejercicio:
articles: un array que enumera los artículos detallados (opcional)
uuid: un UUID V4 que identifica el artículo de forma única. El UUID debe ser único tanto dentro del track como en todos los tracks, y nunca debe cambiarslug: el slug del artículo, que es una cadena en minúsculas y en kebab-case. El slug debe ser único entre todos los slugs de artículos del track. Su longitud debe ser <= 255.title: el título del artículo. Su longitud debe ser <= 255.blurb: una descripción breve de este artículo. Su longitud debe ser <= 350. No se admite Markdown (obligatorio)authors: el o los nombres de usuario de GitHub del autor o los autores del artículo del ejercicio (obligatorio)
contributors: el o los nombres de usuario de GitHub del colaborador o los colaboradores del artículo del ejercicio (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
Propósito: Descripción detallada del enfoque
Presencia: Opcional (obligatorio para los enfoques)
Este archivo contiene una descripción detallada del enfoque. Consulta la documentación para más información sobre qué debe incluir este archivo.
# 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
Propósito: Fragmento que muestra el enfoque
Presencia: Opcional (obligatorio para los artículos)
Este archivo contiene un fragmento pequeño que muestra el artículo. El fragmento se muestra en la página Dig Deeper de un ejercicio.
Su número de líneas debe ser <= 8.
Consulta la documentación para más información sobre qué debe incluir este archivo.
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
Propósito: Proporcionar un punto de partida para los estudiantes.
Presencia: Obligatorio
"files.solution" del archivo .meta/config.json.using System;
public static class Isogram
{
public static bool IsIsogram(string word)
{
throw new NotImplementedException("You need to implement this function.");
}
}
Propósito: Verificar que una solución sea correcta.
Presencia: Obligatorio
"files.test" del archivo .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"));
}
Propósito: Proporcionar una implementación de ejemplo que pasa todos los tests.
Presencia: Obligatorio
"files.example" del archivo .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;
}
}
Propósito: Archivos adicionales de proyecto, compilación o soporte que se requieren para que los tests puedan ejecutarse.
Presencia: Obligatorio si los archivos predeterminados no son suficientes para ejecutar los tests
Algunos lenguajes requieren archivos adicionales para poder ejecutar los tests. Ejemplos de ellos son los archivos de proyecto de C# y los archivos package.json de Node, sin los cuales no será posible ejecutar los tests.
Algunos archivos no son específicos de cada ejercicio, sino que se aplican a todos los ejercicios. Consulta la documentación para más información.
Hay una diferencia en cómo se presenta la documentación de un ejercicio al estudiante cuando usa el editor en el navegador en lugar de la CLI. Consulta este documento para más información.
Cada ejercicio tiene un icono que lo acompaña.
De forma predeterminada, el icono que se muestra es el cuyo nombre coincide con el slug del ejercicio.
Esto se puede sobrescribir especificando la propiedad icon en el archivo .meta/config.json del ejercicio.
Si estás implementando un ejercicio a partir de los metadatos de problem-specifications, probablemente ya exista un icono para ese ejercicio. Si no es así, por favor abre un issue en el repositorio website-icons.