Gli esercizi pratici sono esercizi pensati per permettere agli studenti di risolvere un problema arbitrario, con l'obiettivo di far loro usare i concetti che hanno imparato fino a quel momento.
Vuoi aggiungere il tuo primo esercizio pratico a un track? Dai un'occhiata alla documentazione su come aggiungere un esercizio pratico oppure guarda il nostro video esplicativo 👇
Puoi creare rapidamente la struttura di un nuovo esercizio pratico eseguendo i seguenti comandi dalla directory principale del track:
bin/fetch-configlet
bin/configlet create --practice-exercise <slug>
Per ulteriori informazioni, consulta la documentazione di configlet create
I metadati di un esercizio pratico sono definiti nella chiave exercises.practice del file config.json. I metadati definiscono l'UUID, lo slug e altro ancora dell'esercizio.
{
"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 chiave practices deve elencare gli slug dei concetti che questo esercizio pratico permette attivamente a uno studente di esercitare.
strings). In questi casi consigliamo di scegliere alcuni buoni esercizi che facciano riflettere le persone su quei concetti in modi interessanti. Per esempio, esercizi che richiedono UTF-8, la concatenazione di stringhe, l'enumerazione di caratteri e così via sarebbero tutti buoni esempi.prerequisitesLa chiave prerequisites elenca i concetti che uno studente deve aver completato per poter accedere a questo esercizio pratico.
strings, optional-params, implicit-return.loops o recursion), il manutentore dovrebbe scegliere l'approccio con cui vuole sbloccare l'esercizio, considerando il percorso dello studente all'interno del track. Per esempio, nel caso di loops/recursion, potrebbe pensare che questo esercizio sia una buona pratica iniziale di loops oppure che preferisca lasciarlo più avanti per insegnare la ricorsione. Può anche usare un analizzatore per invitare lo studente a provare un approccio alternativo: «Bel lavoro a risolverlo con i cicli. Potresti anche provare a risolverlo usando la ricorsione.»Ogni esercizio pratico ha la propria directory all'interno della directory exercises/practice del track. Il nome della directory dell'esercizio pratico deve corrispondere alla proprietà slug dell'esercizio pratico, così come definita nel file config.json.
Un esercizio pratico ha quattro tipi di file:
Questi file vengono mostrati allo studente per aiutarlo a capire l'esercizio.
.docs/introduction.md: introducono l'ambientazione e il contesto dell'esercizio (opzionale).docs/introduction.append.md: testo di introduzione aggiuntivo da accodare dopo l'introduzione esistente (opzionale).docs/instructions.md: forniscono le istruzioni per l'esercizio (obbligatorio).docs/instructions.append.md: testo di introduzione aggiuntivo da accodare dopo le istruzioni esistenti (opzionale).docs/hints.md: forniscono suggerimenti a uno studente per aiutarlo a sbloccarsi nell'esercizio (opzionale)Questi file non vengono mostrati allo studente, ma servono a definire i metadati dell'esercizio.
.meta/config.json: contiene metainformazioni sull'esercizio (obbligatorio).meta/design.md: descrive la progettazione dell'esercizio (opzionale).meta/tests.toml: contiene informazioni su quali test sono implementati (opzionale)Questi file descrivono gli approcci per l'esercizio.
.approaches/introduction.md: introduzione agli approcci più comuni per l'esercizio (opzionale).approaches/config.json: metadati degli approcci (opzionale).approaches/<approach-slug>/content.md: descrizione dell'approccio (opzionale).approaches/<approach-slug>/snippet.txt: snippet che mostra l'approccio (opzionale)Questi file descrivono gli articoli per l'esercizio.
.articles/config.json: metadati degli articoli (opzionale).articles/<article-slug>/content.md: descrizione dell'articolo (opzionale).articles/<article-slug>/snippet.md: snippet che mostra l'articolo (opzionale)I file specifici del linguaggio, come i file di implementazione e di test. I nomi di questi file dipendono dal 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 (example implementation)
├── Isogram.cs (stub implementation)
└── IsogramTests.cs (tests)
.docs/introduction.md
Scopo: Introdurre allo studente l'ambientazione e il contesto dell'esercizio.
Presenza: Obbligatorio se l'esercizio implementa un esercizio di Problem Specifications con un file introduction.md
Se l'esercizio implementa un esercizio di Problem Specifications, il contenuto di questo file deve corrispondere al file introduction.md dell'esercizio di Problem Specifications. configlet ha una funzionalità per sincronizzare automaticamente il contenuto di questo file.
Se l'esercizio non è basato su un esercizio di Problem Specifications, tieni presente quanto segue:
Per noi è molto importante che i contenuti di Exercism siano sicuri per tutti, quindi spesso pecchiamo di prudenza nel decidere se una storia sia appropriata o meno. Sebbene prestiamo attenzione a ciò che uniamo, sappiamo che è difficile rendersi conto di ciò che può essere percepito come problematico: per questo assumeremo sempre che tu stia agendo in buona fede e faremo del nostro meglio per individuare eventuali problemi in fase di revisione in modo non conflittuale. Se vuoi verificare una storia con noi, menziona @exercism/leadership e la esamineremo insieme. Ecco alcuni punti guida:
# Introduction
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
.docs/introduction.append.md
Scopo: Testo di introduzione aggiuntivo da accodare dopo l'introduzione esistente.
Presenza: Opzionale
In alcuni (rari) casi, potresti voler ampliare il file introduction.md dell'esercizio, per esempio quando l'esercizio ha implementato test non coperti dalle istruzioni esistenti.
Un track che non vuole che Bob gestisca messaggi non ASCII potrebbe aggiungere quanto segue:
# Introduction append
## Note
As part of his teenage rebellion, Bob has decided to only communicate using ASCII.
I file append dovrebbero iniziare con un'intestazione H1. Questa intestazione non viene mostrata, ma dovrebbe comunque essere presente. Spesso l'intestazione H1 è seguita da un'intestazione H2, che aiuta a separare il contenuto generico da quello specifico del track.
.docs/instructions.md
Scopo: Fornire le istruzioni per l'esercizio.
Presenza: Obbligatorio
Se l'esercizio implementa un esercizio di Problem Specifications, il contenuto di questo file deve corrispondere al file instructions.md dell'esercizio di Problem Specifications (o al file description.md se non esiste un file instructions.md). configlet ha una funzionalità per sincronizzare automaticamente il contenuto di questo file.
Se l'esercizio non è basato su un esercizio di Problem Specifications, tieni presente quanto segue:
Per noi è molto importante che i contenuti di Exercism siano sicuri per tutti, quindi spesso pecchiamo di prudenza nel decidere se una storia sia appropriata o meno. Sebbene prestiamo attenzione a ciò che uniamo, sappiamo che è difficile rendersi conto di ciò che può essere percepito come problematico: per questo assumeremo sempre che tu stia agendo in buona fede e faremo del nostro meglio per individuare eventuali problemi in fase di revisione in modo non conflittuale. Se vuoi verificare una storia con noi, menziona @exercism/leadership e la esamineremo insieme. Ecco alcuni punti guida:
# 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
Scopo: Testo di istruzioni aggiuntivo da accodare dopo le istruzioni esistenti.
Presenza: Opzionale
In alcuni (rari) casi, potresti voler ampliare il file instructions.md dell'esercizio, per esempio quando l'esercizio ha implementato test non coperti dalle istruzioni esistenti.
# 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.
I file append dovrebbero iniziare con un'intestazione H1. Questa intestazione non viene mostrata, ma dovrebbe comunque essere presente. Spesso l'intestazione H1 è seguita da un'intestazione H2, che aiuta a separare il contenuto generico da quello specifico del track.
.docs/hints.md
Scopo: Fornire suggerimenti a uno studente per aiutarlo a sbloccarsi in un esercizio.
Presenza: Opzionale
## General.Consultare i suggerimenti non sarà un percorso "consigliato" e ne sconsiglieremo (con delicatezza) l'uso, a meno che lo studente non riesca a procedere senza. Per questo vale la pena considerare che lo studente che li legge sarà un po' confuso o sopraffatto e forse frustrato.
## General
- There are many [built-in methods][integers] to simplify working with integers.
[integers]: https://ruby-doc.org/core-2.7.0/Integer.html
Scopo: Descrivere la progettazione dell'esercizio.
Presenza: Opzionale
Questo file contiene informazioni sulla progettazione dell'esercizio, tra cui cose come il suo obiettivo, i suoi obiettivi didattici, cosa non insegnare e altro ancora.
Esiste per informare i futuri manutentori o contributori sull'ambito e sui limiti di un esercizio, ed evitare la tendenza naturale a rendere gli esercizi sempre più complessi nel 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
Scopo: Contiene metainformazioni sull'esercizio.
Presenza: Obbligatorio
Questo file contiene metainformazioni sull'esercizio:
authors: Gli username GitHub dell'/degli autore/i dell'esercizio (opzionale)
contributors: Gli username GitHub del/degli contributore/i dell'esercizio (opzionale)
files: Le posizioni dei file usati in questo esercizio, relative alla directory dell'esercizio (obbligatorio)
solution: il/gli file di implementazione stub (obbligatorio)test: il/gli file di test (obbligatorio)example: il/gli file di implementazione di esempio (obbligatorio)editor: file aggiuntivi mostrati in sola lettura nell'editor (opzionale)invalidator: file che, quando modificati, fanno sì che una soluzione diventi obsoleta (opzionale)language_versions Requisiti di versione del linguaggio (opzionale)blurb: Una breve descrizione di questo esercizio. La sua lunghezza deve essere <= 350. Markdown non è supportato (obbligatorio)source: La fonte su cui si basa questo esercizio (opzionale)source_url: L'URL della fonte su cui si basa questo esercizio (opzionale)test_runner: Indica se le soluzioni di questo esercizio devono essere testate nel test runner. Il valore predefinito è true se non specificato. (opzionale)representer: Metainformazioni relative a come il representer elabora questo file (opzionale)
version: Un numero intero per la versione del representer da usare per l'esercizio (obbligatorio se la chiave superiore è presente)icon: Lo slug dell'icona (vedi l'elenco completo delle icone). Se non specificato, verrà usato lo slug dell'esercizio (opzionale)custom: Qualsiasi dato non standard specifico dell'esercizio. Può essere usato per personalizzare il comportamento degli strumenti del track per singolo esercizio (opzionale)Se qualcuno è sia autore che contributore, elencalo solo come autore.
{
"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"
}
Tieni presente che:
language_versions è una stringa libera che i track possono usare e interpretare come preferiscono.Scopo: Contiene informazioni su quali test sono implementati.
Presenza: Opzionale
Questo file contiene informazioni su quali test vengono implementati, a condizione che l'esercizio abbia dei test definiti nel suo file canonical-data.json all'interno del repo problem-specifications.
Esiste per aiutare i manutentori a tenere traccia di quali test sono implementati e per documentare (facoltativamente) perché un certo test non è implementato. Può anche servire a individuare i test non implementati.
Lo strumento configlet gestisce l'aggiornamento e la sincronizzazione di questo file con i dati del repo problem-specifications tramite il comando configlet sync. Durante la sincronizzazione, per ogni test non implementato configlet chiederà se includerlo o meno.
# 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
Scopo: Introduzione agli approcci più comuni per l'esercizio
Presenza: Opzionale
Questo file descrive gli approcci più comuni per l'esercizio. Consulta la documentazione per maggiori informazioni su cosa deve contenere questo file.
# 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
Scopo: Metadati degli approcci
Presenza: Opzionale (obbligatorio quando esiste un'introduzione agli approcci o un approccio)
Questo file contiene metainformazioni sugli approcci dell'esercizio:
introduction: Gli username GitHub dell'autore o degli autori dell'introduzione agli approcci dell'esercizio (opzionale)
authors: Gli username GitHub dell'autore o degli autori dell'introduzione agli approcci dell'esercizio (obbligatorio)
contributors: Gli username GitHub del contributore o dei contributori dell'introduzione agli approcci dell'esercizio (opzionale)
approaches: Un array che elenca gli approcci dettagliati (opzionale)
uuid: un UUID V4 che identifica univocamente l'approccio. L'UUID deve essere unico sia all'interno del track sia in tutti i track, e non deve mai cambiareslug: lo slug dell'approccio, una stringa in minuscolo in kebab-case. Lo slug deve essere unico tra tutti gli slug degli approcci del track. La sua lunghezza deve essere <= 255.title: il titolo dell'approccio. La sua lunghezza deve essere <= 255.blurb: Una breve descrizione di questo approccio. La sua lunghezza deve essere <= 350. Markdown non è supportato (obbligatorio)authors: Gli username GitHub dell'autore o degli autori dell'approccio dell'esercizio (obbligatorio)
contributors: Gli username GitHub del contributore o dei contributori dell'approccio dell'esercizio (opzionale)
tags: Specificano le condizioni in base a cui una soluzione inviata viene collegata a un approccio. (opzionale)
all: Un array di tag che devono essere tutti presenti su una soluzione inviata (opzionale, a meno che any non abbia elementi)any: Un array di tag di cui almeno uno deve essere presente su una soluzione inviata (opzionale, a meno che all non abbia elementi)not: nessuno dei tag deve essere presente su una soluzione inviata (opzionale){
"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
Scopo: Descrizione dettagliata dell'approccio
Presenza: Opzionale (obbligatorio per gli approcci)
Questo file contiene una descrizione dettagliata dell'approccio. Consulta la documentazione per maggiori informazioni su cosa deve contenere questo file.
# 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
Scopo: Snippet che mostra l'approccio
Presenza: Opzionale (obbligatorio per gli approcci)
Questo file contiene un piccolo snippet che mostra l'approccio. Lo snippet viene mostrato nella pagina "Dig Deeper" di un esercizio.
Il suo numero di righe deve essere <= 8.
Consulta la documentazione per maggiori informazioni su cosa deve contenere questo file.
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
Scopo: Metadati degli articoli
Presenza: Opzionale (obbligatorio quando esiste un articolo)
Questo file contiene metainformazioni sugli articoli dell'esercizio:
articles: Un array che elenca gli articoli dettagliati (opzionale)
uuid: un UUID V4 che identifica univocamente l'articolo. L'UUID deve essere unico sia all'interno del track sia in tutti i track, e non deve mai cambiareslug: lo slug dell'articolo, una stringa in minuscolo in kebab-case. Lo slug deve essere unico tra tutti gli slug degli articoli del track. La sua lunghezza deve essere <= 255.title: il titolo dell'articolo. La sua lunghezza deve essere <= 255.blurb: Una breve descrizione di questo articolo. La sua lunghezza deve essere <= 350. Markdown non è supportato (obbligatorio)authors: Gli username GitHub dell'autore o degli autori dell'articolo dell'esercizio (obbligatorio)
contributors: Gli username GitHub del contributore o dei contributori dell'articolo dell'esercizio (opzionale)
{
"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
Scopo: Descrizione dettagliata dell'approccio
Presenza: Opzionale (obbligatorio per gli approcci)
Questo file contiene una descrizione dettagliata dell'approccio. Consulta la documentazione per maggiori informazioni su cosa deve contenere questo file.
# 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
Scopo: Snippet che mostra l'approccio
Presenza: Opzionale (obbligatorio per gli articoli)
Questo file contiene un piccolo snippet che mostra l'articolo. Lo snippet viene mostrato nella pagina "Dig Deeper" di un esercizio.
Il suo numero di righe deve essere <= 8.
Consulta la documentazione per maggiori informazioni su cosa deve contenere questo file.
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
Scopo: Fornire un punto di partenza per gli studenti.
Presenza: Obbligatorio
"files.solution" del file .meta/config.json.using System;
public static class Isogram
{
public static bool IsIsogram(string word)
{
throw new NotImplementedException("You need to implement this function.");
}
}
Scopo: Verificare la correttezza di una soluzione.
Presenza: Obbligatorio
"files.test" del file .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"));
}
Scopo: Fornire un'implementazione di esempio che supera tutti i test.
Presenza: Obbligatorio
"files.example" del file .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;
}
}
Scopo: File aggiuntivi di progetto, di build o di supporto necessari perché i test possano essere eseguiti.
Presenza: Obbligatorio se i file predefiniti non bastano per eseguire i test
Alcuni linguaggi richiedono file aggiuntivi perché i test possano essere eseguiti. Ne sono un esempio i file di progetto di C# e i file package.json di Node, senza i quali non sarà possibile eseguire i test.
Alcuni file non sono specifici di singoli esercizi, ma valgono invece per tutti gli esercizi. Consulta la documentazione per maggiori informazioni.
C'è una differenza nel modo in cui la documentazione di un esercizio viene presentata allo studente quando usa l'editor nel browser rispetto a quando usa la CLI. Vedi questo documento per maggiori informazioni.
Ogni esercizio ha un'icona associata.
Per impostazione predefinita, l'icona mostrata è quella il cui nome corrisponde allo slug dell'esercizio.
Puoi sovrascrivere questo comportamento specificando la proprietà icon nel file .meta/config.json dell'esercizio.
Se stai implementando un esercizio a partire dai metadati di problem-specifications, probabilmente esiste già un'icona per quell'esercizio. In caso contrario, apri una issue nel repository website-icons.