Parcours
/
Swift
Swift
/
Exercices
/
Apprenti magicien
Apprenti magicien

Apprenti magicien

Exercice d'apprentissage

Introduction

Les tableaux sont l'un des trois principaux types de collections de Swift. Un tableau est une liste ordonnée d'éléments. Un tableau peut contenir des éléments de n'importe quel type, mais tous les éléments d'un même tableau doivent être du même type. Un tableau est mutable lorsqu'il est affecté à une variable : on peut alors ajouter, supprimer ou modifier ses éléments après la création du tableau. Lorsqu'il est affecté à une constante, un tableau est immuable, ce qui signifie que son contenu ne peut pas être modifié.

Un littéral de tableau s'écrit comme une liste d'éléments séparés par des virgules et entourés de crochets ([...]). Swift peut déduire le type du tableau à partir des éléments du littéral.

let evenInts = [2, 4, 6, 8, 10, 12]
var oddInts = [1, 3, 5, 7, 9, 11, 13]
let greetings = ["Hello!", "Hi!", "¡Hola!"]

On peut aussi préciser le type explicitement. Le type d'un tableau peut s'écrire de deux façons : Array<T> ou la syntaxe abrégée [T], où T est le type des valeurs que contient le tableau.

let evenInts: Array<Int> = [2, 4, 6, 8, 10, 12]
var oddInts: [Int] = [1, 3, 5, 7, 9, 11, 13]
let greetings: [String] = ["Hello!", "Hi!", "¡Hola!"]

Taille d'un tableau

On peut déterminer le nombre d'éléments d'un tableau à l'aide de sa propriété count :

evenInts.count
// returns 6

Tableaux vides

Pour créer un tableau vide, il faut préciser son type. On peut le faire avec la syntaxe d'initialisation de tableau ou avec une annotation de type explicite :

let emptyArray = [Int]()
let emptyArray2 = Array<Int>()
let emptyArray3: [Int] = []

Tableaux multidimensionnels

On peut imbriquer des tableaux pour créer des tableaux multidimensionnels. Lorsque l'on type explicitement un tableau imbriqué, il faut entourer le type des éléments de crochets imbriqués, comme [[Int]] ou Array<Array<Int>> :

let multiDimArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let multiDimArray2: [[Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Ajoute un élément à un tableau

On peut ajouter un élément à la fin d'un tableau mutable avec la méthode append(_:) :

var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.append(15)
// oddInts is now [1, 3, 5, 7, 9, 11, 13, 15]

Insère un élément dans un tableau

On peut insérer un élément à un indice précis avec la méthode insert(_:at:). Cette méthode prend deux arguments : l'élément à insérer et l'indice auquel l'insérer.

var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.insert(0, at: 0)
// oddInts is now [0, 1, 3, 5, 7, 9, 11, 13]

Additionne deux tableaux

On peut combiner deux tableaux en un seul avec l'opérateur +. L'opérateur + crée et renvoie un nouveau tableau ; il ne modifie pas les tableaux d'origine.

var oddInts = [1, 3, 5, 7, 9, 11, 13]
let combined = oddInts + [15, 17, 19]
// combined is [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

print(oddInts)
// prints [1, 3, 5, 7, 9, 11, 13]

Accède aux éléments d'un tableau

On peut accéder à un élément précis d'un tableau en plaçant son indice entre crochets ([]), après le nom du tableau. Les indices d'un tableau sont des valeurs Int indexées à partir de zéro, 0 correspondant au premier élément. Accéder à un indice hors de la plage valide provoque une erreur d'exécution et fait planter le programme.

let evenInts = [2, 4, 6, 8, 10, 12]
let oddInts = [1, 3, 5, 7, 9, 11, 13]

evenInts[2]
// returns 6

oddInts[7]
// Fatal error: Index out of range

Modifie les éléments d'un tableau

On peut modifier un élément d'un tableau mutable en affectant une nouvelle valeur à un indice précis. Comme pour la lecture des éléments, utiliser un indice hors de la plage valide provoque une erreur d'exécution.

var evenInts = [2, 4, 6, 8, 10, 12]

evenInts[2] = 0
// evenInts is now [2, 4, 0, 8, 10, 12]

Convertis un tableau en string et inversement

On peut assembler un tableau de strings en une seule string avec la méthode joined(separator:), qui prend une string servant de séparateur :

let evenInts = ["2", "4", "6", "8", "10", "12"]
let evenIntsString = evenInts.joined(separator: ", ")
// returns "2, 4, 6, 8, 10, 12"

On peut découper une string en un tableau de sous-chaînes avec la méthode split(separator:), en passant le caractère délimiteur :

let evenIntsString = "2, 4, 6, 8, 10, 12"
let evenInts = evenIntsString.split(separator: ",")
// returns ["2", " 4", " 6", " 8", " 10", " 12"]

Supprime un élément d'un tableau

On peut supprimer un élément à un indice donné avec la méthode remove(at:). L'indice doit se trouver dans les limites valides du tableau ; sinon, une erreur d'exécution se produit.

var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.remove(at: 3)
// oddInts is now [1, 3, 5, 9, 11, 13]

Pour supprimer le dernier élément d'un tableau, utilise la méthode removeLast(). Appeler removeLast() sur un tableau vide provoque une erreur d'exécution.

var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.removeLast()
// oddInts is now [1, 3, 5, 7, 9, 11]

Instructions

Pour devenir magicienne, Elyse doit s'entraîner sur quelques bases. Elle a une pile de cartes qu'elle souhaite manipuler.

Pour simplifier un peu les choses, elle n'utilise que les cartes de 1 à 10, ce qui permet de représenter sa pile de cartes par un tableau de nombres. La position d'une carte donnée correspond à l'indice dans le tableau. Autrement dit, la position 0 correspond à la première carte, la position 1 à la deuxième, et ainsi de suite.

Note

Toutes les fonctions doivent modifier le tableau de cartes puis renvoyer le tableau modifié. C'est une façon courante de travailler, connue sous le nom de Builder pattern, qui permet d'enchaîner élégamment les fonctions les unes aux autres.

1. Récupère une carte d'une pile

Pour piocher une carte, renvoie la carte à l'indice position de la pile donnée.

Implémente la fonction getCard(at:from:) qui prend deux arguments : at, qui est la position de la carte dans la pile, et from, qui est la pile de cartes. La fonction doit renvoyer la carte à la position index de la pile donnée.

let index = 2
getCard(at: index, from: [1, 2, 4, 1])
// returns 4

2. Change une carte dans la pile

Fais un tour de passe-passe et échange la carte à l'indice position avec la carte de remplacement fournie.

Implémente la fonction setCard(at:in:to) qui prend trois arguments : at, qui est la position de la carte dans la pile, in, qui est la pile de cartes, et to, qui est la nouvelle carte destinée à remplacer la carte à la position index. La fonction doit renvoyer une copie de la pile dans laquelle la carte à la position index est remplacée par la nouvelle carte. Si index n'est pas un indice valide dans la pile, la pile d'origine doit être renvoyée, inchangée.

let index = 2
let newCard = 6
setCard(at: index, in: [1, 2, 4, 1], to: newCard)
// returns [1, 2, 6, 1]

3. Insère une carte au sommet de la pile

Fais apparaître une carte en insérant une nouvelle carte au sommet de la pile.

Implémente la fonction insert(_:atTopOf:) qui prend deux arguments : la nouvelle carte à insérer et la pile de cartes. La fonction doit renvoyer une copie de la pile, avec la nouvelle carte fournie ajoutée au sommet de la pile.

let newCard = 8
insert(newCard, atTopOf: [5, 9, 7, 1])
// returns [5, 9, 7, 1, 8]

4. Retire une carte de la pile

Fais disparaître une carte en retirant de la pile la carte à la position donnée.

Implémente la fonction removeCard(at:from:) qui prend deux arguments : at, qui est la position de la carte dans la pile, et from, qui est la pile de cartes. La fonction doit renvoyer une copie de la pile dans laquelle la carte à la position index a été retirée. Si index n'est pas un indice valide dans la pile, la pile d'origine doit être renvoyée, inchangée.

let index = 2
removeCard(at: index, from: [3, 2, 6, 4, 8])
// returns [3, 2, 4, 8]

5. Insère une carte dans la pile

Fais apparaître une carte en insérant une nouvelle carte à la position donnée dans la pile.

Implémente la fonction insert(_:at:from:) qui prend trois arguments : la nouvelle carte à insérer, la position à laquelle la nouvelle carte doit être insérée, et la pile de cartes. La fonction doit renvoyer une copie de la pile avec la nouvelle carte fournie ajoutée à la position donnée. Si index n'est pas un indice valide dans la pile, la pile d'origine doit être renvoyée, inchangée.

let newCard = 8
insert(newCard, at: 2, from: [5, 9, 7, 1])
// returns [5, 9, 8, 7, 1]

6. Vérifie la taille de la pile

Vérifie si la taille de la pile est égale à stackSize ou non.

Implémente la fonction checkSizeOfStack(_:_:) qui prend deux arguments : stack, qui est la pile de cartes, et stackSize, qui est la taille de la pile. La fonction doit renvoyer true si la taille de la pile est égale à stackSize et false sinon.

let stackSize = 4
checkSizeOfStack([3, 2, 6, 4, 8], stackSize)
// returns false
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Swift Exercism

Prêt à commencer Apprenti magicien ?

Inscris-toi sur Exercism pour apprendre et maîtriser Swift avec 35 concepts116 exercices, et un vrai mentorat humain, le tout gratuitement.