échange deux élément d'une liste en Ocaml

échange deux élément d'une liste en Ocaml

Le problème exposé dans ce sujet a été résolu.

Bonjour,

j’essaie d’écrire une fonction qui échange deux éléments d’une liste en ocaml. elle prend en paramètre une liste et deux indices,

Voici ce que j’ai fait je ne retrouve pas l’erreur .

recherche_indice t l renvoie l’indice de l’élément t dans la liste l

element_indi l irenvoie l’élément à l’indice i

ces deux fonctions fonctionne correctement

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let echange l a b =

let rec ech l1 l3 a b =match l3 with
    |[] -> l1
    |(t::l2)-> match (recherche_indice t l) with
      |a-> ech ((element_indi l b)::l1) l2 a b
      |b-> ech ((element_indi l a)::l1) l2 a b
      | _ ->ech (t::l1) l2 a b 

  in ech [] l a b 
;;

`

quand je l’exécute avec echange ['b';'c';'d'] 3 1;; ce la me renvoie [b,b,b] et si je change les indices ce la me renvoie [c,c,c] ou [d,d,d]

et quand je compile j’ai cette erreurs this match case is unused. en faisant référence à la ligne a-> et b->

merci d’avance pour votre aide.

Salut,

Ton code gagnerait à utiliser des noms de variables explicites, on se perd actuellement facilement entre les l1, l2 et l3.

Aussi, je ne comprends pas pourquoi il t’es nécessaire de faire appel à recherche_indice. Les indices te sont connus : ils sont fournis en paramètres. Et comme tu itères sur la liste depuis le début, tu peux garder la trace de l’indice actuel à chaque récursion.

Bonsoir,

Ton problème vient du fait que tu essaies d’utiliser quelque chose qui n’est pas présent dans Ocaml. En particulier, lorsque tu fais un pattern matching, un pattern qui utilise un nom de variable matche avec n’importe quel valeur, il lie juste la valeur du pattern au nom de la variable (donc dans ton pattern matching c’est toujours la ligne numéro 6 du pattern qui est utilisé).

Tu peux trouver plus d’informations sur le site suivante : https://caml.inria.fr/pub/docs/manual-ocaml/patterns.html et en particulier la partie "Variable patterns".

+0 -0

Bonsoir merci pour vos réponses

@entwanne j’ai suivie tes conseils j’ai remplacé recherche_indice par un conteur n mais j’ai toujours le mème soucis

init pour initiale

nouv pour nouveau

cour pour courant

@Jozifo je n’ai pas bien compris pourquoi il lit à chaque fois que la ligne 6, j’ai cru comprendre qu’en ajoutant un when afin de l’obliger a exécuter ce match seulement quand (n!=a && n!=b) mais cela ne fonctionne pas j’ai le même résultat

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let echange init a b =

  let rec ech nouv cour a b n =match cour with
    |[] -> nouv
    |(t::l2)-> match n with
       a -> ech ((element_indi init b)::nouv) l2 a b (n+1)
      |b -> ech ((element_indi init a)::nouv) l2 a b (n+1)
      | _ when ((n!=a) && (n!=b)) ->ech (t::nouv) l2 a b (n+1) 

  in ech [] init a b 1 
;;

Prenons un pattern matching plus simple (en Ocaml):

1
2
3
4
let a = 5
match 1, 2 with 
 | a, b -> true
 | _, _ -> false

Que va renvoyer ce code ? Il va renvoyer true. Pourquoi ? Comme c’est expliqué sur le lien https://caml.inria.fr/pub/docs/manual-ocaml/patterns.html.

A pattern that consists in a value name matches any value, binding the name to the value. The pattern _ also matches any value, but does not bind any name.

Nous arrivons dans la ligne 3, le nom de variable est lié à la valeur. Donc lorsque nous sommes à la ligne 3 nous avons a = 1 et b = 2 (ATTENTION : la valeur qui était assignée à la variable a précédemment (c’était 5) n’est en aucun cas comparé).

En fait | a, b -> blabla fait exactement la même chose que | _, _ -> blabla sauf que les valeurs du matching sont fixé à une variable dont le nom est précisé (ici a et b) et ce même si les variables sont utilisés auparavant. En fait

Et ce que tu essayes de faire (vérifier que aet n sont égaux) n’est pas possible avec un pattern matching pour cela il faut utiliser des if / then / else.

TLDR: En mettant | a, b -> blabla tu crées une nouvelle variable qui va prendre la valeur du matching. Cette nouvelle variable peut tout matcher.

+1 -0

Bonjour, Merci beaucoup, je comprend mieux J’ai remplacé le match par un if/then/elseet ça fonctionne :D

Voila mon nouveau code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let echange init a b =

  let rec ech nouv cour a b n =match cour with
    |[] -> nouv
    |(t::l2)->if n=a then ((element_indi init b)::(ech nouv l2 a b (n+1)))
            else if (b=n) then ((element_indi init a)::(ech nouv l2 a b (n+1)))
                else (t::(ech nouv l2 a b (n+1)))

  in ech [] init a b 1 
;;

`

Salut,

Tu peux garder ton match. Ici, il te faut « juste » utiliser when. Si on reprend l’exemple de @Jozifo, pour lui donner le comportement attendu, on écrirait ceci.

1
2
3
4
let a = 5
match 1, 2 with 
 | a, b when a = a -> true
 | _, _            -> false

Mais c’est toujours un peu confus, donc on va renommer le a du match.

1
2
3
4
let a = 5
match 1, 2 with 
 | x, y when x = a -> true
 | _, _            -> false

Et là, on comprend assez bien ce qui est testé.

+1 -1

Merci @Karnaj je trouve votre méthode très intéressante

Voici mon nouveau code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let echange init a b =

  let rec ech nouv cour a b n =match cour with
    |[] -> nouv
    |(t::l2)-> match n with
      | x when x=a-> ((element_indi init b)::(ech nouv l2 a b (n+1)))
      | y when y=b-> ((element_indi init a)::(ech nouv l2 a b (n+1)))
      | _  ->(t::(ech nouv l2 a b (n+1)))

  in ech [] init a b 1 
;;
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte