Julia, comme la plupart des langages de programmation, propose une grande variété de types de collections.
Certaines sont ordonnées par nature (notamment les Vectors et les Arrays multidimensionnels), ce qui permet d'accéder aux éléments par leur position.
D'autres collections ne sont pas ordonnées (Sets, Dicts), et l'on doit accéder aux éléments par clé ou par valeur.
Dans le cas le plus simple, supposons que l'on ait un Vector de Ints et que l'on veuille le trier par ordre croissant.
julia> v = [3, 2, 4, 1]
4-element Vector{Int64}:
3
2
4
1
julia> sort(v)
4-element Vector{Int64}:
1
2
3
4
# sort descending
julia> sort(v, rev=true)
4-element Vector{Int64}:
4
3
2
1
Simple !
La fonction sort() a un nom évident et, apparemment, renvoie le Vector trié.
Je plaisante ! À ce stade du programme, tu te doutes peut-être (à juste titre) qu'il y a des nuances dont il faut discuter.
Après avoir exécuté sort(v), que vaut v ?
julia> v
4-element Vector{Int64}:
3
2
4
1
julia> issorted(v)
false
Le vecteur d'origine n'est pas modifié.
sort() est une fonction non mutante qui renvoie une copie de son entrée.
C'est une bonne conception dans de nombreux contextes : on a une fonction pure dont le comportement est facile à appréhender, même dans du code parallèle ou distribué.
À l'inverse, imaginons que l'on ait un tableau d'un milliard de strings et que l'on veuille le trier.
Le tri sera probablement lent. De plus, il faut tout copier (lent !) et allouer suffisamment de mémoire (plusieurs gigaoctets !) pour stocker la copie.
Compare avec ce code assez semblable :
# v is as previously
julia> issorted(v)
false
julia> sort!(v)
4-element Vector{Int64}:
1
2
3
4
julia> v
4-element Vector{Int64}:
1
2
3
4
julia> issorted(v)
true
À présent, le Vector d'entrée est trié sur place, sans copie, et l'ordre d'origine est définitivement perdu.
Cela peut être efficace, cela peut être source de bugs et entraîner des effets de bord inattendus, cela peut aussi dérouter les autres personnes qui utilisent ton code. Choisis avec soin !
sort!() est une « fonction mutante » et, par convention (très forte), toute fonction qui modifie ses entrées a un ! ajouté à son nom, en guise d'avertissement pour les programmeurs.
Si les éléments à trier sont de gros objets, il peut être plus simple de travailler avec leur indice de position.
julia> langs = ["Julia", "C++", "Python", "Elixir"]
4-element Vector{String}:
"Julia"
"C++"
"Python"
"Elixir"
julia> inxs = sortperm(langs) # => Integers
4-element Vector{Int64}:
2
4
1
3
julia> langs[inxs] # sort the entire vector
4-element Vector{String}:
"C++"
"Elixir"
"Julia"
"Python"
julia> langs[inxs[1:2]] # slice the indices
2-element Vector{String}:
"C++"
"Elixir"
Comme langs est un Vector, chaque indice est un entier dans l'intervalle 1:length(langs).
La sortie de sortperm() est une permutation de ces entiers, qui correspond au tri du vecteur d'entrée.
Tu as été recruté comme assistant ingénieur de production dans une entreprise qui fabrique des courtepointes pour tortues.
Les commandes arrivent tout au long de la journée sous la forme d'un nom ou d'un numéro de client, accompagné d'une quantité commandée. Elles sont ensuite traitées le matin, avant le début de la production du jour.
Tu peux rentrer chez toi avec ton salaire complet dès que toutes les commandes du jour sont honorées, ce qui incite à raccourcir la journée de travail autant que possible. Comme chaque commande est traitée par une seule machine, planifier d'abord les commandes les plus importantes permet de reporter le coût de lancement d'un travail sur les plus petites, ce qui raccourcit la durée totale de production. Tu as donc décidé de fournir quelques fonctions de tri pour accélérer cette planification, afin de pouvoir rentrer tricoter un pull pour ta tortue.
Comme on l'a vu, le tableau de quantités doit être trié du plus grand au plus petit. Vu la taille potentiellement importante de ces tableaux, ils doivent être triés en place. Pour que tout reste cohérent, tu devras aussi pouvoir trier le tableau de clients en suivant les quantités, ce qui nécessite une permutation de tri des quantités.
Écris une fonction sortquantity!(qty) qui prend un Vector de quantités de type Integer.
Cette fonction trie l'entrée qty en place par ordre décroissant et renvoie une permutation de tri de cet ordre.
julia> qty = [8, 9, 5, 6]
4-element Vector{Int64}:
8
9
5
6
julia> sortquantity!(qty)
4-element Vector{Int64}:
2
1
4
3
julia> qty # original vector is sorted in-place
4-element Vector{Int64}:
9
8
6
5
Comme indiqué plus haut, tu dois garder les clients dans un ordre bien défini.
Écris une fonction sortcustomer(cust, srtperm) qui prend un Vector de clients cust et un Vector de permutation de tri srtperm.
Cette fonction renvoie un nouveau tableau contenant les clients dans l'ordre prescrit par la permutation de tri.
julia> cust = ["a", "b", "c"]
3-element Vector{String}:
"a"
"b"
"c"
julia> sortcustomer(cust, [2, 3, 1])
3-element Vector{String}:
"b"
"c"
"a"
julia> cust # original vector remains unsorted
3-element Vector{String}:
"a"
"b"
"c"
Tu peux maintenant assembler le tout pour aider ces tortues à rester au chaud ! Tu sais désormais trier correctement les quantités et les clients, mais tu dois pouvoir retrouver l'ordre d'origine pour l'expédition. On peut y parvenir avec une permutation de tri inverse.
Écris une fonction production_schedule!(cust, qty) qui prend un Vector de clients et un Vector de quantités.
Cette fonction trie les quantités en place par ordre décroissant.
Elle renvoie un nouveau Vector de clients triés dans le même ordre que les quantités, ainsi qu'une permutation de tri inverse permettant de rétablir l'ordre d'origine des vecteurs triés.
julia> cust, qty = ["a", "b", "c"], [2, 3, 1]
(["a", "b", "c"], [2, 3, 1])
julia> orderedcust, invperm = production_schedule!(cust, qty)
(["b", "a", "c"], [2, 1, 3])
julia> qty # has been sorted in-place
3-element Vector{Int64}:
3
2
1
julia> orderedcust[invperm], qty[invperm] # inverse permutation gives original ordering
(["a", "b", "c"], [2, 3, 1])
Inscris-toi sur Exercism pour apprendre et maîtriser Julia avec 35 concepts128 exercices, et un vrai mentorat humain, le tout gratuitement.