Page 1 of 3

Problème Programmation

Unread postPosted: 16 Sep 2014, 16:56
by Panardinho
Bonjour,
Cela fait depuis 1 semaine que j'ai acheté une TI Nspire CX CAS et je n'arrive pas à réaliser un programme qui nous donne tous les diviseurs d'un nombre.

Voici ce que j'ai fait

Code: Select all
Define LibPub div(x)=
Func
:Local p
:For p,1,floor(√(x))
:  If ((x)/(p))=floor(((x)/(p))) Then
:    Disp p,((x)/(p))
:  EndIf
:EndFor
:EndFunc


Le problème c'est que lorsque j'essaie de tester l'algorithme, on m'affiche "Erreur: erreur de domaine".

Est ce que quelqu'un pourrait m'indiquer où se trouve l'erreur et également les erreurs "d'écriture" de l'algorithme comme c'est la première fois que je programme sur TI ?
Et si quelqu'un a une idée pour améliorer l'algorithme notamment pour ne pas afficher 2 fois les mêmes valeurs quand on rentre un carré parfait, elle est bienvenue :)

Merci d'avance !

Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 17:19
by Bisam
L'écriture de ta fonction est quasiment parfaite (Bravo en particulier pour l'utilisation d'une fonction, et celle de l'instruction 'Local').
Cependant, pour que ce soit une fonction, il faut qu'elle renvoie une valeur (et non qu'elle se contente d'afficher des résultats).

Tu peux par exemple, stocker les valeurs au fur et à mesure dans une liste (voire dans 2 listes, si tu veux facilement garder les diviseurs dans l'ordre croissant).

Je ne sais pas du tout d'où vient ton "Erreur de domaine", à moins que tu aies essayé ta fonction sur un "x" négatif...

Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 18:16
by davidElmaleh
Pour compléter ce qu'à dit Bisam, tu dois avoir un "return" en fin de ta fonction.
Et pour répondre à ta dernière question, tu peux utiliser un autre "if" :p Ou bien, pour faire un code plus court, écrire :
Code: Select all
when(p=x/p,{p},{p,x/p})

Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 19:17
by Adriweb
Pour le fun, une version qui renvoie une liste des diviseurs en se basant sur la fonction factor :
Code: Select all
Define LibPub factors(n)=
Func
:Local s,d,l,lastpos,i,j,tmp
:s:=string(factor(n))
:d:=dim(s)
:l:={}
:lastpos:=1
:For i,1,d
:  If i=d or mid(s,i,1)="*" Then
:    tmp:=mid(s,lastpos,i-lastpos+when(i=d,1,0))
:    For j,1,dim(tmp)
:      If mid(tmp,j,1)="^" Then
:        tmp:=mid(tmp,1,j-1)
:      EndIf
:    EndFor
:    If expr(tmp)≠n Then
:      l:=augment(l,{expr(tmp)})
:    EndIf
:    lastpos:=i+1
:  EndIf
:EndFor
:Return l
:EndFunc


(je laisse les "optimiseurs" professionnels raccourcir le code...:P)


Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 20:51
by Bisam
Adriweb wrote:(je laisse les "optimiseurs" professionnels raccourcir le code...:P)

Challenge accepted !

Code: Select all
Define LibPub factors(n)=
Func
: Local s, d, l, i0, i, tmp
: s := string(factor(n)) & "*"
: d := dim(s)
: i0 := 1
: l := {}
: While i0 ≤ d
:   i := instring(s, "*", i0)
:   tmp := mid(s, i0, i - i0)
:   i0 := i + 1
:   i := instring(tmp, "^")
:   If i > 0
:     tmp := left(tmp, i - 1)
:   l := augment(l, {expr(tmp)})
: EndWhile
: EndFunc


Modifications effectuées :
  • rajouté un "*" à la fin de la factorisation pour éviter de traiter à part le cas de la fin de ligne
  • utilisé la fonction "instring" pour rechercher les caractères "*" et "^"
  • remplacé un "mid" par "left" lorsque l'on commence au début de la chaîne
  • raccourci le nom de la variable "lastpos" en "i0"
  • effectué le calcul de "l" dans tous les cas, même si n est premier, et en fin de boucle (comme ça, le "return" final est superflu : la TI renvoie automatiquement le dernier résultat calculé hors d'un test)
  • supprimé la variable "j" devenue inutile en remontant la ligne d'affectation de "i0"

Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 21:30
by Adriweb
Bien joué :)
Je ne connais pas suffisamment les subtilites du langage pour reflechir correctement a ce genre d'optimisations... :P
un explode/split aurait ete le bienvenue :P

Bisam wrote:rajouté un "*" à la fin de la factorisation pour éviter de traiter à part le cas de la fin de ligne

Effectivement, pas bete. Ca m'embetait d'avoir a gerer ca avec un when... :P

Bisam wrote:utilisé la fonction "instring" pour rechercher les caractères "*" et "^"

Eh, oui, ca evite les For...

Bisam wrote:remplacé un "mid" par "left" lorsque l'on commence au début de la chaîne

Je suppose que c'est parce que c'est plus rapide derriere ? Parce que sinon c'est pareil, non ?

Bisam wrote:raccourci le nom de la variable "lastpos" en "i0"

Certes :P

Bisam wrote:effectué le calcul de "l" dans tous les cas, même si n est premier, et en fin de boucle (comme ça, le "return" final est superflu : la TI renvoie automatiquement le dernier résultat calculé hors d'un test)

Ah oui, ca je savais ( \o/ ) - mais ca devient limite de la legere obfuscation la, ce qui va pas grandement aider les debutants :P

Bisam wrote:supprimé la variable "j" devenue inutile en remontant la ligne d'affectation de "i0"

Hmm ok

Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 22:04
by Panardinho
Merci de vos réponses, mais ne connaissant pas toutes les fonctions utilisées le second algorithme ne me parle pas trop encore.

Je suis arrivé à quelque chose de correct (enfin je pense) avec une liste mais on me dit maintenant qu'il y a trop d'arguments...
Quel peut etre le problème ?

Sinon à quoi sert le Return et comment introduire le when dans l'algorithme. Je pense avoir réussi avec un If mais pas avec le when?

Re: Problème Programmation

Unread postPosted: 16 Sep 2014, 22:10
by Bisam
Publie ton algorithme (tu peux faire un copier-coller depuis le logiciel sur ton ordi) et on te dira ce qui ne va pas... mais sinon, on risque de parler dans le vide.

Par ailleurs, pour les fonctions que tu ne connais pas encore, je te conseille vivement de consulter le Guide de référence.

Re: Problème Programmation

Unread postPosted: 17 Sep 2014, 13:01
by Panardinho
Ok merci pour le conseil !

Voilà ce que je fais, je suis un peu perdu je ne sais plus si ça a un sens. A votre avis ce serait préférable d'utiliser une boucle While au lieu d'une boucle For ?

Code: Select all
Define LibPub div(x)=
Func
:Local p,x,l
:l:={}
:p:=1
:For p,1,floor(√(x))
:  If p=((x)/(p)) Then
:    l:={p}
:   Else
:   If ((x)/(p))=floor(((x)/(p))) Then
:   l:={p,((x)/(p))}
:   EndIf
:  EndIf
: EndFor
: Return l
:EndFunc

Re: Problème Programmation

Unread postPosted: 17 Sep 2014, 13:34
by zero44
*s'incruste dans le topic en mode ninja revenu d'entre les morts*

Déjà, à mon avis tu peux virer
Code: Select all
If ((x)/(p))=floor(((x)/(p))) Then

et le remplacer par
Code: Select all
If mod(x,p)=0

Ça vérifie que x est de la forme p*k+0 ;)

Ensuite, une boucle for marche très bien, mais je te conseille de la faire commencer à 2, à moins que tu veuilles avoir 1 dans ta liste :)

Concernant ton problème de carrés parfaits.. C'est sale :D si je fais div(65536) ça donne quoi ? Essaie pour voir.. Mais j'ai peur d'un {2, 4, 8,... ,256} assez lourd :P
Enfin ça c'est si c'est censé retourner une liste..
Teste avec ces valeurs et dis-moi le résultat donné/attendu, ça m'aidera à comprendre :)
div(2) div(4) div(36) div(49) div(98)