2017-10-20 29 views
0

J'essaie de déterminer quelle liste d'entiers est la plus grande. La représentation de [1;2;3] est actuellement 123. Donc donné deux listes d'entiers, je veux comparer chaque élément pour déterminer quel nombre est plus grand à la fin. Renvoyant 1 si list1 > list2, -1 si list1 < list2 et 0 s'ils sont égaux. C'est ce que j'ai jusqu'ici, mais quand j'essaie de l'exécuter, j'ai des erreurs et je ne comprends pas pourquoi. On m'a également demandé de faire tous les récurrents dans la forme de récurrence de la queue chaque fois que possible. Est-ce la récursion correcte de la queue?Déterminer quelle liste d'entiers est la plus grande

let rec compare' list1 list2 currentOrder = match (list1, list2) with 
    | [],[]      -> 0 
    | list1, []     -> 1 
    | [], list2     -> -1 
    | car1::cdr1, car2::cdr2 ->  (*car1 contains the current element and cdr1 contains the rest of the list. Ex car1 = [1], cdr2 = [2;3]*) 
    let nextCompare = 
     (
      if cdr1 = [] && cdr2 = [] 
      then 0 
      else 1 
     )       
    in 
    (
     if (nextCompare != 0)(*To check if we are not at the end of the list*) 
     then (  (*Compare the cars to determine the currentOrder and recursively call with the next number*) 
     if car1 > car2 
     then (compare' (cdr1 cdr2 1)) 
     else if car1 < car2 
     then (compare' (cdr1 cdr2 -1)) 
     else (compare' cdr1 cdr2 currentOrder) 
    ) 
     else (*we are at the end of the list so we want to return the current order*) 
     ( (*Still need to check in case there is only 1 digit number, because we did not update currentOrder for it to be returned*) 
     if car1 > car2 
     then 1 
     else if car1 < car2 
     then -1 
     else currentOrder 
    ) 
    ) 


Printf.printf (compare' [1;2;3] [3;2;1] 0) 
+0

Quelles sont les erreurs? – glennsl

+0

@glennsl Pour la ligne "(compare '(cdr1 cdr2 1))" Cette expression a le type' une liste Ceci n'est pas une fonction; il ne peut pas être appliqué. – davy890

+0

Votre problème ici est que vous avez trop de parens. Vous essayez d'appliquer 'cdr2' et' 1' à 'cdr1', ce qui se traduira par le fait que vous vous plaignez que vous traitez la liste' cdr1' comme une fonction :) – glennsl

Répondre

0

Le premier problème que vous aviez eu quelques parenthèses supplémentaires autour des arguments de quelques applications de fonction (par exemple (compare' (cdr1 cdr2 1))) qui indique OCaml que vous souhaitez appeler cdr1 avec les arguments cdr2 et 1, puis appliquer la résultat de cela à la compare'. Le compilateur se plaindra donc que vous essayez d'utiliser la liste cdr1 en tant que fonction. C'est une erreur simple à faire si vous avez l'habitude de faire une application avec des parenthèses.

Le deuxième problème est que vous avez eu -1 sans parenthèses, que le compilateur interprétera comme application 1 à l'opérateur - binaire, et donc se plaignent que le résultat de c'est une fonction et non un int, comme on pouvait s'y attendre . La raison de ce comportement étrange est que OCaml supporte l'application de fonction partielle, ce qui provoque certaines ambiguïtés. Désambiguquez-le, il vous suffit de l'entourer entre parenthèses: (-1). Et enfin, il y avait un peu de redondance dans votre code, donc je l'ai simplifié un peu pour vous. Moins de code signifie aussi moins d'endroits à vis, et de regarder à travers pour trouver screwups, qui est très pratique quand vous apprenez :)

let rec compare' list1 list2 currentOrder = 
    match list1, list2 with 
    | [], []      -> currentOrder 
    | _, []      -> 1 
    | [], _      -> -1 
    | car1::cdr1, car2::cdr2 -> 
    let order = 
     if car1 > car2 then 1 
     else if car1 < car2 then -1 
     else currentOrder 
    in 
    compare' cdr1 cdr2 order 

Je donne cependant aucune garantie que cela est logiquement correct, il est juste une transformation de ce que vous aviez écrit (en fait, je sais que ce n'est pas correct, mais c'est une mission pour une raison).

+0

Simplification absolument incroyable de ce que je voulais faire. Cependant, quand je l'ai couru, en ce qui concerne la ligne: comparer 'commande cdr1 cdr2, j'obtiens l'erreur Cette fonction a type' une liste -> 'une liste -> int -> int Il est appliqué à trop d'arguments; peut-être avez-vous oublié un '; ' Qu'est-ce que ça veut dire? – davy890

+0

Cela signifie probablement que vous devez ajouter un ';;' après cette fonction pour terminer la déclaration de niveau supérieur, ou ajouter 'let() =' avant Printf.printf ... '.En général, vous ne devez pas mettre les instructions directement au niveau supérieur, car le compilateur n'est pas capable de séparer l'instruction de la déclaration précédente. Il pense 'Printf ...' est juste un autre argument à tout ce qui est venu avant. – glennsl

+0

L'erreur logique que vous avez mentionnée est-elle le retour de l'ordre du dernier chiffre? Ex. Si je comparais 123 et 321, la valeur de retour serait 1 (donné 123 est list1). Si c'est le cas, qu'il n'y a pas de problème parce que c'était vraiment ce que je voulais. Mon erreur en décrivant la représentation du nombre ci-dessus, [1,2,3] était en fait 321, de sorte qu'il serait plus simple de faire des opérations mathématiques d'ordre inférieur à supérieur. – davy890