pyromaths/0000755000175000017500000000000011734627256013307 5ustar didrocksdidrockspyromaths/MANIFEST.in0000644000175000017500000000032211702101415015015 0ustar didrocksdidrocksinclude AUTHORS COPYING NEWS pyromaths MANIFEST.in recursive-include data/images * recursive-include data/packages * recursive-include data/templates * recursive-include data/linux * recursive-include debian * pyromaths/data/0000755000175000017500000000000011734627250014212 5ustar didrocksdidrockspyromaths/data/packages/0000755000175000017500000000000011734627250015770 5ustar didrocksdidrockspyromaths/data/packages/tabvar.tex0000644000175000017500000004326411702101415017763 0ustar didrocksdidrocks%-- pour griser des cases \definecolor{gristabvar}{rgb}{0.7669 0.7669 0.7669} %-- Dimensions sur lesquelles on peut agir facilement \newdimen\tabdim%-- taille minimale (horizontale) d'une case \newdimen\tabblanc%-- blanc ajout verticalement chaque case (6 fois en tout !) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % MACROS POUR FAIRE UN TABLEAU DE VARIATIONS % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \catcode`\@=11 %-- Les diverses dimensions dont j'ai besoin \newdimen\tv@mydimen \newdimen\tv@mydimendeux \newdimen\tv@dimYHaut%-- taille verticale de la case en haut \newdimen\tv@dimYMilieu%-- taille verticale de la case du milieu \newdimen\tv@dimYBas%-- taille verticale de la case du bas \newdimen\tv@dimX%-- tampon pour les calculs bass sur la largeur de la case courante \newdimen\tv@Xdim%-- largeur de la case courante pour les calculs \newdimen\tv@YTotal%-- hauteur totale \newcount\tv@countLigne%-- Pour savoir le numro de la ligne actuelle \newdimen\tv@DX%-- pour savoir o est le trait de milieu de case courant %-- On fixe les dimensions par dfaut \tabdim=0.8cm \tabblanc=2pt %-- Pour savoir si on est en train de calculer les tailles ou de tracer le tableau de variations \newif\iftv@calcul %--- Mettre les valeurs par dfaut \def\psdefaut{\psset{xunit=1cm,yunit=1cm,runit=1cm,linewidth=0.4pt,linestyle=solid,linecolor=black}} %-- quelques abbrviations commodes... \let\dsp=\displaystyle \let\spt=\scriptstyle %------------- MACROS POUR MANIPULER LES DIMENSIONS %-- Met dans \tv@mydimen la taille Y (depth+height) de #1 \def\initY#1{% \setbox100=\hbox{#1}% \global\tv@mydimen=\ht100\global\advance\tv@mydimen by\dp100} %-- Met dans \tv@mydimen le rel Sup(la taille X (width) de #1 , \tabdim) \def\initX#1{\setbox100=\hbox{#1}% \ifdim\wd100>\tabdim \global\tv@mydimen=\wd100 \else \global\tv@mydimen=\tabdim \fi} %-- Met dans \tv@mydimen la taille X (width) de #1 \def\initx#1{\setbox100=\hbox{#1}\global\tv@mydimen=\wd100} %-- Calcule la hauteur totale = YHaut+YMilieu+YBas \def\calculeYTotal{% \global\tv@YTotal=\tv@dimYHaut\global\advance\tv@YTotal by\tv@dimYMilieu\global\advance\tv@YTotal by\tv@dimYBas} %-- Fixer les trois dimensions, dans l'ordre : Haut Milieu Bas \def\setY#1#2#3{\global\tv@dimYHaut=#1\global\tv@dimYMilieu=#2\global\tv@dimYBas=#3\relax} %-- Mettre le max de #1,#2 dans #1 \def\max#1#2{\ifdim#2>#1\global#1=#2\fi} %-- macro pour grer le calcul de \tv@Xdim : #1 est un contenu afficher \def\GererX#1{% \initX{#1}\tv@mydimen=1.1\tv@mydimen% \max{\tv@Xdim}{\tv@mydimen}} %-- macro pour grer le calcul de \tv@Xdim : #1 est une dimension \def\GererXDimension#1{% \tv@mydimen=#1% \tv@mydimen=1.1\tv@mydimen% \max{\tv@Xdim}{\tv@mydimen}% \max{\tv@Xdim}{\tabdim}%-- taille minimale d'une case = \tabdim } %-- cas simple : dx vaux la moiti de la largeur de #1. On retrouve aprs a le bon dx dans \tv@DX \def\GererDXSimple#1{% \initX{#1}\tv@mydimen=1.1\tv@mydimen \tv@mydimen=0.5\tv@mydimen \max{\tv@DX}{\tv@mydimen}% } %-- cas complexe : #1 est une proposition de DX. On retrouve aprs a le bon dx dans \tv@DX \def\GererDXDimension#1{% \tv@mydimen=#1% \max{\tv@DX}{\tv@mydimen}% \max{\tv@DX}{0.5\tabdim}%-- au minimum = 1/2 tabdim } %-------------- MACROS POUR POSER UN TEXTE %-- (elles supposent que \tv@DX contient la bonne valeur au moment de l'appel) \def\tabvarputhaut#1{% \iftv@calcul \initY{#1}% \max{\tv@dimYHaut}{\tv@mydimen}% \fi \rput(\tv@DX,-0.5\tv@dimYHaut){#1}} \def\tabvarputmilieu#1{% \iftv@calcul \initY{#1}% \max{\tv@dimYMilieu}{\tv@mydimen}% \fi% \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by 0.5\tv@dimYMilieu \rput(\tv@DX,-\tv@mydimen){#1}} \def\tabvarputbas#1{% \iftv@calcul \initY{#1}% \max{\tv@dimYBas}{\tv@mydimen}% \fi% \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by \tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas \rput(\tv@DX,-\tv@mydimen){#1}} %-------------- MACROS POUR LES TRAITS VERTICAUX % (elles supposent que \tv@DX contient la bonne valeur au moment de l'appel) % %-- traits verticaux simples \def\traithaut{\psline(\tv@DX,0)(\tv@DX,-\tv@dimYHaut)} \def\traitmilieu{\tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu \psline(\tv@DX,-\tv@dimYHaut)(\tv@DX,-\tv@mydimen)} \def\traitbas{\tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu \dimen100=\tv@mydimen\advance\tv@mydimen by\tv@dimYBas \psline(\tv@DX,-\dimen100)(\tv@DX,-\tv@mydimen)} %-- doubles traits verticaux \def\doubletraithaut{\psline[doubleline=true,doublesep=1pt](\tv@DX,0)(\tv@DX,-\tv@dimYHaut)} \def\doubletraitmilieu{\tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu \psline[doubleline=true,doublesep=1pt](\tv@DX,-\tv@dimYHaut)(\tv@DX,-\tv@mydimen)} \def\doubletraitbas{\tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu \dimen100=\tv@mydimen\advance\tv@mydimen by\tv@dimYBas \psline[doubleline=true,doublesep=1pt](\tv@DX,-\dimen100)(\tv@DX,-\tv@mydimen)} %-- trait simple, occupant toute la hauteur \def\trait{\traithaut\traitmilieu\traitbas} %-- trait double, occupant toute la hauteur \def\dbt{\doubletraithaut\doubletraitmilieu\doubletraitbas} %-------------- MACROS POUR LES FLCHES %-- flche montante (au milieu) \def\fm{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimen)(0.9\tv@dimX,-\tv@dimYHaut)}\hfil}} %-- flche descendante (au milieu) \def\fd{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@dimYHaut)(0.9\tv@dimX,-\tv@mydimen)}\hfil}} %-- flche horizontale en haut \def\fhh{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-0.5\tv@dimYHaut)(0.9\tv@dimX,-0.5\tv@dimYHaut)}\hfil}} %-- flche horizontale au milieu \def\fhm{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by 0.5\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimen)(0.9\tv@dimX,-\tv@mydimen)}\hfil}} %-- flche horizontale en bas \def\fhb{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu\advance\tv@mydimen by0.5\tv@dimYBas \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimen)(0.9\tv@dimX,-\tv@mydimen)}\hfil}} %-- flche montante en partie basse \def\fmb{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas \tv@mydimendeux=\tv@dimYHaut\advance\tv@mydimendeux by 0.5\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimen)(0.9\tv@dimX,-\tv@mydimendeux)}\hfil}} %-- flche descendante en partie basse \def\fdb{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas \tv@mydimendeux=\tv@dimYHaut\advance\tv@mydimendeux by 0.5\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimendeux)(0.9\tv@dimX,-\tv@mydimen)}\hfil}} %-- flche montante en partie haute \def\fmh{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=0.5\tv@dimYHaut\tv@mydimendeux=\tv@dimYHaut\advance\tv@mydimendeux by 0.5\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimendeux)(0.9\tv@dimX,-\tv@mydimen)}\hfil}} %-- flche descendante en partie haute \def\fdh{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi \tv@mydimen=0.5\tv@dimYHaut\tv@mydimendeux=\tv@dimYHaut\advance\tv@mydimendeux by 0.5\tv@dimYMilieu \tv@dimX=\tv@Xdim\advance\tv@dimX by -\tv@DX %-- tv@dimX = ce qui reste droite de DX \hbox to\tv@Xdim{\rput(\tv@DX,0){\psline{->}(-0.9\tv@DX,-\tv@mydimen)(0.9\tv@dimX,-\tv@mydimendeux)}\hfil}} %-- MACROS SIMPLIFIES POUR LES TEXTES (compatibilit avec mes anciennes macros) %-- texte au milieu \def\tx#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to \tv@Xdim{\tabvarputmilieu{$\dsp #1$}\hfil}% } %-- texte en haut \def\txh#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\tabvarputhaut{$\dsp #1$}\hfil}% } %-- texte en bas \def\txb#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\tabvarputbas{$\dsp#1$}\hfil}% } %-- texte milieu + trait \def\txt#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\traithaut\tabvarputmilieu{$\dsp #1$}\traitbas\hfil}% } %-- texte haut + trait \def\txht#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\tabvarputhaut{$\dsp #1$}\traitmilieu\traitbas\hfil}% } %--texte bas + trait \def\txbt#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\traithaut\traitmilieu\tabvarputbas{$\dsp #1$}\hfil}% } %-- Texte pour la premire ligne \def\xt#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\tabvarputmilieu{$\dsp#1$}\traitbas\hfil}% } %--Trait double + texte crit en haut \def\xdbt#1{% \iftv@calcul \GererX{$\dsp#1$}% \GererDXSimple{$\dsp#1$}% \fi \hbox to\tv@Xdim{\tabvarputmilieu{$\dsp#1$}\doubletraitbas\hfil}% } %-- Trait double + texte gauche en haut(#1) et texte droite en bas(#2) \def\txdbthb#1#2{% \iftv@calcul \initY{$\dsp #1$}\max{\tv@dimYHaut}{\tv@mydimen}% \initY{$\dsp #2$}\max{\tv@dimYBas}{\tv@mydimen}% %-- calcul et gestion de DX \initx{$\dsp#1$}\advance\tv@mydimen by 3 pt\relax \GererDXDimension{\tv@mydimen}% %-- calcul et gestion de la largeur totale \initx{$\dsp#1$}\max{\tv@mydimen}{\tv@DX}% \global\advance\tv@mydimen by 3pt\global\tv@dimX=\tv@mydimen \initx{$\dsp#2$}\global\advance\tv@mydimen by\tv@dimX \GererXDimension{\tv@mydimen}% \fi% %-- construction du texte + trait double \hbox to\tv@Xdim{% \rput[r](\tv@DX,0){\rput[r](-3pt,-0.5\tv@dimYHaut){$\dsp#1$}}% % \dbt % \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by \tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas \rput[l](\tv@DX,0){\rput[l](3pt,-\tv@mydimen){$\dsp #2$}}% \hfil}% } %-- Trait double + texte gauche en haut(#1) et texte droite en haut(#2) \def\txdbthh#1#2{% \iftv@calcul \initY{$\dsp #1$}\max{\tv@dimYHaut}{\tv@mydimen}% \initY{$\dsp #2$}\max{\tv@dimYHaut}{\tv@mydimen}% %-- calcul et gestion de DX \initx{$\dsp#1$}\advance\tv@mydimen by 3 pt\relax \GererDXDimension{\tv@mydimen}% %-- calcul et gestion de la largeur totale \initx{$\dsp#1$}\max{\tv@mydimen}{\tv@DX}% \global\advance\tv@mydimen by 3pt\global\tv@dimX=\tv@mydimen \initx{$\dsp#2$}\global\advance\tv@mydimen by\tv@dimX \GererXDimension{\tv@mydimen}% \fi% \hbox to\tv@Xdim{% \rput[r](\tv@DX,0){\rput[r](-3pt,-0.5\tv@dimYHaut){$\dsp#1$}}% % \dbt % \rput[l](\tv@DX,0){\rput[l](3pt,-0.5\tv@dimYHaut){$\dsp #2$}} \hfil}% }% %-- Trait double + texte gauche en bas (#1) et texte droite en haut(#2) \def\txdbtbh#1#2{% \iftv@calcul \initY{$\dsp #1$}\max\tv@dimYBas\tv@mydimen% \initY{$\dsp #2$}\max\tv@dimYHaut\tv@mydimen% %-- calcul et gestion de DX \initx{$\dsp#1$}\advance\tv@mydimen by 3 pt\relax \GererDXDimension{\tv@mydimen}% %-- calcul et gestion de la largeur totale \initx{$\dsp#1$}\max{\tv@mydimen}{\tv@DX}% \global\advance\tv@mydimen by 3pt\global\tv@dimX=\tv@mydimen \initx{$\dsp#2$}\global\advance\tv@mydimen by\tv@dimX \GererXDimension{\tv@mydimen}% \fi% \hbox to\tv@Xdim{% \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by \tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas \rput[r](\tv@DX,0){\rput[r](-3pt,-\tv@mydimen){$\dsp#1$}}% % \dbt % \rput[l](\tv@DX,0){\rput[l](3pt,-0.5\tv@dimYHaut){$\dsp #2$}} \hfil}% }% %-- Trait double + texte gauche en bas(#1) et texte droite en bas(#2) \def\txdbtbb#1#2{% \iftv@calcul% \initY{$\dsp #1$}\max{\tv@dimYBas}{\tv@mydimen}% \initY{$\dsp #2$}\max{\tv@dimYBas}{\tv@mydimen}% %-- calcul et gestion de DX \initx{$\dsp#1$}\advance\tv@mydimen by 3 pt% \GererDXDimension{\tv@mydimen}% %-- calcul et gestion de la largeur totale \initx{$\dsp#1$}\max{\tv@mydimen}{0.90909\tv@DX}%-- reprendre la bonne valeur de DX qui a t multipli par 1.1 \global\advance\tv@mydimen by 3pt\global\tv@dimX=\tv@mydimen% \initx{$\dsp#2$}\global\advance\tv@mydimen by\tv@dimX% \GererXDimension{\tv@mydimen}% \fi% \hbox to\tv@Xdim{% \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas\relax% \rput[r](\tv@DX,0){\rput[r](-3pt,-\tv@mydimen){$\dsp#1$}}% % \dbt % \tv@mydimen=\tv@dimYHaut\advance\tv@mydimen by\tv@dimYMilieu\advance\tv@mydimen by 0.5\tv@dimYBas\relax \rput[l](\tv@DX,0){\rput[l](3pt,-\tv@mydimen){$\dsp #2$}}% \hfil}% }% %-- Griser une case \def\grise{% \iftv@calcul \GererXDimension{\tabdim}% \GererDXDimension{0.5\tabdim}% \fi% \hbox to\tv@Xdim{\psframe[linecolor=gristabvar,fillstyle=solid,fillcolor=gristabvar](0,0)(\tv@Xdim,-\tv@YTotal)\hfil}} %-- MACROS MANIPULATION DES DONNES %-- Repiqu dans le TeXBook page 378 : list macro, lgrement modifi. \toksdef\ta=0 \toksdef\tb=2 %-- ajoute un item droite de la liste : #1 = item, #2 = liste \long\def\rightappenditem#1\to#2{\ta={\\{#1}}\tb=\expandafter{#2}% \xdef#2{\the\tb\the\ta}} %-- ajoute un item gauche de la liste : #1 = item, #2 = liste \long\def\leftappenditem#1\to#2{\ta={\\{#1}}\tb=\expandafter{#2}% \xdef#2{\the\ta\the\tb}} %-- extrait l'item de gauche de la liste et ampute celle-ci. #1 = liste, #2 = macro qui va % recevoir l'item extrait. \def\lop#1\to#2{\expandafter\lopoff#1\lopoff#1#2} \long\def\lopoff\\#1#2\lopoff#3#4{\gdef#4{#1}\gdef#3{#2}} %-- On dmarre avec une liste vide %-- \listeY est une macro qui contiendra les dimensions, sous la forme : % \\{}\\{}\\{}\\{}...\\{} % %-- \listeX est une macro qui contiendra les dimensions, sous la forme : % \\{}\\{}\\{}\\{}...\\{} \def\clearListes{\gdef\listeY{}\gdef\listeX{}\gdef\listeDX{}} %-- Sauvegarde des trois hauteurs \def\savedimsY{% \expandafter\rightappenditem\the\tv@dimYHaut\to\listeY \expandafter\rightappenditem\the\tv@dimYMilieu\to\listeY \expandafter\rightappenditem\the\tv@dimYBas\to\listeY} %-- Lecture des trois hauteurs + ajout de blanc + initialisation de \tv@YTotal \def\litY{% \lop\listeY\to\a \tv@dimYHaut=\a \lop\listeY\to\a \tv@dimYMilieu=\a \lop\listeY\to\a \tv@dimYBas=\a \global\advance\tv@dimYHaut by 2\tabblanc \global\advance\tv@dimYMilieu by 2\tabblanc \global\advance\tv@dimYBas by 2\tabblanc \calculeYTotal} %-- Ajout d'une dimension X listeX \def\ajouteX#1{% \expandafter\rightappenditem\the #1\to\listeX} %-- Ajout d'une dimension X listeX ( gauche => initialisation) \def\ajouteXAGauche#1{% \expandafter\leftappenditem\the #1\to\listeX} %-- Extrait la dimension X de gauche de \listeX et la stocke dans \tv@Xdim \def\extraitX{\lop\listeX\to\a\tv@Xdim=\a} %-- Ajout d'une dimension dx listeDX \def\ajouteDX#1{% \expandafter\rightappenditem\the #1\to\listeDX} %-- Ajout d'une dimension dx listeDX ( gauche => initialisation) \def\ajouteDXAGauche#1{% \expandafter\leftappenditem\the #1\to\listeDX} %-- Extrait la dimension dx de gauche de \listeDX et la stocke dans \tv@DX \def\extraitDX{\lop\listeDX\to\a\tv@DX=\a} %-- Macro juste pour initialiser \listeX et \listeDX avec le bon nombre de champs \def\initListeXListeDX#1{% \global\tv@countLigne=0 \setbox150=\vbox{\halign{% \global\advance\tv@countLigne by 1 \ifnum\tv@countLigne=1 \tv@mydimen=0pt \ajouteXAGauche{\tv@mydimen}% \ajouteDXAGauche{\tv@mydimen}% \fi ##\hfil\vrule&&% \hfil \ifnum\tv@countLigne=1 \tv@mydimen=0pt \ajouteXAGauche{\tv@mydimen}% \ajouteDXAGauche{\tv@mydimen}% \fi ##\hfil\cr% #1}}} %-- MACRO PRINCIPALE : TRAC DU TABLEAU OU SIMPLE CALCUL DES HAUTEURS \def\TABVAR#1{% \vbox{\vglue\smallskipamount\nobreak% {\offinterlineskip\everycr{\noalign{\hrule}}% \iftv@calcul \else \litY \fi%-- lecture du premier champ (bidon : on le saute) \hbox{\vrule\vbox{\halign{% \iftv@calcul \savedimsY \setY{0pt}{0pt}{0pt}%-- Mode calcul : sauver les dimensions et remettre zro \else \litY%-- Mode trac : rcuprer les dimensions et calcul de \tv@YTotal \fi \vrule height 0pt depth \tv@YTotal width 0pt\extraitX\extraitDX##\ajouteX{\tv@Xdim}\ajouteDX{\tv@DX}% \vrule&&% \extraitX\extraitDX##\ajouteX{\tv@Xdim}\ajouteDX{\tv@DX}\cr% #1}}\vrule}} \iftv@calcul \savedimsY%-- dernire ligne : on sauve les dimensions \fi \medbreak% }} %--------------- LA MACRO FINALE POUR FAIRE UN TABLEAU DE VARIATIONS % \def\tabvar#1{{\clearListes\initListeXListeDX{#1}\tv@calcultrue% \psset{linewidth=.4pt}%-- fixer la largeur des lignes... \setbox150=\hbox{\TABVAR{#1}}\tv@calculfalse\TABVAR{#1}}} \catcode`\@=12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % FIN DES MACROS POUR TABLEAU DE VARIATION % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Local Variables: %%% mode: plain-tex %%% TeX-master: t %%% End: pyromaths/data/packages/._tabvar.tex0000644000175000017500000000031511702101415020166 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/._templates0000755000175000017500000000031511702101415016333 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/._images0000755000175000017500000000031511702412011015577 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/templates/0000755000175000017500000000000011702101415016171 5ustar didrocksdidrockspyromaths/data/templates/._pyromaths.tex0000644000175000017500000000031511702101415021155 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/templates/evaluation.tex0000644000175000017500000000517611702101415021073 0ustar didrocksdidrocks% entete %%!TEX TS-program = latex \documentclass[a4paper,11pt]{article} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage[frenchb]{babel} \usepackage[autolanguage]{numprint} \usepackage[fleqn]{amsmath} \usepackage{amssymb,multicol,calc,vmargin,cancel,fancyhdr,units,pst-eucl,wrapfig,wasysym,pst-plot,tabularx,textcomp} \setmarginsrb{1.5cm}{1.5cm}{1.5cm}{1.5cm}{.5cm}{.5cm}{.5cm}{1.cm} \newcounter{exo} \setlength{\headheight}{18pt} \setlength{\fboxsep}{1em} \setlength\parindent{0em} \setlength\mathindent{0em} \setlength{\columnsep}{30pt} \usepackage[bookmarks=true, bookmarksnumbered=true, ps2pdf, pagebackref=true,% colorlinks=true,linkcolor=blue,plainpages=true]{hyperref} \hypersetup{pdfauthor={Jérôme Ortais},pdfsubject={Exercices de mathématiques},pdftitle={Exercices créés par Pyromaths, un logiciel libre en Python sous licence GPL}} \makeatletter \newcommand\styleexo[1][]{ \renewcommand{\theenumi}{\arabic{enumi}} \renewcommand{\labelenumi}{$\blacktriangleright$\textbf{\theenumi.}} \renewcommand{\theenumii}{\alph{enumii}} \renewcommand{\labelenumii}{\textbf{\theenumii)}} {\fontfamily{pag}\fontseries{b}\selectfont \underline{#1 \theexo} } \par\@afterheading\vspace{0.5\baselineskip minus 0.2\baselineskip} } \newcommand*\exercice{% \psset{unit=1cm} %\ifthenelse{\equal{\theexo}{0}} {} {\filbreak} \refstepcounter{exo}% \stepcounter{nocalcul}% \par\addvspace{1.5\baselineskip minus 1\baselineskip}% \@ifstar% {\penalty-130\styleexo[Corrigé de l'exercice]}% {\penalty-130\styleexo[Exercice]}% } \makeatother \newlength{\ltxt} \newcounter{fig} \newcommand{\figureadroite}[2]{ \setlength{\ltxt}{\linewidth} \setbox\thefig=\hbox{#1} \addtolength{\ltxt}{-\wd\thefig} \addtolength{\ltxt}{-10pt} \begin{minipage}{\ltxt} #2 \end{minipage} \hfill \begin{minipage}{\wd\thefig} #1 \end{minipage} \refstepcounter{fig} } \count1=\year \count2=\year \ifnum\month<8\advance\count1by-1\else\advance\count2by1\fi \pagestyle{fancy} \renewcommand{\headrulewidth}{0pt}% filet en haut de page \lhead[]{} \rhead[]{} \chead[]{} \cfoot{\textsl{\footnotesize{Année \number\count1/\number\count2}}} \rfoot{\textsl{\tiny{http://www.pyromaths.org}}} \begin{document} ##{{BOOKMARK}}## \newcounter{nocalcul}[exo] \renewcommand{\thenocalcul}{\Alph{nocalcul}} \raggedcolumns \setlength{\columnseprule}{0.5pt} {\noindent \textbf{NOM :} \hfill \textbf{##{{NIVEAU}}##}}\par \vskip 0.3cm {\noindent \textbf{Prénom :} \hfill \begin{center} {\large \textbf{##{{TITRE}}##}}\par \end{center} \vskip 0.3cm \hrule\vspace{\baselineskip} % fin entete % pied de page \end{document} % fin pied de page pyromaths/data/templates/._evaluation.tex0000644000175000017500000000031511702101415021276 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/templates/pyromaths.tex0000644000175000017500000000654011702101415020746 0ustar didrocksdidrocks% entete %%!TEX TS-program = latex \documentclass[a4paper,11pt]{article} \usepackage[utf8]{inputenc} % UTF-8 \usepackage[T1]{fontenc} \usepackage[frenchb]{babel} % francisation \usepackage[fleqn]{amsmath} % aligne le mode maths à gauche \usepackage{amssymb} % the amsfont symbols \usepackage[table, usenames, svgnames]{xcolor} % Couleurs \usepackage{multicol} % Multi-colonnes \usepackage{fancyhdr} % Mise en page, en-tête et pied de page \usepackage{calc} % Opérations \usepackage{marvosym} % Martin Vogels Symbole (\EUR) \usepackage{cancel} % draw diagonal lines \usepackage{units} % typesetting units and nice fractions \usepackage[autolanguage]{numprint} % écrituredes virgules \usepackage{tabularx} % creates a paragraph-like column whose width % automatically expands \usepackage{wrapfig} % allows figures or tables to have text wrapped around \usepackage{pst-eucl, pst-plot} % figures géométriques \usepackage{wasysym} % Symbole Euro %\usepackage{textcomp} \input{##{{TABVAR}}##} \usepackage[a4paper, dvips, left=1.5cm, right=1.5cm, top=2cm,% bottom=2cm, marginpar=5mm, marginparsep=5pt]{geometry} \newcounter{exo} \setlength{\headheight}{18pt} \setlength{\fboxsep}{1em} \setlength\parindent{0em} \setlength\mathindent{0em} \setlength{\columnsep}{30pt} \usepackage[bookmarks=true, bookmarksnumbered=true, ps2pdf, pagebackref=true,% colorlinks=true,linkcolor=blue,plainpages=true]{hyperref} \hypersetup{pdfauthor={Jérôme Ortais},pdfsubject={Exercices de mathématiques},pdftitle={Exercices créés par Pyromaths, un logiciel libre en Python sous licence GPL}} \makeatletter \newcommand\styleexo[1][]{ \renewcommand{\theenumi}{\arabic{enumi}} \renewcommand{\labelenumi}{$\blacktriangleright$\textbf{\theenumi.}} \renewcommand{\theenumii}{\alph{enumii}} \renewcommand{\labelenumii}{\textbf{\theenumii)}} {\fontfamily{pag}\fontseries{b}\selectfont \underline{#1 \theexo}} \par\@afterheading\vspace{0.5\baselineskip minus 0.2\baselineskip}} \newcommand*\exercice{% \psset{unit=1cm, dash=4pt 4pt, PointName=default,linecolor=Maroon, dotstyle=x, linestyle=solid, hatchcolor=Peru, gridcolor=Olive, subgridcolor=Olive, fillcolor=Peru} %\ifthenelse{\equal{\theexo}{0}}{}{\filbreak} \refstepcounter{exo}% \stepcounter{nocalcul}% \par\addvspace{1.5\baselineskip minus 1\baselineskip}% \@ifstar% {\penalty-130\styleexo[Corrigé de l'exercice]}% {\penalty-130\styleexo[Exercice]}% } \makeatother \newlength{\ltxt} \newcounter{fig} \newcommand{\figureadroite}[2]{ \setlength{\ltxt}{\linewidth} \setbox\thefig=\hbox{#1} \addtolength{\ltxt}{-\wd\thefig} \addtolength{\ltxt}{-10pt} \begin{minipage}{\ltxt} #2 \end{minipage} \hfill \begin{minipage}{\wd\thefig} #1 \end{minipage} \refstepcounter{fig} } \count1=\year \count2=\year \ifnum\month<8\advance\count1by-1\else\advance\count2by1\fi \pagestyle{fancy} \cfoot{\textsl{\footnotesize{Année \number\count1/\number\count2}}} \rfoot{\textsl{\tiny{http://www.pyromaths.org}}} \lhead{\textsl{\footnotesize{Page \thepage/ \pageref{LastPage}}}} \chead{\Large{\textsc{##{{TITRE}}##}}} \rhead{\textsl{\footnotesize{##{{NIVEAU}}##}}} \DecimalMathComma \begin{document} ##{{BOOKMARK}}## \newcounter{nocalcul}[exo] \renewcommand{\thenocalcul}{\Alph{nocalcul}} \raggedcolumns \setlength{\columnseprule}{0.5pt} % fin entete % pied de page \end{document} % fin pied de page pyromaths/data/._packages0000755000175000017500000000031511702101415016113 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/0000755000175000017500000000000011734627251015460 5ustar didrocksdidrockspyromaths/data/images/._pyromaths.png0000644000175000017500000000031511702101415020410 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/._pyromaths-banniere.png0000644000175000017500000000031511702101415022171 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/whatsthis.png0000644000175000017500000000050411702101415020163 0ustar didrocksdidrocksPNG  IHDRH-sRGB pHYs  IDAT(ϕ=N@? "KHHu6q@k"Q ] rkN@H+kyFٴ=g!AͿ8<Έ6"WʲpǙu.^Yu74Pl®k-ٰf[濒e?Lsi?&IENDB`pyromaths/data/images/._pyromaths.ico0000644000175000017500000000031511702101415020376 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/._whatsthis.png0000644000175000017500000000031511702101415020400 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/0000755000175000017500000000000011734627251017470 5ustar didrocksdidrockspyromaths/data/images/vignettes/4e-06.png0000644000175000017500000001060111560531274020723 0ustar didrocksdidrocksPNG  IHDRGTѠHIDATx흽u:>:u 2*@B2"%$$$sX׾>+c F?|_*\^SK#csO(K>=l"ǣή&H_1"oyH_x|-ks,}$lR3 %9c2һ (\C7ְl't l ӡƘθŹ@/7ٶ;Ĩ: Ca,IdXS7ds]b 2Srs]v0|p+J:i z :OU, T38;K0'jD7e5e `L|;N˹N=Ju" k2ztL9C|QS7 B\c7EQDlɏU͖d7\7hcO:(ັ@׼) 뺮+ C^WPBDSQlV]o#cH[Qu{>;+kn|*6nd/PzbH8t:;`\pkLzpj^-eן7 t:lGug9}c?}o|xǵtJ{kk}# 78a~%P\W B {'C>7yi;Bǥ?uj_Z~ɸ`+h3UT~T 6uTP3#+bg;H>tqSݣ;2]Zw}9aaXPLl2ҐvX%od: JڟR־gi&o <Q/ŽmyA=7sChijxbP&1[ ewq@mgatv"6CGrץ<œ. ވ\CBOy%CYPC%!1_0y d*BwҾ wݼ &״m~5Img)Sfw z_6dLkx|sܨ 5fÛFz쉈AQP'F)=^ߗJyxXDHӷpށk#~qD}*d)Ӻ9L֭]UN/w,75wG0_Eƪ~UE:g)_ōL~U_UЇOs&4*qDDUQD.)e5xY3a=f=F{i07S'L%4}8\MpQoט)qBM^X0f'ߓuOwt=~2 pY9BztY*cBI]@u 2˲~ ?Cu7{m/rmT< tHi;Eȿ_ϊ(yWyar!aR?/Y f]8J ¹ڷb-r]: 6I $`:j$4݈[춯D8L eB2_hWas Υ  -1F춯+Sj;.2iK^nmϟ Ct_ؾd-l:Ze;}cһ;w&Z@s]8Lu(vjdw~({n B YN$ws>w>)<6 [lFƌMؾT1.y!jy<j7Ӆ>֏qS p{:rq=+h,]AĻz;t m5t9$'5M<l_G(<)D!oP!N'w/~_y՗^S>{\JhM`?*z_t:AP!ބ3C1x"bDsA_U^,wQ*1ܔPr9{q'$XxV[f}Kا,,}8 c,X Ƨxғҹ*_vl']L,6~ @oYAƝJ935E,)!aQ ):W76d6d56=:w*}N*7`K*mS{Jw (d;nD! f"^uwOb;^'&>!PZFQ% ʹ`[f"R,, &K3<דCY pT>yd-kB.\o{QS[zZ )&ߐL?DNتPz"~u&?KwxJPkDj˖87k蝄,o}s'5&9UzVdG"?F/7KP|zG!nWLdZaޝÙtD{rɐ9u3~B|Nƛ?,?  : l0IENDB`pyromaths/data/images/vignettes/6e-15.png0000644000175000017500000000763011560531274020735 0ustar didrocksdidrocksPNG  IHDRsV`PLTEݺТĊp`]OI=8+xwvr?UTTOOB44%#>qbZIDATx]kw* sH/mTe+]'iy^8=;fa5T?~_Ɖj6UI1Gd1ZG_Ł__amccBjq8ۏ4 aϱvUMwJ1E"h A}|oun t6F N?Ƈ#[MU!9?""LEk}2pWok~9DmarƩl #:A*(܌ؐ=on#a02@p+C;d i PME@PEn&0`fjѷTe il0bJ3AQ" 1H ndx0#9D=h{ ɳk\"oY,=i[FYZ,T{'? >waӪOQv=2bE#֥gmȾiDBj]S}|2BNhvOQxllc;J3]kڗ%֜C7B I)ę!=|pe~@om_x#XQ6{fOC0ƈ)<76FejqvsN φpU*\ W·Ux\.7\.,ÿ' L"=qw{OcՆgo%=vǷ>2xBo!_جؘ ٨ ^JWOzZӪ6\UpU*\ W}|ҿT#g1`nlT K?k{ G@Gǯ<{v9v\^m^D!އ_'!̡q׽n@ bCMo P-s&Q]ae0}7}36o,j(,Wnޅ<=NGE$hp>7aK䍏Ia B)Ew xOC{*K\b" LSGl#ß#Ha`^6+!5MC'AhV5MG(yErz{DeRlVΧnFa|'.z*q (&n%2:SF)¢K2\!v(4s`9 +E('o)#astsA>'P"W ;6FcybDTknp.1}"12|Y\HϱQq.#sLsԧß@?e6w`3ng__ׯ!7.|?elԕisg;UpU*\ WioWHmW1tsL|F:M0FM5e^1[IENDB`pyromaths/data/images/vignettes/._2e-00.png0000644000175000017500000000031511560531274021131 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/3e-10.png0000644000175000017500000002277111560531274020730 0ustar didrocksdidrocksPNG  IHDRan%IDATx];ܨz) Bl@!1111ynR3c{,>[*j$z|<<C~ECi Ue0M cKoϱ5pp) Qu'H^ l X{z[hI % dMw&~)㮽Sx?ß5@vEOM׏xd z, 4̎Y$O2=0$/_;EOM֍DB">y%tH'~Zdow/4 SvJȠq?@nϔ4u8݃kjj#`Bvvm/NË4.cS0"j߈NYq,pKa^p`jf|oJS1SJ"vj¬< zj\teтqΠCV0X9(a{* FʂRF0>bA hUDVRZ; k]~ h}LgToAPg.5q@! ЮJ[m_jvkiW^G^i(<70nwaʸ5 1uxH]veT T:5I0 #+%iaV*vQ#FM=˨fސ=m??h$_±;AIC_j Z:luv f2d-awY {ru8TZz7APk=D8 ~^ '42es֗t@!-R= !$A+h|@zdTCzXKmQ h4X c@@YX :nAAFQioPt~-5(҉\=xܐ+`@~tڝX c?}2qrqaOsl'o1ꖇXRւ@v8ΙkC\R<!܁ag+pXCcmˡqi@ G=m`-+[C©'y7~v,! a^u] `N%uvuEvFSc[}8@WSUpd p5D =:ycDs!p,OPY`-Ѹl@X\Vւtl>* `=@n)XACVb׊^+)иVkJ V:0d%MH)($S[SCZPLkZdqFT F@X^kiԆ:@ k %@8]ŒRBIr[(o"3xu@oNj;#߽ 2N?T4-P|Jsf%oN7{bb^& tyQGoO؈Q-;#(yz6N )033!<9Wc!lSK< 㱗׆{y# wntg~㽇.-@ϯc~ yK<}o~!?z [w";?V6/aχc!ސ^~Gp{zgVCxw=>*}}|@}>DCߎh@ύN0f8eL<|L< oLc ch' ̓1]s977|n$4^ݣ>D!`2ۜnw+®A7#%]CieWua(`Bk;d=WcdK ihP,.7O@nؖ; BY6?KF zM/8@X57 .HK)mcy_lFJjDZ!`H+"rZ H(>XP1^#,^vb9vk KA/,)( R:.Jun2:q)O8W\ .&4myq xee*i{LK/Zi6te9HD bGp47#np1܊@ Ʀ jfpIBS0o@~dAgѓI[`7h ,"^16iu VDZ 7IϡvUM"m^"0HDHqЖfl"p+0SG낦,jGڬ^dLk{AVGє%k `$m-fXQH6cuZIേGw::3$-NmuI8LVQ7mnW3:^ۆRSrw|mܜo]WL_q%\}૷$dP{|m.@~o ߈nLDiD\M<4#,9Gs߉g@0i#43N>7FP9w.dn`pO70?/oB5<m~m~mmx~A_桷`gW|+;<>]I_@ט|‹h_~~Y; tÍ,όlbo 3# 5?&r~Jν%Ecې_^&MFR3HIG33dy͌b43#6-@>zBlP_ޫ?4?~Mݼ4X3';`79L qT|G<}dtz&`NӾ:3{>>0R5x7vor ^߿Ҏo4~}"H?I&7h6З wsT ƢRDYtsFm$`cd=3&W#|߭nM7;vUk$j9G#h %Lu n%;c%,wGd3x\]E}`םݫ8C͈##_E<qtL8ڗDX[v(t.7>}f=?JyDꊆP#|nP Gn6Fy(+ڒB/+ùݳ?Oi?4KWyf r2 ZedUJgF~2tu? <o3J9G³/fy7Y>t;A[X>i ufAqI3c 8+b-5hXLnt FY:͐) \dae3ݚ$;+9U;/UtrN _$ʍSک~K΋ (@c晟F2y}"vTe#|F5 LW266Ht|<97sy7?Ίfk<|CU>lOڰ"_>\M߿1UG-oȁpC .v?͋ʁ󇞝>>"Fnjkf頑84 0Q"6cOWXf~ֲJˍLn213 BE^=ByM fFKJ 3ڂΡ37<-30b!Fg&2><<#CUX 8HB{3 ƏUzmOjFNɳ o=/ޔǹ|O+OxqI,O{FBxm|\BqTC3^Ea"L=áQu6c7\W9,(F':j`$C2j͘&Jzxd%"G1va Q5 !Gpvд_i^ PBҦ{\6`04Ũ/lB&}il`eR2̠em{,F.cö.κJXc<hzǺg,$P*',2òg$!3 Pn6W(k,3D$.ͦQ%kW.uպz-^?ۭx$k7kIT q`FufӘb0a.Gghx`ضd(U| -Dσyi^Xc`ϻVBK3ւ($(w`<Zs(=1 ?M\v0F &%1Jv~.+%We"KY %(;&Oc3`ǃ3z-XeKK،%WѵQ6ۢ(+q;Rzel- !L/"z\_!\Z,IWߗP,COlV KBYK2ٵ$l,.SvA&Z_B9d;S2}v ~I6K9KL}XEFd-!HHWpx46MB)h69}UwBaEɥz>Q oa;`gJ:lEχ%ڄs1f39U4{P ' E!G_٣(MF[2t~N>!Hv4h,6\ D>ͨ'|~}}|񡏑ح"=]09?a;IzB¯a3揿,~÷~B&z)bLg`~]mV":qt1>J~^9qV$`3]*ρtotpj&}| y{߳BfDFHk^e,Yqot6PcXz~Ò@J;AK)́JT\nZ?UZF FP+(& F&*f w_ V0+P;=d$?t6/g;UF+tE25g*KjA 'Im_Rkفi?^cy-[֗K`ny4DʣҡCL+GֻOң.4"b^c'=``wot]ACmܖTC<CORaѽ®$6 l@fAR`Ⱪ'hCQ'͍EʎVH`$~^+Lx,|6lX { )I@Kl a\\r,o[7] f46Sh5HD0FH]2gxyߍRH]h6-Fƴ;} zs7c*j8EZӛvd,S)7I~mƦ6SG+$qjttq?Z/1YCQUFہ=ik 'R 5zM:iaOO^۞v6n: n۳1gIYw?=~e@RGϽssUpp.h߬ %,!3ʧj{a&ZZƛEre^>{hĽ1vA| 5jg3ɨEU;j"t"Uor wU6Dy3Q[moL |گ6N4&Qng`?fnPճi\ |&?v4|u#ݗ/[l[_'m26m' wd?% Caoc>ڕ`r{Z0S{ gVW$p`$휩tuwxƨk9jniL&5Y0&-.l=3f'pFͳ@IrIŃ~A nMvNs"#dj 8"$zZk w`?zEݣ5;;JE Z)*J:8 jzG7u1@!U4_O6XsԌ7'<3phi:tcU}DϠ03 yto05Fۨr{6z!f/ނ6wSts xGB?~p+~Su-[T/#=%d57>3`w?_)c~L8 IENDB`pyromaths/data/images/vignettes/._3e-01.png0000644000175000017500000000031511560531274021133 0ustar didrocksdidrocksMac OS X  2ATTRG 55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-05.png0000644000175000017500000000577111560531274020740 0ustar didrocksdidrocksPNG  IHDR9wi IDATx휽P$ S l| \, Tɠz4;;~gRM0zԼjD7h#eAtNOwW8ʋ5RK W w0#}ܯsU]!s~N(>:ё+"s7~05-mR( @*O*X%Q]% e۪ @@MЀ%߂F0 C*tMkN(JBV!j8!P4IeA:J4".뾡؅HH"Kdj$cyPe=z VqxAz$$%,MBHQh|u VAZcvE@+%|cÅ.:OD a$H9 5Z❂UP":5)켍z+: 潂U26;oY,!B|N]{c DtY~nӀh(k(Q@jfv=u q^P@e4r2E$8HB;6L_qh 0 !ͦhDW g24ͣX[3 ]G/(=Ԕ! ţ$/ Bi ۳4Q)~w~a|'g!?;,܍,9\E3g0 a~&z?ʷ]n'}//(MiQ_{ǞsMPKqk ~g~f'I#K4 uQҀshhf+@._;(.p=7/ 3 (Ǒ wżZʈ>]|Lt0@C4\ϓ1 hr@;PQ1ɹH,!x߸ g)/yf^p92?#%VP:g⯘\]dil7kQYz_n" /4Mlo5`8A˰ggVJXgա /Ss+ec2jTw,[{a ϱ tT1fKPD50ҋ2`QF@3C!jE_ ~"uw^cmXa6"m}=`~gf?,gU#fn]: 4 I. If#$:xCRR9=ZeB1hP^U?o-,s|jig7Ю]M7=s%'ԧ*~Yqȩv *UKfٌ:0ITޑȴNۺD@ho7ҥѺ}DBx\ %m ,F3&hE5s6^c=}FW0g1Vk-3׊_^wɷ+ݟ2GUU1{챕+S7wq;>g1mhhOPG&ѯaN鄣C󡁃1>^X5 ~upmۭ8uePG "{*! /@Dy^Um3]lwkhnGk)jsi0Y;fgv!g 0h腙W&d{gn^;w\n͟T3O6lQ K; f=o ;SP؏'q-p (~@qb)R XWCi2w QA9Qhg~RA?/ 2 aЀN{9twK$cؙ;,MrPdwr`H@NO}5Z݄>ad8@agfs% L 4J|Ap3li'a˽]9I- Bo v#QvLBzT8@~%[ONbtsF5vl!T!-t|h&n/.JI Ps%,`iI;Ldm̍MsHKFùF$$8 d NvhV PY&.`(}V̡R9ߋ+q:nUt%B)cܼwXܼ'^f ,CH8>GUz]|?zlz:yU7{C**XrcdzsahyEUFi_!whn{㦾~:k}87z^8fCz1'A5rU* Sp,5/ 22Ow^g'"|ݛ%C%Lx-oa-Xh^uoxš8(ǹDIENDB`pyromaths/data/images/vignettes/._6e-12.png0000644000175000017500000000031511560531274021140 0ustar didrocksdidrocksMac OS X  2ATTRGw55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-06.png0000644000175000017500000000031511560531274021143 0ustar didrocksdidrocksMac OS X  2ATTRGk55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-03.png0000644000175000017500000001321211560531274020721 0ustar didrocksdidrocksPNG  IHDRK)[QIDATx],Ӟ[*x|t|d$Bb18j= NwO=~Y{ݩS*PT߾o3ﻎ`{WhmݭuW^gl#}|peqGn;^bZ qnǂzzQå\M /u`f0 "/? 0zZX3L0ڀRa"o7@6Fs_m(W@b`eu晑7y趩\66g{O L7^Ym#v P} 9]/#F@)#[4"QXfT%(Io(bX(s`<ۿ1/`Lw;r[@33Ê-M!|."ZlnY wAb P-QAʿSaZ 0:+׊. Bz[U+0(۶SF!uȕ1BB0HAu-5m6q02Sցt/A]_zC"*N]ַ Z~HV= 6k0c`P+zvmߓRUk*wkO99…\ִc٩[5"oI]߆\M`}>=6ATIT}1)fxWzVlUhU\a6h[/¸WM΃EdRԐPzA.ji䜆Bj60 +d8mkVKjА 87T\۠U BP\4P .h*s4;qQuu"Y,bkO"YZ؀H$R84$.‰ !5t ezx6FHRK8 fKivT cˆ &FBLJ (@ 5 e* !3xv;//MR(0Aa*S1"\ϨOn> Ҋ]@)Q"b\ aoZw3[OTnІSeVEAunNGKZƆ^M9 FAKPZ<RIn(dF-AdQ@7˝Z@Yo 5PILEAh%hiAbEL:LM WΨ)4X_u2Xm+ ]LsAvŠrBGIH4zq ȨG{3yD"JEF\2"̒,@հ$63f -R'AIf0&նwIQbL8V0%gW;K:0om省mj%XQMRi[(CJKZ0V־j&YZٮ*5Zi#ֶcmc&c5ш 6@ȲN7dKw#j5:٪M kWF +-M9]@b@ߚ –3։*0NIԷ'0I֙i^!LN ~TY67e3-.M0c_s4y2ŘR BUKzW~%?B66[7k\ᦌmdk|{AN+Q:ʴzccjcx0ޘ]r|F(CP$c{V{?sU_^~{sU~4quh$?鲏 姼uhK89ß%Jj옯H>IϘxc^$K2b/ti3}^i'muj@ /_4z }}#i3>DeOM xڞ6;5-%KUw3m#G5 7_0 KAc@$@y8"I8R$m)vΌ /@_Q Ӏd|<“F \=zQ;^ Yhڵ篪9g'\zs9SLx%"IzSU:|(gTdse`PH¡ 䈮~v|ꜫ#rZ;\8ߧ^EBZ;F4l ?GŮIEFz~ J=GkEw$kZ<^!n&NF/ӛbJ05(%/hȏLѝf1$t5t 36 C=OrЌDcsS=Ę%نFi֍I@~?E g)ɔ SLgL3nL&;v@mIfk=  n思ȽwHܺ69JJfޝD閄! ?#Q)t.@dC{(iI"S!h&3;0fZ|Zǰ#jG;`%7)f0=eAmQJh.{ac^'!0棫fB!-[ 99 %wHѶ1 iyxm&7^ A9"#  B?\Y˓scMgԅuџbƒ1FO` O+c9ƴ?2@1 M4M{=O!{,cǫx f)Mہ09'98#r癒[lFm1&q H2;hQG )e~t‚\.뗫 LZR4k J}}{+F-q񊷂Rdטa%RJQ HvK G_1F@ 0'na t_-ιS faatr_ZVΙ:tt}>:Jp(DЉeh:[Ziׇ-S+;;r⛽|y70ān6$*fNW;A2❗)`,ll2gb~ 9y4&RX-\+`~vzRǕ[em[yG1}//bJ1t9aO5ciR7/dVsiIj6@xSRIDX(jufMqtv|o2:ѥ)mצO^Bӡ>,<D6B2Vb$YZP#=QWo|!0܏Ñ) /Zξ[T/_yh+jN!ᲈzY!̙CbC1N|ɢ/6Ko _#R^6Gcvw8h5(B#@3 A\NFo3I// 3eXQe%9#Y{_ynox9jv ö=C AUW^ ǝ3v%Χ0mz>:7V*#aѼ1@~AY7cfIV FC/BC^R3L8[RjGTGrj{ߎ9(&c6Ã7򜿰5`aG|pj0%Ntq𒖸sz|W5Q1e> GwXcf~q8S~)t*~Qo M&Ro)\Dr(SٚDE>TO1I7G^?WΩ; 4}B 'E&4-0z'iaR ȣL_4/ G!J0 )%BG!?XcR ].%^Q{nlJGs-9L2=N3xQ&b=^4fFqjɥ!p:Lz_c!W;:m~34@{M/W=oJb1&Վ51RO,$zƃh i9~?AL}U8ߡzoPLlfn͠|:Ȟe`P ݾ # eAQbª~'Z0r!Ykh$&T#?HtǁzoDZ6|dB^yTùyFEsYpoY ~휻Cܼ( [p /JҢ^)x̘YĎYJT[[&+Zr *)3#˼]{4\ozw̜)%\Lȝm Vo*+ o'\:zީ tDRJHi}tBmN9bzm¹* "ޡ rdQx@l!Pfe#xMQ߀PQ_(u8g4Lz;`/ A93Z.=PG0L[WYMa2$?$J#KA/^r\g}z+ 8x[|B ?%Wz52W'm)z TBIξ x'PR>z|Grvўf냠Ecr=Lӛ!2krTsoj)mF/ KUWkr~@jOIU5 |)cC֌&o8UR~]hgKc7Zs~7rvzXz#\Ntt3֜E޳QUUNaKv9"f1zlk\ۙ3vAٛsn3񾠣޼*Q#CqYQHBe>[3#IٟyVp巌cm\BuJmᡂ4zî^yИ[q#MkƜ Q]aF|v[t27/*{q/I= 7|` 0Gi7I=ju4?į{dYXӻF";糛2T@5a&_b:i"mz-\3ƜtPçFIo?ƞv?k Xz<0\9ԱJ*v="^k,Fq6\ qՙToщ 4Z!eV}@@.25j+a >VnFo ( :F٣i. ٧@'05{34fNus)B6֧lwzl3*Si4}& FCcgz/"8˱gySخX"郌#>|a ?>Gp*?d5?] {A 'IENDB`pyromaths/data/images/vignettes/6e-19.png0000644000175000017500000001723411560531274020742 0ustar didrocksdidrocksPNG  IHDR*PA`PLTEǰ֮̐qq`^^TT>>m44))7))IDATxٖ D\hɦ >3(@(A{}f~ṷ3~ž}eG7|}ȭa݄?8 7_;翥D H3>.B@pNg :|]Coe. ty48pM`-H4! fH:p@WevI[@g0isv@9~qtG ~賣$;(fN]cǠ$Ot<-Zclx y(>%;kv66.h| `|gQ̇Nΰ6xwJ=hbu:p|4. 'AGL^zG9NX<+9Oև[Xt6X0A{0|Uw<!z];@ jӊAj`Mj*_#X:XWhA| "8_ nhw+>xx碯pvr8O0^hm]1hQ/VQ.:*:C:鼵6V:!t g=ް0P(R2F_~hk1`-7PTZ#6F0CY̨j+q`pGYkHFmO_hk9UDm(|v4p_tFyT(Ԗj T`#x605R0+&^̋UpԽooڽښwX}W纼@TPڏ6DMSP-?&oɂfٯ !om~`P PX_(&XQ*{ȅ%ctPp9TF|HvUoqb`" o;> fIQJ ]o4U#G( QKvUhB;S V<2{ E/ݔaҔv߷\(' VĚ q_vUX C}|]j UjQpgF*'SBr+B0 St0>д["X_?1@ۊPw[xD8M \(H;6YRDC)ߎusm~BКqm 'R6toP ^{D4:WM ,1{&9â1][Is[1)>-aڽLYU-!$.S0)WaZk%ٛ E+X Z!Pn,حxsbu- Ɠ0T/Ft Q6K`}Nǔ ̩\rM ߬߹t{bXKBKJ R}/ִ D,zvqhϖVВUV ]/SX.>^B 1pDag? {=K9`ϭ;阐>$T-XgZ_33YG cR JE~X$ pD6(Wx|!d$=x5M(ﻶivyxpXOWKG8yIS`(vMv\ '}K%U E$if&1| xzO<,ВP{f-IM xXzbH\`ĘHU0޾ra4)âNT\'^o AOG$(+Hk񠕸d5! o Rn;)x|  ծue"bb{(򭿵{njW>TyZ~^4\}"@]E@էSx爇]@]v vڭwxCî#?] nA`L֫]@vhYp5x*)ﶖZ\e|Z)(?M N h$>/ oF9B#`~Wp-^qGlk3qK ߥ ֻḅf'*^.&7-P7H|e7YqQSIR}c:bHo^?f3'Q &X, ]M 9U (k'uKb) b|cA ͨR.E' 4qq 4LSꗆ#~ \|T(c^ń#sv+gξ/s}  iq 8ޥ0:\^og; (HtSoG<+ĜC,Ghb soQpߐK73E][\ C0MߎySܛQ P׆#tvKZ埴b̌]]]c`R밄4.oa{{Sۉ8ToWus -Ż<%`cqGA` $=gSpϫ<ڐĸn,|88 Ax7))XXܾxT"a'*^l)jሃ"A]@Dkޏ-))ȖtbX8"5WSL -% xP" uͧ.JfJSc1n"Q/)> R^bbzሣ}ܢu zMWSaPE-dYњdMS=ۭԹtSxl4~؛<2iZ^S=4:ϲ8q ٭̹t_P_ (cWylil5-[GklmxX&w.Eռh3ʾw.])"pMC9VԱËG̛ogZzDų5Zz~ҹtT3EfL$lb&q4`r m;Tx!6Hz(xSɣ)7<@ LΑ`;Mm(xU~I{k,.. G ,E,AjȳRpĥ$<A2#-$tdiC@@=d ^x}e1lL_.GB]-B0AJ%8<kwV'A JSc1ሂ!n6;c~'_^RH"^eKSD ^`=@ ^IEMyuSkHn_A jߩq]@ LU99#}\b=I[<$i⤕cALTާ@<(ua} y^nFx:IU//HMGpDYW4=&*XH닫W$ f35/ ՞$[(x-A$qJŃx۹!,mPHViJwLD?"&Y𚭖Ӕnbpx"nE}Of`4;1qBP6]uzHWYb#e{U< ,Գl,[]ڽ6YHKHSc1nTx=SVe,x<䆧,9Y]IS67j|A|rCn:}5-13^`fkb~f7l8 &Zv v=tk!hod@a}}ߵmNA ߣ`;2.@7ݾˊFK坨LQͬū^Cf&@@w%>v8% <;Ƣ`UJkZSTEd喒 .0O)QB|N (WL Pp5? FԊ6aΕvi,^&}^1Ճ  IPHT*(^`ji*]RF0%%+BqkJU!z{<@mi$Ai޷?7z2yD ި,DhaP tTIqW< Ů/nEX^`ND!B<I ?yAsJUm%~cD 4aJW/Q0kg#$!ydt}H+}8FIH05k L BV3B`  }00%yV8_>A[s;O0љJQc&K暂k VՀ s~,"0\+D06ό QE5l : AA:,p_WobAPj<1{mNgCZ^vtPC= $3Iaو8KxHb2OF Iy`ǟ輩Z(2gkumj.7.ݷ)Xz NO//ϴS3MtkE,( BAPP((PP(( J BAPP(( BAPP(( BAPP(( BAPP(( BAPP(( BAPP(( BAPP(HB`]!,(?V5]O^h_rih~PFenD4;GQIENDB`pyromaths/data/images/vignettes/3e-02.png0000644000175000017500000001156011560531274020723 0ustar didrocksdidrocksPNG  IHDR>i C7IDATx|=*m9@3`l, aa1\|L,y8b~2O{[]կKU'" x&"D?"?~?[5-eKAϋj CCh=VG_@!į2e_wn;.uC_%κIty:Ah,,knD҉Qy\Iё9&,U/lRc`AOqs:#, s )P.q^tHU<\u_q!B;+;z|@xKfc`!%L(SJm~2SƜڟlvLd"(qs=!I{SB8YM7&$0q@h.ॴY[^֒`"nRBT \{:UKi$١Ls%+@F-8H Z QHx-׍V"heإ^F- '2`n۶JSys1'.^p9\[lfXƧwXi}.m|G8@n 9270Ba S!6}*#sl+)zvyPa7 WHc/<,ւCOa9zcd `^9x{!ֱ`6$TM_ v G'as;G\KĒhc8i+f+ p3p\P]iGS ܃<7%qBz ,&EBvdڍmJێ W/lx56:V1{k~eq J!\jNV.ag-}rcQ/ Bۤpy+( :h5j`icicyaIiV ):th8ڼ\չ[#\DvO6E )s䘉.d&m}:Ɂi' x˺x=%WJ?8tv:LK{Ʉ625܀d_`/L#z)Zs+j5<ւv k_PEG7M*P^K)ɏ]RR }D)ώ%R=@L(x cJGWj[i@9[W} }fpx/>3=ͧI6]yu~җ4{{ETo߲y."ͩG)o?f\7.;A_@>X3wM"ҟfWeWBv#w @vi6j ,FU hսw"kVN:QvmΥRR)˧WQ/+ I4K.9iQctB6{йC?5'yTFP?G w}L4:χ5<:..~R^*_4pycItR", yphP?i!#qp" Na7O9:6Ațι =fqK4-@΅'M)G?<9WBb(iBmpaB˝Kfuak" sJU0v9(+5CXd)#`Uh0c7a2:KR"^aʾ*5@Ձ&K47^LQ"JDeEuԃ e @>뷳9t>MOY%? w^r ;()_b@5,ЁR^84V@ EcveNcEsn#p ŲH!qhAX$#x(!qbX, p3wfuvH Xs` DX3`7( ºA ,l'^q)qgXX*NwI~e8-+Bػ^8AfҖ:"S b88̡'@2Dا xyxQƳl@XfYdTi\cm8xgjm*H.:30 ڔ`7L.BǺiCH18dqvA \f6huϙi4X+`7L nC䩣RN]ઞqQ,l '. ht|"'.p! ù s/s|KD;pc0 ũCq{;JSTDžyB~<N s ZϻdMMg*\`U5\jJܗ#rࢷ)ٹ99V4\SkSiՉU?7ϔָh ¢6.75) kZuUX]x<1UX@`l,MZ:76@@b,xr ޥS^4:ag1jbZGOyуS 뽡Q*F\WK zWat  ީ"lk*ؐ\*0 >0ژ}q~?{ ǏuAUFqǎ@Fd3!1WN%x51(xUmj F]?PɎ>"k) <⊳C_;}WK//1$|UߧK7~ u][vY{@]T%G n;w;݊컋k/]p=[B<yN^zgO;soYunC;}w/ޣI-7/9ʘۊ]@7.5hXM To= |ya߸p65o\ƲNԊJ}k,/ii@P{{Q%ܪ52g*kl;U]7%~ ,K WXA}*߱}~|QIKo6cC|8Oޕё~^Fz@_i'dz]V֞3ą 3N-,,鬛QXˋB_7FvLVRAYAz'czva/NgG1 rׅ=F0ݱν=u X ϡxӽ /jx[ܸ5t:#UESzx ueП.g$ YUI,:a՜WIqGyP@O@cr3a{nvJFɠj>`7T@Z@HQnQAuGs m!|h|]d 8|@ύziJPw!_ڎVZK+@n!b V>=Wg<*{nQS8R@`Lfr}h>MVPU=ؖJ VݰH,.v.8_T=senu"_̱n"NFo&={T7RְmAqݰ^ؙ'rYg_y@CJ57%Bj-nvtcKPk5q-%dk]xXWFHEccaҭR޾?&IN V2ax_`6<Fe@eٶm=d׽4H `erh) <5â1B>*Ye6Vu 林쌛4";]v enc׹a~x .\r! @0 )BՎs+c\a*plp0J\Hb>N!S9CB1I-,Y)l@ÌֱYx|RHbɡSZW ڗXVK”B90+۶_10?>ݳC.4C8!3+̙A7 0`3X1%xl&@(Da1%a)mpy1+x6j£D z+5C1%ÔCA=dM,eVۂeիXA y %33V"e-RJA 3(xBܷD3fphw!Z gꤔ$hB9xC*nAxH3eyYk]ւ,Ah[Z[Z#qe݃v6oieruUG\̫Üa.q9vO1""zV>8jЛXuT*@Z{ni?R=o:FYq*\K WZngNOnB:ņ  ԌS8g-#V2j9)(ۧbJȵu Re^x{%>^FFx/"XL6{eH)YI[^x}}8Xzvo*bo8^wE󽕩/#>6>3%l i:sS73vi\_{7y<|ſ˯$$BG2ޣ'_+|IZE=a~TUv0|^r3Z l߸p}IENDB`pyromaths/data/images/vignettes/3e-07.png0000644000175000017500000002366211560531274020736 0ustar didrocksdidrocksPNG  IHDR 'yIDATx]U)tm `bcbW\JZIWV.E.-}z@|~ýI$x_ @\/|pgLy,Rsw:kw-mYq}V^E 7+yvCFf3MI]X8oGJM]*vM0dJ+J2*&[v1.YjĸBj٭wRfXi q8ՋwhUUg ZV%>#YyF%8[ѕi D2ݿ@-"*[=AkrYn,Ny}x,541 !LL/{l)!A0K+eԑ҆i̊EӺP EZu+ݢ[/neMTK)R#n xt+ׅk'1Z`Ji:UX\jܬaWUm{XDڵ:t[\vC1}>$AiZ{VLi(=&(&q&GwPCtT ;RvuU1\wAխ5icֳ*5rUؠe4f%rk.]ZNőɒk)+}M5^T}YՕ_T#pQ?/ɭ6F(&ChyL?{Cki2ZޛDseEݰK_lcJȫp%v~at4%\*M"88_ZQ5nؙ@;Ҿ-J;E2\T۞>jl1Mi׋\.۷bYtRnX\=EeY.B:Nu-[rDLKl%Q%щg2g2rſ)raX^z3A!U-UaXgV.2Hta5_\L M%z9 % V.M $:T*EA6ؕ^uiAkRVƕk6$lۆ{6͕Rߍ97~[#J:e[Wy,1Efu/KFxӺT;r )Ur)rՍc1[mzwiꢲ>pI x>b#RLokH)D *%B*d,VCMp'AT+ޥEfO$WW.ck^nVkXT 얬FHoR QXrV7z6nX";WA5_-7IUu:R*cPR'{UF$CHRF֌#WHb !%uZ8z jCZHI1B,u>FR6ϽZɸ1f+A8pR\_M%#֡ZfcHd]3ʨB SHjg4mR{g_ %v2ë>$td+>!c"&*!χB27g3re]tj9kkk3[AQ]z8P76b.Z0ALy!7M0F$>5 ؏}gxk;^:&ޕ|/^,7;ו7Qǭ?~m_I''g:????????????????????????????Z@*}N'WI0X-< |}V okSMÃP-q#E߳6-=JC9^A"GgF]_eF" {O@B"?qP/gz!&Ӏ:]Y@{+orɷ'Bn岹ҭ8b7ouRs]=n/4ٷ8qAf(?o.9ɞ^n =w6wMZQnȴ_ipxfh:s>0XY90dؚ5+1]4A Lp9̿ٝku, åךc`7LWk$2/fVzYD_7(;s1xW\I6޴\{%oZx+6Vz'Վdvek$9c>+_ #Al9T%/opi}_.$#Q[dzMJo-MQЫb)x$;&JSQy|׬հ.k:pAE$ â&EsIߪ 5_e.˫ c2aPg.^0cb=pnPg]+M闸rT&)\=rٽ{҇Cy(ɚ%O`1~teΑۇR~i]7Kr\.O,ˬ\V, C)L2Z^r-/S5WՊJE'Kx2YҔevQ6WEe^LkX,hi:󳘍VGvC8FEkW]eF8' by t֫8QIOvF"W n4WI\:ú_.&B4JBPa\D v1:˩f*sDSw_EJo`nu6o@^T% !oI㉞e]j/2ZdY#˺H&ՌQŘn~W6B,3,*YkAn,`]{DlaP`)rrI%C/sʒ k2`itKj? mPxCV}?6 'س 5:\.zgz:KU=RnFW Mg%٭-dEK`#=sK5Kz8-45Jp-MU'cVbLuZ.ރ`#\Zb-p #45q*2 U3taYCru9w)bT.n=wV-l#U**im~)3RB"2ZnG-$CU^RYRH`_e:`,!O#$1UNӯӶx 3-s0^r:RI-U6_o%5fPR'HYԼű$g8Pr'/R`;I.@%k%6|Kn%ug/l>sa ҷS#Yef{ )(l^e5՚*CfɃwY$9cm o-yB"w*rK1wSkZ|?QcB7'87MQ[4TkWe1 Ӹ[6|W-e4H% HLa|veͽG]}[XԼ)cMC1_Uo/Z^hX&6uҧBb0ne6<'WQO1`V- S`^RJ 9pd:>eVk'{Ws3MW֏Y ^c^?e_O _* '9Ł[5LxV_[t,RU=2VÛGn6dÚ/u3}s ۟p.*+uf,.!+//s o<ټq=RS-NNF}6Af"~ȁNg&5\R^7_KQ-C2 YhZ*Un[tŭjp)E1Z>AQ}+3tneRL,t[4e\5Q (1Ow)Ef"ՠ/Yu:fi&[N-n͖5d\jTzDQRU 3~ -Ym:Bobnj@]WJg[k_.92__L6h*Ge\T-^ZNMﵔԾ/\̞23\T{_ [w3?zL U%<;KqI`R[6ٳ~fΊ\-ϛiwXc7Q8%3у\.Iuamh.G[74"io7L0j:ՙVRl3-Q7D TVF'~g27˅a唪{mI3G7\\D߇,*1ѺKsKM̉֙°Lnh5 hP%OI`Sr'M(utv%شvk64` 2WS yǒ}SjV?쌀 z9K֐b\U/,W8>ڦWzXݬ.*@pd/9Jfpݛ.i,yk9T_y!Eue9֥JMvP%.Y/`UNKQ%V& (#Ӛ/fVKfmX\uY[Loʃޖ*y )E*ٸa5R|3`ֿ|#d[XsbpZG1(=* {9ĕх5c<Ǭ}@:CHIc5c 2jcZHI*]ȑcta>!]őf+T3dlڣ^̞DziWRuF襑= \[e1|79Ƹ Jkbۮ)gfõY8{+׬c{.b G5^#5Oھs:<Qqϼ~coRI$WwynOU})?\«E xOj}t #9-+3PRHtߘA>.$=9rX+q# {kRppg{wX8_'YKْ0o8ez~ī !߃dIcP$bozlw'jv;(LOfȪ\鞺g_*qdQnS5{sarAzۅ+-܏%Q8+_y3mo)A_ 馦mבp)\q 'd`t#&Ari{]T|]Ÿ7(jRXg_y!oH$o J0)zR qynmc:AƎrTuLs؎c1ʁtv%u/ٺq&E_{ O<)yKXuJ}[t/%!~RG+=;j4?.ab@Sj+=}RtiJb蟱~ =ǥkSߑĔ9cFuFf"P#po:S5hBcǃnmmc{mA%!U%~DsHѫ4ۖ PZՒ߅\Z8A[$*I ?nB9桅ǍcOP#Ak/0XC!jL_E' 8 Դ_MU!M Ax𗧂-}h i 0ep L:}yeDU##aM#Np] Sk/(Z&8lr(U0XyAiZI;9VINpJl Ω*,4*,:/UMa: gÁX*4$LNYMǰV7):Xyd ~B-9I9L8 j՚v X͚c۠WCp&B$mT8sPm-AKÃ;)F.q7- 7A)mZ e`<$ HOVǶ'u#݇s6 KI8@c 0ms9  "P<# t+1B}EʱSfphj eI Lp]r܅^aZhQ`K!o%B⇠g3@gj-jAJBb.Ppni-ov !l%I("0Cs8a`0h|/!,Y ˔ WiiL8 mswnۍj;o 2j7yY^5{6Ƒ m#L:58ȂFAj݆NJ])hXkAr# agdiU@x n, <_gFCex҈>\9/erV!mIu@ &MnA%ƦO&>|ꛜ\M.'@ٴYJjޔ3A*A(W-׋vs4>mS9AN[ĒF.0;WĪjn2hCB"=[|BMEp&$o=0Bb[ cǼPUP jH3D|bYZz5| q" &(:vBauaP cZ}9T0fR1 jrc2Ig[c(1aŧSBuH@9w3cah(ڛc8aD(1)Gc޻@LCNQz`4}4:#ǶJ2!\4l)({c:b5Xx8h6uZ: +7/v0k:it 6%U_AnCZ0\5D8Bb9Ank >ZYQOp݃"Р936&h xj17i\ Es;2!j,X߫h`pK T2v-1]LY -.&QS 0w`4 p b ,0 m l[v& < &$J=a.!0d'_"HxǸD|A#P|K뎘k@L1]F@djPJ`)36SBʸVPE6ډ  RҠjrA 3(-fJ;3Q B0kTfP> P$ [n/Ʒy-Iy*E$,xg}7L\p%,*3/ !"g3PBLo@ &6_q李&88dydf'Bg1nBoU~Lrߡ_O p#Vy _D5Gu/ #j!M-+Zi])5/{gE]ua8ú .zI{NO4`G`=&oΈT}1 "B*@=PGNoaj[n*#Q3(B'*-'@`+>N+G#`<(cQ;- ֕N؀`7W@ G_('EL;;5j]L@&XaA}_tTZ׳$-Bf߶ZsT@cgM췀)8E ];"1Edb3JAK'6k \A+ּ[^&prbD ^1@+7k<b« N(Dr#SP !vjbl H&&\~\"m2q#hhҮI_<= Z^+uiTDJ@mL@s"vl!4.kۄwv:JjG6Wi!S,Hq ]bX SP9'#eo0PҜP pfۢ5g |ۙbZ"?\kvER4Xy"VYU$P2zl -1$©"n&2@j}#\&RG[#rs>.yEjkFOlu{1Q+QFyF@T { a2̬z>ΈxH PKC[EH1^3};*xy fQ*#-` ]ܢUy6#32 ӫhE /(a>yctn7׻(Y`e 'DiNMg!Dp!;؝BYqL !$ME.8O B;dCTZNI:(9߁ncޥR-0"xAZ|$VzL0"D=P/I'r1 N~;j|-1h DE{w@4vDY xO@eL`և۠#($&/Iy3:S":/(߿,s*G)W~OO>5Z9i !߁t6ڳ ҢF֙#+^'wkO|⍔R{T6sI߱D_m~{7;0Sq۽L?\6.EoFgڒ0Fo#3ےb}V]5IXYm1z Jvu 4cz&頠>ZÜbQ  O8>k j*oTD^(Hŏ &^ ސ>z#(`KzCs%Z{Jtu\ޮQv<7tSPv?{Sx@K %cLO'!*vU )%^UFff*@lny^ߜ0e:O}{b@NHk4zFu}W䎳Bs}+q@G%m;`nEѴvĥ~L7 P";))qZY> is(KA^N *4# g\h3c:.Z 85췀&PMh5a4 t^&/P^ulS^*+q)ٕCPӯÁ\JܼܓwλB tJ2l6q?'PDXE8G3T,"XpN〣oqEOQ Ҁ 饑+POkLѧQ ?C|V՛hya2-G7AH y:[Sj8h5 Af*ev^@Yfzz.h:yΛ0L' Gw\h ImU&Z }M >6 g䵗1"~Ө8 sc4x#ISP] B}!A0v0N6h9{PY|BcGJ dVc4[$91:ձ4"L ҫ(!o+ȭN2 F~} LTe""x7Q|U)av.$#&\L!0> Pa` d![pt{!(EХ xU.'i!Ǯb쁵z`mwՏ[r[(\7ϥX̯U2U 9Wwݱ0AKGOlmqvP㞈BvD:92z}(ۤ'Ry>.l68`m>:3#BBGPbwNq%aհDc1@]]:Ec+}mt%"zHcF8Is[/. G\F2޺.V{*{Ծďv-o/чMsԒCgxm+ =K2B}!ye37GBOSh4ߓSRwHi"}vkkIENDB`pyromaths/data/images/vignettes/._3e-02.png0000644000175000017500000000031511560531274021134 0ustar didrocksdidrocksMac OS X  2ATTRG 55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/2e-06.png0000644000175000017500000003326111560531274020730 0ustar didrocksdidrocksPNG  IHDRsъ~`PLTE޼ׯҤ͛˕ǐqaSN?8t'nmmEEE%njb6 IDATx]kwk]?p^SIPd NK3fS1fclI䑕m&0wiʥ.~aM.sA.m3X^=50]^s3pAO@34hɥz;,k*?>.Gmxuŵ\:09uQ]^s\!]l&AuK4h5O@,(Ƃݓ`l,(^ 8\Aq] `>Xy2쟌c heAeAeAeAeAeAeAeAeAeAeAeAeAe &F+xh&iLhj,4 o o>A|^ƲM@W˙t;tlwvtSnrcOfUm.],5V V부9烮 @ U 묜riWt8ұͤlMs,@A7%m;}˥i.z>gڲ).]$f&]笴\t-krRԼ.oӷz zn: z z9Wb"C١hvh?1;'f١OúRʂʂʂʂʂʂʂʂʂʂʂʂʂʂ濰,6 3L̼ex`-  Bc;Ƃ?A`c;Ƃ }&55(fǶ[sІi~&ooLPA]_2>ukѶ z<4?d}use'ACOaϤM{dǎة͏9lOO v zk$<tw\rlm{ᶛݟM b1;4>;4.%/mNDn/ f|nvhޙAJ+ * * * * * * * * * * * * * MM? w/vI (%l.c΅``~sA}|:ژ3 ڥ@wL0j14gv2v9 ؙFڎz{"t{&=} m{kø=S:Ա:/Fk/ʂʂʂʂʂʂʂʂʂʂʂʂʂʂ',yjޤ7;4_f;ͩc.KͥnӠi&vw*٠ y= z(@\˥=ݴ%a|vt7S\f,KuI~qk"~3Aphr-h: ڴIP{:L٠xm u^u]KtKզx6jS6jS+Ū/,,,,,,,,,,,,,xU.Λd>)y,VIPcM:|.oay$lfX)lOj_kS\NYiϹtRYz˥s{*N,kzǙxg=? 4=?=O-X1s0vt)aFB7s-A/\ye9hiY>oY+ݭz_=;4sfp|뺎/֬BVM[\])YT0 MsuY``n / P5ȯ˂D k* ^y,),ʂW zT⿷OާxA>ES)>Eoeoܧ^Ʋ]IfRhMO~>&- ? Hr.XaMzjS5Ѧ8ۚ4/^fm)/=_ u.Zz= YGGsyL^?ЦS26@17y27;c+Ť1m^Z_o>,v~. Ae = jOe0T`"V:{+ ^s,XVʂ dM/1)c$賌9>,g,[oɞe$wƂ`X̾$\6Ȥ:6LR[Bv])&@]Po\UP.rm!Ӡan.!5\Ps]UiŶPwCl I|Dz+m{fK6vssS znIa~{,= ^޶9y?t{)@A)];nJCXwEݖ5o"xaN,)CsEͧS4D;J1i k߸R!AsSTVЄ~ MaG,Gu2$[ajޤciG* ~X~X`h`kW5/fhe7.̕?w,nTAgZߧ5`c5 ُǂء8 鲁Ku.m.wɚfK9.IjG~GƵ AGajvW.raty@۹t .*.Z,w4rcgMVJ؇RV ٧ :vԉ>ֵI`S\f,PHˤ&LC.60oHGh8d(io@b{h: 42_f0 A=Mvl n@r'#7nX-D@ah,ͼF ,c١55kFh ^tKT UY`VʂbzT* M}`ĂʂeAU#̛g5oҗMx,9e v,S!\:RKS!rΤi&vw*tK@AzPnO۹Kz iK4h0$Mަ[";v2wmBa 6R:mS|m$=A׭bSuco\P6j4)6~6Ȧ}w,Ww"z>ߺF~߻R#pԕⷲ`cXY,#V. M+ ^ѴuYphZY,G4,xYdVʂʦh+nXri}X.UAK_aS|,}56`S˼6Wc&@^baE~VXcS6E|MqI km1+\:.L=\jOt*6h{䚁vy6襐n٠[yz@ς^ 4rnp䋠zt/);L/ƒgjr/b|}t;gfgu4׳j֕⿣/H$,xa ʂfhJ,x]Vʂe/̂/̂/O!M {RS|OS4)LKOS-}o)n򮔺Or,jIC~lϥ5[sWms(.q \yi gtt3 0 ms|).m]v9ayiKqIC.LZnLڴ̱u6m;t_rss z-t{]On_iST-E۾ӳCޭMihb'XJ1)\+/sX[}e?Ăl^=k j͂se1v\VA>ъsYX_Yk,ȡUNg,9' VY0iJI46:ϰwe10+ ~a,0~{:`4 y) l!j$e8u4f?+Y {"Tr >)S^J~ nOEvM?}j}צPSӧj 'C `3e/VħO9iQj7ժOfȂmZV~\eyn>fVvI&?W}=\ */mzX3rZIZ4n'ASC!yKWAOEvl;tٖ==mW-IrM4znz\.ܶX[]?r^sV휟z}zkO{rvA`"a`z?m4hI#d/^A/[IUsvE8:iJ_62,Migtf uvЀi ҇6Eh?E_:B8DGM&b7߲6e&t-晈C#|Ύ0w5fc'; lnyd1T|X4Xq= XYr- , ʂ_c,0E89׿٦hPYV_1[-dʘ3 s1,ڿBn,gbM&A&ֹdm&f8ff8߆ynvl x(ZZv0{7v.7]N.Ժ·=殐)a=sfpQ}s*AsAm.1 ^u?t{)@A)];Osا?Y/f/Bͧ{j#|RHR|a4,xa؁/cG ce`  lekcK `uB\ersX}j+ ^Fk,[NY6{,H4t Xf!yʂX`piY=R=~#h{޺[~%[_ ڎa1PH}Im.BjKU.sAK:Yu< tX46b.]mMS%Jа*:c݆)а8kY;LKsf.h 쭓Bkv:oo,w"×_)j+ 0D,xX_&}"Y͛&[wǂA~g,87Y9evQri}lf?(.yn m< 9E^.ykii0 ?mK<ݎMhC.gfKK&5Ch9>u烛 x]]N6jt]MA9hO6 MΫWӠYM6lsu# ~ߡ5muXWɦhkl.VT]aal 9hi+lAe/ӠZli55M)$WuW_jMqOM6'5믵)^NǬ\sp2|Ώ]n5G9ގӠu.4 z Aa x,=O/=Y""hqѮ悖*OAat XrlnBrtUD ]}m3ݬc~pȥcri["ק\Ї=z.hg~r z.@AmS@?Vݼ[~FQ,J+ * * * * * * * * * * * * * ~Ikd>)kݔ'=yFFHkdiL5—ii0[m _yovcWk4O@4ȗܕr^/r̤բ=,Vjqhc1GY z *@WAwt.SvS4\@O9rty\EsNnt5X6Z^lPK-㧡*c_L/NOj5rO/ώ}dzIJ e}' ,.$$A~2~tkZǓ</o""6;P00>@&wlWdQ/u5)GL~3Ƃ 7IcR*. ku! 0ARao@ JQXpW(ӹ|fljdDXNf".D! 0I1@Et#YDFH$v  !,b(:COhUH2bEGD}c3LkMFtq@NPFHP0N5P T5o(D>uT@_0 H,D0`l,$8 Mk$vtǎcr`@1Q;3,E HEAH Ј(F$a)Dbz$C|(PE "|RI6&pȐ1@t!Km %Up#U1(5XLziBn4MT1i BG`>'cӂDq#|4 4H#Â#kQQOQFjTđ UюIETIUh1`N( G0ȀDĀT8H~5D *Dj@:$!>(0=J>"B9،¤TÀ@THEg !rCD;Ȉ}M^Hش$XHqTixSw4^E"*1r%}H^lmp 8Vx Gh џ qieA 0ƤDu\Q Ս T 1Ȧue Bߦf<`È]_ 9VCaHˮiCL6q$fPcO~஁+VZ)QAқrW<\XߛGB<&;טQRln%׍QC0S34&dR]Uܗ?l/0e˺T3G3QCp'!ZjycQZjfS1c{;WgZk- .Zh^ҙ^HBAxo23kb39̪>{~pOBGAbfiHkI,2ֻ*%Z',5" mM+cE=F cagc0) `CMQ 6>P 2\C=S=`A._V7*d"2Q7W{T(eZbf Sޯlʚ#|M l!$ٷ;,a%2LolViHraQ" QT0 ,$B XIO_1$ *AI@VAj+y%R `Q%k@ٞ1hoR*D,/dUa`z eDVAdPG%ho4|a"!RD)=EdPF)UGOa,(&kb1DP(TR B ^(#AԉF=R"-H@X!)f8a/z:Aς|,[ew{rE'XIdئ HPBNw`pCH4 uq p@B=z+DAB© P&H,"q;XHOaGqA/=9Kr`YzDa ugODX^KG+E@%׬AxdA謁DXpH -N|Gp&&t:?XǍDpΆhB83E瓼@06kB%R\E?ςH. :%N!D9K:  GDH $D"V" "st1J"B:0&~s!1(LaF GP,L bvWG"11";=7pJi013`I.Ț``@6,aa4"a_ ~5TYِpզ5< 7@H؂$k&mC  O`y0Gm[.̛݀{X*JmX:!px8/jڬ5Ikeo2X3֌06<6UON4 ƚpu8Ŕ(ԣe^$IDQQvA-`*C'Gy ]p-A* ^чx[O _wKe0%:ز ( & ?/ Z_ob akp<%ۢBFx>ˇOihyU4}_>PPw;'*(6RaڨWXk{pWWQ{]dZ4@řN$?jv O-EQ.j͌L5D`sHgnۻ'Ŀ62v.ܷEd Q+I) ]zq7>oC{}!ENuf0A~b$"cx$PPrUuEJ&:{D:M~EAD.-@DI%o=]Cs W!<Dp<سro JCC b l{8I ;L}v  AHJ!I"g PXSp␌ӰƒC%2C\6HPuǠ܅D}(Gp78 b~TQIqd(ZGBы]84z}AEҙ)e!FB C4"p"A~QFTreI4(EqSiOgdVU#c*V,躎0XCr%R |9"&'ы#%9 hTOƱ9(.:!6G҅i " sFUIRESXH) āH$̜+ }ca>eHIe Mǰ| kMp&B,40?|`+RX|BL.QƐD`⃁wX`{LV zi!osDHyɍ&-sB"1^=c=Xo[wԂ0fEByv1} J A$ X٥UJ[=&"J=ks5 ,D{ƫ]h(KeM>CbӴQ :L Rlsc;bɌmW [}M< jEyX,15S/ xPwmixage ȦCMkambmqgYri*ci`ma!&aA2dܲf{@") !HuEϴy+R<=^9QK-p1%y9O ox:l~>1הI|l# |󷒠I{fxecwXeKO"=f*^!fT\Q|ȜeAH/uƐZ2FQ3{+|zݡt!vYu RI,U{׏<;!Gxoh^*v ! yw_"ϯ11:h7$WL;-$$'gr&89Lp,0Dd< .}>XpOuڬ6 TUCfR.B !X;\zƚ` (wؐ{ n镦X*;z"`SDDYbJG 3z7CD%E,˲^AcTD"K\B)=WTJ R} oKG(+G}-e&ES$r߰޽ʀ5DyIP/2c|PD!S:{F$&)`FJ*YGBtMt=FIk{+8" 9H,P@BdD q3c%EK"cnt", M3- "+dAuү /'؄pe1(Hm ozŊG剰TGtRYfHe"(t!}w#ʒNieH'ĠtH 1fh#$#$ X; H ɛ,Pg>. R.1sc!gU>`a%>!5Q@.dS@%AQd4>29e}ww-Y jW }4JT ! wQB)es O1埊=#O)7DuoKu"Tq#_frZPȰ883_7)mAv_7Ƥ9ƤQ.8!UMuញjze\&8IiU_+]0OU~z|đǐwEȓNdbn*ߝS U$zcnt)o=$ʓ\7iޤt{HUH%ԧ!x 辣8S)wW5MN1U#RK-R˿,0`QFMR%،Ă1QaYD*U4J etE,(}(`Х(jG;* !1)\Ica*Ј낋!#RЄ&5|qψuZ@Zr:XyʘuipQnࢽ?hFr?ςD.1,:BLucTXm )}ѩ3u"8Q7u+W3#%®RksB"1!D?;! `@O'Y,D|0} cF~ƃW-̊)袜6)A}$ hRϳ@w5cTȀ$א 6D,T=uôg:0Eǚ‚>f.AY( *)EQ)KΦZ;E`10L G߁s!*HBQBTJ*>%QQU 3cCJB@CE y=;3< > f'ߞ@P6@XDr?ϰ aЄ֘NlCƆC!8[weB >gB bW(%8 ar< -,iL6W[5mnahL `Լ,%=nٌRpaSL))2UO8&7a=`Ο펓wuG%h6ܷ=7ߍl6#q'|n1SmG±E u0v1gy̚ynўFqT@1d=$h`ms;w1Ґm j'?L0sIPIENDB`pyromaths/data/images/vignettes/5e-10.png0000644000175000017500000001301411560531274020720 0ustar didrocksdidrocksPNG  IHDR[W `PLTE÷ӍC΅>΅>̈́>u_rrrXXXV)FFF?(=<4'%r9k9\.S'%t_㸕 z<]./+?x<|9't9{'taA8\߁z\cx:]^> 咟OG=/'AǏF]+DυF\@r~n.wQ߬5sxǢ-7j{k]^-0iT>u j!xu2}[&hG_͍N=G,JSVBB7htuߕnWJ A?Zq5AD6흠"; i@+ Wbstp?hw@tTE tGX<!2ڤ^mR\=ݏe\Of 8v#:nE\=^.Dʌ흖.(n%0)2%2 9oG.D! L! 9J$ 9BC`#/|Qt=qH>2D@DP` L# $)-J@!&#[`% f0S`q.ר`rq70ѥdR\LS&0-[ڬĒ&35GQY1ŖXMx S97zK/cQ8iaL@0цhXMsԙ˃ʚxTqj=k0,]^daMĭ/ǵp"=a ͠eG4֞2Lx 0ᅹsN smbϵ -OA@+Msi3g&}m<H "637L K< 4(tiͭ 1'3Tkb@1C)ՖxAj :VĵN񟴽kpɏ-<yX` }t`;`#kg}=>a]ܒdU#L5!TrlZ0wS%R2.^ۺӪ Mn5Mnuɕ~)%%7Ӟ#RrFLFmKUS 1],VV[7(sY̮}Uo+z|i=m{,vaoȗ%6؏Qs}׀KajG tZXVt /7O;ՈCCֽgyΗ[GQ2o X_Ӿgyk,f,Y㫍,^~R4AT%=/Zojڙ|_ .ѐ ]j B|}bC0YY1pcs@Lsx"k wkBfj߇@Ԇ;7:ȯI vs7𳹞Of?) "l75SeJ7 ;J͗#J'6$*UkL#yZxG>Bw_o~D" &t VibyJv_ҭ&~Nѫ1@,;egxVKŭL`j0s#S $M 6f&9[PԭQح[0 e>~6DGjĞk/FΩY6E1Sd=5yD Fí!zrGZQCR.Hee+f%5UCY,%=jyWB Td&OeLdhV8wK*&F~AO f#Kl8hpCt%R9JY aɲ~ȫpf9z91VKЋ*%Dd=,!^ f#a zAhNI+[s/h!8dms#rҼ!/z!:`6Mx>8PP41͓HpbT2 3K*IG[&T'肰\sFVBaXAXd$F4&x^%t0̀g*Q̓H ]7?[HORh$_yY`t-C/ۧG` 0"yD h\:`w -]I7ޣKeP9 ԴT2-Rƥi&[O.APK#5QYhź -'xE".VY´IJ`Ztegܜ!5 EL^ aTHP˕TVֺ h84c\4/{E1.Lz'[5ϐ[K%AE,6~bK[Ut[= F}I$)EH2¸s!0(1Ac; SѬ!'!3+M3 x)R$4ے5,lXEYa !B qeKHBA$!IihHd-wq>&z#q_S޸:o@XW9L^<5hWDJV4=KaO]vwݵ3[Z-og7оGqجW;b3n^%%Fn|[3̯Bݘscߟbޙ?~M?||pYAFD +{3^jc q?tgG7XçFoq5k6ic]_6| 37mR9o%P](7BaxΓ6zGr #"7;ޝY>̀=T?~w,aoZF5L?>P WQb[G@Ƶ#^4$~>_<(\TU_E _u~`IENDB`pyromaths/data/images/vignettes/._4e-15.png0000644000175000017500000000031511560531274021141 0ustar didrocksdidrocksMac OS X  2ATTRGC55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-01.png0000644000175000017500000003641511560531274020733 0ustar didrocksdidrocksPNG  IHDR5#+ݎC^3݈JH(@`ԋg~;;pjJ_dP ݧ xW zLQ PbITD袃fm|_ "X "XaE{y@tK"9Vv{D {y^jնy-Eڒ1"x P*muuoIvm'Bm.@~ClXwXar^jea dQy0 `1 j2WEƪ zΠ Ԝ%4y+Zŭ.A);_;}$+86mü:Tm_+#oEh.⿍~˜wdQ!V(YbFA1{׻ŊJ Xvc綄RU4mkf@cޒfğP[:na_U&h?wToT#/9}?E]!RWKow* Eۚ&C77.+-km*%YL,Q],pL9, ޳,A0.kj^@U||ռkj W2 c芰%bIlfq%yBؓr u)Vbp,y0EkL?&~ mNJ۳@1ՊV[uj8ZmVk% Gj56h\kQnyHh-i]\VۜNX׺W9ߜ#و辕>&i;2Fw:&k r)r9r *7c\M:hw:lj [,hK Va^jwʂg!xj4 4Av pV-֫퐔pD(KK.y_N"H R-'c`*/l\{cYEȫ@YKK.N68 e@ 6VVj]UAdžÅO ߌY4З bkiɈJe1EC{T=jxlRʗ c+N=~Hc)2).483R:ڡ!XHJ#1llZ  łsY6'VrQ5뀡$X6J#_ɟ_KQ`6ي  (WnAʳ]Sw@괏}.o ˧T>!Ѯ)5p8$6(Ir|£j]NE{VӜpʵ';˥Zsԩ+^ƿs/OIQ!+\O?}qLGף?MEZފrGso}漍Q?|~?˵?]%gOOMBDh~LDx"p['o36َ4I2ʄAM>0ak1M ݎ4ůuM}Vez_ڶv֋%pMy "Z0UNn]w#uuXnF{O&՜5cuk*-e7V#҂XDe2xZ&cj7sm.(P*l]~hf)i dVD& # 7ۇږoeb0@G1*16ˊ wWe@Ǖ+oDR3g#7,V7KG[Jώ HFdޤtTXZKzBb 1j\>$@6j2,%UwsϳYEM=mRTnWaU*AJLy;Velxtm_x xyO _y$$(%"zƁۣxccShXF31^8E %$V4N"<íw+:֏@KgM?oy/BB]xⅉu)ʩJ96s-hmxap z{S 8oc8Y}km;yr^ Ǵk ?U5p=17.!:!%ϊӿ_?%~)o;Q 6bE/ԚMW,!O֏ʮ /g;gSK %b@@܃'17̃ ^Â[bXP `uz: @z~7f?ɽvP 9)eɕвQ)OBvANi7fBVƣ^׀$?@6Jq @ѯB黭!Qm|8h =r[{ N︞긇n`bA ѠC]J[ ^#qʉ5];k{8 @t343Vӊ}$e3Ik'.Y%(o5_Ytnr!f3U BE>q=>5.erKot$Q:J׼0Wp:QG N.8 :C&Zc@뉧o.*߈@XV\=|7Sk>P;T[9ox#VQ3jZzZ4ZŚzVGO3Ϥ|uNbMOoyB}i9 >c:mtg=o;IsW]ڈT=wy?o/ @Wciɍss8~y>yGX5~%+W[+6_)I-W &ug5WJjX#HSq>=P]>HKB;|yc^7cL=wؙ3x{9=N 66ܥy & ㆶ Ɣb {CDִbZ혐[oF©D vodc SvDѪEʣ,ⴏb}Y7;>jRW O.1A یOS~geI'τX>V_kNGC9ǤmpY?I8; %ވoSpwsDJ'$VOpBT7:@R@ț:B4EIFj7@+}gM̡\?!/ m8{;鹣d:=Qf@xэ;b"Q/D-egzf\{]Z8^dkg2~Fba%kuaUlG3Qn s͟.nfF)2Ʒ[JaHGǹ6y :6 ; ~_ɧ\*ҡ2 lG]6#@|()'sL@ɇ VBT DOU GQf:N-G#y>q"d4# mcH "c a}qVfxH8F@/0y8|_xӦjdc` X:mt =lB 1jYܹ<^wiL a/b`~GtqĿ)k``4Zû ՐJnIŁSq)EEb#uxT'5'Œb̼Co!#jzntYc\gRlB/;F)$kLF|-Nwޭ1)O~?]?ooG :Oׂy5+x@ocsɒ_/Ucno|^9H36m&H8g̯@=_9Z`fw7Slos|1SY>[pN cF>L4xZHsCн?|p?nS~7 AހCDQſi n{y r' s{^vpFdx.z 97!$[hk5e̚@^r̨!s"Ju[/L 56 ¼l$ڗ o87!vP6EX'li&#sB_/"}HqjME*sfqX9ĤV1:V,+@aP>/!JAx>BGVEjJM&y=o;%>xiLb$j*lacI'Fn.]cYae6* $I \RGuunي G̮k\WoޗЫ={2["P<`E<8XAA.7~s,cCh֠=t)x_7 jv^y@(AȤTjN*h#(>'iZ27v@櫚~fZ4e*%*e;k?Bً |U* /Dp{֕y06^^g{>@{}G ?x>uG3q@ jvs%T6ۿA;T_3unI >̧&~NïYI'i!`'ㆻLpkĉ<+U$iolB֮m1NGqLȚX쐶z>;T_3unI >&~z3LқU/Xz(ECS^ypzsG9SsvM+xvMC,tx y (zHt) nz{1{hE󸔾WK x㭉5w3<9C /;v_((>s˦y٣{K/f ^̝qNBZ=|( #~BZ /nӉz}ʖƝhV9@(+Mz\=;;唜+ndX v/Ϯce݃1?Q[0bύ&{.6ꕐ2P{4K\f mG0־=sy#6x>[u['4 AY<O[hEuNWSesze:6F 흆4 RBXcs\:eH>"cPA(kcYe͢Q{eޫ`.|_0?} h.0sm,oQF ب:\*}u;㕨Ƨ%o{u|Si]%+\xb3_? Ej]lKMρi9_a鈀f<@SvfW 8tG_p +Oؠs'LuҵtD@g8khw@t4ݘs"ջgRl?'ЧSItbܛ]83M_д'?'G@/:hœwËJ&:ႀޒ^sCp6u O+ex9kVfbpaCH.flB1*1r#Zp >/;TTc.:c Ц]ᮒMOm}t% 6?ݽJ{'.hb34xnYdumh_\'! U98dƳ4FQo8NQׅStDx!r]r (
AO`hS~Q$PY`mĿgi*OҶvay^xK;1[GUG-/kHH߫`hbnd!xZ)m:\ŚJK-}㿛aysmk ֹ Ms! QN%odB}֜ZO匜7ZP^'( . f 4r)aT[)AeVQ\~o,zbWQ $xaD̜>xZe,0L$He@ k+kUtEUjpjA퇚*|#XRXd Y|Bp ny_yLҐGg07!c,+@MЃsת KV`kPŖ|R4Xrݳko@_C50'i$ǵ}0**9G<>Nu5TU)w at(Z_Yn :aO]oT5*=;fIJA*fp؈QaZ~Y$O9aecp d #-۾?! DiD%9IpeB#{AfmQpbF>?y^$@y d^U@(7hgr"ea fJό]ϳIU~Q~cѦ,݃@6bi Tc|r(M[v8U g2s E}Z:# k"t)za6$ 4A lvATD17JP^t5)kkϞ*?@y6-/*֏V/_˳u,^!h؀i  j٧W 2豫w[]~o4(Tܳ{Y:x:핹xVn٪V7[&PXN't}w/oi_DЉPt"Dm<]4g?.ZL+^kg,W'?"y/>%_T{ߐ˟u)9xg—*w'QGȥ'}қ XNCBYU}rb({81v7s{O '-3gk1.BDn(1L?ޝfҾMq:nSaUvI_ɋʧoaqMs:icAywqtVe"otJ?7D/Pn5vGG=s݌쬡/!M %GA@k:S&8&]뭷3MgK k\ Vk俪 [^u C #8 {d7wٯį{HЭ-x@,n9? Z?cEMOPST(Zkzn2iV L>9 ɵ0TF@*@8hCffdJ`RWΏg?m3ZZiWfP??nӇ+zGO +c<[$g(rHLutg*Zji lw"$V3í#o@ @u.nVV;zmu?0R&c٢˨$VmxEyɩWZKg: y'z=?Z٣ +׍WY~t߄7o,Q'_nw%+~B|7:0eMG?AqiS{&a]272'P 4"u`[AwYbek!psc={q|@v`4Ķyj7rǹ?c~Y񛥣Mc/U* xlHy/8zjKB%Pc0lFgub+SܙAs?أ#[=z坲t2NJe [kd j0f~IѓZ?Y>D_{X1yM^}os{ ^ǫ-F%K5p=Oxճ^6׉:?[7?!W>F_WAR7}߱6@]"s%}`i1BKy16=,p,"D0 c CXpKij]_Oʬ\e| @] 3>};HA/._PrA1tx 8z$^^m1Â?~M#MGO-\vnL!+'$/LPɆ|ك|o ?,׀np BYy2X6?];Rھ7g_D} iJ?nӇ+zGϼia0jռME*8Aۉ>/'}I.CeEZ + mpE)tmR6{_1mqdďgG89w9soyP^~>M~CJ0R~?%-K?{_Wߡ;e#FTW']<6zǐۊ@7&0$%9>Ys!_o*~B,8 궵/?pŠ.&vT oOt_GO8vKKB[3>cX/>vЖtr By۬9^i@S~GG{ܳ߱yr69=LTb4qނ| )r?أ==z7\)COzplnp>,=_i/Y>\Z#,BnBM \ᇊ.>?z_g -Se m>l>ӿ?]o E{rJ@uj:zkk|y?yq GЙ11aX£ AV3wKiS%(Gӝ.+|EwdⲣH{e湿_C+c¥@7x_K9,ڲisN qYp'aVρ&ts&~B_W=Tu 12.v}47{ /{grJG^kX{SB){X pW˷㗒4ݞϡ]4 vu3&/~s.ȧwcwL1 $5V3Ÿۛ?PmF}Lm1B ( ;%ZQ~I+6}wz.zG1d{AG٣ٹ+;wh:^KW?/_ᧉaxÿ371?—H+Bu4ƵOhL,v4/;pX Xm 18!`ǯy,ӡ32Xt3H{Y|Ǿw_3c\[WL: ;ptԹQѳMgqD_jF8dSndbuv{( Lp!`/>4QѳMu,fyP"'׭ km3ˇNzS 3^>I_*/K?{_Wueʛ?]9~[h9u`+bC+ vlX>ia+#! qZSFmh' 4@ܯ(z|7$gy_#D]0`Z@ם6]?!-O ܁ w7!;B|=!˧T(eÒg5ot|4eA]H:h2 om~g?yѦV=zڇ-p|vD+$ĥE27pb#tY`ton)//~laM hypoatwY=zU>|n wpy1֏?:ێƊG7.W6⧓ ?PK'7/+|W._>_z,/RO,O1ѫ,uj\\ z鯰|*s.{n~, _H11<^4֒>rPx_ ?SN~OD\X/&_L~/&_L~@_L~/&W-&Mi5KrGoFO `pޘ`սa+>by-iaU 䟁ɚrgyeXTju1B;7/bVy'^wazf1?1My#Bt`"Ε}r24e( :8%aoiΉ!E ߂ߜt2T!E4 %!7_z;X5a[ ,s2 +&RҎ¢Y:<:T'70| 0,rJ7 Ts EUWUH[ agk9I#͌X3#=!DeL0 MM`Sf}}\Ts{$,TځygLjTa^釽i{V Y67z@ і[&7 ACZkff #zk]!v rajJ3#?2xenfExƞ  *D֚uB0Z*K3{0 :眝AͬCUTR-@\Ҳ708*0id]eYPe+Pl)/&ӳ";;T4TPFL,iDŽ,˲$˲,K@rn38BNޠ+g+C`kKs Y!AIVKe^;]IgV pya4AV+u{sb--𺋾f| :/,N 6L>^Q C/K6To0˨ޓ4Bq&g?s[)k&Aϗ5ۙu`ڏu힛ÂN]F2gb.& ;^ #OL@"'E=&IMORInϧ}څS]O͎~()yni#׍XL[_͘-_L~1b|q*L0kݿ:?c|%o%H; +Oqa e±{uJ0O44_c WDR+A0)!as#CU`˖neEr*'KҏRͣQrg3AϘ' M=ɥ%#W7a]yj[qT/ L&3:֓I),W[؃YّހJos܄%8ڠӀI`pWֱ2 ʠ1D%lb5.TF{a[evwjg\䤝Xv`@U'څ^Qeg{lΰ{7mx"B8ls$EpkNҵN}un\澇.:n$0 aôӴ;H A1fw^}i"R&Pλ+>w$r1C*}qz""L'(CẽvGMB RQgSjbXZ1f'yˆa* dk3̐D@EIFD+;L_5x -qޖX c0#Bk;N!"rT~0 3nmS9eXi͕2wr [dn)  $'o'zM=#|o9hŊ_Ѳin]Iy_ÚH(S9I UYі(Tfnr4>Ny>Qt #~/d $efH|0TB(f8&fl>10a~qݺ+x)^{zO"s(ȉvV Ӵ}uL@F 0/y*c4 )$u(SLM!u35l< y)N?^q7}~"M?yڴ>O͋~ҾsRea_70~_mr*u?%3pK]_$/Tػ> .wUOY?ib/&|gMMh_HUW>vf~FwU»s㽂wjjӸ|H_ӗᾝt?TFHP+ayX$1ҿgz;X;8>ƴsI1dv]doZeU23A?>vq5;+FQOٸPM`$iх QQw4)^sk^v{aH:2:DXNV=x7g& Bjf!^Q;nsv0[$rgSä4m'+!.FŜQqn;bmJXr޳FYJWVf|YS$9܌iVoqn /!u?pXɭƷ7ؚ*J95S,L GS10-dH2-HRÔGMLxKKn0ȵiHQIi"R1LcLiEexYJ@6Zkb*Rv/h OI S$\|sO0-\΍~if팵2 ~P@ڸC_1"cDpoҚâJ~]enEmE"/#r&A۷W≟m*|G7RQu_E,C6Љ^ndeuh+Pc,NF(r?Vcb&ٗ74RN[ܿ~77q+眠 q@HYc]g潷Q;HHYអ?>F}47 Nj]n;җS!?#>g+,_!@/0Qr.,JS]'߉ɟA']_w >{Z=IENDB`pyromaths/data/images/vignettes/._4e-13.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRG?55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-12.png0000644000175000017500000001045111560531274020723 0ustar didrocksdidrocksPNG  IHDR2wIDATx=v:Ӏg VY VRe(QDyz@n{l}g^S*T]*2D??|>߿WQQ@TQItgS/^/[տ_QYN?%ߧh<4UxSm}Q?b<;B @ wn ΰO =SZ5f/^']~|k7Dc_. 4ە29AYg,Oȧ?^qCo|ɳ]"iP6q-u@t#ȴsEM(h(|Dϯ5)j}\82@}B0r[E)]:+u4\4Oe`  z y*O-l.$z v^*ʔ8 f]PeZe-0R@v&_mHY^2AKwQr@&B9H>3V$G!7[@ަ('l톶;CSgm-9W: !H]tI=zI$Q".@W?Bۭ J)ة쀈rGö!M`QR~+"mo1q#0];;O1I4L풌fftLf̽!bYQ\שׂfti",SyĎɚg~U' esvAr͆(({+l-JPŎBLOmַB?51Lӌ78f\hgcH)5 ˴Jn +n+]{HIu[ք041:ƁqA>uBRn nut 8{\NL\[RR2zZBZBWn)UهAr}DM0#ӈp_oS]QIC ZT+Ğ'5){-b:7IZ022, 8KS]"3ba1;./>Hvngh&[blu,mD Hi _QJ޶G؍N~k]1=6SױqlI _zbOkey]O4rU4i 4a 3 Cqqlo$AC4ѷHh~D0"c4.9sen2 ]k]%Uh,Hۿ;\ 1GT`14ݤdvo{;ЕE"k\3PPM&jlCI(ehtcF]&¸_? { ›6MFlm1,#nd6s&^ r:F)[7knfff,lc  5 n8!#~ʦݘ\cƖf c{Cr7dlM+3sMpMؚs{cu8/55%] !!LŚ0`|s0no r-Mev|[>ak`M2L?.G.v7m\P%JWQpFdu+GIRjK8LN ИrTT :[طbNu1I)ri2,3ǒQJ 2~r,/rTkͯrJ@N9CPk()*>-Qr]K)4$愤\\+/\uo)_M)");B By)(/I"rRJ/ ?9cU_:=Ur+)1*4~CO1"' ~'/оVq{0ޠS¿ 4 Tq HQ}B?>-I9NH$(1 %?^5(%>iʱPb֔Jz~F3 t)Sװâ^E|~) bmˀs+_,$Ei{D _]}klfv&s~` u_c0XK=w%ײXFDYƎ$\Wq Wm tuOY)E~F@ƺ]B#9Hv~ *Hua|G1L  k_vI FQCkRȾ556OgHhklvE^hV*?J^#۞֒'_0Ph_LW"#월]$^#0XT.Fk5Kկ6<%maDPm( nܺ Fdp *8ІcEHU6;lBmۤ c1;E'sfR+!5rt7eeP%uɎkOfnQSJn(#b+5'V :HmLn7;迹&|Wg[s9]nG6"vD UZ[!P(e{Tf F?H%0X WO K^A劈$5i@XT:ϭҽڿAklq jdv> qqD'g9f!)gvT{uրB*zmہRK >zD6+a؏cq>9(+gP~ ecf O`fUVR[8n!ew S*v;1n%XXzc%ev,nd\Y}((DzmZiݧzw10"= FoKD3mP&aôӆsl' yVcIuѺ4CA7nrXMNXkMyEYY(ѯe>zo5:IB<^k>Wqy|W7A_}=OE<=yխQT5=I9 "r9͗gU*؇>W_o~mJ_׿<ߋ<~P-Z@U?YAf{uN˜ɛJeUu 8̋[\ϟHԭݾc6-,&]]ɛgnX9gC'ϲӍzxhh٧웸C@&6bҀ2Fr:9WډYjJ#H-Ygzcs33o\{Ƕv@j4ǿBCIm9s߫}d=>`3lNbL?^=Z%>Czүirk/k/k?k\:|heča,C ̋49ua #nZGBS&nnƚv#v:LAf?d̋4  T- 3=8",Y KDɛŏʕҨ(hX޸ccXtW-`zOi(!M'i+y7P&ZK=!'Fq4&LKwOo4ї+.t[in41BW{.l Ly6>tnjf2*RL;ƙe M'dt&%R̤!x?H8Nsc'i!EŻ習X+0cL<K"><+aL\&9B7Q$bfYh\wgFccHƇ_nNzb2?%+<S2“,+z<,Ǘ3/o8O.!򼸞IENDB`pyromaths/data/images/vignettes/._6e-20.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRG߇55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-06.png0000644000175000017500000000031511560531274021142 0ustar didrocksdidrocksMac OS X  2ATTRGS55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-03.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRG+55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-03.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRGM55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/3e-03.png0000644000175000017500000001072011560531274020721 0ustar didrocksdidrocksPNG  IHDRPIDATx=*{IZ65h,Al||lLL\\yD$B5sz{͌(_eIq$ϿKW&yg"P6{*F#ҽ^b͵W!BV}=#4 rAduRN*@`дFwZa B 9yjr P򮔲 ixC(]UHM + l:x.2m3*GZv/xk\rKqU @4)YiVU$5O%ƪzcՊ&[гS h{B+U/zViXETTM:[`3q fSzolfy C;~a4R=ZK5/KWta0ގnc%%rm/}\˹յauRH^r$[XZr>͋b*yR`siI%%g¹V_}g7o iy7!p몆}uDr0rY17UW,gPڙ`P6ISrܸ\]4aq9Ƿrq\*g R2wVW&K^ WzJ/_+g/_7N˿^%$/ zM'v>_JQvGksٕG? ̹b'Y?ͅ\|&\r*h29A\vȖx/Ϲ H2'/IsQn| n-Mۅf L1g-ZKg[C!m3#`ܿ䮠fKF'v$PUCĮA %󷲫 EntaIn( }*)pbB Oʉ.17YВ[ :NkHc>+4O3 \gl2]8ᮑ:?ꃻF?ӈ;;0.c3s GJ]gjHQ3iZ1xmb{j ^/D[ j;F9fEc,'dAwAЬ13;,v B;¢1P^;VNqzAރJ;q:L,rU:,,nA0ZkDP Bat U /e9mu0ض0 ;Q) 3|tBegGPSJ)MPxlX2ThsW2dqT 9Kp6&%0*WWq>qb(((>Bi`3 @ٱ0qQ&ۯ>3CEo},] UUe~QU[G*O݌ A`*4o#B4 l:\9~A:@tVC& EgK1˩DX&Dh|dҫ-Y iޤ#zyAgl,YrA/x~>Xo!ցu`ڻFwk<qorc< -FnE\x}eKеό'|' ~J_eT Ġ%IC 3oS[|O_WHg/~<@E[M~EжHDiCM:w}s.zk7u_']b_-ϧeBXp"dOҀ0iIM-Jvq4eDMoۍ=rٙ: PÐgXrrGAO0huen$nMh!7LD0Ttc{|W#gQ]L̀aJDϑƬpOV6;7&{tkWp,qG m2j#a+%]Ͷ=4UBv1ܙIɀq?`Vn}$4Tf>6pxhRU&˝(M+vU0**4Zk=Uq v,o Qi(;3LCM#5j |ZB+pݶm4S[VU.ڶU@P: gZq: ߓm{vRbf=LzދiXeCha9ezvn|k쿎o.vy'vd* 39+-ayܘ <2TFHHhqht"Myj@cX+n,Cb^x7}FShiv`u%k7EOimucr/ɻ;TfvNA]; VjmC(wQ[_hL[[};1%Z!#1lq } v>;nx/1P M_ҷ,!s'Fے+ϛp9d4`9σe৶W/c'YK;xgjrH!DW ppZ-ٟ?yۣ/j1's5j ˣ ﬨ_ KO1`OZ5~I]9eȋϜ?>НI'/`YAVzɅlmO!6Bts羱b^u)7<(!QMe~ipYvۖt]D3唥-a{Vb2X1n1n}eʱ5m_e|׳ PGeO\7fA*Zݚx^u|Ğݒ[f>R^6/mSl*xCrʪ't@xC]ߟ]U{|v0 33*61TtCM柘0eC0{ƥt[0i}ހ-xC;7>õNǹGmHAф\=@cQIq0b&FBzK!Chw R'M#;rsW肍`-=Bvƫ;(dah8 7ٳgɩwv+`.Ǩ=(m4 9A`k5uWܘCC(C\qj9|D9Rj=VvH 8ٝ "Dp]aHG59!]֜s{E(⛙C.Y鮞֩]@IG&qŸ_:bl;7@ހ>0Iw燆ǧ\G`|w꿞???2oO^D)F5Ziχ1CsΨ]i-~ZnfuDюohWy+م~:*ѵ%0EK@!y}ރ^|(}U7o `$9)ܵU r9Wp3L<4f]=07]{ `07/7܃!7/Uḷ;w4p[Y.m#[+J 8 iiuڠ$$l`FX@ FY }PKң@bD@Oj-r>Y:P$:aY?$ЦAns 3rm)/̼@8N.pDu 8 Dvv F:+0r kc&ɥ$&e(ׅ~',KcNUBX H!n}MI8 -G'A"KkZAdܶ\&x~f:h;1{PSsC }$/W0tX(k? H6 K( Ғ]wK8 bSEIB]90An%_i8W@V #n@vMWMUuƾ~V36kR#$D@;ZPgPJqN ewLv^ LJn}3H,;f=a}jc lEesNܖ+B:He1|F8ȴM,If2nI?CRE@r z?_7QX.>W 't0?u&-+mLěS"X & +]ü9a]KܢAHB ue圥F%;ǒƨ`0IhBUZly7H(m'i3_7ihEχ21AZ矁Q#-[Y6mV㘷E}5ԦivJX+1M|N]jr`F.0zܢ؜%AJ_cv{0uo;Aq.5+\/s >jmRAj=ÑZmJQ|/ pԝpDBGjmoP:jmu oFuLNBʙ)\_hGG=w0u M!= =ڻQT C:Pr9/;8|A4^)Tur8|NW,ed4wI?F0طxoMk:<Ƃ;#$zgW.ȷ_G2V6c}߁q_|sGZoM;Z%E}P!I o4{/w0:OڤawEkn7w?r׷C oDޠq=c0136~xC\-.X-߱oϠkQF@̏3~KԘhTr6_?J!2}+GO:?FJ0Z۰3@e\js{܆%[?+1;'p{xp {mF?KN}ygҹv(vA8Et*$Yּ{8T H5 exV0;-bg zθess#'Xs;5G_͈TB Z$b\gFPS(eR 3W`Zo@kuAgH #kȄQĎ^Ewl hd^H?# 0bV B3Zk,>?3es XSצ-RMgΜyj a7 Ym]>iN 9s(0`UYM"x CcΫČ!'Ap")jּ|G0M;}J`PH]1]d!opۙJed"6A-@ݍ4Z’d,;/LRQK˽a$V@+f3 }zd۴ɘBmAM_zB4@2cszu w*:%FޱJ "2`K4]Fk7g^<7[眳A- H=gΗѧ|":qG {?#H*UgRH`jc1, ,bƋ#,mɜbǨl諱1eO~~t¦.u]NG Kyˌ<#/06 ߴ0[ym8- zzxY_K~ģCLS: = P5՚L3 igĚ9hT,ŧu:O`$ dCrqEQ' 4c]ȍo,1Rʂ_J%Bm퓄c-ɗ5fG1Y~YxF?i p=矅Qڵ 3|q 6u- CKDD/e7[]=vx3]+pi(}H%Î^KB!mS6?wxRTUJ/^M?;88|W45x'P9Xcl oGZ=T_F?$ am"{F!aX[xmdu!Nψ+"g"|L;g Ӂ%wHۈ]0W}& 3O1U^xH h 'J" ,v(}ӝq_]̽cCW0cpFstrhN;@^兣N}B~*^w~ҤsNI?a F$)+i$)Wy ܜ6NEdaf!*"*^);T D zJxԝ( 4۔_Q4 kKWʥJq"@ޑ'.B,G Ԋ {h1/8A^%mX#rH5yJgz]zUwʯo$#QQ4=?ւ@X_A56W,e65fnudީDE<լN*BtEN-x'd"ۇ L 6q@JcN__F$i f8S̐Sz CQzy*@ט5]T\rY*]J&^\YtlO*]s%(X:%FXCe$% 4ИӉ0r+JS2sp (]P BLlkE>5V9g9%J:EU  as%(3Awz rޥBuZUi0Ck;$X&3#7iƯzTUgY|ICYr)\9l{C!չjLH#hw !(A/oˋ+;hPb <֫JsGsH\ *핁D0A^S%ľhasGZ;*9}皼ΒESZ].ՠK$CQL .pbMm4nmy$9gƏ_tWQ]F_Yz~fC_Q&ƿPIENDB`pyromaths/data/images/vignettes/2e-00.png0000644000175000017500000000454011560531274020720 0ustar didrocksdidrocksPNG  IHDRBI< 'IDATh1;-h;`Ą eTr9n3޹m?9%_lכP.i;{m|aº"9T?~Y rL v E!r.8CDjN@okk5! ”o BfD#ouCl2҅sB(E9`s/p1_A%g3%.r6RA.DKSlM(.Z3i;n2J5 jm~g6kft5vLc݈۩i38c1Xܙ8GPZ;Pj҄p 3*ĨH  ziC04Tl<T@puDy (t@܄[mNzUwEy2)a!9 Y222ygStaq筦u*`q7Gp DŽhSٱ;RF fa+z ]QIE|9Z֭oeG9Dz1N;46+&lf^Ulû/*q-呢sEfC7_Ehs.t pp(REv.Qug 9lD:4P`få]Hh!aeeB:<3L}Ǻ<* B 1t㝪UE/>n:㐻u )e_1zSeߩu]TۯRZZ癬ieYR a~d3G~/=4]eʾYm?ʿtߦ# ;ӗ"(T/GlgyՇ0/|d IyV^E_WcTxtmlN0 0GD>,[I<BP ΂t:鐟2QuM eNӓua m?Fg ʖ縍Dg$M޻N 3*ZVb(eKEL8WL"B[갌CBV[MrA Wg:puSNhV̈uybUtV.I 2`wzw~*k<,D&܊Y6C}l.!t/WZ;#, a=\s'WPuKߞԵTsrgX4Qsۀ/2Br_c6ce9= ;E2´~ wsJGdOW(/;ʽܥ\¾ ;W*wP^A}RJgM[J :!K-Pn-B;\<6=alP޻1zMއ ԅ:2'x]E\wQ~P|yԑxp2>ƞ;m3.@0<= ˆ:s~V#Z] 20Ԡ.L"ۤ0M;L?jXӈOcliD}qsy.w)/cG]GzI?jW(wȯk2sP2MIENDB`pyromaths/data/images/vignettes/._6e-04.png0000644000175000017500000000031511560531274021141 0ustar didrocksdidrocksMac OS X  2ATTRGg55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-08.png0000644000175000017500000000031511560531274021143 0ustar didrocksdidrocksMac OS X  2ATTRG555com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._3e-00.png0000644000175000017500000000031511560531274021132 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-13.png0000644000175000017500000000031511560531274021141 0ustar didrocksdidrocksMac OS X  2ATTRGy55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/5e-06.png0000644000175000017500000002017011560531274020726 0ustar didrocksdidrocksPNG  IHDR ?IDATx]UnP%J &''%QHF` ɒ,s-0ltX`|c Fco<F{LAs|_@s% 4 v<t,I0(P;;1,i 0ʹWp +1eZmJ1@ylNdp \sA9 L`K;k0t(hIЃU0 U5(%pNkENj ZJ飌UF(zAVF `FTYo@@Zw^Y"KZ<E' z(BsEA+8a!rp ( k8jC+#t<\K.O>n0%ڼncrOFJ)>CRZΧcQ)&O<0`JRHd^Na#^ A4\PV)=2-~dc5}n_6HJx(\ Eީ/Afsҋ>>KeE0:(AW,鴰YC<[(l `o1sa(e@>e GT1 |u0!GO(RrAv!2|N9b6x*×%m>q@UV/Zy 03Ϝ9sEyS|yt9F?9> |>チ`s|09>;1 |z:~1dצ+ j/徃_?Bb<)_H+uo$l% lZ} OXy<" EGvM5ކp3F54Y&]v?HTC&un2gѵ^|s?>Qj/o!E-Q*|o(3Ӈ=P&H@z|zO10L=(ώ\tPq'5Ot^==6"6n?ߙroa`<\jbrHB6dQSCC L6tgd Nȶ=!I@CH/xRB j G`RoA3zqK(P"/0u3x_ lw9$"0*#k5-xf3̴aFCQm0uzz.`Į;LII=(gnlf\0Sםk6c ޺8A0!2?/chn~ ~- 4MoN1[.XgzgM3VOIWpSu"a$..; g B Pjuum;ӭ_wYm\jR/1V~;q@Ƙs9Wl!\A> `HU0u9~r.l嬐<]r 6o~@[8躳& HЅeUAls9Gل$1khzR Rw5'Z "V~ #RlFQ-9\u *KQ j/ցqY Ⱦs4x9풗i:+Q[|\cl+d;[f):耊~ @i̒m@Wv1AǬK_ĄBWMMqf6zJ} @ )K1D j/.ach63lfd^z9uM`mB~w%Fv֏. GځTicd̔72yl_\ըf|3;;0Er>0=D2Lt+߸41ۢ?>_{>Ź;M>>0OG8-`?҄$7-g1Hj.u`S&TO:c6.?/ú!';6,9nmF8W Eͩ_|EhW)9Z7eAw?eCB*΂yGܗ5^00x{ΙC @̐'.^6 h&;!ڌ~b"_2OۼS:^=` !*xu.,FETpqa,5n]%O 6BO Ho nԌ&@f71p`P+jvC8$ywwd}@9\l}AL <KC~`DWkՁ j{q®9x`.Cu uzs mfbML]  \m#XKep|m~yl9$pɆC>VvܥzŃA)qKV~۵a~` ݹ_jio8$w%w.gEc6\h(ݎ6X{t˪sg~w+^d꼺hMD2sf?:{YОz7IhU?]Z:F60=B)^9٣ɗ}@ L?V-5jCdvL i3*1CBN/Ciz?.u !l GbScld2|.~:l]H´*l x)dT6-n^ 6 &;`yz??BgPg x}?$-| )KA0 .?ţ)M4`rO!ΰ/@r &޶`@q`dޤt?e3Bf3*lc\pt5L慸:>ߌD}/ p:VYp]20Q?jO@j~S[\ ng}/6[mȿ RVv\«ٲlW?IC""pѝ Andmcg3]}Z)/[9"[$=PS?3Z7+)Ƹ//[~,O5׹_oj4kW"P{L9͗dy90|0Oؼu"J .zv%wWMOm}3#2}o6 D!{ _yWt]w@06& f+[|X >Z?9F2y|gB@^֩–~~k{{a.-IAɌAb?@D.IxYe?0](sz g)eMmR:3"UUHrJNiz1Y `@ˡes7q\0_Lċ98n@]6Cӣ^iP<LH^6VN"czfQdPH>&`d104jV_fon5(J1`_gx`4H_~1׌hsV ;<=fINLSQT3Bx0D|&\00Bbu{1Xb@O55 mo@םMꌁEq6Ng0pesүc`]gm}Qz E90-vL_xZ*+5(s0VָF/ӼSםƾ|Ѡx~:`Ȅ(e^GYo"]cBb,Pp=]EUu\񜊝sųUq7\iPԪ=8PH?N2빀i[e^UVx 7"PZǶs~m\"0޳6TIJÅZ>""13,0ԤVs+e$t#dbzf JP^f~CNc[!`Fym?S刞 =BgkqY>bgXA Wca#Rs(.xͨil$V_KPa8~軇UǦ^Mw ˝<[sso>z#]ƔV2ߓ`]غH;WyE1uf hyf𾇅8#tDco7="45ibb*U8n0gDr6KӰ =CbNUHy|X"~T^OlV+@A`lG E P9Je#B8NT.G `S\Usr#ցԞ:gOam㐼eo/OPUZCvpM l8)q)Zbnj[L)6o_ =.& bj+zY#ibbqn{\>qzbq|3u\#e oiKFeVu{tl=-V:Omݸ:[:%Bm/LS5`{u(R }Կ&h!eO3z0# [n9#:#@=#jPLJ`0,P~ }1IB]J\%1/\m0S+@E:j]z>0pjPUY)&zȗ\Ž`@nվߟ0WT]=!G!o~ u!z@gZ ^}A22^@' FLÀn{V_Diϯ0Lh0#g͜k'00iP0BY?7b_ϵ [7a`/E!P2J{ &@Kߚ0ĩIr *uKD]փ^Ӡ0@QJ{ $M4(h9ɨx80ҢR`>"ǣ& 炜Ȉ^,\O.4V?`7:|‰).`&u\ӯfݹgsHh<xMťrsCF34aX PBPc=C޴g8z75(]  6($u3(y#nDv+Z$b\; }n7炥G5=pC]s@}Ny_kj15kEZ]υuô:O憎F {x__㸵S[l>w4(ܠg|cΣcU`sat DIENDB`pyromaths/data/images/vignettes/._4e-12.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRG=55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-09.png0000644000175000017500000000031511560531274021144 0ustar didrocksdidrocksMac OS X  2ATTRG755com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._3e-04.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._2e-03.png0000644000175000017500000000031511560531274021134 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/5e-05.png0000644000175000017500000002416311560531274020733 0ustar didrocksdidrocksPNG  IHDR"[`PLTE߾ϡ…iO=3nnme_SSSZ;:E 'IDATx]kw( X ئT ~$nL_}r!? P9#jԁt7w ƯCqjl~z Os_/`r|t77`?0~=-5縟[;G&d˄1CNO sNIאYf"laɜ1eV[Dжe0,da};54?uhjluSuػ+0zUO ia]o?G7cݡlƣxVU;~aԹwuguswF anrMԹitR;w t71aam~ffp9 '@4 / י7If!_A`&)461j[My!!̛$N?cdww璹 "hc6kY! ]a̓lq`4^ͮ0u^g6 @wO ØufiUuXfOZ|gm4~oֹCc1~m?ƯmMX^tW` yxtfߚM R]ṇiCD>w!Ȥ'skPףH;ֻG|_ϝ};6w`tCW?]TxZí1V+2ʖ8;iejt753)]QUC0zƸ_c,O3Fsc1a3YڇݝnkiB1CȌNp\ҝ̟Bf-2=sɤOoj=K n.3.0Jeuy q<u?j^gqά7-6ݴ̪ٴ0~;a>r: c iy9v2w2avf t|7/Mv2w2w2w2w2w2w2w2D _}W#sl>+-t5gSv^vy׍cV־yoss{w.!XwGO|~>kqbTƀ2F!` ƀ @ D.KGۨ0fQaMTG&~K ȀqЅLB f@p nZl}F`Np]b $:-5<~ oIWOMOP&;$.?;LëyhS 'ۥN#*i0ڤb6Jv>YMl`;40ȖeZ\F R\bK.!iz9b Ȟ>!䧗 JJZiL9t !Qs DA]ʅY^2 !uAfLoWn蓠X^C,%%, Y 69/r50huAPBp^Rɔ6ͯ jiaPBiΊ"W@fH3Sja‰gD 2T'^>ZB @Є`P1!!*R@ffω9zJ-j2n;fcT5TF<ՠ Q;U^mYCU;Pi(UAQMQa~58ӠT51TUՔ_-lR.4~Q ,$}0bP<29zhZ{6V;;hB':HC`h)έd)Z,M TxU}U-'*)|}42OcMHS7"3¦Yi&Чؗ3ՅȔ~kmj'{UˏqnOVpxwc\Yg퇟?Z2fɺ7FGG|g~o5??,K5w[wW< I O;cY=/µ\3^wŚT֙9MHq3[d0ϖ /2fHwԏ%E0 $/zO2偁mdĄ@782)ep]A`@`e #ĸݖ#41mc!2 0! b~̺햙"*etCqԝYZ hqƒHAno2Xjǝ#7*#b&2a,Rm!SA0wokNYq6:׳Yh1HDhJ82)5u2BVee *n΄eZUh;F/74Ҝ +10Puwz\szjH67iN1D 4#9`j3K>ju^ARsADA^wY |rtޘg%![ [ke);J훶NqS=m.؊!H`Cޯ9^U!ќS b<}JɠH^0!8t*(|`m%n)H q;,ք]` b+c>'_#Z CojN_[)dLbH]T$^c=<6IEdI3Bk,'fz<~ Q8 f)S8[j?Μ6{SsE)} `sT7zMVǃEx .å))ge MVRU7er>1:ADAM pDMX8 /$X|ya L HB>cI *WMe: dnJoT9SV f1Ϧu.`%x?uzā?-Dj7M3!]6{gFl<ȚjF2smgelkisV eԫ j!|)Д\KS SBQRz4Dߨ2XC[ƕXK *EL}9g?AKVE'tĜWr|>H:_ԫoO2_O[I6߹ǏVGo]肥ȜwnS)}3d1G)}$g=%$͟ڳ!./V|N]`L>ҷBo^\+{|xfoS QUݑiU:/Zn;xq)ZІjyRBL]՞~7d|wiNm#4 )1sː>w}2A>=2զ~vϳEG]ζz*Mx*4i$ɹ2%$X,ѿbtYи5t #y[ cƀBhJgWf4 Rrwe!_v5 Yiaort#!hd`Ǫ?pڄD%Ey5(DU\ԃ`bLTc'Շfck0F5 \J$߹>gnY}/iMs_(ij 2Є( IJL]l%C",H!;bte4}dc*NɶSmĒķs 4+^OS50Sd5ylCr0vS=)/AX43OC,_de0 SIf0nf5 > mF)9. e2LR5:yAV B ƁgdF6a`r+3Y`yh`#Xf1IvmwXfi+zF!{ d!8bƔhbE N] "HųSP,1Ƞ埉' \'9yd1ʼn *#'_.I,!|0 *,4G gn@h]ۃ_L0@Zpd23A.ΕW / BAֻWʟ[fDL_K&+<@e-'(syB>Ĉ-.)N2_v~6Ӂޖ:{I͕ OwS3c`Q a1] 0 S3Ac5W8ǯ7X[CmZGNZ=T/tWGյ^g){K1יveUK:1z2 wMuwwo״<  I4,7'lD۾mPs2s>,rF"r>1L]O{as^anc5aa"aPfq<^-TXմPE&9]?Ub9]m=Bh3Lc Ɲ) kߨ 8'M^cFp,nwpb"ReP$*MΒY+ ̨:jN8M;O3p Y0 Ơ^05p z;7?!s9M!2A͝=B0Ð /q,Øe z"+1eI3,l"BV_s=]Vxib HD$1?=4$ɖeqM~4r:͆SS6,ӗyiRQ}i KbxЂCz2%yOH{A`FZ:|Se`Zc`"Xk}-ngUFTUTa#t1K)*|JTE̖c2]['dv1MQ-SD]5rs$mI8i@t quU9ʖS04$aS''ɐ |S4Al%2bV%SpJhm5~!Z`L2 E&/1eQʎ ҄8$+1)J\{I)/H!W~ # Hade 'c3ʣ !<櫦}ԑLym {ǐS2-!ٱStJM H)Ae@feX15':j*eW"rTE%@Rhyhs?I{}jk>׷)'Ad{"sڬ i_fcw>|%hJr>IN3 YfpF&oYpLN1ҹ;ό̉eƘ᳝d91la I``:ۓ8[:l,RXEMT!`h9*2t:̆T~3K2#Bk DEbL"ʞf [YuS2i&?4v7[uiS2V]zCB@rPI(P\ Dᥔ{~9S"pAQ!xjZTaR"݇f$qZ0==@tqx> lKNEttҙۇ+7w~X2wo[#:ZG>rz;IN}\gӺO r0֎n9]8 mh?x;hѝ]Dƪ|$p$0` qOsWA/fÊ܁kzK G[Enzv}4/!nK/m`4O;Ӝv}Ҝ^0.]г[ߌn* U料7lKmZI,%tR-ukrymɪpՑظ*ӌm+H >+0*˖)=j']} :Guֿ0P3Å bΟ^hA6U$p4Jrl׭/R¾rڈ$``,B*_q'Ґh`%wXm܎eZM7lB6ǨcCѺlV]{y+ ;:ԍ[pZ$E TbO LaRLVBIfU?#f[P\`!: Y@+%XeV%3@\@&mj):z2z a h&ϔ\$x$KLՙxB~EφY.)):%0ĈJk]<կA:˼.b1TB"rv ubՕ6x1?V_D)ҌŠwK M`-TW@D,[@RVDIDp !eE`V h%K (߇x^N/4W8|o xyB(tͲ֮#FFmoIhޱv%(c9霳viGïuV:2ы~~XZ75C[ob=>ݽwhN\X9|=]g ]Ǩ/w~ÓD":̓wGAc|:Yv}q81c/]ݤڨ)Cp3'fq}׻tW"er.`q9}{K9%W/\Bz/M81*+t]AwOd0 ?>Mky?̲o "šR\ A2Vn(]=Mǝ %{r X^v:Mo>۩xZ^hN1!TF 1ls F-m!NHC|o*Y?V-x, ZC׳|Pxøo-e_ڳgA^:(5vģ`xkNC& |]qȠMs[.*tH( %HRI)M"$Ġ9F. $Bn] PQ8"FJ"AFMs&yNӛEN'@ջ'@t š#aW 4aIB7ZfJ#AT,6 T9a <8!{HL~`xܸ& {N"R}_A gš^845m0V+SL!y+b %V' !!!*ăYQφ\Ib!syLQ"4!%TqIm9( ځh$UE>HꠌC*T EXADw&5Sʘo r*$>+q84TT3uY&Y U˙(dk8DQٝb͌5VA0fU*L *KYIbh7#N763,!ͷK)?Rs:בv*l,25/_t8m V[xאy5xҚG}0w{ɴstVOU{9,>gcMG>F}tpxp8tx><[ϱ|!%K}|ñ()P}fmb-ˎSkPffEfvsk0*q1c>L~Xji %Qj@`M@!N#.Ҽydc!!̯R3ֹ $PIAW;*& 1JcnDW/M@oZHVV36*1«j)E"M-%h56`!iM!5@$*&M0&H* 7V,BDrUQDHc'cO`3gXHDS4rj$ĎICQVYB;tA2CHn , II" A8X)NKA>apY`!a<pf272zIbBrJFecA 臺m2x7 9$ I2 z[6$C2 DȜωCE1ITwSN ZvQA>s̙U,!IkYTBCM> B9ſ7'2A⹆m߷]y9"1o4„JQң(hwm x_HGf~~HDE79M+W%tt;EGjCob7Vi ZgJ;'oVq:б bHt|A2zXDZ$l> 9iN/Zݡ`ֵm#xZa\9zψT 'Ai[thk|FOw4unY#* hNa M5Jsjfyn^[>/foUsg_Yr;4xGUK 7*Sy-oVsz'J K࣠u@N_kd~D&>V Z)>EDNI`[uQc9ިdQC1ԫ0^C],: ]M/Zazj?^1 q|x"qxx> 5y _62 [$#ȴrW$Mi! %5a K.,41c^C%犡 wWhNҜiN2@sC~}aҼ73iGԢ}tCY x0h_d&uQ+iY'edznsL>Nd~hNm3Ce2oR-P9yOj2$351֜vYkhNl2?Ws}洩mmmќއof鏘}J%h|4 @&Y~i)%JN٧z`{ڝ̟0%9}ӜF⢰m"r$z WhNc4~~ ל<֎P1s~#c!s/pzTW^\}7~~?5m7gWIENDB`pyromaths/data/images/vignettes/._4e-04.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRG-55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/3e-11.png0000644000175000017500000002077311560531274020731 0ustar didrocksdidrocksPNG  IHDRpK|`PLTEƿwuukeeYXXNNN;;<::5 !VIDATx]vfqy@->kefvp J)z__0+Y"k.> }GD7B ƈ1)Lh=4.k8{p얻|7a?bDD1FĎȜY%W?fکew?f q h<}|DJN]> \'j-5>#Oc,H+I! ؒ(Ytd!+D.rBWoXF_Fu@xՌq: AĐ,X{9T!  F+3! UwX `l %mq3Tϊ A46raqUF@t "3t Ҭg\)EXłz&G40=Q}vjֆWD#ذg ̢=L>B`zDÅGY) N-+HQ@Q{p*%Z|AL3@ Aw`ŔZ{By~AE0M 1 `SNr+ d1f1 )\nEYi82hcր\sa6@hN{_ d P%BhH3PV'-AwaVohڒTY1bEjVR+xNy+U-BSn%Wc-6̧)!:ŤOyrͥkWsSԋ)0 (03T@0<spG ||Dh*Հ>5ϡf0Rȥ:,RJטo l` {sQ\eꏶ@T]A`y<\K @TCj\w@%FԈir+Rd]A7 =J"ĢMC` em܌ sB]a"UtuBSB"|FOv}' iI BhK` 'hA{~` 8) 6J:#rEhLghX,ayU4V1;ǡypL :|mNW42!ڜ1! Y9\ݜJ%:8C "LC.,-KyY=hݲDT /LGSvu"h\ObO89+Ycvb9zG\':ܲDLKӋB5m[ǭy[Bjb zN_N8@vnm "t  nSĆaSlp* %v0`.0 Swes`BT`mp@t1GSY+PI@(3  5 b ii֖{}. 4*80WH+aM҅jiy~ Y4/Nxlm%E-{I4f˓O[q 7/n|`:r]hR̦Mv]KUo Dg&P b9*r3ٷzm9ntJq)\kU'VS 쀐} i dgV7 (.}ApK-->C!%h4b1s:7٢:KaVB~iz<85aJ11q y!C3)ňE[& F J5FL) J)jꬔP L(@UQs< p:I`R 25Ri\`L)p45n 5IPRrf pH-ױ@)(bA@RV:Hy[ApܲRsֱ~' ZQ؆) T0(-5N\"J mvL3D{H]&ge/YYBٜ&?6ݏ} pq8V8ܱ78:cf6C2EOh*#P>/u qۿiD):3Ne60ټ(#U@GzN܋X+p*5DD0i|Vv:aޞ=4#@⇷i;p!`ôk͉1/d s|}G7gBB9bp'Ɓ 5A!h$0L0p H~ Bn  FF1zZ,A߅y Y=[s A?ʂo^6'P MAAǢ` \ĊT\ "ex!؜ l +E3A| 38`JF lN٘@OULQ,4^W vj5UͫUtU#1ikp'`gXi"`@x۵o9nZʁ0)Zd%=fY41eBWhnX} f1fK:0TGhwk@thʁVx)b b*}8|+>RBCL!64f BX.R3^ʗŵYcj8F4 L6y$ZQʗ%< qBɵbwgGD<‚iyF1=et0%*+X yF9lE!MN4c*p==Ws&kK Rp5jk.UC^"e)&akp`k ɂJI5j1jDI恊9?%k0CZxז'ݘU2 6@m`Ymn,f#c[,xm9XZ|&`3/NJiYҳF01/g`ڄP7u3[%A>ք ǭPlK^ر=ї14f7(1ؠ4#Ά+=JJk&g_<`JVyץJ͍i-6甊QC"f1蒄)I"e NL &^)>ru۽JAP >W{O3j>*oew=mBud.N0vj׿AN]."U1 ؕ9W]o&'' 5Ɂ]4>#.:Z(帴F`Ue f ZA/AjDm ih3w\FVpEwCDFlZl#&g]΍ FuP@T8p`unDcS,"@ai i!zXU?Ƨ` 4k[+C) c^u ̀vXcoc3R8[.;*ףLvg KX|S^/Z9Xk U8N66G@S0 |6N3aNWS ه,nrZ3wmx#H_i  qK P "5pMtnhB2a2)6 A, r|Q *p ӌ׿ŻڴmҪ]N}O1Ƙ̚i4;0BK W=GSܤ@Dl}1SXLoVԂ` {5lf8jTqW\'`tC;b1J`\EZ$lCJhPqck>`EFE@\uQcV+uǺ;Lzij9j݆$j۠#ѴpCkGNaH U>kz'63'Xfbp ]>a(ANkL\0US ;224ml#WpPSDdQ3X7Xy|jAeЂ>zco՘1cBnQj_3C:Dc7[,jxفj qtrJ)Q=a3 AAzՔ5|uߪќV8&ϴ~r C`ԝ5n0q,[J7 f`R v gf־[ H#MR5-MCN_8N9@*]bEcSdm2s yp N@X۟Xw+=Tu"!Y%bs0_ b^̅υ2= !dO;s+4FL{Y)Bazh\AQ*BFP&2 ӑg++uvGGoH JmL1\±QQAВAI.&`'U;p=JJ%Tvf# X|iTJJ%THG3cN#ACYZj-A;wJ*X P(p-N+{4%VS̞:w1C>0?ʦt_ w goAu7Ds0ot{o0Ϸ`ӥŗn<~{Y}PDcaspΣwCm=]վȇf8gD;:`97Om6\} >ϲls䅲[uOEhGD"t?{DEʷk$J a|=< (3d2v1q]DS-,zeWRop@ư;w عd>D@ѥ[P0SF|NFIϠqS|_ FP--Ytj=cG?ƣR1J#}MfAG0ڏpJ/Sф 5Ie%5+s.nMX \ qK/P9®Jk4'vk$rᕱd,#*@VU]t<19vrMFZq(2 D]d?|8dJ=\];.߶M#E8,@HY7*K'" ntZalP#|ZUiE&ɵIR?Γ#=8zAx cY[ Ơs4rao:vc݀J"B`]¡&ԄXd( JB츕J]V00ΓIeV1gyʁɎTOD 5{ uz]C;</`"dcw?z|1bJ14ƚ9kujn(N'# aGtP9٭3򇻰IwE<>ac -oJ<֬ ؒB ,h25+IͿS9Y2i:]!FD0Jҧ@rVi6@00d ѐѕ҃@[>#nqƄ "zt 3ي8Yn^H$׏匞]ې'_-ˎ-?mTDz<KW9$2\{B1ǜ>8 ^t2 T0 ^'kEj"kaU ׌Iig|h.5@GU4MD'AmÖ g[x"QD/N_2;ں`tySt lpl|h`k˿(6 2̓STgsnuqXb-BLU]%N#:W0+c}(jAP}]vf Z>ɯB&\)s4 F?bȎZ+NsDFvnd V=Tt׫j߿tWkF f}Ec*_9u1,7EJh~  pi;PjԈ0XWŚdAcSX~B{lhʥ!1 & 3/SՌJRyDYE)==4d"Lpd@\찙'eYB-c7&Td b d RJ&c/I(oNر`xo9H 4t1=4>.5SXΑ;oh~!lv1ۣh|+p műۺ'c}v`t\C/xo~\eIȲ ^?H?8 >Z./r`/%77Rj%31_P^? )qzÍ߷)9r90G ]p_? D2Ax=lW _ .6 CPK#$?JD:<.G8 7}w:P)8jpp 1k fFݨgtl %J?O!Ÿnz[< ݦo 'V/Axp (j$ଧ;Xe ~Ps`-l'xD<(bAǒMLeU>߯V*G@V3 P٫Ƌ}npp./O+M~2[!.qwp@os)s}r(FB'nT9CR8.rN<ˊPvԁɓ:)8p/^Wdv럑pvl>싐_y11@2w Odzs_{YQ?2 g0xkP.?l(^\-O<ˁ{W- ?@fx"oҲ)"#y~G .HJG7 1UcJĶC&qLӻ3xdL͈FOVӍ#K}P"bD` v!=߿UgCOzs}9𾞇o?|c׻7x__(S+hIENDB`pyromaths/data/images/vignettes/._3e-13.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRG!55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/2e-04.png0000644000175000017500000001550711560531274020731 0ustar didrocksdidrocksPNG  IHDR\ IDATx];}kF-%-S&&.Hut&;%u- CduxNP tt/ZW< A Ed>a`0߃$ {EZ\xW^}8n3}$ ?%E?7G<0ޢOOʟYJ@7O woP ]R?aLFc:*U﯊o54Y}f 7h@=@QI>10>xwʊg@f}xR4Ƹ ,˜1 "ni+('8YƠVJa+|;? c x˜gV bPM40 dj0JhVM㺍̫׺BV@+0rGpl%=f= (πSpe~|}'Sr^~IH* /~Y( N$`W?eQ= 9 ցtLFYƛ(uG6~+8QF ^ Euenq{Ga toX t C]ى6lj$ lʝ9` @un68]IP䲠ɁM."3mIX%aX KRH ,@5 anى`ƭmإ D+Аzjo[ŀe C#1w6X -aV@ ctlAHBrɸ澅yZ$ pFY@b;.S,S,uv[3z[ k .XS<9 !yrDn,E/K rvmCqC f6m #T2m[%. kj}ۇŀxØ9lx; N]fsJp+iw$g׺j7nF\gA.D4HWXvv=d Xq!4:e9 Ę .49'7cR8~fIcH*VH;.lQV#}~8\@$۲0O }i-YOF^Z`@&&Hq,#ڲZTvD"5+^W0PYku-.Vh!(*;@Y qk=XuA7U*y&‡y"N"d]}ښu~;)"c'X~aj z@@r!9:pGtwfw8TSr8M𞪶}xK:b*%6逤LH:M .qXs;jG$‚)Dl jP=֗kfAJ7nGc#e{W]]r^du8Cfk^U>8=7xq"y"hO@1qNr_qO th04+x|u^O}-|f}+ "DQ.w,:ZSF|_~Q)j^SFBJ(:X±hr5c[HU 4A xjMcHX@Р˰>ZQ~!_ʪS4___ ɯFI7E*"nO纾݃~}?[d/WVv}㗞='xcyf#-=jLL%9x8W} x=zGoo>۞4)tݚ }7>y$\e[,<ᗞZn4D,4``Up d㪭lG60xZt%!opsXjIJAJ(նŠozokjB$oR@("olr Ǥ >+`ͭ2IJB\*`Ͱ6]!@Lu-fk{7:kܡCy}q;2DH;±9}#3+N}oq3Y~=>~O]ϽgxE{߰ =Q˭Ho$(;M~ %|q~_1[+eA>ڍ[ Kc).Ϩj@~n/V<7tQM.sOm͌) eu(^r"ӓ; 3Ֆ"uK:K3<&K.W\ץoщ'`muhӱN6Qan"d ~G】tp7FrъEl!աcPF}Ua(-nB nE.u.:jvA:YV#$ U(bcB,ts le DIv`_HN$}9tZ ( ]YK[Ka u-.M~0 `5:hCv{X$"ô90N5ߤZpl BqHn OIW|{ خO/LAbDD@P ZvDZ9Bڛǘt2k"y'OBro~ ʡwcN+R.R7nTP^-M۵߽M^~iAϩ?}7C茏2c1u|!uKɓo[OU~3@{EH:;ιo6zҞwյO IaVs75 %yQg0G^3X9\IAN{E,@3|;<;7ӌܣᑶ2E>-)nHP7:Z=N%-i yB]ޑ[EK]a /Ҍi NZ|hsJW+rc3ioGgؽZ;4TY*U9q@KHf"FZD3ҁt{P2<:4#OL\ԙ2FXc W h vf% 0 $7 -͈~,OHW⒙j8֣Fba$a],ͫ5Ն |5K*k}^:W!=vxhܫX(sܳӌ<-8f+*ř<ϔfsG\t6Oεcu-UТ`T݀V/=sK25չ[u<y,OJ\b@#88w1sDOU&v1 ^'tkiC$PnC"Luxa?;p4C'.Vbnsn/Si !ɏx:m;s[aeS ?,cu<' yH rK2Ƙg܍V xw]E7LC}]*ߎX"'* |/@/#e4$_ou>W OV0{$X_@Z7ч{OxO33LiA (ug(cO ޠ+=&.ټbxt+mdnAc{G>eFٙ[C#݅'⽑ts!92Vds@8C"8ð&d(83b *3"|<=L<}^;Fp]RsY?g vU7{E"R]xFr`>!3sO=m M4ZH䊰;4YϛcO>imzʪdl:ЏQ1j l']yV'CAwrkhVo'8\4YFԾO8 B՘ps>kNCѣSe㙺-B l! v&;3|&+wbFnrl!M?F.m>eLxB3#;Ďi19]/&3!kH.˲9aLr8iem[@>T8x,Iifı8Z@ʴHA’<@>qk0 ~~5h`0Qwed, o(Dƞq"(eFp8,jNH2׬ZeIjq< wECT%!%&MB 5ƀ"vHeYvt%=VW-xd=7 /\KtU+8vX; w%jkπiFy`ʐ9vgccLi+0m: ( !*Z1zZ6VQZ˭g@]n!gww[@؁J|mZk9m%?)] H>X4muYGrd ֥'q@T"G $nYDt9's&BKeB"˩~IWᤷrhs. %\.$K9LbGa=i9 |}`/ԴLG]MRy{qO>qI~v( d'9cp+OBcw\`Nupb6hޗ#luCdBTFv$Z9T[qa2Pg9)v^AjIY]i! =IWnh]|ՠ@*([4&jR ՇpRsCj㐦F9CjD^UA@Jxb7JUQ5IU<}<&aNG'>G [;zkVyBeIb!co_>F7P|[{m>g{GsuEe4&i=od7>| 07ƙlϸ1|w7ZaBᢜl⟐>|+^h‡Llߺbe^WSB?tfj~qǃ峺gi!+O"yˮ/\,_?hCbuqIENDB`pyromaths/data/images/vignettes/._3e-07.png0000644000175000017500000000031511560531274021141 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-05.png0000644000175000017500000000031511560531274021141 0ustar didrocksdidrocksMac OS X  2ATTRGQ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/2e-05.png0000644000175000017500000001657711560531274020742 0ustar didrocksdidrocksPNG  IHDRn FIDATx]=䨲Mh'@\-`cŕ_gYYU==sW|j ~"?x Z~` ZiCW?~?НU)ljOĈ(ЛlNZ=Lx|RJOoǥ =F4uo)uoTkuĩ&TPSGNj+@[1^FRӓ ۚ `B_m0DyU?C!  ƀ qaz܏cH ~pBH|=ḡxb6`dٵYv(m]/꾅Լȿ !Fl|d#u}T,b69F01zzCxL2Q!>)p/WF=3VsZӃo'(3rM0jE`Py ]FHы%s3 =vWA<%S츥"Zpi>C:Rw k ]:ԗe 0yd!})xaJi7"P6t} F~ЇZ: 6kj{PFPmAԧFp.Y}EvXwX"awo54nD|[zp^{$0@EF`JG2i^ gZN$yUP#!os2wHhѲ,8;o =[֣xAKhBX: 8 3V :l^K;HA+HWDV!* CHh{V 2-eh-ݩÃ@tι%GW6K@0̐RiɴRua/I(b Zj3#NbJ9)T;8`/Hyհ I.AjYW8EdR4& N)P! @yz ^)UT06 th?@4$>gHSN DqNu &ANd䬵F0w/W˼{2[9=@6J`#Mr+\]R z!8C)tr &"T$4+/ 5V"ocZh萾/ cp+Y޼"J䶵RZkm A%"=F'c[.R{LSF+G0 nė(#oCUCBA/ 0Y6e1 dVhi]4uIBZ00m6פc߽zj "2DQIEZþM6ȕBȣv;3?$Cѡx:,uhu;Vy 3JEр2:t}|D~oUlzbGCP`aCFksi0.&* JJG 6D{-9~JΕCʙ)TZjah t_PkkQ|Ӯ4Rm֎jFR QzV)P=@r*ogTPJ@1sxJ:替P:1Z#dBLwcXɁj*赡5"eKb575_rxm3NS¼ы?VЧ?AH5)dz[~0*Wb98pCx_I*< 1qC3? y3Du[&]}k~៰xT )}+*܌^-/c[<֡/7hr:6'!F("ء4eo:E$f 1 ר}9%q}:nn[/! 2" yB틷r/g3ƏdMǵë3c?3> A;tJɺO`%_EBs~LDW>9WOKکRx8הЭ9ٽɴ>`PȂ'#$1E' *O}9CT|c 'R~~h`}Nd , %$!:ȚVLsgPߣ 确g hkDZ{K,9 fTh&?iRWLa]˲VAdx21@8ͼv\.^:g(^f d?di¬^`?=[ށӁV'N$"fKl/ї0҉sއ)C`du쭩C7NUsmʆ,`Nm'c/~teQ{lcE3V]iE"VJj :5 Z.3ևQ !!54sXj&JG7(umʆyVڃSX-֪Jau8"Jyt8S8oAD] 'A5q y2|rr7XoR; i1kPROP6ʆ/ D 4"R0l҄D٫)S| )ZVf !@G./ko< gς_ѦlևEn րC e(n7<'^!-s6pZK@ar "҅$x쇠NdQ\6:o {Op#z2 eY>8E""# C`M2ىp $]@+u XaIFAY%hZuS+CF݃^|CACPk'VUT;G>!m`&&k3֧ЀV@Pkm )e @ʡGPka TkkRFŵCвs}\r)JέiH1pg~]Xe;>Կ3N),4 SAfeQs!ؼ/9þ,)[ڿ=|z?7 "  ̡GEN=n: ԁ/ǻ@ym5C_9OgXȰ򪵟?2fq=ӆ1h֡/Q"RJi X&o } eCa7~r_"A巄h7񋈇#|)IUO㯷 LfhڌF?W &z? Ƚ3i¿1n !fZ4hMqemڋ(`oTA..f(tKp# kEԦ5wj-A퐦vm9UZbYb7% nj4$;"Jɞ;K? J\Dn{\G6 {D^c[+Zy cMb]byV{0#מ:48H|{ U e|Su>ξWFٮc'3jd]sp rjႄpFf%HQ5sfc-A3<+7[ THP4h[N$͞kmE e'@(DB`M݌q(}4:!  t<3[P! @NAָ%D6оrew?t|jϴ6H"_G "{6@o #v%ѼNk]]56i[K[n$\yi6-3y$mq}ip'rY=lLC6GD/#Ӟyc~:L>GclIg1ؾq?těEϦ?J~BM?Q]~C )0æpai/dH{)}oo+mw"|nN396H ([~]{yPmfcۖK_'[e?DOb?_sWIEǵK+Ͽwhˊs {-}C7ID'+U{&p&=@;b|B $L xNhfs)=O-v_պUu+7S+z Wܪ=[J# )g\ PO蒵kY=%\ܗDe$S1rh10&)5'h~M;o%$0IJ8ehHƣ}ґh~M FӾW%_ ŝ3 _N/3J&2zT]Lm0K֑Z Coǽ 걩HpFxKļf6󿬕Zσ NhڀM$:ꊺN8Q yhw-fap{P6T1:lU@P'+딵c ;+.і R7m'xTͲU(ZehΠ Py ɹ18& =tszx/k~w)>U;} )a۾C0Vu't$}fڎ(GX uB:sCBL ",]7pt :v:CVH+{+woVsy+ mD8,PkVkuөtơ{ 5k 2,{l_4фu{ǡNjM89 .ʤfhä_gC!?r\BjmM(TkCJV{}ãu #iT{Rȹ6vhjHW|N]76Rso*AIWb࿴J?N$isO7P{6?~.L)dplb;* Lb]2Փs#-rXMoIPI 5VYڹ9$ `.!W^wl]c*Y#\j6QTOub/B]lz&1 fW*(eGFO(_bَKBwz0t%[,-ky5xZ̢ԋtnsqVvvE(#m6 U6wF[ IoHL>(p#ބml뛵MxZ۰XK{@PX݄jim/Ns3>VotЗQG/z ܽo#M-?&قӞ"1s;f|bHю9|4"s;$꠺נ/MsXyN^co:h柲~h` tҜ2 D <@Ą311QD 8M2ܨ[3.Tܻt* /d%| _P@ |nIENDB`pyromaths/data/images/vignettes/4e-08.png0000644000175000017500000001040211560531274020724 0ustar didrocksdidrocksPNG  IHDR9wiIDATx휱:H#"`H `äǢ Bw RΞ3BjgZ$wgn@^/|0mc]GX+ߠvK"tgwa,C Q2"""[؜v`Ez|(v0vLS%%rz*KR+ N<4aBCFs*4v ۀhM*M2,͚ZC|653W|MŪ0)^)hW6tE.-Syq;pNMvbF\ە閥q25UdCOSS|4ѹ,ȁ&zՓPnJ'1m,cqjDNq, NLׅTt,elw? slVzw62wL-V:y7,(T3fT^+T3>wC7jboiX{u܎ī SSB7W]Ѓ7!\So5zp]QͨHhx(㜽z{",90:_@M)9I5 [ 098B8-)caIiIȡy4 }XӒ- _ KJTH)-)1mc1x_ B/)Xۡ"O|9>}&!6t!>p;6'9ې1x7B8]]N}ĎvۻTyϻ,́^Z/.no?noۛ9noۛAysf׿϶ 濃B7m<ǬګYz"?gO+XϘ&!6~s'C?t\ֱ_$%>J $ (B6$+EnH{J?us˭Wj YËa$ǁ8Jy}ufrjD(vsnA<4buΚQ꡵Ѻ9bY[!:h]8*QϺ,nPã<&zH 7a+5dfxBtX>=$7Iesb NS}=1I1*IBW%]D!#Q1*v=@EDԞ;抾;z8aLo]0/͐<0zG% bQ ɸ&6L-"1 zlu ]q:j B`yd9tXGhq\.=60795 ۬Y꺮}k2JC@|Os{qO˲n8 yL__΁MhwK^gHtێ, cS3Pn8Ѓқ+aQr@oW{OmJ G@ΡY WOeZk]E#JQ0Y w w]C 7ߞ0۫66aM:v>(~ێpwfGt]^` V@(mb0CBA⇀R,#ÌPE-ċ޶mj{AEU?5Ǝ!@lo2BiYt\ڈZ!#( PP{3e{s A^].kGm,jj*=~`p&|f_x$&mQ"w4zZM6 \09Kwmzֺ;όeJH%d#m*[~u,,"e,8c`l$*qf+Ed+|7v|(fѭ!goΕ1x?U z_X \=KyZ?+݌!t]ȋmp\1xw ϘWK~uL@܋ט?u[rS(q;I1*ݶ"c_?$Ϡ"9nf^t|oWs=XʕWe5(({泙7$?S?=OJG9OC3:9, FGy^>aQIWv^1a$_r9| sl2-g-N?nq?~O`/lVu[<٬|m6lm 'rrRAWwm,:M2Y&q!Wvג}3"&Dͨ=.6) }'4;&ص!h*M$'rhSsRuVפ-tafGv2Bu9Jr?fT;悻c2vЏLmn%Mjʷ88v5׉JZ~;fGkl6׃rK.3x}4* 2gN?b.2@6m62B ;6fKA~]-]цe?h=oXe92hh&sTdޢׁ} %/ bX0>l 60u =I= .trWq{Yh^"vdR>{@X(3$f@M(*9)wa 6|v -mi΁'$f7H5VMS9.fɁ馦`lqH3zbԕpvaB7=x#M׃>2P1؁QЙ Z- z5Xm|8,5a5f38-:׶&Q,[1 ZHoϞ\4r5z\Y.ʦ$AQ׮ 4qS3 ], " yf%famg9.';(w&5/Pl$#~9 ܲ]u]W!*se< 4uY%ͩ>V*G5,YCNR3BW1Y23Q{ꆙPЫ BE89G24>9ޚ6Bρ^#3=EOEa'zy0(2C'SUe$G;Z4BAyoaް~AK(wPۛ?~8>IzIENDB`pyromaths/data/images/vignettes/4e-02.png0000644000175000017500000001240011560531274020716 0ustar didrocksdidrocksPNG  IHDRLUIDATx]9 } ek l)+L|sr2kʬ8H%3ۉ5cc1#ev*}|Px2v(FHyw,$G{yDy8 "+(ZR)Kf 灊 з_Nm`0ހfH~-2Kׅ5s iye6H %fnc[̠"/^U(cZkA)4 ZA\~+mFWZCvoOY.Y}e`vCeZ@R70#C+LT7^i~N8(RhשrP՟[ g.]Q鶴g>@hAױEeFd%BFn Y]_#(-*)de$(%: `$H$ԪӢ~ҩX7F%?:3ksՈzqR}ȳj ZM:Ub1j2ZYV'QӕZ[θSM.G{EZYjRJ]̈iSD*B><-fIF[X"7b@Xʂu:No E.T֙SrP! Ą 3X XfCJ(_@KxrδZ/3B!0(:%(Bk2eCUW 4ff0XGou*Xb9ԩԉTSG2GPʍf`>6H^: %<cv8}ZJ(eH"Xݷ)h0(VKQxtAqY L9(4ݪ tR)QNsinlaG4O ܠ-".4ե`Y4* |7(:!۪,6i.,6ZG>f^Rǭ/XO55x(֯qJՍb倬̌kA 60z~Wd2\lz]zU3XgHڽB);ё ޔ i<'B4 i7lGpâgH,g~ݠ p4( sueY H ׂ6V-֍Dn:UH\#O4e:(_ '=׹W-\6@7;7Z\jZi"=icEV"@Zi &ҬW%بDPb2:#`$97 Ӳʉ#:H:Bz57%`K2re*hiâ'OK~L:޻in PgIgd[u ~ bhBI$Gx=n Bh~Jd))kbQqFK:nT0 ;9e)΂S%Hׄ\gIhU:QHұ=E*u]k#"*-$XP}NWP!hT6Bh{s%*4DD(ȡJJO q,\꾤h[ * :B9HWhV_<%~*jֆZBO51Rcg7ZZJE:S*J^ς$~)3Prhx@B{.4Vl Ƹ*Ÿ{cӍ݌>O^T/{нUYgd wJG}1нͪtP|j,Qm^nWo,eўlgB )}/Pp13vTrr.鿗v\u ꪇ4#7Er|Pϖ OzlK5??G_ +rr9ܸ3oGf( 0)? 8Lbi-1(5/H\-F&_vC 5 xr4>jHpP`.x_rШ١!ty +67o0ag6bn1m+g党ޏWZi*`u]ufTֹF5X Q&(z#-nsDci|HͿ1L D.u]TJ_=|qH\s9.rQo\N1h\`JTOa쨹MrQSu01[묵+S (:m1UԔn~}9 t E{ %&O,֚zt?4i Zk]{d[eנ4)Wbx$i>Ƈ4{yCkD1д zGkm,%4SF%}^0)Bk ܸdr1s4&kjr9Q\E(SɩRM-*|=*﬈BT0:?p`>T#F~P+lKƂ]] 1$;! Ƨ#{;*e7ݕ;4嗘>\'\!9k۷8 n2#: v  hl; r)lA!&3{B @|hgԴ%&̯P(x~0/s?8 Zg477?|hYS39 J(Nss]E|HPqw`4dqzyVpv8fߓԊԺ[)yuVC8X}idX=<:ǎd][oL_n ~w֭jhkǖ//Z{j-_LSv|r1@/VO~L>4%*JTb~M_xM^u<SzNhE=Ve~yr?_TQJb*EdL_ Bk2;2T3$G}7뿨>hi+K%??l~s t͘"ƌ"ݻ4cr^ai^OhS Y*\)B:pm ɌF͘#3ߤinuX|Kw(Rʸt& ߓ- CaW>ݨk wRJR(FUPA_ 쭵炨N;j) Z&Ʒ>'hF.U?aH ϭ[wߝuR*?'@GS#8diF ҝ]D^{qcqH<Oo(SB?zwi(8y(޼7B!͍U9 _*FyƼen]We0%,BכBN}3Ʉp (8w?V5 æ*.W҅aaD>ʹvN}= SpEQ'E`T|tXu<|xr0dW7֭ -c^g`jM~P,~0Q~p @1i>(@muP =%AU"u =:^}J3UvT) h:IG铱 U֟\Z@26dTIVDr0w9(?~W}t|Cd;]广*`-kπ?n+ꮩddؐz{_{@6K D'K|ߧt򀓛/IENDB`pyromaths/data/images/vignettes/6e-09.png0000644000175000017500000001535011560531274020736 0ustar didrocksdidrocksPNG  IHDR~MIDATx]#0 R " " W +ҹݶvsgǞݦiA D ח{_3C8~~C@ o1 c Y1BD ͂LdVL5:XW#NkQ tX1D;z |JFGǫۨu0MP4~# hB<Py;pIkX]@λ'TDs#kj &q ޛPt/I$J{V`L;:B@?#%AБjtEJBE"#Tqt$\c슠tsБ:`iY8 j" g`]<&-Y -?؜,)vt۠f}kun0`P kʑz (J]qc@dqM H.C"&h:+4v& \.6VN#J`:[I1lVUU/YXEdI;& C:*ZʗkX6MR&*/6ŕ/*iUvlUEV6ɗbɂ끏 5TЉ$ZD PF)WLDDGB*@M\Hz*R T1 h&ߍ,6Nb>rKȲoOB<>lsR`6(2[˩N鷿+gD|@pF0O}w)g8rb`L,8ˉ8ˉ8ˉ8ˉ}9 'rb` [?b``&G\gM Dd.Ǽ/V>Z8;iS69b5g i_?s[ BQXA))F1|%VA!C]hWכ4!X` JB ځI .;'rArS /GM+n J0oE =CaCkU!‎`P/ 4D5[2BhRmg7WM#uǮja`.qkv0+ųm}|"? z"_33s[\%thh.+7mt(n. S @@j AQ Q4N0լne>a.0@m6 2뷠/sj1Ɛ;b\t 2߯ڨCk$T~Sv.Jm /$CyQ ª]I!Ue hY1XU}tmC:l9cww.&"SZTjhCP=:bD7yVDֻUO5&BK)w> T@7>Rbp +etRN!2\!lxwyлzv.w Hz?b5΄3mL ǗWzu']>~ui@(F&dw92*ov0 ֯Gt$"@m/|DU1'㳇a(1`@~sN v'"_x\fC[9c~:~wF~!YjŽߏgE=ޱ9$/9,ҦMZ{;  $s\Iϔ6Wݪ/9$vV`*d(S5ƌS7;3s9$4Lɱ~{cӔ"Cˏd!3ґ#`6`^lKhHLs. *vCbf;Dm`kUVYtAl2\)n8l}! yȟ&ߑ#e#Cb͈ 6uՀM:!jtpY k)Wx#:ƌU1/q;ğU &iFt.5%QE8$}mʜT *!˚B!岍TChl^An0!Įq^I?`EQEM)Ǎ׌hLDS'UdK %]ZV!Z*^#b.^b izjVK7r7ɸPEa_ՂF1oRev肢o0Q)F423 Y $& laIYSHQ c14#84Ҥl; Ĥb`҆૝1X@eS|Ȁ8ԒQ\dА,&X7 ()!ȒCґ.J]!ye`øOi! P+MZi,+FV-l]3 HcU 0YZqH 57ZoWV4dԬD2`[I.XvTȨ T?J(Vl9$Z7\lSí6SEG^Z*-)7pJNcbl>O&rH"Cr@YkD`"V72jJ*]ZN6R$SqH>l7FcD^zn^sHV],{*+-lE-DF X?~F{x~#; gLzk'g9$EdCG~ʨ9cVrƌΘ//SiN;pb6_o, 5H2<$km좎 ϗ ?=[1htԁ4Gt3k'>hɩ 48|1Iop>;0b2c `_[PC @ %Tt$@ e)AL)Two)keXijjmvEtnTA\@k&!9D} Nȹ87W9$. ۑlhk0:m 1MCx<(J}nga"l4y{࿏e5(F4h0,BAP6B#vA d4!DrRXA֐n"2>|aX%~=6&"+zWydއN@HGLڀnb1;bv-6A (( -QLJIb0xPE>iHF-3 tL~kv&8 @NH>6:3 R}kxbqCT }˝s uAS}"r@W!dom~adx)\>޷~/R2Ajib@,R!1&#I6O0u!GZ@!u!}ך vrٱۻFJFoIxO8=-fX 뚙Q2Wy 7~(ݒ<-%Uw%<ݲ4]H:;~¾j%p_R}wIڞ ɠH,?GgYH f־ 3G|7ƇL-1ЗjXqH>XL|T/Ca'Gz,8e{,&҉ظuhA]3z!:XbI6E |PmWSL#fȊCth] A6(@>3٢!kkB (ʔT pWϧi z\sUc^ RUBW-A7l*|Jf!ثdG(#%j8~ZN PF + F!J! @/_M\@%fYFV)( jF #X{f ؊B(~^Ytբ ve{îuH'jHsAvsR;jWrht b @3nd!1]Gz5V e% AC:eD.7$bM8b`. ?r]ѡ:JnYT@JA*3 +~``bM4 Iznj>")w 2TEMX-' 5*hx:\@CƮ61/˒t1ɢ\hW˚=; |B;T$dj>?NK N~pH'$u,YVD AR^Y'ۧЍ$Ť̪Sƃ+(dQam,:ŞPsjʎPeC[Ȓ(g\1f!p̩8$? ):,%[/^ Ssc9mLYe 1T2d~yyqH p@|J7L+O4.u4O|`\~O7o=cD}ξt쭟K5TL{2zD9#ߘ ;7~Bbv56޸Cmbه3ɑ81pb*R!{|s&`@"^rpj4jRw=|3e,Ƌ!ƳR0GH.c8{:RBQnC[mjua#)]mϔ+Q '/H̐bϟ^U9(h7l]T[Uk~ČF_qGRЂ{G%p؜f ѡi+W 8dc`<T،PBv`tq玣NPDCQ1C^%KbF}‚T `=gnĊ"=oŲW"q~:6&y q[@#V݋?L=%+sA/rD=aJ ͮ߰>\^ H}$ٝVZ;olIkڞؽpKC? YOd:\3) +e-SH_5`Yw m`3*šbrЮ4-WjA7d BnnhA%FHBkѠWBeUkUgU_crb]t6d+~gzGA@ 4RLY}ۤ. _s+Po\@1vIL~cKp^Ƌe+{\XUm֏0p31Ze6r7=>d;\u![ q|?'#ް&I+O~p粗w>ut*OϚɳ,#RZZq3nxb'N eӿ/ ̋ `QxpH>9aFh!xr,/֋> Y2m۽aNEwxEMe>VnJf0[~K[KaJ{?DqKSESS9gd|6+/Vꁪ.8*RJ_+;pW)CIUΎ}%8:fqHH.Weysް# R?aZ$jhsjX-/9$P{| QtE5Mp)xKf;ԷSƆ,ȵ (z`%9-!/v bJZ+Qjjrv~!ACCpu.ғD=S Lo) %xŏ;,Cc ur^*cWĈdm-9$"+9/V]ksFb'2 yGVǔu8.p}!Q D UǙ+&B|D6`]poC"Ti EaX1w1@*a-WD5["RΩ^OcU2Jɪ ZCG)2c[pH%L?,2Řv4 0Dd(Y݇B;IHf& C1@LVFWƯs*nWגZ]U6BR* gwprKr CpimWZzCf_4ZVc(!{4_|%#A ŷK)E(GNN~BT^QFr*/:9F4bDO9fb0 ff^~{YSNE>{~b@Re%g$ sH>{zKy$, CʏTGغ}C'F/kX}~'7EČ[jkYN ^єA)YIENDB`pyromaths/data/images/vignettes/._6e-15.png0000644000175000017500000000031511560531274021143 0ustar didrocksdidrocksMac OS X  2ATTRG}55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-13.png0000644000175000017500000000460011560531274020723 0ustar didrocksdidrocksPNG  IHDR2% GIDATh=(؁#8 3B2RbrBD$dvBQL`3SU982Bz-!J?a'lnlc3í{Ŀ]{H:@U.WMal*glcX{}S-zW=nִf;59:|| XMN\ SM$]Dly1Wiޟ!%N99ջ=)=uw ERd d|#FpS[N~q9J~N]#@F@:Q@fR&n_l/:Y\_Ou Ft;DM%GV`Vŀ~?X 2PFhSE=Or5S0G#̰M@w 2 /1E`8=EbUCcNUM蔤JFZRFEu2kvAU0>Icq"fD>ޟй ɸ6J%NHo'@: ܡm!5*y=ic92yK` [T^4t-Ć(,V:@ lc]Xd0m+*qZ%na #N)P+JǕY^CeJ񀁝ƽql9\wyaaS~T$`*}oo%8fĂ8>8ODV&k#]Jrnvc2`*/`qUuy!fR:@JiLʽ\@tʑ.I2O;TKNd^1^SW<`E#63'z)~NMxr2z-wXz%Hԩ_\xՒ}^d+U)Gf8A8'X<&?`W/U,ٯi}U,.\d%EVAnf c_0(Λ8D`BcZk2!2;Ң$hQg} FNQVeό9Sm3ޖ|; 9Lؑ6tUl6Xhuɐ 3ʯA]\, Ǽ٩iDDLb. j*QMQ*ل~}ڥ:RWR44pkJJ^uF]VEmgo9ɹB29zzA/:+[d}!gD⃪5a5Щfd'r1/6/ҽĔC93$P"@(rW8vn4ÌK_|Xq ۜԹb]!jPZC)BMe_,Vfu M̋fE}A8<C4.p Iew!!)6qeS,GX0d!D Cx4d%HݍDGm/}i)j " S` Ĺ4 pz#@5t؉⸺=mq{K]^gun?zL KzʻA1hWc,Y\k` @ͽP%^MӶ`VM t~hvsK9{X’RZX%vM0Ȭіf˰ 5|GibݧRŅLPe|s6pJKS[:Z0 IIjJӪmM ڢ~ jdUcͺͺi]1ee{Y/KѺ6m.O;\GwR߮?e$M῜g w !WϢʼ\ʚO^c!DѠA0hmO(odNѬ&,Ơ1Nnޮ3}voOo[?8]$oW) B׶9GPY?WBJOEm/րoiͪ0rR[?Hw5h`UBP e>W Q& hn4"ײCw{sR!DqSaY h9 @Q'D%0C?y|&` )@8Vg8ZyhXnXʛu0X!8zbbHvڵcA[=܇rG߸eh7'ZbѴa.-=? z p4 `܀ᶫ ܶfL(޿k!Wm moF-yIjbj%HYh; N<,GChi~p,Ok]ϳ3p+,s ]R,Fpw4Z~v[<vvEݤ ,& X|bF^7&,SBbU-Vj84 ڢ+EQ^)A)V X V6R&, 4eSV kJAp*d D4Ua Bx `1jP3 :2#WKX#q 1Ť%@ s  H a!V 0nnpC8Y>`D@P Y+R@ tH"ݚX%ЬIpkX|7chMa7G5^@́ނ ة df]2]o!, zb^aqɍJgmx X1Tg 0&o7OH-aqbyt5ymoGp π,pl' |`1YaN +a 2Ǣ Xtt XÁ9+ }D.;Wƨ͎K 'a=7@Z$_䚼38sx6,FV1`PVso'482G\uoҧ6Vec}a*2* ViU?+UdH̀u0_d<aX2]`2a[Kw[02H9g,܄Ud:O*fWpmBu'1@_0}CKU7ozNikÈL!o&:1EaIU'o˺b@-kXP)ͼe!}YAw 2ݡe]g -/A.Ib2_WoMKK46ӟi˲VV,vƧ^nքc m KGCU"b%3niYg,j#Dқtdz.^h 2 ma :h|۷V6Bۗ+jyi\8r7G;(LbH\Kn(^rRB,RsejnPK& #BG5֗RJZx+mX7\76{HR< Q[kF@ϥc+(b-y6hjP9z.o|܄G+e4-X36ņmI/ sw.twϬƵ^t8ƳW(ދ=^cq~=?Ѹk#׮,CHϙhw{ܫ!ȧ{9{66"9D]fms:w.buW:?=Axj3دX43R?# ?ƂBW=q`5ws>2G0(jrZB !O`<]Oc3ɏ :fD^Ji*[ZiO?Q_w1Ư~XTs2!HN߂w]_Tj*Ϫe:̜˿7)P+y`K^_Zι\KG>~뉩 [@b )>X%7d77PIKdY; }X??a!_o ]']D;y%؁y svC)gk8Ѧf;VA!J!;x<~#V߿9X%2DT&lw\}O x/[mڵ;8+_BKW?ob|B^AY#LT{ 4YBFjT lʃNo\s cS`G-.sx`&͉yaOFU;"^. ,c-¶ 4>/zs"d3؟"f sm}k; j8Hsܕ=%dIgg-x8XNj>:uͧ;,ZG?! 'FhR0V"I\F\V$U5="$$74QiUFU"xsg46 R1dѓr~N oRz56w|. w9IENDB`pyromaths/data/images/vignettes/4e-07.png0000644000175000017500000001074211560531274020732 0ustar didrocksdidrocksPNG  IHDRVIDATx]=Ӟ &܀*%!$JUT?oegY Mhh5!1Ju!soi+- Y|;vnӽt!k7v*BRV/ Q]Ƥ"Ш _$^G0)^W'jC<@ Z5*QW@dz KA85g$"= /^%c}*&g_tɌ <=e ,,"+G7vDڹCy*m*Woo%jPAI6y=J ;0 DK\ &%Rk5?.e^+%vӊ`J\Sgg `qXi{dx_ -#@kAgku('AqWpޣ܋[2 uހ= Ch}LZ9MLB `_rQ䒔 X+Vs5N''Z erR=2FdDt@ 1)&ui,y^1umi%փ0Ff""xlحA 1;"lk!D0FMxļC_'n#)Mg b'e6 |AetR8t} Xa8s̠Kև9[pBp+R^)؈2,).r%E,)U_\{X]@Nuvŗ @sHl)[:evt3]^޳ph6sqA-rUلu%AD7l^ \}bLj=U沛_- wGDRhUz0:,5ٹӞih7 nTJʮ͆C5CZ]+؞?۳̑.v,C60]>J^KW?ߵK + / +3;3O^OROW9cZUUd G{ZCP #8-N=Q?[Ÿz$XaB` ʓZkjTO6. +fBϨ*Ejc\f aQ\ 0Mgw D<`'LoB3@:D#MԸv )D VXcHwv:gڎɬC`o$@:d0Q "<;q%rfr??Y2aLNrHrT3c̔/u 0 `'rPߍדBd!GQ ŷH?* U#^t ygDsZR@z`l 5a%$.>Э5Z0˃I0!`Zf/5=P 0I*<5©'VQ i:GC {?'=F,hIf, ?{DHZB A~23f+#%2ZTXEY{C {?'=F,h2@X!a`:P=Zg_!L7?pa`ePrhGỹOrn_klU:Iفl[z^n|7K ôA`_i>f!>L|:QXÛI+AFʠ=`uDbj4P_"S먟DRCB`B790.(R01R){Q-1^F  Ƈ% ˱bE6zC=j-D=Sҫt߄_Njݓ k_5>\r pm#6^@>)+/$ K/7rߘ rpZXOܔ#z# bX[gzan_rD wr zmf'b'Ipݏq9h oݹ=;]A@LCMA- ZcE ~ mh8߹ӡ+熑 9ui_1Hw\nGLm^U?++,\ѫYGwlA#'] #TkBJ~Q?~W 52Osە{ܵ^a S?,~;WޮT5s.T{ߙ]GRПBo?͝+n-{ϯ.6iSAwnC ş:!)FziߪMqNtV DxL@^nO }EcLQϥ>@ c.aÓ+@hdAC9L@du:B)u gsGq,2F`}E ڡ9>OևJ Ʌ] 91 Vr(@xTBpp @B=Ƶ@u}i&aK N!@yEXm3ċ~Zv yxNPs9O ] Ԁ8oջ8  KD XUF l{mB!7Azck?u'J WU@\~Xد mQ> ZpQ[o m{ ї:;H`lWϳEr5k΍4~{8-(j6>#V}uO lYq|ÅI}?=lu7΍Uh j}#V bcqҴ^@EAtGq=@+VnyZX/(3@^q:o8 麑^@ԋڛh)Äηt>4| b_`/M&J/o ÿ`@_3[;M //)W>eVIENDB`pyromaths/data/images/vignettes/5e-08.png0000644000175000017500000001137511560531274020737 0ustar didrocksdidrocksPNG  IHDR1[9IDATx?(g+ :sDF)3$NXN9==LSOwAB H?#?7@)0;'G",3NC:O 6ase۴"7pE%9t'ڀ՜GsaC3LAںT>!OݹuGv"TrכnG^otONEla47a膄[>#|nb D,ʚPYrOۿV2+H ZioHH]=w;6j~e>ϗ85+rY fX,+r ^aVfc%npy\O7j:ND؆˛s3~عqv n#{o>P/jaN+'Z)]E6MIn퓑`2Nך8rB̵抰Ű} slqlTBW4nPba閨:.7[oP/KOq% a1iYT=ݲYc@8K;kWOkԀva3;B AY m uVC`kOmBKTvPd7 s"qndbY+lָٖ$ #"ѫ0Mc5,coa͞nOEIR\ viFe,ƞlnj8.\}lm. Ʀ2ٜ{:؟0&ɢ¾z C>KL(]j+>KoO=}2lu0ƩGmTC*:hF`b\Ȇ[*㨭~CFaozٯ*!Vs(p]6y=dv': !c2&#lVO/ ڸ:uZ, DbnOSf'wl3k?vs!Bk7f=k׳ CsuOmqޖ ٥MA])CգPoQs< kD5{=rP,Vڔk*,y\,gR[5W֜=t@Uj_׳qySZJ-fޙ}}ᦹD5RYKT'G%>܄ vku+|H5/,:h?6>`# "[< ?>_=Sh/3 _d\[{\}3&W>"#USgx&H(}zB/Q _߅k쨮[WO)){z3EEF>"n<_߼5Or?y~Oɹ-)iNQՑN&ˮ8C!ϟRs _5O^^W3L!nk\r\A- zݷ] BMY+eےc_X|kRR*?cOnݬTbƵf L!D_1Qikc]ٟ< wͽG23n;BhJ ,٢ m٩-֥"n+iL!@کo5u Kܯw^斴g_/V%?V8|],cR6c%-s",.an b')-,MS9  gG]vt1,iz(]A~FnG kJ[:w~[04A+>WX93&PԮ\_hac3]CLCzÀR~njCs<3ZItBs7O@7,֡a>`8o&b2=T<̾u.`0Ftaj۪}( }KO}a ptI0$oJ'⦅VD88^ Lޝ\._"mGXGtty4 (O;uN(k|t{ BY]Lv*PpDsJ?~FfROGhzn8; }tH!8OךlA=*H] ӈ% snA7"ҾR]ɣiȆ GD#~H,Z?]Τ WeO r xx ^t]Z =c~gq9 :bZ'|n9& + d CToP3;<k*@,C[0ökBГ%>Q璜i29TOC`ש6N(޴3uGX k2Ψyhg2%*6_rx'{Rc60;(x\_ʒv8dUhQQEz@ 1*z0?gG`xCOʼ VFk nʯڙ Ds8#屲w6PIve$Xk-A0Je[Mi[X+.@;YhC9D4ӇKO¾s6d֮ %8#n랚\iQz|IqFdLjil%eM/ T/akn[_Ma40ϡ9ٷ }IVl\g} (ks1dA)_"١5[ҊgSLcfT89Ե,m3.f Mo"őqcUFuOG@KumO[ltju 7NhO [9מ.1|v!Bߪ-ж;&Sס*n0 @<#V{vY.A|) ħ鑨}!FH^L?(rBH1f( ;_h/ʜ~iH Qz_| Ї}?>~v]*U]JlJqgӓT7h&PlzF>PG Jh7At}}d*7|OhPR_C5.݆ɸJ__cezz<D1j jz̊;þ"[*S::lج觳6ygXwJ4YŎ2SW5¦jR]12W_RwaҼj+I/@uG Vy%]iA¨.,yDR_aؙqfEzVW0$tJU+MKx8'7ۚ n 76MS%9OrnλZ'7}4u}`r+@ S\]$Mn~Zd ktLw%Q49?P4)!89_۽<u=ş/τqG`uq߾a5i%nB טo{߻|9E^L]_|:Ɇ#.NLB~#;?Px+uᆪr7E* i(O& *ryKLs_[Zۡl(B۠c mwʲDGuxyg# =5jgz8/yIENDB`pyromaths/data/images/vignettes/6e-08.png0000644000175000017500000001011411560531274020726 0ustar didrocksdidrocksPNG  IHDR8#%jIDATx\ҽ(" @ʀ11qebak}Ҍf};z?߽Cj4Rnp&Ư&쏊_fsAjfO #r%y+ks1v{EF' ] *Or6ևy9X*΃fye誃o?60URnjoRc, 6S%p:@`T0zB}*\A K+R;Atb[\Atެ 'F6QY]fVcXњKZ *CeDkBQV`pV:SIgٶY61omd-A۠4_KWI[C`J#Z k{ߣ<&ۇl%:D 06i.!x5@yYʪ:@Gv!}l`Y")ySVh,輇@AU@H@-bW Ud4F6M#)λMtFt%Q@$[qEI9LaSK3dD0ah@4"v0-bPRB (K 7~جGآ7f0`F DHc'ULCtT~R$ZjY C&4H5+Ha!Oʋ0H^ck&4 gVerڇDѶr_M3I۾n5oug,NB3ga `aYW,'i-摶:6륁\[fM29Byl,ы(&&#w#,IAoY;/GFNtԜJs wshQcr"p@I{9Vx)画0`؏VK+GkAm`fĽ:PcϽjG@Nj&I0?k|7Gs~ͮ<7;Μ+C :nϹ [ -/[?/<?!".ggQ~cl˷lOnz>Nߐސ{;)7ޔӛwzSNoߔӛy M˨{?%c.5hOD9>]ן&|>;prwahzƗǵR=~#T۟ەoqks~ƥ)ӯ!zʏWCD3_E>^lhb`[Γ,8c폘;)[5bt r ].݅_7 )me/? k 06k1TTRpDsʲ^aI;wӔ1^V1a`FۜyBvQNF1yRΐa`Ѧs%Yƣ \La<-n@_yhF n5@‚xa`}X ]Xƾ#l#O3_{#A:Sd[:`ɇ %$65m₂Y*J6 +˲Ͻ<yV0-@y4 Uu  D["-[ o" CP LP9Iϛ}h jXCʗe 8z7K}405CY6+'SǂE[)LfF= Ɂj`O lW YԺmV58!S(Ey7%]׶(0%+ h*8F`tѦhɊ&HUa4y!T ]qa],P*Ze,H Ft( D^,= ҍ`0:,g<*Q~vʩ ҍN%Lk҆.:nku@7/enQ'cBa`7 *@]ձ nz?.uYd,`\"VM]uKe9 BIfn~q^2F0]ʆ;Rn2/xh+7NN}qackA]vuu^m`˞`ru[0Legm1aS؅:AY (_Ьf0YC4qr8 g*p&Oq0v gRMU$G@r6#[ #?tk;cIWהO4)Up|lM& ߝɸN)p69͸͢׬3 Fx & M$:EͶѴצ"k 6eYXMgt ʙ~n:zݼ?0T]O떆9^MiU%&/)Eܩ1~,PTCw; /;23="EЇ^8&ǧc_ @ 2[4ê884ڂ^!;L1ghLMpׇ>9?z4N -ɣgox}Ǭ3|hφo[?y/S_'їCȧlYuA4# oro{KC/kİ7LW!=݇yRClzƈgV `dc>X{Js4ޔ3 /Opң5{i ]E9$d9: _e`kR.\.GBg& 5A8nP~<ڬ ɐw+U84?3!xd>*ߢqDhx /G@NFBo+xS ʇX`h3mf{&n6(Z>u%Y33H_VeeeAE𶁁bqBD0c7֎UȈ*;{XEF],pGFuH60PDi*t p[3FX#v>pg"g2DB2 xa>Dƾ$tE3eN8^dI~]oh ȴ}o 4ܚ<Fye3`k"L":AbMR+n*wvv }g,2H!sY|F,pP)X.Ʊ^]"0 b?DƎ-7)_YeC|xZLr؋m.o+ӖyK.<2-ʭ=:"bِ-AK" f-mcw^dH&)c@or }{c0P׽ZRǽg0攮ƽtةΠ}ZÞFgtyK4#r11UK{@=0Jhcz.}SkG5I^1| ۤb_y=!ݤF8X/#y-`s0G?FQcČVo-VgxNt;\ =k wO!$&pIENDB`pyromaths/data/images/vignettes/._2e-04.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/3e-04.png0000644000175000017500000001141611560531274020725 0ustar didrocksdidrocksPNG  IHDRPSIDATx=*ӆgSڃb-A[`919)!)1)!@-nwϙ\3n(+Pbd R򊦇~ Kq%Dzҙ._`}"u~ BAAh mjԼ#oPІ6@Jt$\(tB׊ lJZ;tX침uSZކm19yϱC2eQ)..,zImZF=nY*JM 8EZnM.eqiuvfjUVر*CQziv!X=ǩFlkp CōmLalX9eL(Gye62IњS4((E[bӝG-t(QFPzHѽ:3&FeB:4@:Sa,Lukr[ޱ&|ORa[[goBԦ0>έM\j(q֌i `ܐ`$vvFQU50)!!/0h;4X^ ;;?-mgR{5K4Dh.jYRk y{PK4k*2UߩB}7j])Qk;@~EBL n(Z+1se/̗=u'w{uӃ}uwͽ=ܷW!hACQ7w}3/|K~Bm7y`Sx3mtt c'=w^˓ U譗X|7X_LMQX_Z䈥0$4bo8O\|b˗+ S^ H{zWSޚ wP^ޭx !ϗBC}XtBSB}[l%m ]DGGH=RS߲L!/,o Hb;RAjieg8D䰡L3XLʽ)﹏QR0m(hML7i0|YCB`1kN)k騊gO'E-o4C4qY!E9nTEertFM'mZiW9 õu P}ͼa˜.$mR'4A䶯ccX[kZ N:I:B6Nkuqw2dzfD3y[ ֺNg%$ T6P;V?X i@hCF8Vn\Zk^{9=QYP4ދni:X( 7i9 ƚlz)7!FGhsfJ)J\踅\"؀? 6kj:ܠ+\J)EsB)0GUׅQ1,rQ7qDn)a݄rh4Bhs/ &ѢH;ĚayeiA.wGU Zl3eDfäx:K& - ݺk-nq癯ck(ǑuLmt13]DIՃnp]ETkgi]Ǹ1wWuᦐr/k'A0?`, > /zta;* bC޴]h G%I#=،]Llb_116h3qtL<=:_M>q/W`w%V$c /u³Ey mpsö_׃ mq䏷g9|`(z&c!~ю?.b+YkmqC劻d@D:)϶xEӥ #9=vmل۞C꧶)7]"wGi^`j[bGßR~~Sc5tW᭗5"}`X2߃|.m KɆ앾M^/M$a#V*^/M`L6-ӓkYov*S{ܶ=hcSn8v^\*%6c!>|^x982բ5bipf62+Q08D?+nc(=iu'XFM8JCaMlWv2t1FWdM0ٱGHчJH>륪;c+9),;0ҵP@;Ǒ聧$X &GUߡӚP7a؎R)uOVge,;v3IpL &?mXmqzo(ձtjcvòWtRVUcjdS]/'[ܹ<6 Cdm06c1:]jw !!g :-d,sZ}Mjj>&ɝ^*GɛÙzg i{/KıfeG+:>%7ĞJ'@riVe\Iv"z/{܊At[2fq2$$dc%/Mc>ˎVizʒ{K,gi@:& ZgaʷM,c1<c:XJj>HܯUcj,wrԎιɱH.k5XYS=XI!űƘh TKzz߷t]#ڴP_~r3xa9%|i[{(@>w_=:s/Kck[/(Dzc<|cgW⩇'Eod I_gݢIu~|E?–?|#/(m}CSKy[8ݎOU\HRWXSCã5yMR?>"E Gjk=CU%oRHsh"jpdH,fuA.ES{bDV@4%oIJ3/t6u\< ;k5DSE`X9>דX9!d e a;#ngBthУuVcGiX]詏oۍӃ4ڐ˽7Kь ^X*²c߶]hRJG5g v[@Mm]W06&K)^w+E-z m(Kj)F[Bq.$7,JЯ 4+~JǸ#]A.uڱ#(j=N\mkmq?ڴ-1Vx8~ aᇕN<<8yxȅHv,/e~[myZvgKf~c6.6-*K,HٞݤoRhG͘D_$wz^=ލ%ҊWcS C~fITr[,fTAPujr,]< Q+msbHˎ5( Sν{uf|Yʜ΁g˓IGltH[l/7~Lhj^upv|q]a띃of *] i fET Љ& ,.# 4;&=i?+d wu+:F\y8|[{[A/_e>ikMٗsK+{xǰnoVl^ZiP{)2W'ݑ4yV:[QKdOUiVV-nagjV鏁Vv/wq (7(~hf4ȞڈlVUb!@_>r d8E+\CޅrۇH|]yB{i8>VKp%G[飜ьJl+μ~Z?惬?-G s!|k}Y$;78IENDB`pyromaths/data/images/vignettes/._6e-18.png0000644000175000017500000000031511560531274021146 0ustar didrocksdidrocksMac OS X  2ATTRG߃55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-08.png0000644000175000017500000000031511560531274021145 0ustar didrocksdidrocksMac OS X  2ATTRGo55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-11.png0000644000175000017500000001511011560531274020721 0ustar didrocksdidrocksPNG  IHDRO&`PLTE{{{qqqaaaQMM;;;B=IDATx[w:<Ym]y0$iOZLc(3զFUg$7>=nfJf>{A`S3_Nn-FK7uE"4(t2 "Bz{{rB@_m; #Ns7Z+pϺqADD?LbP \ RP (E30y(hsQ 9l3G B̗n,ίTV9:e #MSD.q쐳bI:єE(qhR ~G 1!btC1 `qҭ+y ҜCqZ.S<c=@)%_x (pl@72ZDSjDsqhkɈ ǩWb"f k7YsW%+0#rDֈR*y" 5th>\&-@!c >9/?3|s!u -y2X&-zJ f13T-3v 5\!ylh{o3wO5"n!uU npO] e8#x 0R6 R30xt0Ȁ 6F "T .t`l ѥ?F3ίLs]a`-M "h}^6J|5C՛/i})-,п{km6smM8 &?vus*7avda>8RJakRJþncǩ~rq4^'z) -A$ ꦎw;yOyo;~T)%@Btd#zJ@q8t+]V%X!PZ %h mTi`"&֬{A%O-2LKeR-6$ZMx\ZsҹeT͋=? Pż ~ c4iA&Va KxqnQ~  e̋aP_<-!, tSeqK\.l8x^rǒwTƸX. \+~7A^nlh,+ v q.v^iIuZ02K>˲, ĜvTs#{@G/B-El1UjDža &ZDRW{OJ:5)|:A!5uAP':|dN޲mL{l0s/qtc"icN%*WwrFUDx((@ @ @ < E((+C؁H@p%vdQ'@""<(&瀀`kֺLk,F  w>)jzwa p a*7y&7H~]3WgV x$% Ƒ Pr-,0 ϣxΈH;2! <Ɲa} GQ~dgæEl؅ /niq=R%rcnr5oiu%1ݹ֥ĭKDRth=>W0|w\?k.c+1Ng8c9a@CաrigSc iņ 7Fl+Kg^/|O73~BP w>z@) Ra@D(ܔ1 W CA,lӼi> Q'(ʀPCMjl.iߏ@p у0$T8MnO43aKO0F2f:@s#\9̓ytp~I 0|ӏoM?O~~}oZUJCWsF"#JwRsH겟R'ܣ>@lqLAGI/R@ KDDd@ @ @ @ @ @ @ @ @ @]CMaGB0qoGn-JJ 5@ @ @ @ @ R Bত~k$Jo0$fN ӁB-0|U]b߼(@@I<VHKt,0ysa-|(| lXײ{w?~ Ѝzf9#f_D7ǖ#0 fWֹfCs<CHP V%C\l/ ~96#߮ ,:mtP03C)ajɈ !6,t0.˰mtJv(L 7v@-8}xWw{m%^?tCS:FLlж a:P" p pxg9,흗; +o/ aS K: 4`}a@0 C!@'_CכtJhPz7m1!=Ue}j- &14sWy_aѡx+x>tw膦;+Q!P~:R^ѽRh@K6C:e'fkFmkYY_L?lQ M֦}0).} m,»)YV{`)sWtН Kߩnp^ I%^ /: ؼ Ϸc^)!%ăAp @ @ @ @ @ @ @ |=jRxԑ\  Xh#t @ @ @ @ xc ^ݝ@+AƖ߈Z ! : 7eb%x"RjS* Ja/jAI 4ؼa5i42 P'0R'RM¾ kSQ pCqd#@p`f'g>ᆄBwk=H/5%pmt>{ h gWTX'7 ClلzOpSJid??\EΊqqhbnTdκ@ɞ@@wȾ&C,`8f!g I =TnݡzeB v'1aB@Z" AY!py pwC߾D m7 LюF4Is}WK`UF{GeO H5\Vp\K:0^d =C_mhu}Cˡ7[inJ;9Pt\ CB '74RӁٔ.g uB 3/@k 燺ˡM|ث~00""Ї}. &&O{00hiEh\E|.-N5@Hn+u ^Q c( }Q xN%d`e@p^ @H xi68as@)tJ %^~@ @ @ @ >@`$M=D D .9{Ʃ>+<P8K7$ IQG&(@ |\ % fC`0#A?,%Zo'2 S^^ [fA xJq ĶY"ES@@臓Ƒ D?c:? J<?M*!0`ZS@xw-F&<Y¡^R xt0 @H:hKM JMFkl8 |:?^;nٯ ŁN}7;ϟ|A7ro@j8pk(c`l#|D`h8l1+u`(JO8Ck JaIVWu3> Ø=4P84iiB| =!avPFkA %K|%#vs 9"G5B \ u-2ח I z(!v R~B\}]2V\9^8 oK=Wmo.Į%To6&,n<6k2]>`4@0 C,bo@ꝀI:Tt`qy NmqatS: X! AͭUW9\\֡N 9,Pㄜ.&\\-l6f\߻۔4tg1l֞4З @le6F06hP6ղB t͢_ o_r/]]|mf9:)zUz 0/b g^&l@ {L x}1 nhk-)!l@ 1 0[ %@p @ @ @ @ h-ޅwaL@b=]X:!t @ C) 0|F% 3~Q "`; )qO 'I%xtG@a!=(+1`^S&rǢ?B}Ʋ`8~kJ0,Bu5}2FZͯ>׹V#uFhRBPAFM"Wy`=h@\6 >M$cf!"5ޡJߒu0WSt aD )!!9 Ϋ)N=0GĄc<`$nE׬1f]ojJ9D !+g%`[L A k0z}IÎk ;sG;uc p` haGQ]-;KyfO:pn7 ww-HP>5z"Rʫl\ ǻ}F&WB 8#5^ )vӤw: ֩@$՗1O^k+J@ ؒc^ L @ @ @ @ @ @ ~@|Q@@+`ҽafщNK\҂{؁R IENDB`pyromaths/data/images/vignettes/5e-11.png0000644000175000017500000002575011560531274020733 0ustar didrocksdidrocksPNG  IHDR~G+IDATx]9*2Xv-S,|\60щ!'OwA C@DCϾO >'tY|Om\xX{qi&i8`ޣAÏ7ضXu_Bx&a28u~h@[>p.RV)n@9pH:G:>AP,!+я "3T@@^ ZxXRo2%vxAQ))"NL#~G fRⰠ ǝ//;M[96vfTTY m 5Y(8ue-e)J ! WJ]SE$u+ JLH̭?w]o B!! _VͲ46!HQ%FEGQۢPU7Y ( .d3Y aa`AGZ̳ތF^Z9ݢlemTypU(\V=a2K ZNJ 3YTVGHI'rf̳nL{^|0FɹH- 0jy >aR6 wV#0ji&DM*MMu&V&T1gkl|}[9V(m<ĠD?wZB 2 3 j!7A]|&1(~ 6'e6 1 aa|A),f ldYE*ʃQP0 G/+z-os fy.,MK!̅铖 ZaRT0npa ˎȭ1Ȫ"˿F< : u4@JAƝ|_7K+N9, uS,:O jF٠& jy;e,=6T.x(WC;4PgݴlRemE9 -xph#v++O}@( (YL׭>1QH{^i9 cRaVuZBT` bLoY(*!Eˡ뺮Sk%?rV7yQ!4$VlhR_kRۢ,RG,D,C(j&%w q!t ;nXE>EEca#pQ^_^{#OKVY' Fpb]8(IL܂ f kDլE{Ln=_OZ 9FbVTǖ&Hg_n=90q@ 0Fta4s7@yF4gzrVlz(@(qC:Q,۱nc<`/\.QqFF['flj"Kϡa@̪ IXTTT&6F!ѳ3cd9Fe"C$ak3 ^QA@ R $f)_1r0L;6iiBoET#& +{`ؐ-h!ފނ9U@9б'8cnt DP16c+qKqM%]D^^cº$ Gnѻ}o* _7oK+Ғ|!hV:UD -qci#Ŕvlv.1 ŸmΣĘ.ykբZ%돊+Dp q @|yl.&Ғ|J1&/9c6VAiI>BoYM܃й%֚{* *׃QY .栕<O(9B.?_6G_à{⨽_JԿWC{x+Mw.g9[ ro ;,b7BNNP/97,v;؉-0\ :-?՛r%AFw:L%8z6[N%n_FBP9E)B@Z &vځO_ϕ\vDKH@|O †Ń`"0IB* nYqņ%SAA) L 8X{8F^p3rm] 8&Sf\=d@xarƢ Ƞ4ziA؜@," Sf*@Z>#2 30MQ3fa [8D'!9`7MF@ނ)B`[a-k8XШf n7~0Qk6*x:`' _jy e|nH) ƗӒx_˂zk>Y]@۞FSH3-oӷfWS}+'{>UPϵG=%p >K?iV|hQw]BUOx-mD_uk_N.z 'xpz{s@ڪ8+Pqro5paJ#<>DC V .e(WgSqq{o鑭9L1>W)_~Lc_ T!\S^:ވg.Ӯ\y =XS# SBPE"7&nM@ *]u_'ͧC\@H2"Sy{hF8sCP*'cQeH @ذ],X$Ѓ@beF? ~4(;9#9 ;;K S("_v@ZkY@(췁4_3t_Gs yܙ S?{^v(YߪѾ"ScmtMNW#OC\ !BuS wd 9|8Zv;N i?aa0Ԣ~zZ Ćm@3yhnb"`=pBnyR֡6}<ȿmiAMֱJk+M!AhfcӶHvm\{>o]ьgMٛ{#9eJ`TWl6+B<(VO5m T ,"x} o;:I۽Mᢉ k.OoxV`*tfRȨE *d)BS-01N o @\}AitΕPDŽ&.{\.mzQÄkDvP#Ek(|>t%E LaP%hf}V (<Rgk ButJߐ@@>to;?Y݆oFģ^SQT{6m77Х S%cbu.4q5iuou|0~vA',5:ݶOTnB&~@+.ՖjUhUD.zF٣Ȟ@yMm W Kn+ǰ^_E?Q[gm[俺ʟyֶD # P2@!.$B7kEY%@O5Ah/37>a#pdj @ 5O_9u;[5nrG٦[ <ՙAs`۔$D:n ggqv yu'IKvC264 ȃxVEqƞl!Bh!]Nw5(rsw>8] @E_5A{5נ8{ @_׀j5C'ƸL7=zD Hm{)X;P1]y%׀?uY>)Ƹ6 ӹO;S?@ѺCW.nzj!h^ښSy"U"pƇ^wE11Ƥw*c̱&h3{ye{e93c`أPMw {wl1gW!]gCO@NB#g,WO{O_8?[lԣ{?zqX|<>Wg>{я=suo'_ nO,)<-~$g G},K١Zg؛9A@t&r='+CD? 09oߧIE =ny d5xOC2]VkDߗ?a%~@`T]zx_tNs'.Ufg5p@"{t.Oj2"E!G !ucOɟmWn70ZF-yxv tO D7p|$3xZ@V%fǾ<"$ٱO)??1bSHvlC?<1 ?!@ae~j>@`qVbR0=RZTX\ZnO_{l×?Bn9?!Nc>ByNŽ.,Ll_U$ J>FԹ<&"l-XO5,M^c\"Ō D Z@Wc{!P^(fף mVt! P ]/W%PT =3NTmʶ~r$\ťIz-LӖ= CyW{H>_6ۑ( * Ԍm=}DJ}jVrbs.sa&cɀQ%*/Hp%nF6Qjk)SJ)G䈣PT%7/έnRcr)7#b*%kSfb/[t m6 2ih뀼Jojy!洶 䇂lwҀZ0<l-( mK$m4 ~ kYaVVlbrv%ȊŬ0mwrKڤqʊϲg9a[fiqVlX0Ef'>: nZC2UǬH'V:˞eTQ`dY."OLL`"zVS !&tz a|(n2 A:YKWMXf#BD@MCI(z繇AK5>0yS zon]vpt@mY!Dަ3J-ĂB+ނG!@2xeEOKm0 o'w;eyx~ !Czϋ֮( ꭏ ]ZːSa[ i? &_O9V_s L(_땥JVS4˙7 Cs^-M vڞ:YeW*U`_)@D`:=5g aWJ.FLCg8ײyQ~ ,-1[PMckcTێя M5 O]8 xM$1ǣ,ZE qQ $qH=-Ӑ%<-+&i(D+ T߃y36'9%HQI+1^1 p¦ڋ6 >x7>3Woe Z ւxno# ,Oy]=}W8=@O̧$(dU3L ƁQ1;e: MqQ3I&zf"8e f(p38 y7xiɨF¬t78~s\o ~ez$ I6{7 zfnoE\ը[o 0sw)`NR ڄweB]~ƠǸNokҁ%gb5R;[i+@ ͼRڀ9 +[&L5~rZA.%%Kqێ& })Ư!GENojHx'O5/#_8I僻?R?u 75l2\;y><ayu j8KM?~v'Bſ2ʙMV߰VSf{݊6.\1/}bl2ש$xz4G a݉pJE)IT{wZ3u?JIi Fmd|pZ 5]qHYnˎTRoRf ^8^-@P0oA;Cߜw9NTYKU y z\KȮǢ 0'G 56d[6.->Fҁ`;Z2oWku8 b嘵<_@YwIǎ:MXXu]ש.poۥ @aR` +BooU.!s³kobapEZѧ.|&}EZF'>,O ̭|j:T)ˬ́Y&8 ZrK ]Xy(G[e ql#^ `Tjݙ=H4C}Wv (ڍ slLHmؐA‰nuV}azdvb6 ;tK䬺P,`gg`쬤3 [ f ^k ofT#Pꄻe{d)ʻj^$|z{9Q_󙏞p45 1 t<7k<`w2pPGƁ 4rB?lE{fn!գ붚S\(!bts>.zdž ͩR9gbLv>к.N1kY%THG_ھ3R\m[.q8񨵁\fRxPbL--H*:vha-l(/[%Dp Oޖ\cVrg6l1-վE$D Fc̗tcL7`7džwʛy_9\A2:7=_$>[4VλWb֠;uZ&l>=|pϞ _6to!zytGߣvkVh>(T+/4_z8 ۡb.JSAtUw.m\Ѹw-<˃Q_xI~pd锿,N#>8 _Ez xB;v kʼn|Pe6hԘQ x^΁P.^uܾD=:wo?Ιs@}|L?<>T_&r&.+V~2pTAQ~mV@׋_u rqy^j3ou\caCQtmy'e_ Cr];?[ol^E]HKߕ* 9"GAM6lg\5h>3✪%RB9f%"nsC m|/CKni%%}k2-TxݨyыLPQP-3\oi  [=D̊o 4zGA[gA(~<*kzbŰiV"ȷ?mY1HEo1`VrhN?_ƨ̍3L ?&-!/ZƧ22gu,C.g+ rۼeTögȮ櫇%6u'\ C*=Ÿl|AoVzuVa\\ùbcj̶kNen~5i Eq_6ףύe-ֻ0+Y,19@BjVf7lȳ)zr䊙sX!bcYG"[;]=+xay/8ܵSY!-T9S %2v?-rYrqi~qc{V}X47IA "0^5?<ż~fE`{ϸ( cys"z4x V&1)0e.?|=u[d [;gZ}Y@b7~1JNiM0z|Mk8yrn@ ¨KxAg^,b3.@nC7O&g4pwAg(m؆4Ii1~\oW&d'mbZjx=AɲIM0J NiMJ/Utz/Lȱξ/z|@  B m?s羅ج@O֜Ow,P wYo^unՏ;KcysZ[  G=yTvUuvqH]qw+(sԎWWg}߯PQ<;'\Ϙ"ߍ {X>aU&'};N#c4F;FiMĿ}BIENDB`pyromaths/data/images/vignettes/3e-12.png0000644000175000017500000001024311560531274020721 0ustar didrocksdidrocksPNG  IHDR=O+`PLTEŻyvvliijTTZHH5**`IDATxv۸ZDb [ d'޽ORd @F //;|&9Б#3pϥfY:h˕$R*ؚ %e/hLKO^?~YK5ZS'G)/T40iDXGU-X""A{r>z(aP ~|#тR'I= JW3uГwO:kK(tve q&(;j)4_ ϕ=r=6:-K" (RCVwDY'{N (0 :6 vE`bmƒp;5yiljdy'F";yS3#ꠣ~>T$i E\EPq=xVGF)r#VT5tɭ5Sh ƂK#,lf6Z9Vͯ[8 L멅۵ZL\j#ZJ 8kuf߲nD3c=b':mڻbG^3ҳo+KB^_Q |N{7jszgzQFjD;ȝhG/ ,Ӻmejc3 b봎}g'% IInH(9D+q9sXgf5Ft|ӏ tJAFZ~RnFP~gk(F线ԈfjN:N3(Fql>q$LF?moe̘g^ŢA-0 "-z.Ϙg4<fK% GP6pmLkoQّ)a$BI1VVekpCEǙaJ^c lUmUF9Jl#/5V(T|p4"zFp>G]cVlqm/ccj .`a'$bP{'*1b ]4D(Xֈ2f7C YW.QSQv5h.Otv5b]1jc.-)j06{+德|Ehњ]{x߃_Bߞ(u)(Wu_űkJV/bSqݾ!. }Ŏn̬푒O{o 8 K={^[/ƒZ0̌cf;vZ42oxo_>٢eي?l[|P8C0a%8 7ðs_Q}_ֈ_|w]%:/ m|mKjoy'}ٱnWlMkNneZh@d{4U J臈 ޏ|wȋV,/j]ݶQ~R iX򓅽t9\\ٶ(?1DSf,!SaN*^"~XmٶM?%RGs-fE%CX\ bP3&.Dc=:Չ<K9|T=)a1RJ!];M^z#{U0u/3qLȁZ%3#nFEL9邮 Y4Xf= /:o9fp 4bvԥɿ` (~ܝhV>^X }@-L .@W"sv}>L3N&4#=az_GM#yEFL^tOF#bȯymV!w~/C}fsѵ}Sk$XʴB qYJKGyl18nZ-gKK^!f0a!BhuT(eE&n cSS.Y"Jb-=ck!fOSs/yqqQįN 3A`g^V,lfi"O.^hei(Լ[0Z''DBјCOpcO6m/Is/%4KGh]! Fbj|eoQ/z-঻`;N?ofZG?7=bRQ]ɱ(0=3oaTWr# ,ӑ;ø)Zg5(jB O1e+NW݊ +/ Fa;Jhv/ulP;D+`J=ՕWvEq[1kdz݄^ӪSQaTjzQ5*25;`ezZ|Aѻi4DQZ`/if.yr|޷s?OZӹLf >+;WDGhc+t}-mP]FF/nq4macM:Lo˘v]4]k#킢vrQ{]K_rԂBE4E+.ZbA (;3<-B0s\F[FK2])MwZ奐P3W"fk)E[Rt1V)P"195ܑSf5WGUFb 5[YSTR"l*^@+Zٵ}Š11x_XR.z%FX *_LL+>s:';/yyGƇ\w?9;_x>+AOe,rk;JN;_LFS<ƇMcQCyf煐wu'=~~E0pco3 &FF] N NOpS`vzv>AƃG9ԕVY>/|W9R9ߧ>wNE/ܺ((Y_96x1 cy>wͿ%ocK{}GWw{9~I c7_sU`5}[@xťw{U('MihyF}m,m^f5{fYcmۜ6[-_]ʶmml[{hcs=Ɋu_c@_|M}\zl.pVҽYfͥŬڬ'RSe:V0Bg`{#k3^[Mn !yƒ͋w+Ftw N~d'F^o:m{yz^NkryZyJGMnj+yy5_J?|2{߿VK[R_pXB˷ٰ&ONݰR)~ƍIprIENDB`pyromaths/data/images/vignettes/._3e-10.png0000644000175000017500000000031511560531274021133 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-11.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG;55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/2e-03.png0000644000175000017500000000771711560531274020734 0ustar didrocksdidrocksPNG  IHDR^1IDATx[(}1(%b+MظxؘERfw9}f$Ur)p_>]H>b}߾`) Fie[_Y?u|OInx?N}7V0:I?rgԬߪ{cI/Koo0I]jim,q `) x~Nj_-Ay)y! 8:s> =XWqhzR[b ߁{$\<[qt2ĭkn_e;ea[\OhdGXb?CXY~LMކ^/9hoYЁoۧi C7_UְY$DgaIt$ vEt0vf&#AvXQRZ9m mTNXe@إ!ZJ)$Vw <BWu"m7 X ]+K0p&߿4M<},EiEPRfr=. +*$N0, Kb0ڝn: ip4;E4hsmjgZ؛\t$sιN0մUZIZtu(ܭ/[62$(eJ =ǥ l-o7ii2[!B}8Cm9xB ]t iELk^ʘls;=us_( Ӗ-`\<ܷK?_@јGvshփd'DCqX jjKl3w/q`œESQ®-D8̰+kLCBT㡽ײ,X"ĺ^"N܁Zfl,XاDdY; ې %^XwW7zeVvΚJj*m'Eiݤl)y A; %g<4k;2ms[\LeQ] 6jML{2̢[#HŲ4pƨ"c\ppJj) DlDH!j#Bb&Vv_V3[z M_R?> .gwZ;m"[mVk `k×긹ɰ_Yk':v`bɽ> b6)1X}4v{\-ݛzB+@PI7Ҿdyu6=t<k}>:"KǤ ͞Hŷo#S#θcWN.]oFm:i|o@]KU7?ߺ~[u5t+s}] KoX㲢~iA$ƕ6g9f+B9ՕEg3P+TXcL ?<˲S:gGE/i PKk>X;._JqtA039پ?w>,{ǽE4j4ɦ_nV$w\mI7+OB􃟍aN3.q-[C }]~SH7xAg4MIYŸܴq}MiuXSuvCܜ|NvqnyV*ٕ5eKZB.=o] ?a_Բg*A99Ϯ\l̪l9٥dkNXnƁpKS=0oWRG cR5C}YrׯFSf+0[߅o??~Yߜ_?Nq炿`_J/>ӏxBŮMh3.U'I26 >~&V$}Vҹ%Iw) ;6N?^ `}M X3_V)H|r]~Rtb_K{LexQ_[Oا~ p+2NBb?Bt:ξ)ŷu8<9‘ QG>t7rw̆G͔6{fr ,!$?9Ɩ B6J5kE_82n-AIъ)%PEAv`ZRυ!ws,Ĵ^K'J q%{;Zg4-tl6E沴.B^Z]z[}ޗ4o,(B\4eM Ⱦ !dWZui)j-elFy/$(T{%n%dK?Xr2O|,s\7aY:_{c0A^_w&Gr1Yfn`эxу*AweUK.k~41O^/( e]Ye](]%#|Teݬu͡P,[Os$ft}#wo1}l-fOa(jyHHp1`z]0 }46^lGqNƙ٧.q{@698[يcMӤ*u\N,T%aǨas % jBǚ۠.@$T ʅLK%G'@ENzWصN"qtrpєlj o-1# E%B[1{biכfRf3I9&eZVf9(O)e ݪ-)aRfF-s|TՍ02):Kz4ݓ. S8e琯9\\i_$?iؔ{>Q֭5;ݽExo,3~S?B}p8Z^[!0xT:h}O͐?2>N|cǟV|I?okҗPG1\)ufE&/yyOV|e 9GX_"p[ B'佻B'Dp:ueݶ# 2a>4Nn26}qn n Wb :㨾.*cew2:stiջ au-V|SɮO$_o>2YKʖRϴk"u@`_p~G:yξm^6: |ң=UEEyz.r]F\Z勪 6$ "׶1 u!BsHHF ٧8k^P$!@~ϞE}1WFDq]Uҽy#sC@ꁲ}Bt!Twz"0<?c6m ?{2[ާ"nƅQe BQ; )ͽ9zr \E;ZdHmncQ]X!9zVAqu'prdsђõ>`|^j|{Շ 5a=^FC>D/qxҭ\!w7!yVܱ9BOf=̄@2 KL5.5fr=.3o3瑞~XA_q}'}?eDDJ#,z\.>^mT U5.q.'Oz":UEAP+*r,Ư/ 6 K!d,Kw@Eon__ ,yq*E0//)}q+,ߋ.Vk'eig%_21.(:z"x!9$gW/*[5==yI_oBuzY烆y $dBuZD)q*;"Nh>ϮP, S2?S(BpPJZujm.nS\bSϻ}@hyqN" 1E. :Ipb5%{*B>Cg+D7Th.Bpio +dFt9?6֜Ő}#]Hw-se=K݅܊C뽑7Y~r}؏wWiriOqݢrK/QP&9pf\/*|Ye,~?3y-\/ru2';e0%.E*=nBgћG:#\r*<ӎԿG?]76q#tykL[>Vlmt@2{JxK^EܗSngD{yvpľex ^`v5 -G$0C` !0C` !0C` !0C` !0C` !o{A]<׏}_jar 0(@6EA^LqJ 8/%-@, ,۹K*GL)e&u@IE.CwBcF3J[ˬЖQ$p45!{BYQd>A H={ !,RFX:JK07 Banݕ /DŽ+>B^/·]vp< IݥIq"=agG #U98\졇23~ xVѪiz e l!6TeGTJW0|SCC@ϐXP3(r`Ld)cu&P1 ZPR_΢ApޯU* u?nKя'1cè; l('1@A{kb3cef\a 6 nq+_xCp?5rd"PpT J7XU@O'PQP1{;koڕE_eRxz~0J"z.聲 C><]UJ5O?JEl *!@LA. DKr/ĀУ!sNC#A(m-s:aXup>&/@?z Jsۧ3 ->AwZGޟvi N-!pK@:xTY47TH.IaOLgћ~~;:~JoZc ih.hH_>6'1C` !0C` !0C` !0C` !0C` !0A!z$lM3rۋNT,X$Fy)-SI_j___t9` VXu` CkZ"C` !0C` !0C` !0C` !0C` !0#OO71@y`0v;Xc !8(J;JEwiqC@TQlS/ _*]CpG@2$AIe_(9!#EBaM]O'D@{L!_5hyaVX "e"o#CAƲ"oT{Rѽ@=ՔƉ$Dis1UrKCGпO=EA9#"" 0" 2uP1;Uz㩳.°΢D@/˺'>Y<!W'1.?!4 [`CKDO.3Cp7ZcX$`u[ !9Yu](s8R|*Fɪo|vI (oGB` MC36 44C44UihDQ!xXI !0C` !0C` !0C` !0C` !0C` ml. r %u `^zTR뗥]CUVX0H`C` !0C` !0C` !0C` !0C` !m|\ȆxTiXx_UwC.WˣFC6`"r>FQX{Bp_JZi-o=KR`(=לAin!D.3|V67wTYJK0whCX ŃwaM$p45p,rTI qX$xQaFq(ȀrE3#Jv~_ІԈ~=&G@FfX2cp; j$Ȏ(D, #lnnp=b:2hm(=Bj(}A R+ZqCYҖlĘe-[Dȹe#"g72ﴌ*e]EgbbYt9מae4S2Xg!k)~iO;я| <'ņ]|CiT"PP!eH C](1ϾvCm#uZçgjpr"7ګoف,!Χz|SZgѷF/W(`7ӎ(5'r^{(vyك 8?}_~cnM;9TQekFy02ۜǒdls:Ar*Uc?K +,ʼn!5EqpPFPrF4vG 3 [y1{G*$lsbs9/2/+e zAh~([| PZD*#gٍI)#dO 0 LW3wFDq #)[?O+{mGG:`^{!OP5UQ}eX`^>NjAS4.tYC6,`0   CWUfV癗$ `Ė@֓S O-o(*yc̼-@J%a~hkUP˅<:vAꇊQ5;"~_`='vbޡ=˄ˆ +rEup@{qP+23zT#hǂ&(dlFlp{tA "_ 7AMHgC7;0^SPos% ѓekݠ@슧gx=z S~n_/IX&[ |jA@NT{~+?=3XDsB<@`j|XYS(ڦ-W?M[XјA~]UP S+|&L  Ehlj;MCcχ ZEQ QsOjufWm\7$ zek/"Itt%dfxCIeDBN#|*/Xho:N$|1oE׀`@簩8UE_CAUc"ڊC.4}/ \RВ4m^@c)+J}'8 f_uK 0,G`_. Ȇ8"+v!m!&RUc:0dYQX#NߡX Z@lo7A},k(l,{8ŋq ] ,0@͇}d#,*DU&iD|GgwCS@OPlx0}1N Gx>7<1jӗ}M1ISv^O lW" oi  m͑$x_`S)# :o(-Frhzd#X 2 -O/EHVV VReVo! K.ޭ&bmaAIY=>M7fP' % ^u J]"Uӏo50 S=\AaV \0KyʩWP"iP- S 6ARP*rq@ X{ TTJ/8~p/_T+Uz8(4(%0 wʛ^!Uu~B^/?ЭoU)@ش@5PLoaAQ3y=Y5Qq  J`ƍJ>Y u^R ϥZn>BRHROy^=")$ 2~6(o]BͭIMi5\O9gՖ򒏿P-%$U*X30IE7{2r5pE1P[?vI*d::X $W L3f:FՀTdU tF7t ۇߎjL ң%v aޕc߆i6Q<@ r p{Q> 9`I>ົ>pns:myPH^Ƚ =IM`EHGx5=瘞8^)R~IΗ >!If .EMqԶP9!I 1ӟ}uq'C#  ʢq<$qTueO Jx1A͘KrDDyn:Fu((:0,cnMd4LU>~JH(9bB=I6"U@} N;WDP ƽeDE[%A:L;:kok$A IP)|bKRܶvA5E#s7bm% (Uʀy~):*?eF_R9ފhM?,þ)6(~=Pf+YEfi4J/uzs ' %a^(_< 2[c( 3E'KHDzH݅fj], ȦP?tFIc$)GL01' W`@'EyR06H0ke@? `tdue_o+e !;MNJ>G'B( nxO}ھ&Ԣӻ=#<}Ь"U$n].{um}\6"O 8.qEtR?%Tm1D24 eڗI^"ї:_En?e2l,,*}}>F}zf]$QVaAלC:En|be$V&(:]wq4$Q6QiĎ! *]U ʀ!^@bdZ zwP.PD1M^9&[:o(E;#y9yڊ ȟAh; H wG>Xُ @1yQd(xA#4BFkÁPߕ|,XQc ^)r4B ^)W$dMQ38 O  !`Y>Y~5vKEvK!I6]yzF6"#1Om 2/A_$@Tӥ$)E78=OXq3)$9Bsq2`*Yau1E&E{w!͑)pMPt*ҥމS4FrL4]4!If \LK (-eJzz]F.$ItN;8,)$ 8H4Q<$Q׋ܬ~ouy |Уemg&Y J}'ѥVtԠo~FI6N&GE!H.*>+̠R[+ s_cK|e] y[Q \Fxax:Ii"a'lt miJ*W3BS s뽀P mrIZ6.(l3g|e|Pkp>\BmP`[!i1M`)PZP^)+b_lf9P']EFB䎀\O'[Uְm-@&@m~ChG`O=j35BH F9ї6_ƿ+D54U͉-ed;elK -V841 fo.唟_']ۘdwYiX,CYf(]ͲQ5Ͳ:LA)cL8;LHc8o0e(*jYfB<}oGOtq@e&†Rle@յ ۵21uYfRXiw-9 ,3zYUYfI(%Xʭֶ%R4dm٫@՜ϖ-^t2yo 1. UT,32ϛ[3q`*0ȦD#tӅmA; @*\A6DVB gk)20Z* Ȟōh0ta VX0ƠE]^s5'@ v Xbl^uF/D; A.UCѼFd -LnV# ASW>\<`R)3R 3Zd&0 jB}&'EIBƩ05Ơq&d/sz^p}ԩޑe D=NψixixXƠ^{*CVsm|.v [L9 - ,A3]n8thZRVnd&rE اdX`g#nA?C_Y U#?X`g`LaW0f#eCj:y;`L׺99uC 7 p vF@"F‘Oeqgeх'd{5NX UdZR9+Cagg_,35Le&˻&eF}OBL\<;mPkzC/Yf"d@'nlnzDy$2#rF|Qs9/2@T<* Dd+F(7}H6C B#fi3½C@K^ CR Xd|Vcg3n -PB 17YJ_Yn*G!O:"އvG1 0avB@i9 tZ>J)Y$/7۝4.cWgz3SkJ\ev(_ EYYfG̣fK_kʘi H^ei|(}:3 ʨ@ IvU)c=eFQWrH>~@##b@O)cv]IyIJpA,1( "1N'((O*e̾([D!@+'v+!@)6h?Y5B)cDQ G@@ ,`Eb:: : 8_hn!g x L sI'RxAylx#}Wg |>q;'1;̸̀ܦ6&ZlsH㶎1{eS#a#=*:qwӒ<1%!aȂ#L r%Y]QXFaFǤ(j)d q1☫=ȱ5 14wF2бtE=?8'X{|U|ʁh$(3Vl0o+ B3 Su|ۖ=9pKД`m,3&@ܢ|U9go*XY,1&~Haq7.̴iDRƦc{$r Z u+@nΪU̴wִ4+PAr Z\ٗ(^]`۫:8(EOl=@@a 2(-  ĮSBM;f`>W~BAT\2Bd y6Qrڿ`OXo{#hmӮ4H?+"inAv@isHI[;n1yD:UL;EYnX lȜ. 3p6^ۻʪy1~6 }(^PD ED@o}_gL\ci8Lg,9֖I}iM,=@;$iZqڃ͖^,u,3n 7Mct휰9u ן9^7{Lezgkk&^f8YYfbw5DW뼝^f!_J(JBL{MfA0}&m{1UX^Ȝ[h㧜Un-K%As@B"Z$Ș }$/I)PZ@>:AYomq zh-> @@hCC @J8h&0cCg!  !@\{?Bh&04vE@th'an .5![ye06w<ķ,3: ,32YɷT'ivMmI/?en,CMjPHˍ9˼%C,3S9gRp)- wΐ$R4K+)e2T™̝a28 >j$%*drU=>w}B" }JtX;`!Sę Lu"y xռ !׬hH#@(w>6EjQiiۢu`k$C+ܪÃ% #YbT1O8 霠QK dU?'s YnŦWb[E%q- ##C!4 HN ҵgHms/|)<`Kl^GSaum $ˑd:h`0%6,%VN$ɤ]@2L}p?CYh8c- QZ5$Ѻ/H8q¥Tq0`^O|Y}>RD-ls[veIENDB`pyromaths/data/images/vignettes/._6e-02.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRGc55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-09.png0000644000175000017500000000031511560531274021145 0ustar didrocksdidrocksMac OS X  2ATTRGY55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-14.png0000644000175000017500000001137211560531274020730 0ustar didrocksdidrocksPNG  IHDRk%`PLTE~~|pp]]\XXfGG|;;^))QcUIDATxv,_kGDRso:ߖa)fNE8o*r~+J#94AЭhoa(l6*/&!)`x e>.!YBh6_WkK::҇=f1\Ts^,?o}bqTRia Д'f?u+En^}_u !,sxaZ}_" 7 'b?\ Ծi}>ߥ8:Gv^e8{S%v5{00bP úB WUQJ`XLZ26VJ^~T%ON1}ᗊ1/N! R4ۿ׼;&nMS&L^Fɕz_t}'Pl|˪"jF}SZvyLSb}62|kmA7*xUB{|ԋAa,;#5]ohMg+#'YzWav(8:4o7v}PXޡ} hĉB+pT(AfQJ]_7ٲFNP7&'˜Cs!jD \zಝ7DH-"\>+MTοj+Va%a_;+ xϘ.r1ga\-qK71SY^dǻޣ Eԟtq\UphHSI~؛?FK}XaJ>A&`pJ;G[e`5syp-6DG `0$l^yl3Y S85vpQ+yj.1X|h $ުymc1V&e_Bt^{+GU TB CF IvkCS'llLC0oM!mLi!v_i60mGA fslͺĒǐe!zSXrT.P3傗0'\H-"V nۘ ͱmmQB0[}N^۸CKW* *\PBEH͜b+zR6zDC]e#qsom>"1k':z6\%\$M.qT.x1nM`ZD[ f3?[aDG DWUڄ\U?A:Uk@PR7!"&ѥDZuX!u4ylMYaءv̦AȎ> !:#.c:>^\!Yb1_CдHw1_Q譋lrGj[.# ZyxUB5x- S%&XS]qiMk`ۤ'\7fMy:gEPٲ-$qy rgOQG&MQ8Mi*,EOm Y|'R\}D8ѤZHVߠ% ;nx1aEL1!ĉ1bcHa2".z#!vYZtX~YYˆ E_.!q qqq$,3&ĵrﱋ݄Ї`]?/ s{yqCF/a Խޢ ~,_6+ՃQנ  m*70Dr8zƳ_q_ɟ7{p-}E_X5.%o^^A<&¸ JD@)Z)?.cʥS|*QT P""Jq)Qԋ}T{r[TbCBW2JkaBGZ^iM`qq^ > ϏF_"0$QRuq4R7﹒7yE=o;x^L}cyo+x״Ϧ<Lɟ7h!)!q ܘlaZV9va_4 XԃG">XbgK"~il"0]|5y@Edw"eA~{cu6ލKaryj@n&Hx c6eLlhc{."0\-|,F,M3Cuq<`r 1/80&ZäjFuZ +w'3D(A ԇf9L*W,ܯg=aC.}a)ZsL6A b@38GF_!R(z ږ ^zp z~qS?9rlΆ7x)lbt6LzmE\E6Gr(!6 !(sΙ ^W3u]}]%H\$sH.! K?5@n^!2G.L(bTyvG"M e~<#Дˣ\t>'D0y|S9Qڑ~SB(K"_jq }O|}dкk%/ R*9c˥cpARLԡ!@H^%/fyF>"ZԏmiSlOw9}m\ljA#&_ȲSl~Y5v-4zuv@ɆfNK]vS)6LSjhuH:n}I%| Xn;efN Nmۮ\J_jN_،'bkZE-MT`11mI蝁qН麾mM7w- @kL uJe-mkLۘQ+_Olq95I$ %Uv m:J&(`>+&>V_}|ƈ+}?riOY& x ~^*Y|n'QabT=!y/]??ףSzj٥3WP>Dux0TBIoK@)Mcf QOk;i aLY~5oN(߀ш&::ԍ/qnpqyF^?4:Z%>?){ qq 36s$D|D_SjÑk=>M%8RR2SC^lZ1L~+~sS )u(!MSJ&m)*GRT,锂u@uɲƳ.$<p˓7bh BaLtF${kDD.iz]C+{]_7-J "Zfe(!g|̡+{ 7Kw7M5Eh57rO4 x%7}f7Ct׋wWwՌ:w_9? Th^B&tF^9?,u>Qь_4c!7~0/^%@R3V3<{|TCՌe|+K&}B3? qZ}tò|؟u?:hF¾zo~ْ?O,߭ظOJ1u_.uWk!gq+F{ERyYIV"{/ȘL뾯~loz}_FD}u]B˺f&iۮ7 4yhnGΩ>bO3xV݌|O:`إ%f)82-#O6N6־Ry~t$un6tfIT㽯sw[c; ׎rSgq<d} :܍A&]=,WsG32җNjzэSsot|ט'+ )4 2b: -%֚'g)M.9xQlDN)4.X>|B&[j+C *M199vP}]orrXnՔ0u'yAtr#4:r`6Oua#LUi[#tE:'tB?ѱ[O5ԍ֗ƾ`[-ط`[-?[-U, _fן?}촤E[!yJ?ɨ_Z-ޚxݜ^h:W8j) q|hFΦLނB:/#Ǿ|RUWylg{Oրeg"h,ۻIK eA{*c]0`5 vDBaYS` "dXy,MKY7ui~|\606 Ğaiu sÔ6A)q֞D|ie  8~\km b)TiRx`א%P#p"8K(zcr,!n4ve89Th"ıP"'h[bX!TSN}eAa}ƱV5 q+ov!< V*THqik1q.! $%S!0AYS<)̢kJ_Ɖ@ƜBM HoO:K %w>h!6ƘWVCXAG6* xf]⪙ZóGNsWKT6\}C!9Tp1@;dN4BLZqDI&/i9l=vݢ :Rh%Nte@%%v--RJ).6A[) Lz cL3=l3cUcW]Y v@%@@>>vPz.@Ǝr N}qң{cfy @.gםA?d/XnHײG=\8-zMD@5=/!\}l'u?C:ԥ>0< .KlDz|eGԟJuiyb_Y?~E: x w7\~Õ٘H@_T?)W Guh?-دnG0EN7mwVa?oB/JO觔".3?}_m'_O&|8'a/NgA==%-DwqΉ/ ^O%oҐiT@]LȦJ±!ҋh9GF_}p= zzg>R?CS_WDܵ1,>-Z$X9n]w-OÙ Zrgju0eQ/B[t)܍"xnc@qMIk[x%%<3Qz̹@DxBP ?DMV e=.H6aPag:?sW~PYj)ځge#"0ލTY3N\z˨k78X=$ F' QF}Aa<2K_y ֒>=s <^Gvګ~QOe"|ǮjL[^K<HKPHΞ>>hݓixy\8nOvz6=OK|ݎyWJ .0Le/'MCb> cl9x\_@w,J]z)O;`J%L ?7<%(6+dA 󺽻`v7'Y9K Z2D9'x $'h-n@z|b3,oP%a0KfA5xnTaGTn:T9 VKĮIxxEsK't쪮HDVPu?3P|;aFrbJ^qM e@wטB.zW_VĘ`g$nQ+.0 D1'ioH =ع 5Z $1~Vcx˻484V_9Q~I V.oBaTÕ5i;)juKZQx3j @ ~~DF,A=:{^C ;rO>Guן;;lK'%t^d'iH.G"}E%57PW/}ނ&*DrCIENDB`pyromaths/data/images/vignettes/6e-00.png0000644000175000017500000001366011560531274020727 0ustar didrocksdidrocksPNG  IHDRmatwIDATx]U@2P@ )[`b33tvgg-@Eq)*,"y*\`@S~Y'! suD5b=r>@}{= A>Tl.%W2߽waz,8#-BhYq?7>QL dQ6hD?#Cy,xxYO빌=2\ƿsz._e빌aȿF_<򿱛3Zri;zmM;4ws~4ɸkKSx\:ɱ`4Mç 'x>c|z(=Gїu7zu&gv Tզ{:cڔwC 1 o~Ɖ>NK BR%atLŶ hAss383F"Ozgí8S)-tlN 9 uA?82Xq[P4*PG%~ c_ ?`D.dOb㢹ZAȠ<7Y0?Hh4AѢW ]-$BPh*bےΉ-EZ׾ cƷ8ĀL =1ςUU+ͥN@rmBjJfכ@<l ƾްnZ`m|:WR`p?` , "8'N/ر銛e#0$7tw| 2!2HX=|y.Q`}C utiKªvfzUU?*p PP2% 0làq)(Kbƿuv2zGȈsι!H)#u=F, tn=M0F~Uݙ_sEY!@pƁ0XAImܯ`l C]cH@F'gd+0T8| 5WH9' GP @` 0ƿ3 }s # P B/xi", 9WؙkZ7߳WU-"IV2٠uinpm .A cf(;h!_ll`(QBeG޷h P9"e>:A)?j'O0&c%2AA$_`AE`$L>΂^ aMsN,eH{b*9眫5-pjp/"/͙ h cQqH"Om4>ͅ0^x< f=}ojwlc# x m`ѓ0TJoyAÇ qAF5oCky]An[;BbG0^^{0._ƿXoO~;sySAQ6~]ƒ|7}}|a}oYr QpZn FO4w ؖ3&1/+5*7%[a 'lz QƊ u/]s{D=Ϻ ś?PUu7J`α/;ch qLy_@l`P k2H/`lc 2XQaVc Ww#,z`Z dػGF7qP}RQAEm Ɗ `HEA ZvW/`*xPDzos?x|GL eK*qN5@Jk\X?dgYCo1Ɔ Bڵ ~~ch! Ƃ6җƯMӝ`n8n7 2l}I;eiJJ37獿lt= ŴL-?Vf7)csDM۴qJ&v:yv h ͊//"bBw JYao۴.a{gߥ0flF&ؐ5:|SaSTeFg􃛳5 wvȐZW\#}Owx6uAɷF0]Xax}vίcW82?ȴ*怍ou0jsγ~SzxƵw]_ƿX S Ɖn`FA#{MInRAo1bOCZ9t QKƼSܒ*i5kVlLbM7Җ-`P4mkn?[Φ>Zڒ&CɳAwIdv=`dܨ(Vlbd,oƃҔ81"LQ8c-HwEI73|eu/z}" ~KEhRlbxIS8s,˜-@F^JsMtjflYu#i!sZB#W*>`ߪ( P'YMtOiJVlaLҖga36q r(~xl_b`7ʖnu,jdxm1&~;!=5er5u-Rs5kKil0b `* J`2FEBU|8/2Y D\&$8#ʚ)YBAҔXXJ[2": c+ohEFYPQe`(iA "W_2q]o|`, KGṞf̷)bBoԔØ-W0b۵}T|UUP4m RpC ٯWLx-b(4%vZqAMɊ-Ia|xNA.>q.!~·50 F~1 W1T+6FD޿B=kz;KiF1'xm76)Zwp8;1X]~NĢߦTEqƑՔlx ko϶2}0q]z//_Ƨ9:p>1^Lom:jꗶ ŋ A?3~`|J˲sQMa/$߈9$_`Oި(lɪ?%{4i^38^,"==k1 ^ܴЎ)ݩw~E_(<%s8cݝBycc- P~ZJnۻW4/NR8)tyy4^;i"xs;1NJoʨ 6Uȗ`]={5$-mkMI*e0OIo]sl|V뚍Cs X=S ʕB|M^Mۊ?xrF~䢠=زq$pMQ̱ea(F{փA5z890it6.!8p~JE2~Ief(s016UqƓ<% s _?Vh Czvl-Rb, GTy5'ya%ȯe;}Ah"Gޝߤذq0[+6vFoTZ"?ecsqRQlwiy^*Mx?9iC\/9mJ%Oܭ*X)pJy-Wl8 a>83$_ݺ#ût(/&hg`T+6)ycƹc6v9JM,~W]hJ%[6)[E6~,o7NE-_3|~|LEqx06S9hA(DoD%/t~|s'+fO]+ ).b2yLs}{ E">Å0L{,d޿S[3ym [6B٣YHvȧ\=ҲX=c82f%c@T͓> l+ wն4Cv?asoƊe[hA4ݘ}0VVlAت/gb3t#N@68t/g R2' ̕`jC!l*L⎡)SQic0eB,So2$Gl`[[!9:!yyU r1ѻӞ2~snJb!_x6Al<,l [706lm!(1fOM@cAom6l02Zaes95+ xna胋+c0H)U۪nNR\m @>$=ԓ@SpY} c%Khz@ Dݕ8 !#ӆZVUTkX.93OeLsoUuq4!l RJ!-=0֚~;60Ԇ-4 &s>6lޔxR9!?mߘYti&e ;ېB!>"Nm[cյ-R=wqv*lM RXM \xƖ-Yx-O MPKn` F2BP^~S.Oko|Fe_ʋi@,*<1u~sR+! :!4(}V?>Q{;F~5Ŀ1M-a0l&}yP8Al2?"ܟ>0 >4$QM#IENDB`pyromaths/data/images/vignettes/3e-08.png0000644000175000017500000000316111560531274020727 0ustar didrocksdidrocksPNG  IHDRUGs8IDATh=FgK,, vbcbb!B"pU=SS3D+)I!_^A`3>w})/ߩB ?Zj}А"; SU%k\z%{{R4HlU[-ٷ/&Kx|Ľl3 HymwkpEjh+Sq6MT%QQx뺮{6=8 +<ӯ移~j뺮$,Iޠ*՝/H1k9:s`VٞˠZ*Iq#cub5X{AYkx<t\ΧowM`o%n*jtHMEā)ae|s3܍&E^slL}$,2. wAJM 蹗ʛTϔSe7jg p]$NAv`~4^919.q& /K=wPϧ7ϣ]ee8^jOЕj>2rf5iVt~]XYp֤b9/Ҭ8/El٦7ΛF4ί g[2cxa kMxs. ׬U|(2 L8mVn3PoT.ڹh?e`5JHvc#ka5~gIF: !v͵1/h*1: )3R9$UR%RW 2\k4n1;W߀] A6))v%U"mBUB7|" ,mEL41 77L.6 *Ur5*'.0b92UM p:sSߐ}8Vw i7dZ">%DZ¬X3qKf-,ń.a gRer],r]1A {}*Y&$m}MVXٙʺ'dA#¡ы/5VFe 9Jkz[&XM\T4"MWz!(.CPQmn&1l* NŋRmRu=o-_^_a4TzII'9x@ z(C̘fkZ $yh57֎{=qܪ:*X$丕1b-:=l{-kj OѯI{>[;:z)xPشb[>4ߴ%#/7~*Jz//T8&Cu&NQ/8.;"Ju/wG*I>xU8 E FtԻՙODuZk ,@nYmVmkj*(N{Z;2js9qYu:s\y&D}o{9真lQ_(C^Wb `N^o++ @uP*6jB| "E94yY.nu}t՚߭n)nz|\~z|cW>uXj >TBQԬkK.IENDB`pyromaths/data/images/vignettes/._5e-01.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRGI55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-14.png0000644000175000017500000001174611560531274020737 0ustar didrocksdidrocksPNG  IHDRQIDATx]=<ӽ[aڂ6-hJɵJ*%"RHHT}\w}[1RM Om $cL:MxbBr=~hػ*xiE"$xtPpWKMܠ^ 05]p ^ ݳػٮ޳,!zQY +MFXxJN,8ta7c)h[ cB00H DeůdWY-zfHFY'l+@Ls[!3ei[Rۀ^3,J$zDfw6+ a >}qRAk@QnZ~!4_)#RR?@S\@~@iS& }Q1.ŷ{=[P {|ѱj"G>@iS|x*3u6[};cYF Փ\t}*V!՟ SXhz4`zX z2 ϬOE}4V0fD۲js=Q1x=m0$^N[co3Zk1m-Tog`9Dn1ƶMsΝZhcp;d`\݌EP:6e61uvY[<\ @@5a%@M_6f 'Q}n#<]Lgshš#@6an@A;N攁cf¤@ 2.i@`R$ȍ#2ms !,I-sO h:m x|wL" aD7Y]laj2*zC7̮O*Tr'r,I6[֭Cmm]A9D1L;ڰFa\e݃H Bn7Y&'BúXO& H;9B&+M!X(tl$hDi[pi) dg+Zd:Ar;qc6Z`7Գ ȊQ ] V(>͠Y ;gqM%BF#swt~Δؙ)O&l7 ~ɥi#w][KXY3z L]zznPdRg:!dΪh@27sy!z]$''="Hs;Sxm H)3c+è覄uZnJkWҾWAv$֯(U E߷6!<]Q뽸~g"|'lvl>R݈KO?SJ%~|bߓO?-3SOWGO|zG oȧXKiSW͒NȧϹA>j>!_*^C HoG>˧714bhG>ʧO` ||zwMF7ȧN5 2|oOZc*FȧV>/k|5>?O?d[m{RoO)^O>;{i4M3Θ]OЅuԺȧft t6v#Ӏ}|B-05ȧvt@jݏ|/Ou?|9O/^\7#ȧ?myYyi[kϗw2sEਦ,_4A,4SJ3R&~+-6=[~qZ!<0ZkJSiSt@z)П磋[ע ʗ~P-N{\4§y%*\2@z, ~e 4I~TwqfR@Ncf| a2)ƔWq @79gMNc*.&mX,OZiL9X'l=YдWr`fYV~˘JP~_iu'œvLEǐ"#]g7J\A-f!ˬo8|WY3q~t׶.Y. :ӱDBZ+;#P2ѵ{ ZYAºr!&{ER7 `nUi*{E]A8*P mC cUԍu_Kԭ7k{qT|$YIñƂMKlD(,һsZ"9ʧYXW.˧RաF^ 0 Za(O6;0W֝"Y fȐ:ńy"[Dg5i{dTzҺFGf- xQ=hk9g*NI\iNYwsΩ(d}N"95L1 os\9o#B(kU|FBV9C=8և+fdLz44&J*4+8qLcXkUcˊkN)45 N }y}ss/+PM,<"  ; )h]<6ܥa@z `yHyӬR)Ppׅsб ͟u!1YOW_|gH??ߍ-;B;xPoqUݪk dayM>}lgbUƳ:~>K#ӠI?IENDB`pyromaths/data/images/vignettes/6e-17.png0000644000175000017500000006701411560531274020741 0ustar didrocksdidrocksPNG  IHDR1G`PLTEۺժΜʮƎw亓XݫyĩD؜d7ԒS6wvFEE@7)8%,mgIDATx]kw䨮^c~`lJ*tzzZ}N1hK[ԇ#æ f ?M/ D wz9ag& #= IE'W9-PD>90}a(y5ހ,M;K<᯵/ق< 7r36A`. ?lwhMm~b/u-ޘ!$y!{l~ӃMaoS6xl~6_^UCx'GrHs^d6*6@7=[6 &Fm~ߜӷ (, H1xl6}MnpA4*2-aۀMOen6 6`z-6mMmae6 a6 C1` ޟsMcI1߄(67[|[7C0[xsZnÆaQ06!,70VY1x`f0iȷ28~q\cOJz[G2t<wCFV1#3F"tN&cN?huOr>꾆ȐO$2i[ 52r %=s%2]d!2Xp^5tʘJ1Idy/a Wyd誺A(Г{ d*zB@GhAUs@z%cRp^B#S G_C0St,x=pOi6Pi>Ms![k@A a% Э- `pXGdB28e%o,.AvʨQu]2z}v5~t!Ah>$hj!j 9R !$h ye2@[ 2lnphQrA^&#]9B` 7.W tAהN%6rЪ୦-m֜Ki >4B(vx<@zkЇSkFx^(q{)Ɯ2:uPDQFy1Olx?B<@x)mWt tMG_ =j869~̉-p9+ W3k5~5NW=⥖%SXŔ]U^Kf.%x [.%1D K ڵ%ȧހN%hsS̚)l C-58}+ ^J@(.p.+Yr/Uy@WQFKf B<4(}8 k Li=I<ތhjA䋡 j2S6(#8$:/ %335)Ql:=+-Ж6Z@Ow @eWzf}0B O9 T&Z͢B((#xryO@!wj1" 'B=Zdb )*(##QZ2Y/ІƫLo L)M5R]]7(&6؂3@KR*?iIDJI-jH)2FU]TIҒRWCJrRCSea/R) 2Qr蔡Ta5R} 'G/uQ($vZR%SeK#PT-R&)tHS͒ft4lJUĄZ~i% G5+q!/4qվw.κvnYi6ʹX]&l3/u69XǗ ,ᬝ&ʰκklnf Ls֭Gcֺ{:Oi.V5KGjHMFڅHW񖦵HQ5K3[w8G98ݼ3/Dg6v9:&vv-&̖dr0 t.2`s7&| =,U"x #h΂-LKF G|͊L[0`ԇE4己)Xs>I!1E[,F\2ze^ˁ ؀bq/hZS:5=Ak+'B3Rҝwh! lGv<h*4w~8d T;2RRޯ IJ)e^J),KR҄V*RRJIu9qʨi*~WcGa\*4q}ORQ$R K%ц|iCQD;",%R7 .2.=̜]2 )wː&!- l}A< [k=/CW;2t/Ơy*Gl-G*Z˵P2 ZQLPScj8˵k(SFň{ ~/P\X=5{#!^`?_5y!ԓd !8?"2K Ӝ]}hanPX޾GLQWBjY_2& OS 4NDxhɁ\2@(A4OuN:쨓AʌĠ aSKFçs/@a+H V w= 7D-kЍ+XqW+H& 1%K`9w=7M"v<)&0!s==)^ݛVI9(G55ŀ : a+#͍zGF޷P4} c9t;1 $>3r<cQjgE|L˙x $U$Pl50x?  3,M@w=KZ@}ja@H)H/zZm?]99tC!ceH"0.]k:teЕDƳhd'mrؤ`6YQl!I\ L}6( I7WrM.IK2PC73 ЕzQ?!"E ,gq 7+3ܘ"QoYr3 ,sTm~=6m[ [eAJcTgiz 5@7O.BW$tx.a@H^#c=$ !8tc-\&R!.>'@ C1 6 Go`‡1\&kA?  Mߐ|eR_Qf?>).pqJ)%Wy.I\iҕR+"Oᇈk,6SPߓ}BaAMCl z*3yr>gWE[ 0倀,@H{L'] .+Gs ,ݡK{.B)@7 VST'8@1jƂ@fA !. `+dԽ ׺d_"{@ qLk\&q<e q5ƹ%QDSݰaqf?O.L 11VLܞa $b(b2y\WY.$R2!e"1 9H$/a\ }29O IQDyiAyϪ Yxh E_IJ2'[\<컸L%|JSGm\&z_т2CM@i6Ym~P؊|hBE<'Q.`ؿd=}Oq՝? 6oAB{obPvX\&?}4/jOq\CV^ߤG$\&4xËoK(0er3=N`-R'XG{ KPD)frΟ0E"F.of*F.*O0*&Qˌ-XX̢ӺII (0%` "}nWlgS B5/THaYQLPE.Ƞ{k@(PSok{,CVژ%"Y|;O Y(vAmiJ9^} w')ȗY;54C=]S {1ylxa1kun1躮kc ?s{s5܄5:vGu]3˴6Ut]`#mbY|F"8 T ;e#m6|mMT~lhtOX'ldv8a⏑j"|UUVjպ4Zʭlլu9[=rk[УiL`ӪS#dd0>\\2q({9Fڙ*U3'Wq_I2gg\剷IE?_pEOmrf7exڧ2<8 mL%+n/]2<˘IRV(B,f ӂm8}] ,TT+NU E-x0nWq1\;UTn.{{fɝV1l,w=N@ܡیgB8m>9w=ۜ:tHCW\RQR2dN+?P ElRQmTYnsL2i s޾)~`ʟB)LJ*5uJ9&+)ANsES8rLß0Gh,dBkK[Gc2ˤ1—lpne¸LDeTD\&E\&:/Z0P!S[c">edSS4oMZV3F] c tژ\]aLQ1F)T(0(W5EQUancB٧ 3'cۧUn] c˜¬}~ =\é׹*bm`2lS2r$W9~{> {{{'=RM2o][Ul^iqIUҧJpqs̅1zscjmc ˜Y\b cY{آZ"c4K{TZǶ1" k0˜=ֱ=c Ӭl "ʰkN7U 𫸹dcd'>ܫZ6ּc>3jiqLRΒV "v%Ea~vE\ij O,l){g)7]D")Ǩ/$ʘJq'8Q2YƳo0 *v.1ib>;nw؁H ?RC9^SQDֱ馳>'3óv,lv6A+6/.F.{y}$X0B4]D(be<3dwh5HOx`wUwKX#l=mceG hgy:w+' m {Xbq'pE'E_:'[1~8rp(Yt:˫X_EiA{6Y29QD+n0N2u=s.D O?2<&j?]RQm1~/~F ngTŚo]!B@kGW=_\RQm E9˩)/El>'|\%:t% Z66K"ڜ;;vUOl`8fvi@74&(e4:t%Fg1eZW-Yr*uz"D?뀐D@-8Ĝ6繈dJ4tyxYr2|ج=]~,Ld͚U?21h#+Oip@1AWBW>eт]B!EdZt ׈`+mn1p\("5 E-Ed$zp/Ѱ%(KdoF-t|OY~tErrPD+E|FVbɅ""G)Vdy.UB34>e ]k/OcdX~Կpw@'M%ߡYY?2!BeF.B"{1jΊZٛPЬ}e("(idP2׿d"p(bD a rpҨ6tI`rxW ,7exƴ σ#Nw_ r}(Ys<0 U^4=WT{$X@j_1#/A -B.k":RnZEhwtq5(b2<{]HKXx- ݟX~h)76gYL갟 5"60S8:c"VIEƽ])E9k#e/ G2a(Yʍ?_{hVBM(f]ϖUTиW+No>?\ tP|-D`؛_c ~6 $p\oq29$8$_ۛKZs[My%=eq9,v.u9P:pHs|:>?ӛJZ~:ܾZv?m>8mE N.vAjEy2DhPngk/Vڏr P.A ~lj"vPy->"-^ K-v0~pWr߸;,~z ¯OjAGZi'E}uxh| <՟"߱"Z P{ ,~12ZÿZh@}<wi2;em5ŨZohpw8|hOZ۵@` d1mA0C=]_5jo?$.%XA 0`ג1^Ղ/tn%PZ b:[ ާ z$ :fl^ B_*~H@o(Ö 'Em`h Ծ7YkȳR0Że oU"y [$Bgғ󌉱:{!`qP3ID^ -B.I+-^ ՗P }!%EAJeݟq>qs>Ǿvxuc_yycq[/LQ#k4ZJȾSI&Fstڹ e2U>H?j% IRJF&#]P3Γ~(IB ? 5Qh Gʥ^s2vyNTߴ/{bA|dhehdwpF[][VݭpF[BDP g"xC 5@b։ФոB\v&^ m>+4soq,*^ A[CP/ elm@~6Իl/~} Qq0v G{8 _Jì!ߩoA3S+@@P_Ny>H;B^ GPCC`>__9#\v+T+Ps+ ,}/Z+yJO(%t*Z/jaOp @}> -TsܖgGL % m?|} MC@s'pL x89>؜ZB{Xh8ctdP'BggBABgaeK#ZD'"xbds#(A9a5g[1B_yсXI¡o;lBl&Vx^.%dL,E?GƢi5v'wmx#)oH> ¡,O}:ުb&mͬe]ǥDh$ЪSU5τ-Me]׮Memկv^kji?voMeo۷~ >+atiSÙe2UVv+kvu;km5~cQ`-9ZZU[vd-U8.E'Be*sPt#sIJ]z8cQ~^hebdne~*Wj)UԔ\ ×$z-t淟}l^.TRhwP+wJ-FGb 'i{<i2|}.'Ȫ3d8Fт/ C\͝Ç@ߏSqV!u8soq?Z< ݃rQ E9)d"_[|}?S5kdfA@jD@e`=ԖQpuPPbܦ+1'E,!U v&^{ 0!͆ pv~cg'?E ){4KHcx"DQY%T~=`57qgM=/%rfmeĬ2T؍@fjkRysք@t ^OceͻPGD'\ZМK(8ۉ(J4Y@B7y Bg/P<D)"w69QDBN;% Hast{A>G&{ c @a*2iƪu@}%9Id@ !P (@ַ"ȠiEx)fO>|~NZ-h0^#T} h^E߽euckPM÷}چai=̴-q?W 2PCw6̡x4+HR2/Y(j똵gJjs?& vE$E,1ۓ@"8y"Q:DqgÿtRph(bufSa;tݮb]sR+H% 9 P 4+roEp9xG +K f2wM%1z} ZP:(uETݍ"ROjD튿V]pWP) Re*yf(bvE-͹ ]Aҭ1Ex]? Zw_o#*MsosŴkq-`oKLygnSnM9-e? ׊.Yt-:59(SZ=LWcP<'ǎn%`~ .1Mj[6O!MB^TE6,KPDksʟ"\ vf[GݸPTd( \r~E%}PRwa(-dOn%w-榼\Mr~ DĔ_a7,:()sEZLAvܔ%&QA(BYC9 ᛵ@@ph=y;QO䭄DM^S@ `)f) TPDMw."Svz5E\T\&Q +U*M ]ȂC@=i eor^4G'DY !df*.]ܝ" );=S HOW9 cy3BDu6I ݸX]!}=ȄqT5O.Q.#G'׊`iEYEcZzZeO. k^eQV u$,:2R2BeeiS\=[(#&7((W[4LFaSOS];tQ( 7']Y.^+]/(b\.KmFjzEtsa9W6\Ǿ[6tytsb[-¨p)wMeУ, t3"oiԥvMUfMUf12:2U6{Tf=a:WGc/v2JטKF_4saU⾊51MrGwoTKkإ6UedLUURTUUMSuh3+1fçu8vۑ^ 3;SUzT2պXSN,SuԮ+ӬTGw?֘k_PD9Jr Lӹ0[x 'Fs(GSF 9%ca% + E0Ű"GE^ݏ@9IQTSb3?@."ٴ^ߊÙ;]ssǹ@:$9!oNm!+рH(b_r](ZdЬ8h"ʥ:QDcS8xp~ B7meQAEqE,+\H$`ƒ!Ţ.AM-M6EQDch,2Ohu4k$w+H9 R39t w=KϜVfM9K~w Yصs%YL<18ʙuR3湈+[V%pt# е{{Ꮷ+HY?(MbELVg_yf Z:Ь(T'YLNBܨ GQDrM n%':]! t EL\ArQv-UI2bfbTiO "ğDAmV^AS1 !з{dP1rWcqu`؁[ ^["tէB>B+hO(JBW&3H|0x햐F@F hySC _28kAp|j?@+ЍT#'ሻ/-HPD+!ܔϒU]ύlʙ^CWzWgXxP6x9 /Li%(bųh'"Lo8t |j4C(` ,xās=_ExymʟB4 dIJφsx:M$!7xVMӦy_n+j>Nh2"V(Gb؏AfNo2+] "5 h9L<X) |6 D!oM\ʙ^3\&&mʻhaHl[İ+İs;I4.A B,vsKq1a,) 4 E.xMbʻ!![QtƝ+".:MЕ2) Z0x_F߂d۸.B\{kKZcQJ߹W3\&Ԟ3QZea*"s2 U~ie+.E|BEs?O?)^(U,]QDS3OdAmi%DBz6!QT0w9|"NNe= e50  >?j GUW}cd^.ō"E\E}mܘb˜^4]1FOKaMSaLQ0W[S1Tcl2L?U榈2JS,Musz4aTTGUS4a#^”nx-I;/I1_"0\:W^mac7/mGjHɸ\r11h,&N1\LѮMaLn\d=ljeK ֵƱ׮y]nu n^n캳BHEϥf浙[}8c_؍]ݜf:g%NԠlҸOyq湻e4uuxn؍s?G:ίnne;(Ʊ;HscK7>cd]wg&(b"f%E͉"`!@rX~ {Yw.1E:Q4t+@~gdA!%Ӷh\"V(d hW9E̠2R@I@c\Bn3̹]%GWQptRC7J0p]er˄8Ʌ"r!SC(82x ѹteoȲ8,+cE[Ì}-Ep47(!Ee "Q`#CLQ֑^pʮ QVuABpA1@"";I $sPP^8 &"6MQĦ?ɍ0[{{cFdO#|uIx -UWq1Tub91!8܈HT:nwb.fx+Pn+dFHR2ј>G@oO%wD0OgvoX2VS@1. 5`Ŵ0Sܡ5RUcpoh?x?ld62ߊ 0l9$(Eti9LQ@ﲨ8-UNL`^sZ\ E$ oXAqK7+3ԸCת$ D '/;ЦN0 G( -!ltP_hJPJ x]bאbw?!@3%-]Y f{&b숻/[B&6`+?0lh't+2 ]ґ~RCڕhoR×T:xsqϰ Cŀb0aPoe/1'pYLt/;?;_`@0lCxDD'CW4tsZ}p8٠&湈'IX0|r > KΣl0[y)|[ f  2.o ~k ~.PI9 1?2ɖɇ-d&do7uVaذ 'ɛ9zHAaB@Her q.j=>Q1Y >U1- ŀ#)'MMV"**VaPхdQFexe@o+cz 2B҃f>%18.ON/BIJ]1*!teG?/oȻTLWO1wYl,F`>}=qHc|3)ܒ™[Uy8L32u)cY;O1=xZ!D..Ӕ7]4"CN sd $ yZ}eeh'Ʌ"Rs.L͊ ׬rblDcOSk!r n.ˁȦ52+CS ۔cs9h|Y zrL&wL(2$L2 .ʂY^balg.\&*f(9%xsR̞{B6geB \&"`s !~XsWSO#EĊgXu,|Qƃ;AVLLخRE. \&e"r=7)f1(b!!_ʢ⮠er(s޲\Dwۂ=)c/یŝZ,C`ޡ_7x:ʊReJED}Weߩی=E,CѼWE\((NHE(-2_K %o!c'++'h -лPĄֶ_%hL4>-PJ+  XWE \&mn9dOùLgWـ.-\&gQʹAoE4 mQ2(yc1kZRuRBh,y.b2"rĹ66&C,:߸L.rimO.% p}1"{2ܔ2yO *V^q2 {n%pܼǀvB1rS2s{wqD0<8 1.K]U 1.xSlQX&ID!mP= k}iw0E0jyC¸"-UWZ2yerqr\Xe*"HBXT\<8L% IBW2D\&G\&'H 2ɗPT}1_hP}:!"RP$k8YWrgjeSv\&B\\&;\&Y@$Oa%\&U^1tCWUn.G\&qY&@kݗ?z`E m/P sO(Y"Sq+Mr2|%Nd]yuyÏeyu?cc9{g91$ceԺ/Jk\2*PϔU'!FJں.S/ya.Ze¸ԕ=S9)șnZe"UMJ7bd*~}Rgq(r $6g*ggjgCWK*uE+/Y%}ğQ#ga/BVM"6M@ ̕)t>%>L+ Ĥ!o͓H,:ks4i.bZT!Ԕw!cMMz t҂2ELLe-]bgbU ](Z}/t#3@h~d9 d,) ^iҼx_BW~̒ŕΧLgL.KзEPDPSRU Z m+nʋȺrLN&|[lrxym62=eB].v)/Ǘ!) J]t=\&%QG+D@Fvj0 Lˤ+¾.*nQ IL~P'L e)iecXc5{&ԯgEPSw1*.\ ] r^E:Ne'2mbm 3A:|}8.rZbf )ֆkbOAٯ+h1U@jc= X1-e¼65.ns9)ZVY3wJzG4C]0λ@w"`my !L-ôNyBszGWTc舻/[.!k>*ٜD!ARxQzmu-dn |b >hֺo?P 2\(N\A)8ME "VWTs w=66'>EDzX gn@H4"C"/al}|'O>hAj >zWaK#0 U$B!3!cQĪncmjz"2yLX@Zj8BIBHկƝ}xP29S–_# $~bFnʟB"I4ELBW+_2! >Xjկ?o~C]y1{o7r/|A~W ?Q BJ;!!`돹L2BUpuEK, ˤ?iD̺޾~N٫:B)^ zz T/ye !m@HQr4I'8Yt>eW %UZCbPZ]{{Y-ZPa"U1O!ER_2yDЕsdde=LǛSz䍔~SlLcx8RrNT~}$2LI(}SL0?cuF%ts{zH@"Q iy@y 2d\\&* JLBHL>xq곯"g O-pǾ=K01jK u AUL;Zt{(W!kddAFE^]6ze`od>uMsqsװO9n&? m&]XBhЧοDz$_~vܓ;Z}ex[~O Q2@;笵k[M]37I焾]e_ m~Rh:R;⧅䳯gOZ=@k{2Q?lEH:2{i?HBDrVB;loa#/utZ݆ [x5cɻPճ̿|(~B09[ՂZW j_-ՂZW j;Z%33Ze9,lڂ؂`>3h[EMlB ]Ďn k]e܍wK",fYBB\q U]^ լNhiWHz-8 կ1t?~cq%'Caاs[3v}4g3~*|.>Zu, u -b|A$3>(rm.Lǟ)w`.s[2c-EN^WGIOçQbL_Oc 9ؗcTZN&CB3R6_T%t/S [{RO3ȣ"PG MP -jچPyⱩ1-P{ J8@oP@t/R]-8t` ab@7=[6 jV  Mc؆? MӖ@ 76`΋Ղ܊`V"[7lf$G-oC5?; OgMAK6oۀ\]`aj O[y '6ma؆m3Wۖcڂ gĠ{`BiZ4( A :W@1?5 /@!HS$^Ndg!^Ļ1Nk/-A/KZ/Ӱ-T.`?'ˢ(l iK=69]Zi -짅3SThZhag..ڼZ4e"&BkU"PhD3s 裑jYSZi???9'uIENDB`pyromaths/data/images/vignettes/._3e-11.png0000644000175000017500000000031511560531274021134 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-03.png0000644000175000017500000000031511560531274021140 0ustar didrocksdidrocksMac OS X  2ATTRGe55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-19.png0000644000175000017500000000031511560531274021147 0ustar didrocksdidrocksMac OS X  2ATTRG߅55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._3e-12.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-00.png0000644000175000017500000000031511560531274021134 0ustar didrocksdidrocksMac OS X  2ATTRGG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-14.png0000644000175000017500000000031511560531274021140 0ustar didrocksdidrocksMac OS X  2ATTRGA55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-07.png0000644000175000017500000000031511560531274021143 0ustar didrocksdidrocksMac OS X  2ATTRGU55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-04.png0000644000175000017500000001131511560531274020724 0ustar didrocksdidrocksPNG  IHDRJ;IDATx];,Z6*Xk`,bQayR=U=ߝZ1%Jʓ#OBah{!kPQ/ltVc,0g57!V0 WQpVT \ =F0 PVZ /Ak4]RR 3(PPNJ ,Y;Rh(- `*zAL <@,i逗S\̉o!vhv; T5B h84/" hkmg5l J݂2 F7X-z4k'3UH¨ FJّ¢h8-cZ$cyҪZaZW"3V+aLJfAPԚe!2O?fN[X Dla#Kًh^C`hE f!$P 0´!z๰䕄]w Cҡy>' 3ߛ!X 胐O |s,z;w0l(N0ZKy; )O&>+1zVa&u3Z3`U3*?IX!ñʑxo7HGP̿ףfqX4E>! tl#i7ӀƠf Z@+4c2+fH̼\;HIg4 Y "Xâ V8` ;8@vFbK';x;x"qg-0sC\͇fڊѣΩL c@>RD@ Aѷ @D |<Ű-<X˹ Z'?.6e%{M[|A39ؗ]>w^4s1 Q+8¾֢tq,"86#ѝhm`_k9ܤ%1@OVi.7 Wх}Mm^<:ܴKk-Mq ،,%:/?拿?uSgK^|؜NpYɇ׳`zf܈>b K0+DvO;sљGo+si/wvinDelA,^3< UXNk챍0Y\ UfN6inA;]YvwsuUϣa` V'euV nŖ@tBCL>+hwm7_FVB< M ^ﳋa`Ryi3ɝ@"슛q (HK ) {Dmmh,ںm=(dCg乪_MfBA0CK xss-Gqy b2xA*Ll5ڏ= iG2NЎ9HF1Ƙ=vVjm03ˈFCK&3 G&@(,(]h,a(&,GR{]sy6f̥k11^t:  A'ЀZkB0ZZ "n90]DqYzY GǫEAX UQLPP ʾ: <&# *Uw5Zk ai!YkJJ)A U=/@(iiX=шMfBX`PЮ>]f#XHX^ aURJ)-@1 AXƓOʢ#!([7U@~B#Ze&H Kzr Π!F@@ L"*iT6NAG@k}KM5Y E7YFc|)}/q_#]f"dU&sֻpjfgFмA~};2'^yJ>ag na7WgH xCyxsЄC4 ҾX[45z{liN}jQ /BhQ?ӣe@a^i4̿(^z/t^?H]O2F9H+sd>,w ,A>oD:rQچۺ0!wó!8%Z>__s}<L|5(2$iʯYc\W"VϳBo 9WfNirlG IYB䌵PjlָtR̶At~@+A&Rp`r<:u=cfl5f@"vsgFU Q6t!su#ؐK V8/|`+^x:NtPYnݤw> <8 (<aqWPhY9$w/9@Z/*A2r/֤YTAjF:ޙ;K_Zny̡ BϘYFpoZ X -WjJ#PҮ%QmϷ5r#8hmWYıw `4Y:2\aO)i@~t\b!c=g!jq:Z>i92LbkjEō%6JI}fnDP tp;$ʸnA򦨽Fvy8Gzeicϝ(^~$^4|__vM)"K<˝7xGOQ;x sEHXu1ƅxEHt{3=eyQnE2G-@[l{,L]sFoK>E E?%R2b<#@l2PXirt/4C0Q]K[ ᡒ%ӖvQ?! Qc2zA_XsG sBoޜ8 DHUx#9GzL C\3hf// 4j'|(h3f/E5t x.Р]P:0,P_I/s3lPch0NPu t?T΂xFh(c#} 43;W6 Ùa$k&4 & &>ud^؅ rw%_D YH, 'ܖa6}?*;- xCQĮ}ɦҶ n 36k5|q3s҇#4"v%_P$KN'9# t/ -E̡r%_m0P?0+iHuA&Ⱥf!>H7oDolNnP[Q^z\K6چ BQcRUu@tqz}~Lh(@KnXJ?謁 ݁-#"K/y3 ]c 3Kz_ MfB.Y|'/m{t9ߎrGy3o9v\]N߳sd?|<ێIENDB`pyromaths/data/images/vignettes/._4e-05.png0000644000175000017500000000031511560531274021140 0ustar didrocksdidrocksMac OS X  2ATTRG/55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/5e-04.png0000644000175000017500000001233011560531274020723 0ustar didrocksdidrocksPNG  IHDRK7IDATx];렲hJ5 ( !"RPm}cw_k:}ZB6ߢ }pblDBBR))+jЗ,XҷʣbKG(c#,t%}WY[j%K8W6_) @ω(ta%w@%)O@F~4MLW\g?<(;$JCqǞ=J:sg.Yq(PF ;\2;㣓"7 @-A- 7uJ0<*9JNVj֩n7Jht@X-%Ng ypy> J83nPCURCIA5Ď01A4`!FY;`{˩/p0 7.0cLMEGނv1–=e_.N =G ̠=k Bq٥iDo h/# JSbt g]\N%b]7IGp]8QNAID ܀+ E+3 &@g9 ̢ 0Mr|ӷ7It}2T\ - |VTCMPN|Xfz0ÄbO{=փ ]V(۽{񮟺 uf'sKGe~'5X a@GI3u'V i$0;od1:㮸;á:ŊKc9B݂b;hQ-lIG1 @DQoB־;0 TzaH=Fp!v[AX]%èm@A# Tز7[M݌z~ө$B杜CybԯA$;pfY5ew;EvR.s28K/F+:[`ɏ(_ sM~8!\ ť'YK[N3KLl3[o,6eK~&"PrfyK\qA͞h&SV[:Q{XLaϧLsM)Y&2QeEK&&ԜK)TJwױ Set^Bэp AW6-:7+˚޴pݕv@E%Z%Qqj7P/![_'$i qt0(\٧+!++sDZf eK9-l8zi8T ά]DEF WpeO2og P w7^_b?b?b?b?b?b?K}2vʯ^OAJ_{xX]x߼;>PŮPogD/4ٮ ߺ8n~= BXPozg(6sSA2|J,!(cUvbI ~, a&oyʩz>0V ճ7 p[%g-z@Jr'~SGE,n; ~)oUcwJNٟ;kncMl^$ݨaHڙ[oT3@8!K}M ]h,f !~NŽ%0/ !Α5A7%et#{/ԋfe_Xz@QgpTbjXTP]j5zFg(>j-sa<h]14]&On${ zDb)Ԅen^?l*K,X\l|*kU6gLìxQtzz~+Z+#ݽnIf e{S5heѮʜ%WΊj`@(z3ȏ%"zد.)U֣O34X_n;eZA6|X bB6U yQ:z{(FMjY0BYsAHzo_=0Ewƕ?bma(i)WVh,ڭ(@R@,KyLr~aefҨa$u<%m`|l.o1$l 9Uy~2DaSl0,y7iz)JP020c_cƒ 0+Yy Km|{]yXXc g{@jb~kAbmRJ`e>X~ "X)20h)V퉻 \_5] H BZkMsVT5U#\` Cʽn`+Fom<+r4"^oqϱϜ.ݛ!CHgh]AsFadm10HM;*5QQ\2;M՘G)>h]z}fSPrV]YQ)nU LVi:3?F.%iAIf Y x!d|Pr203s4|ۮ7|oc6'H >" q( Vd]F:.^Z'fh4X\ֱ^$.6ӓ[l;4 :fRm0>"W6sN^z4J 5͓'bO}kh;6*P2*Q%; ~:43 =4*S(]k GBcl}u-AEz#0[bMНJU{R3dQVWLp$4B>IT5Ft1,?5O^|B颳[[Dq0Jm>R>q(b+ndZ_!Z)w#"yW<{h ZBbtZgRp>!Zg#Tn< @^ 谸Y66y^I=g6|* w G7 ͨϞ=~B?.듧` Kkr.[>lY@CyF'?R\a=Ħ\x| 5nK_:wO/4nsd1W Dg;A"cr';)**a0[Y$Loiml޼ lz9aaw$s3~9 Wb:|gDV,8$טu0շ /U̙:(BbcA-;YZKHCbocۑ;ra*"+Q¨1O[m>YȀv;ړrT>ںQg6/?>P QpsOb1XzbmBt VVӳa!ʚK 34(zZsMgSp^?Y8h5LeY{Zhw<|h}aܬ/%'!b KTPJ)iy#RrXsi,Jdmruqm3\n !.Мg]؊ރ0XCώPp6|zW!pA!4-O>jr$؄R^`+& \<Ɓ}Cug50š[أ^^a)ͧ…mCZZ" b ^aE!FCVCԡ7z] Sγ2-w!|3Nr /OD!D% F.l ,g`f."}'w 90#ڔq e7}%t[r"+]#VX!96-j>[> .U̝NMςqbB֯A2Gv\-0|U|Fb6͵_5"d07kľ|`:U?՟L~򹟿(^Zg[cLwfSj HV P i=0`ֱ䥩Q5A9uGQfZZ8LӨ}5>ADžlSkwË6$/y502q 'E2Oh6Z`8%p&mbq"oI1'hHʧ[(S"zp`@rQf|kHӃ0 f0vFW??HH*#M IzMLwGXYOd[fĬU' :+ ~nh}}?M^SkhR+q ľN`*Tl2dm'?f7ʃ/e.bs KPwyͳ xǶL?e)ˈ`Z7/$X~h \,Nۗ1Hn'yH;9c25f}85ɮO}XJn{8ևoBES'/IB{0XZM/1?9 j`-hIENDB`pyromaths/data/images/vignettes/3e-05.png0000644000175000017500000000643211560531274020730 0ustar didrocksdidrocksPNG  IHDR%SN IDATx=*{9 0[>Ŕ+K \X{νvήW,-em6AD?[1~X/[c/y56)gyk5oWr9}&*o?w(lVp>q=WAĹ(ؚnpjIWZj^j_t:,S{x];L҃W^5䎏B'M :C=gc;>!`eWg;t8 KaKuq!Si`"0o0Wr2mX'\_N>##"r,\"v^9sϺ$Hr]u16;@}߷&]QR&(Fk&wB ۛ~z&*r勻vǸAy2riv %Ц9 *1"3WI6''J& {nr@/7V\2EydPR^]xz c&{ֲz0U# RwK@K)tbu%?qI8:VŮ`̺+%ϊ̈́4E0WfOA@9g7`(E뜳6xsήh `x뜳 X?gw#‰RZ=j0ЧYsι \`IOrJ@+:5PM>P5$aAYZkm2$؅UG d:5"}Ue`N@3x>QX2ltJKQ6ٶisci*F))v̼^ 6éFw Vetp JǼ0Ks?h66FE'k(F :?wnPEDNiQQq[;9vJ)K"hqBX rRJ|g)*HUr0al(VU]i7.mɭYП34U_xG"Ji7;/noW_HO\~Pz'-P?5Jp6b!Fv2nۻsiby@Ӥʌf:U;M0`*,{rR|]瞊~~8ϔ&F].~Rg 8czz]E_L;M=^feYQ@6~1FQׅ͙_$ޛKryiޖ$J"(IfXlp 0V>ځ>YU~8󫸊3M4].B/Z٨-,E"ebtOM.WZkYٔ\bMfAW ȺE?JՓKt?ɥtQ+ehO޻24y4t8k|}PJsiɈD5DCi˲j~Od)ޔ;؅e˜'"3ArIs]!8C_ jvƏ2m|h4$q8{0Nb;[8j [XoVFNzo?uf{ҽ—AYx8U'Ut(:åҿ C_~vVk( :߫[1IꃒtK/B^Q.̗ / 6s#^KkB55e3qm5F6P't;>>]."4dnbӲ V&"9J\"kX&OL®N3ܢ]9lQջ3궬Z·EI6nj;r23@h "G "9/Oa xb:n<#lZT ΐP** NܾJ4qvY2fs[s /ˊ]2^,K%A[J?Zz6ƋQQϟ{t~v?(J~å^=3&Ө^FK kޝKgt=Fip |.lg? G=(])ry)yد~wk^7Sfh&^Rg3tя73bMexͪ2Vb(DٵYjV#@ᾯ(7GU8HLIbs@s@zFBmS{O(].wwL֊GV֢N br-l݆$< N nogtnO[k>O#W.ݼOŅxܤ6m M4}咈M fsD ;+VV8}ݳ .V(]tz2X&~̋PѦV-4'S>ՁrW3a+SpJݬfSxj떺4dlKq uS*g ̺N^v,-FySn^ n:#V(BϪ.Q83wQ8(\$˽6Y7ًdY⾋֚6 qfSO#@ͺ=\WUvh=45beWhv\e:LKtS8ߒKWnk/i`u[%J:lbWfmqw ߹4pۄ~<ŋql<%.ZccmsS߃o@5d"1ǴᛴN+nJw`ɽ%h-J.v9| Sn8fc5o;0us[ |C h;lMմ=dzq5fXSHv|J*cWVrw||9Wws%=Pko}lq!eo&}IENDB`pyromaths/data/images/vignettes/._6e-07.png0000644000175000017500000000031511560531274021144 0ustar didrocksdidrocksMac OS X  2ATTRGm55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-10.png0000644000175000017500000001036711560531274020727 0ustar didrocksdidrocksPNG  IHDRldUIDATx1:ӆϞ b@+%SBFLDBF2L~@6;?߽5ת9,$"Zv˿؋HgW_B4Z"䆚zw5r;ᾪq rոz5B_}`5YD; -"uyQRW& `̱o9) :=Υ[7S6U`>JdtI Hz\̉ ry<¬3",)MFKާZ.,˭ʥ rªVXԺkbm2͝fVv][+Ak?FM8E\+qN8o+l{it%fl"U=6uu-zszg3VY\퍧n:75֞j 6möT j*)E^WKj AצfXr"ۗۉQo_kX8rf\{}sg==vٟ#>LԿI?؟|# gf+O<o7]}:"'xW8zw&{rk켦paf>u87k??Tu[ E=6.ZkC7f1f 줕sN3/؄l];v~tXpmUHd ll zIFCX=lC. h2.ؒ#{, g~PcCjh=Ki܍aEfD"1{D~C^&Wi<.im)HГaKG|#k9g'D#TAUf cǑuV"l'=C7?ZzQau9|*aՇKmеږvN`ƒ~Ǐj@ Ah{c2V0#@"tN2E^3[+ ;eݤ1t9z`k2ލ%r`) {݌zňvL5"XeYeI#:W"|S`ۻm2Äy  qYeW!Bۓmޜ_ h ,&CXeY9`ʌ-ցsMLJLm@lBqz#BeI6 4Bj!)eXňS5Lb2v}wx2c70pYfaW|Bnz3mDzC0̴ 0^n3{kayd 8B6[&09ɠz[`< OHK<~'O!a k#g&}voh9]_#$[Tx07Q#?``f~l*TC[E-p+03E$1_rN~g0WMH ~)n˶}^+`'X`s)`t?<B1M;-]x5= 5@X#g ̽.؉EU.=Ku 2[Vɛ^{O$^+ӈ 1]^\!~G#^@`7E㦹yMaG1Ҍq?&ۃQlʣC!4j{w&,uB8^P﮽Ta00&!hׅJN#2E -j{Wc֡dqDŽо$: l؏mˠbڀ ✫4-j2`IIvO6L s\4!,af,4agfEX&)unaz5,j|\YՆз Ov5[y% ;3 acnB`FL:@JHD@Gk܉v1"ngĦ~.?{!ňh p#Bei( O6S2+BvC<>8= CڄЙJeD轍 !rEL3͙i,t}>.oeBuYnQ;jۮUDnܙp#ӏ<{@CdwI߾ޛp%#WՏP_Wv5rԘ91jIog}]0Qa'5-ι/uD0'.=q?[>L/.~X߂-z絛o y<5R^\-/4Ö²_e^ȃu]'6S }‡!Ah4#w[Xd>c6]׽l~:w(#-f'|m(wrkOD>EŎG8l骶s&Ә@4 H_J!<4ih-BΈ cg"Ht pQ¦F2.:1gQ~3#74 ,)-L YLWᨚA'l]Eh,*W:DXBtBR Ԥ3"HP<AWw.`+q#r`I]WzBfm+H71BRk.yͦ,AuGD`}ay3AWr6.uvo% 6ݐ+HG ]YqD3H݉V:K$ʓ '8G31b48 qtUDxt@ V $O F@aX Hwz$cz&"^+:[~}Y="mc9zjALtqAwFM㽌W1/H¢YF y ?{9t i=Q 'bwroq.n05?``wQ#/ %^A2{b&߽ߋs;5嗝9Meb.koJobfz{) B> :l vg9?_:}x]=[wQ,[鬶ISΘ0X3&i!g4[I p\>n-:"[4ʤ|@v@ d`o۟u>drƴaT9c${bGWfCDMm&=X-"%fBAN~Iwt%F=䌁$:??g4[c  G# s'Ҵ<$}N bQmk!'<F]s ժ!g|m䌝fUq$/0C?HPR.)}M~~Z2ܲJ3e3֭J7:3lP3d;K~l1"}߇ 59l }߇ANm]uе%|LMg]Ȩ11g Ąmo3v-g1"SjazJMzL+RgI.'MM,]1@wCΘWu!g,[R/R[8$ht-'bWO,rD8?rGmOvHC7' \{E}i|OFܾ4fԼ.Ssowr0ܙ'E{;<ӿShh$IENDB`pyromaths/data/images/vignettes/._4e-06.png0000644000175000017500000000031511560531274021141 0ustar didrocksdidrocksMac OS X  2ATTRG155com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-15.png0000644000175000017500000001107411560531274020730 0ustar didrocksdidrocksPNG  IHDRQ9U`PLTEyuuu``YPP]AAC((QIDATx]w(ZX@| 幐؎t1+V$Kl j2-"WyWW'lO ?"`[?a_ux[}Ɤc*/;=?wW_P+,@/;C𸭈/--sz{nE],qq}p3'D}Xʛ;ͯ֏JnzG tif+/"Namvn|"nH,~OpWw/,,ޟH? d*teOzc2q]?۸LLP(w`cΪIFَgI} ;z Z@%㶠گ-%""l="*U1}]rCD sZεL52 A=ɰfc'J ΂d_ ٝ^wnԇbDGrYoXyv1v˔Q׊EM)j&N7ׯ}xgn/nݣ(REO)&_~Oa{ysaZKN`.ZRlXm" XX(j Q5qv51ܐ&1mie(3mJϤFi4}qi(9 ne(m"IDj4Gs>M-!'4ҤApQ{fw%6J@ڋ)+lHîH-ȸ,2*=--bygvwW, : ^| q[ _WݳǍh6mP G3 -*Fn[䰽bǖ`IWDQp 0VA,v` m_*ҬUĹ>In-Tގg[,]Wc&G}&L/PΛazLDƔF^a ,k-pECP PP7?n~_WswC22$-t=cܖ4ϵы] dzm%}jei&뿘VI7X׼Ý+%M-ZL-kXDPR|)s[kOZZ5B{Kt%k&#f|Mf:li JH5jr5Km>W>nį[ʔJIKt*#sɖlybfGZgd?gRYb C0e\=\CFD=[Js)_s)ƸK:e15W׬]0#׫RQA;8q^ez+(WKᓎe87dӉ'˃/n:BIoA<W淼õ#RGc(\rQ=qJ c~\OQF,g|Ds<GG}{.9 ݁RrK4̈xZb/b^=p^k/ou~8mƯC8h`>n]ZST%=k]bg}Қ-΂F_4Ou8&G#p[+t\?AΧ½c$ƁkY;ܸ:hn1q|:,n?pQb_x72̏Z{7+_a[~40_0|T+A9+7ѐ9=-YIyb2!IAa:펡Dԁir7jMeB0GA8ZGr7~8DqkTC'K{@x6ZԽ}l滤Lk|./Y-.GQfjB|61i5~fnT`SckgOO͟ `7 T3Kp'n306]$#KshWBKoRyP Jpe@m2!ց>ѻ1!5S޴&LqA[nY윧 -3(ZE&0`lbx;RJm&AG.v!OhD_Ywqvbu?ﺲEZdmQVܵsI GalӥEz6a+5"mƥѣl]kAwǢޔn 7Zogm1AF37!a=\2gQdžktP޹L9Cch=6ȕQ4RsTB?i!Z\њ6Ѧ/^wDaP#1\53:6hCϟAdG Y(} SCz6R?p@gĈ!ǔ,Wb1ݺC 7ݏݏ=.d=045؍nbz[ cc/:*R% zmIeW- s_4-IRE(. \tSXKdH}jvQk9kl6TS r'k[~]w'f>z,9QRvґfy Gqq #$צL4-[f56z/^FfGޏ{kn2CifZ_1CHkx 7K]Ŕ4K!|4؇knS2$wZ~a+v϶}H$%H6٧ „\-n[sm _Ѧ2S.DkjmzuȎ=Gwãpa],yv-)d0(925_'Zf[ymxZQ@ 牳&&JQAe/wW._ < pm>zeU4Z; c=0m0h`Iȫ˯_xԞuNu_FR%s{ػ 0l 54_c/Jؾ|#!5$]+>¶qf}nEѱuZ)%7.4 EX(᳸;+󄭠љZa8G'?AfɫXE>_~ߜJn;)k, ;KUJS-Q#}Αuouź}cQń2e mL0+F-YKmKiԜZwQk֖SBIZ0ĖZY- -]/qIKГEPǸzR`0 "E^GPǚFлUPÑJ+vix؍t}{c\F-,dp-_P Oc_w߃䟟HyӭVoOI2O^+TZXE >}^}7*N^Ӛ"8N;+fzJ[!.%aĐj pZn]>+=`7lZoX3ݟ|5_ycxC䶼z x8Ҽ N6e.W_?Z>Q]^= + ckz^oeK(^WJtȻxVt׌}kFW¾ o= ͓17,swWLTK//U/a2OCO/}iq)j'c*1w)+9Uf m-ŇN:bNIENDB`pyromaths/data/images/vignettes/6e-03.png0000644000175000017500000000556211560531274020734 0ustar didrocksdidrocksPNG  IHDRPG*N 9IDATx흿q</Q! vP:` !Abv~_@Ie[l7ڹ$\o"|'_|@!QfBm{Rj@} 03R" $+A4\5Z5<@cʼR2oihhgg; vR X[z1}O+YMw8뙺 ʡul!W>>nd7 naXD{k!D~/ey鲔yOplJF%`T: 0u{EH.lH+Kd&Z)+M")nawp9}]rkYޝG[a>%mZ{-ΟOWf+^xx/^%+^ S^ˣ6]h#/¼Xvgp '>_Əj/|=gf^b}z"$M%sR7īB5d2O=g;==jJ͟ODì@Pup^ FTy'2"4IB}ق !դ tJ yz+5 Qn0 )01ԮR~~+L)7P9\;,[ZuTSYL#1vgB쭶FpX˂4hVL`YQm17J]]&_j@P#Mg-FiaZ]ybn>'ɁGR7p[6ժPWsZ?8D`6+zlE(6DfXZ۬Oa|<3oZ֎x7> ZkuhOj-Mf1f23xHkB61ׄ[/1;tMV $r9r}I!97GesV9Fмs9Wiz]xӘUOXC?M)s\JZ vԀI0 ܓ)4ԺUʧ0V m 5lz5xVhb+ ZaqrPc0 P!#b,ԡ#7GqӢ ikַ;u8Y2Ox4aa Ŗf;>'=p{ak_hX=) h$ }ёa?>xDG)Ma{OJMstC;f|3X *wge%9qZP{s}&<_y^w;kX5'@-K wĻēیw! cp3lb<6B=_Wݠ⧽to1=EpV,yL7N,U[>Wa:*1q )Qۊ^U;ͼ}Bbr2֛K=;1*L߆TۊnjI9{U p/޾WAQʽ ` ~~Oa ] W\Tہym\x\1wkJ N3/};~yuCGCt_T! u+(S>o.} =b*|uBïn]/7?0KP&i Lqs*d {ec^\Wa4^ 0F@r~yM3o6r ak\B4x]{N;bc.nEiB2C0-ndqF;Ы K9}d{+MvS"1fi0`󓐷ݣ`9U* QAdo U[tϝߊn '3!ICC l4ECf~BaD=3h ]HYB>;W"DJqU_na^!4ƯCa(JPgJF ?C8PTO@rviR{p*^N5KC"QN؛'BosSy,6ZYppͽ.>:s#a'b LM\6qH9[oCEn-֭Wh([i0Lث`UW䍀&,YZM  "A@ߐw00VK;,@ވ`-4N1ֽj::,] J xB]oht}cG*!Q΃V.fG ɐ`*4B$gJ0eC18&7<[0VI٨A\9/q%=p9=p H*9䰳Q J`E"F'r 5p-22OA26-g*Y.DalfjVB(Ja}]]sޕ~ U UbIK3W\*, `LXR0 "8)vWb͠36 fl QaYgy~ A1c L7ZT یmF(Ǥ.`&_^ss|܄Qa0*LɎS* VNnFify6cRPF4,ޤ!!ăRAVRºi 3u|#MlӨIx{]&B;qH'/[Ff@0T8cgÔQG+4D;u2 S 7 a-tg NUFh3F8eüa0e9l( dwraF٩iT 61faP"[="l{S#4j9iw28&& pA2A4I.d~#mSQf ~f(:8 ܐl+ ̸`"O8U6y*N:LjDa.T1 wa`7dwrۜJ07T ':1~*s~HXuDpC>Ʃ3iHeF6rq^D#GTbҐ ?YD>)GFUj#mŢ`b`f7fMGaSftGKjp,!3.vZX@**!,:.f~!&VCj4-l'0g3.̼xǝ]ZIhޚj1Q! R sD0%TꧥHndA*NKQAtzpq6%bqm nQ4~j{Lj"Ooi>b X ilGjN)LA4>.*j2M9 Ķ1H9Iv !B C qG Hd fig.xSZ= ƭ™ZC )mݵsvc(f&h*RN6a⟻`/{D=W=T:X_!Zmi{v[2i&?*ʃpyЯ";:# :CCAx܌(FG7Ȟ0ax>j.yT95(_')bȮgB@52QM nitBL=񢂗-9ͯ"c(gTiW ȯ׏82*mUuƤP;aTp[:oFχH@K;OQT DmOt}dBA( Fx}$7RGI1˿)4z|JiA@- C^؞T6RJ)]d@ !2n06zR q 3F1(!:E03{}@G550v0 RJyBYh wp b6 !$J:JbtEEJ,JjAaԨ C!]U#ˡTERJ.̯`D 7BE̯`(Xx`~Z2´gpwA_ly(BZs=ղO9@BTFa-P@>hcIa<}j\Z+5]+QAgo Řbk[leLۙp`; ӯ H>-Vл8bVkbú*8Q!d/!㒰(`9^8Rtd،R; ee4VBw_c^r"O|򨇯X/<O=Apֳee_ai6KrzVd&3e<0Jt:zmDS a/=r_fpq10^@K3PlZAޗT;0Pk)]C҃(MZG]>D#FCa|zFp[FKgs1V./ӰN# t3QnnfJ04xqz`v5މR)G?FW! \7P۔J%Fn Rt&*ygjDR@]|SxH^pƜjI/Rق7bI|znN WpoUE_fyIp_"{];QF9I3^nJ M~?롣L+H@@,/"YeD9RixR v(ذζV<)Nޯu&c+uDU,19Wy( )\@Zx6Ti+@哳`+[2B/PjRL%@bdu]1ƞO .jpY!TvU~({n _JՃ!V8ᠯL'& ,-HCNì[fs+ڏϗҠ .GZղ^eTrLSGI5ƾzEؿ~ A3*TjyCS<̌mSOTwL.S\u rB"0,ڿEt$ɯQHQĽ$0mҥ1_Nd0=a?2s`(fM[xTvϝ%@vz >mcT~ oT*f'Hn~Qڍ g/i?c+`TzbE'^%++"m:GR\X3k12 Q"nX[fyaH3\ߎT\@9 VѨWMoPcb1|HJidEJTjc+Qys,y I//G.+.Wff£?49߯(ENeo|=8ݞ?v?vuIENDB`pyromaths/data/images/vignettes/._5e-11.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRG]55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-07.png0000644000175000017500000000031511560531274021142 0ustar didrocksdidrocksMac OS X  2ATTRG355com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-01.png0000644000175000017500000000031511560531274021134 0ustar didrocksdidrocksMac OS X  2ATTRG'55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-18.png0000644000175000017500000002326111560531274020736 0ustar didrocksdidrocksPNG  IHDRN\`PLTE߿޻޼ӥ˗ȒpöMOd@1zySQK66v4K& IDATx]۶* [@ ^V[mm=ΩK#g$$ǭgoo){NJa 0LHʩbnh u(CLWI.\3eP^:ZtN 9`lq.0_^݀l6S#Qnud!NG qYޘs(X`I $HY~Q# p(YL$i. 8@y0@ cXkH^v$vz6W=5  4 moEM Ok6`ԀH&ZiKJܐՊț)+$ $m! Җ4|5iʢ2HpDPiI&"`DFGkR ՠ m hKdv1D$g4 7I#Z?Qzu"m53d5#",֟F$|AؚY֐0 H3DڒzY@,Ƽ(Q@&"O 0bLmY-h+̏7Hi+V0`5j\[жè,Qa-IE2@:<HX-dZ+DZ*[yN$MLN)iңIHFDa=0}Sa6w`69(;7_?"!LXn;Z-0"HJkt#@ؑYIF`Zk,¿X0оyNdE: wTZK;FVUVgңUfzY.lu,` 2Ҁ[ r#"j=vH i@e@duoD%UxP4㕭R)9hl_\hbp <!I*oi EE3Pe5p|` k?xam-#IЍC&[[[K z ?9ik- Q +{Hφ`8GLUi " Dh<X ҼwV " "zTPkP+jhKD (Kjc50 HJi܆9H@aV e_Vi"+ "$&͍V Hkr qk "5? "0[ 1Vy 0 pK a m&&`-IKܒZmI{? ӇBiƪ(Y^JX&%! e F.(- f\+Bh5  LZsBKAhZBJ \K𗄿 !J˚(7\0"I Z0TXu J Ņ_T! H/R³p-!s%RZނ !kV#IiAٱQg]~zȿBЖ:w@Ą|e%}{|$;UJ{O?*!*_^<#⁨yUq.tTֺ QT2}}yO0/|\."nG]VR+sac\*DN%+_%Ryչn PSC!aSk2ɚe 33_Qʬ9dVx&] !!R򴄀JI36rR&e%/^V2G6gyD:FU͋s r6kD.,t 6)ݪ)χ|N(aW/hIK!Vևԗ%\r TJGy$ߜe|];9Dz,Rׇ(p6)L(`m 4F#};ЏGLOX-3:x6DD#KaƱi1mز 6)Ly5`:oOlC@*"y|# ^AFlCB.Y:1L "6!A<}FFh _lF@zD)\# `a/6# @`&Y  Ct؂"WU? k]- <>Y;wn] iTCV)Lv!$ ݊2@6{Y0ߴl@ V/_O<i<mz4晃S|o3ku͉z_H8s] INεgZ[;Oɝ)5gzlnh51 VQgVf4ƹљ4ìH-ΝHWKjZ]FO" ŁJ9KruH]N=R}!ryB _pM9CoF=B$(`m[fh> k0ѲRSK$A0fcL9gz#Z.DBbHw3!24UJ&ZP 0y3fdHA- `RIfV`-[|\&ZPJt<]%?\w9'cS"v$bbH#x,(;ּ4jk@v+Jgcـ G@슀&U :ν3c/ |QA@J%GX@qz\F@m\rmFX &c`(DSIG/R*ɜR|jq;ʘ8.W7Z+̉0v&,j @آ"=2N[h/S4f4ӱx4o eVtC\\88ukѠ1sƌ}xx9v&KR`ljBxr"SPq#v@Ʃv_&3@}G> Q{b!;u'NX#E {wP\&H* Ze AkU3+% ʊcKoچG;< QZcΉE(! DqQj_ ZD#0? zW[_C@8;Uӌ$u>ٔgcМXG#!c)5z­dP&j_8_| A,Fd=GvҐPifG" ao!hTY>16Dc0Ꮪ Z_C0ѬA^c02/U`;{߮ TK|0A?Zb< YBaeqq-1Cm{{fy6ͽ…B0ޝŊy"^{ z\aؕxX,.RjIgjuU9,r^9k3'#3AUO3+'#ڱЛF.?N54kgyy@O"ӇG@>"P94h1g0? !3hS6րT)1grb^D0e})f'pF *aSpq|jNf+vz`N<9 (3n0 I`>f<&ن hP9 b)3hr}35f#A4S4?~)cn+H@׳9=>&[U1|dAW "3"}%'cb>t]9߼aQ!uIeG1w,3QlRJx23u=JL2shHfYf0Fˌ,31"Sܲ5r*Ru}.4efV)QKz\&Ybޱ FQrt_KߝGHb?♙?2àwC,3K13AALz\$UϏj"C̩,|jʘ5&Rl] z  TNb!0/\gi^C@d*GrLq$ʘ6  |R]~E$[hSC,321ShO "'j>ɾ#y ;" S<a`_OYfi^E@2t3\z?3)c 7"љTw1[m%7Ɨ0y 4+DL:A"p p;&mqf•e:Y0=>w_%ӼHzp$2ĜJlg)ETOjc e'8uvJLO0]dbu;Zk˟/"nhH[isHמ mKHa|۞1rdu.֚ZU/aȸ -_S8≪v<Ά'fy Lr1%c/TwJ15>k>LIُ rV81EM6x" B*2(Vsz1͋4N 2 iϥ3yAd(0wSStLJ=>7]f.Vac) 0#~y5Л/B)cq"}^ٍ1D@;n#C!ms5xxyʘ;^C@AL N8 wq"w߫%E(c#@:G(&z H >:̜ `NS5>z2f Dk4+m"Ud yXfNQA9ˌpN&DDLP@u/zg=1ͬٵ. eϽredOQƸ ʘEbi+d2=T&=,t=6We&8 gA!1(-YQw|q]4szD6y2y iB )`ᰶ<rgԀci#p\@w ;SϏ#wU X z%jś+r vN(fp~҄>  8j%12V d" }!!T6[_#E"x]2mӄ> ĐwL;rű[= :8zx "Bd(8F@.-~GHyw1k 4!S0(P cxV" bű= Z7-iBC@"Cri8@@@#BC)qSߪ qJ'D'1" FPLbWX4:y7\_Fy"w=)?V\w.UAcD4+MQ3Q܋4 'nf0˼ pBLș2jxjZ^6eF9Jձ2I%eTdef>_ H{UVQl`멋:sq1M2sumۭL\yeˢ[,3ٹ>42>O39CIkMY3s9ԬْԶfh]n%1M;;N?1 .߶gQ8׳i9b'3A45kD^ 2 'l2f $`sFBgwaFN\ 7VlAXa5Ȓ\Deq"܍輟[ :- ?ZqȹT@~@s}&يH` Eʘ=sFz5db@o" )cvA@6B@_OAw=4[v|PCHeʘ}89s}"C>|CL UyԬ ˔10=_@`@$ي `wDJ!(cvBkae<BMi6# >ZN`PL$ wpKL#7OEӏ؀)o-RTp~Α|'PwFB΍"Cґ緐Qw;#2QƞUv)aH!rK2OKRND 2LjwBHux&7?q)*36-IBr>Bv\;Pj%?F!d 2qJTP-ynETݸcPs=En4j+_RƋPNDRűD1k]OBˣBr e>@fA`8kg({ib7Ȕ  rU[T [g&諯|qe}&\H+= ^ EA g1!M1r5G&""9!Đ2f'a`'Yzc; @!o `b,=ّ{:Q o~ H9{# U kk(cCtR`V䙠_@51{!L슀@30|sxNLvWN}pPEViex$ٗ9*Rue܎|θ+¬1 @3bƥM iB;OE=X[,q?|aE|%)XEL) kdA-(cGE$b8 &s#ӶC{>nƸr6%GZ7:LLLE&eyHםnt; uE/Q1CH-IENDB`pyromaths/data/images/vignettes/6e-07.png0000644000175000017500000000657211560531274020742 0ustar didrocksdidrocksPNG  IHDR9wi AIDATx흽*w8HȁH S ~fF79绢 Q l3G0Z Xmql0j {|l4RTVE fA׃5˹.vEE}^x-ehc[u`s 8zZdT.ހиƢ0J3_ƌVޮ3A|(jC6,# b(30:/؀N gM"cU4V &kM1F0dcmsA#0ڛvX[>xcYkRSƛ6O9 djik*MQ1(ߴ A*h PF al96 =VP $ DI$5tL1XCFcs@zh EW0kajcAhC | l9C~4A3D 0UAxA`'`mN*5¨B9?ʠ`$F m0-`Y"|1 䡡9w(f D@-j" 7m #jd'Aː ·!ذ:;$#yTpIBS%#2c9L3Zd#2.K=7Cn*jOR8L\(IQ*B;ND;JqlTkB0cSFji4-.500-,TRD S1j-߸W6@Ski, j x:ځ_ܺl6uy1=H}9\o>Μ\|z. fic(|)d8;.7n`‡vH 鰁#6pt8aG:lH ;Yȇ ׂ9|_{̿{DneKLúÈߨSC?'sjoU!]-nTw%J5dN^D7Tde~*>Òo6_E&ԶXvJ]1R~2Q/oR` t=RVfVnԳdۀ f| p!3#)-3Ňyd7ګ:_L`$s2[$UE`gOplب\+3؜9QD#2]Mx: E{s  xn!rUׯ2viATiۤUB@L@5RY UKh944>L j؂Ȃ%eЬ2]`(k4H%-ɽFI-)88D`0m$Cl:ys\ 5y(rc01WOaSm3!e3r?ff2.zۥah d&$fo0@3FSD~!+ZRw2No@74Dkx?W4MDWD(QO>OciyY@<"DJ|/:}.~2)X H^c|f] 3dl@ y#d;/FeS{+մ8* w@1;WkowA'YKW۶i49mN6}QѬR ʌ98ߚ1 y6o.$)3[:*1z#oK=]r66fG6/s 3x܏? Ûk[f^p8ftfa^t]"Oϗ%*Wף,ڍǭ#z%0nS]..2㞙1ν[A#Su?; r/_Gk.wYz33G;p0;e(x9 ߽M̭O{/ Ƿk7f}_d9g_#o? <'+n63?PGn>ln} N Sm$>S>ϙrL{0sc(7zf4jg7cxqmE0 *jg6IJbs kA6F f87rlJasA0B ~{g|0 Wl@ 4Wfzc.0G׬m.¦ 1]K٧^R|7pü ?QNb:Jhek$ #D7nкYw{dmXQJNul ̕yJ0>v y3ŒAKd ]T)a̢23s/|˼Ф6J0Z1Q;@d|Y^¯wA8zm2L PeրL8:ǻigzQ7`[ EERk;efqR+㌾<>` Iͭ3դF"Ai@{TX L23 'ӳmjA)c܏v`@04P&H. 0G0kAQ"bw"}k e(A(r~*>0d-j5` |NPLUdĝәef$Tz;8 O Ǐyžkib̗bejFLs0eԲ,fZqj"k/c}^1穴-3h @h`) ZZ|~Bvu'Op?| esʹiF3X!ճA)v"foy.|'?0c7ں={~moD~ 3377<+M(+G:lHJdIENDB`pyromaths/data/images/vignettes/._5e-04.png0000644000175000017500000000031511560531274021140 0ustar didrocksdidrocksMac OS X  2ATTRGO55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/4e-01.png0000644000175000017500000001175411560531274020730 0ustar didrocksdidrocksPNG  IHDRKXIDATx] k+ȉ*T*U) H)ȶ<ƞ{߷;Խ3}Mᐈ@N^g+IN (r(픊-tCA7ߖHƣˇԨέԫS/Zs=31#Z[}pud#E(>.P&6[gy " @%?N *; E>*WuӥP rld@D8ıO\:ĥ REekjO;?OZq:zBrS[ꢟZ DS0[hI\tYˮ+@ik@kzg,WtVsbKBځhI v0\rq@^0F'@e/ iZS˥!,9ר!\-HזTUZd"3ccZyd@JlBtT`f!eԶ(+9nJaQ jy3@ P4b)r09meGJS5 *T"zMJĭF&"gީ BԶsI(5s/E 0ݨQ#bD~N]F8)٥*!AY*1Ś~T}OK=;鄇 T?* $F8qX;bvgCG~BAb£0\i 71 ϱaP, ¦L@cg#``4GN@V9vX8z@JeXEˠZ`0,ḆTvg& 8gpTI,OԮ<8,{apAvvyU]VsPCX:XǠws _O3KNahEYg~Vdɉ5#XDe4hF$JIYpA{|bBo >ޏO}Wwnp[$<2,GosM@{ c?8O"A;l`GҠ5̂@ lg g::P`$\pee-ʏ44}|fnd,VutXxp*xpRes` Gpee"^䠭eK\%B67.:S@ -b)mnާ.#8z'_jy/)l X\RBXsrV$M@uhϲc8M!Κ@ [.. %O =6|*BX &WJ"΢O봭t aMN)l ٭rVd.H{f`][Ha a a0\t(ӏ滷3d2բ>-µ."u]y<@/s[?0F'7(ђD-nGpQ5}{N_@Pګ\ɝp96@spS% 9JVAQQ< ZEstQAg˕/$8pzOL*ݿ_cݿ_c/.;nׄ}6'M0)@gW_w Z_kɆ~+g;= k0>Q)kZ[Z[`YZ[ŀfn 1q}#.O)9z ~9  Aguam-  3.dL} ɾ]ҝ-!Xfؼaˮ*ݲ[_W+ar{EIO.":s[L.P"(pg7MKm{݌e @M{NGY% G=Lt3!X>f-,SXZ0J!j.sn& ~_OXs95j F)w]j啁h]f0rv UكL ZQMwpFu[fmZ.xkĢxo&9cz|y#Z8LX9RhZ^-6@P9QRB: *}XzooTk}[۶zI8H 6,r U>S$zve98u/gZ>9u7"g^XhVAǗg>Ê@68~=fF{/R7 Gqwu[Л-K\||krބg,n/_2/]Qo[zCRõ5壐9 QrQo/7uP1[»h3M[g0>vg Xa>gz+oYD(SBЩƨw÷ԚC{7>ǡi;+nB 8hXɸF]WYL| )N;U }s@R^}>bcB*oXjL8(Mʗr9SiK }YTt}n%Fwyfw c NYhJ (Z!JDƆ.!j~L6ۿɸ gK2u7S<̶i v7_^1z}6CzlyUV Y0ob@ˆg>>̴S]=9z Ҽ)Z2snu 6^bӕE<5'ij~&2wOq?sXovUv;fhf|Rw;oFKXY΍0 {juY v90hNjv 7-3%d6}f/[ -p(o {ɮp?[qɨSmv=CCxG$+-q/֚jI9m ={49+6(-q7Ҋ:$>ƚC^Ѵ^RƖͼ--Fl/RI O?D=ؓFR([8 >8|arT{p/ T*]GMJl4NoWEЫ U Vk7"5b>H7`LycZQyVZQsk5;MBP#7AE㵩a [P2W}g`Z&cj̺̠̔ac^w+q~MaZ'QV[@ȇt3K׏4Qd30 '8cݣQ!;G3BuJs@^EJb566@ ȐDX~&IhL07Ng\5.0|F[%}73W@muYEcx>FeTbqg%7-sժqtYWod+k`9Nk÷Kpޮ aY^;%/u&G갧7MfPyV:+㬋֝^>;Mf4-Yso=P02_ (Dx6+0nw?TPciLQ8xO՞-/g~PQ؟Nib\^.z![ %N=[.W DgL6s_z6gDQ~ȴb 1?wj֖)D=w:hwt] _,=;"_oVCC|'Mpg.Mw0&{ðn6 *9=wygXYc@wf(=7[0mwkn_KO'N8,Tz ĻgNV>c|iN3ߏ{{H2Hz')?0gb`<\Eu\J}r.-}IENDB`pyromaths/data/images/vignettes/2e-01.png0000644000175000017500000001005211560531274020714 0ustar didrocksdidrocksPNG  IHDRLTQIDATx1r*f1lU rrr@NLJDUT_ i<{+ۇ{FBi~'A)0{χArԇ>D"a{}nŽWo JzD%tL8 " x~\ ΢G:YLDD~TRze"W &5uR&@H[O[?l'Zdmdu0B]:BqFBi0Nx7/M H1"-[ lbqd\͠Sz&;:k,҉a$:4݈L].7G="0ɔŔEXs& Ch|!0p-kdY\*sYt#؁o Q_FԸjc#l9M4m!+v GQ0tm-ZcV`el6NӘ+̱1@ljKEhqfB(04g=4VJ մCɵYqm> ~/3ﶜh9>j+)su^LMgA=W Gr/fX#$w(:qA@YS^` {"g/G/6r~GL?y3.JF߁%iσSIO˿˚<-mͯ.-J)wa_?w.l,6 B}}gi`HfW;Yt>{t{I~"ү!4z """oOݓ招r]G΍9ٕBBpHiԬ*әL~IUɗ~9mtˮ]DuFچqa,."]:gþ ֲ ֲˉ g"p{SP r:yprv|:MOwZ]ul ԐΨ !f E9^Ǜyr[)H;4;݋[VBNW z  `.Wodʨ\2Db0GA{~ d˹MM5%\HO|`3 *z賷znzNd>S4YSoj:`":aNjR%Mm+G%B7nrgkjU{ED-Ub<:%v<'`X7LZP%hp͙ܤ~ ހ >)Ml4P*:l&)9 ՙ"@3{@TTTv1$yJFݏ2iZ+d%DiF -؜,*U0vSa>=sW%V&g M΀kgإC``Ȉ,ڈsK '60 k  &/`6Y1 &G xk8[kd,axir¶W f26Џ܎3Y2`? N$54K Ic(sze0eFgvW,٘ߙ$ݛm̬lTv!|(%2u L)B?kJ@I2LW% Gki>Rǵ4TjE~W'AO4{n\;vgn͝G~Ff O9zz=ӹ#vA!C>|o:&5DL7I7nE րLql& ZB];yv c`u} ZH CydM2/v5ʗ)$ɼ~S(L>{R/3!GLďa@5S77gdO9tTS)Zk /=ôixO'bY/ti)QKGjY.0k{2<~<‹JJ=JJQ0Lg5| !fKͭlw\S}޼epݖtG9|aY5-fE@&5}`,7:֜o,v DSHʝik0ap\*>̩ JBџ A++yvrCRGj†T9c!u`n8S4 і[]6c2CIʢKDX&:ԗ Nt /Uwzn Lr, !L: PbjVQB3xջ@u#ݼ9`"k50s@?lz3#6Z{s17Rjmq|v;el9L jPv24c,ƻavX=vp)o.Vz-!ˊvr:&—7EU 7Ma3eRx0?fy!ƙ#s.4_7/]x7BH*1ao>"ov!k.z=_2W()oT̿`_\0lGiW2?@:0Zk4{kknNMy{˨Lhc^-8a}X8X[ wh߉2wwV B H,NMۉfKHk?DB>UZW`J%NqRR5jMDכpDZNV厒0[;0YD(?EV/0 ~ ߯avedgn>sw Dž@x ZAZk82_7?-u{t9C`':P;yc2^beǞK| P2 5t3l-Pfp5AיL:`Zz=!qd|n~NrlQ=:\:)ߌe-̹¹_k4Z {t>\2y|Hgw󀺼کL^QcHpb;iCJݿ (S2&\bBFIENDB`pyromaths/data/images/vignettes/._6e-17.png0000644000175000017500000000031511560531274021145 0ustar didrocksdidrocksMac OS X  2ATTRG߁55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-16.png0000644000175000017500000002561211560531274020736 0ustar didrocksdidrocksPNG  IHDR^W`PLTEװyvvfffRRRNN988Q"" e*IDATx]v;&YՖd-E, gDt+7o?&^SiVĔmT"B_pO1@e୫[$L  6@v a0I3VD$ P@ T ,ĀjO `f9 yb*+  V-RDl>fcg-r*V@hѿ}$f<1Z@*J5.Тh(%vA VY0MӔp& J`x| zy!Г hʿ]=́!V@@5&P E9, ZيG[]-W :.Ay/AAB)%JsV R.bv1+"ˆɀ ĦriƔ2B5%l&fds2grWC%22 kS-%[+ѕ[=D@P%[R"X J-:M %I_/ޗP*1˟R"t ѕVe4: tN߼GGQ溏@[';i8:q2˟33RZKǼϯjx,o-N0(C4P@X3Z#0\=弽@[TЊ݆%UC=6b̎=d- }[P]eP_Qq#7(}Ix=.Z=ϕP7= p6%@=Qdf&v,6Pu[ >TϪaDςAc 3 ,'cP0H€ z cg7oz 6pIgQځ|府.a@e\w n F!52kc Fܗ -gK`yO=V%X&3U[`0' ~WCťc 8YϨEЀ(3ւ!@`"n )}7`ʹY}ՈQj5EE#\JFNErDY cQBv0%g}ٞ\E(-Cv klۖbk{ )CSHFߜ*9]-ar̪c( >oa0zx,r|zxv Ȯ%ѵ/nKLPZmdPq"evv,Vgt;i Qjw+jE3$ g%ݥedn#ĩ稙չ%|f(wAeC0{wnS]Sݻ(r5gxrP&^mNdA$[]\3 )]P nOLDS t⛴1fGA;o_g7Ln1L9 ^|1c}=ogn_~5 :%$~hY⠃:蠃:蠃:蠃:蠃:蠃:蠃qA0 9w:OQSUfZ.Nv'a' Xp0~EV>g(78 1;J/.a& lm y=2* s~vDĴ# d=䙅/2Bk#꨷gb vZ]teDhg= n~9uk-V9Nx(W;j'A H&i,"t'Cbkuln p[M(nsV;s3Y vJkW`'bp{T{c]!.U gjz4e b_[!8;dr[2#%R R2l3CGץ͡JSAr-j2Pr2k03\ %I%3TLMe1)dlJT<|* O% ag+c ̑e*(%9~rYçju*Ks@H>!GFpă4 f*4eT{sSKmm 50t-B%4VbA0[30#6Pj&VݢX :4G_M~@BC~+Zh"z0ĆXBԤZ4 ,G)5DW3&Sm u'QPi05 06z;e4MS@kr[j0/!yvP1(]wBSt(qZMDCz1:X[mm|S&ԍ@7uj DGsns@:{}1D.hŲqDJ5z]C^Pƹi_vVM4ճNu{g>MSP*p2oaCV4bG-*D@X²%!P A ^djtAV4Y-A-`n <[7 xF1b!,7Q#nZb]@^^-A` Y 4M$̔YD2ᤗ$HU.RѴ"pvGnCCi-:Ӥ B2qk2N6cW4ר4Mn=fmMz+Z"D)pM,W=DyقQU&Jv 9*m7ܔ/ܭ *ܼ//ۤwvԍ_:#7C1<)x\ ɸQf絈>᳖ޛ1AG%|d]IrդLv‡' _Cd f S0V4яM]=7;=L'5BI,죍l?vH^y®556|ZCVAtQ߉J'{ݡc$~9x{bɯeã3)CXE{u#Y6_TӜ q4sf^FmQڌg2 o3 _b m ^3mElb<^Xg}xք]@'ޕ$ |ԃ#g>tAtAtATP@i4y='w />bKCkfFg h\f CA ]?>|%&9 |[̷Tt`x;4YM[)r؜Teby7x (Y2D(  #v4u7~3gN(![bA!A_4BLL:F5L@=lt\⣼>TE* B{[:Q"МQ!|ٌ@}H`Cy(;! DwHRxOQnfGy=4ts*o 3 7\%BN^5ݬ( >7de HMͼ^.[P-l= m, h˸[=@d 9JCw]h_:#AHv TP@( @zJt?la' o^gݠdpx,ha@4Dek>)'PWcKe4]"VT}No6{-6& %T+-ou$f;:!tAg)˲`φǺDw 3_cͤsAP.j#ϣ7%4sт}0~@ܒDb@!Tfo/˨$@0ūiA[PE'b G0->\N 9e0{c~,# C >-ąAʜ(-Tח3Fmg (rI,]*#X%YЂt]>똠ug>w(˂߆\ߊ߈YQ@PaU~PpXEPQAw vf޾eF`8Z|vxsF $o|]_Vl8*[k^} Ʃ:g̲`5ಮ?\;0Yb'gq z"31bXJ=㸜0r_#VQ;޺SDe^|}@,xM)Z)e=:$b<5K8#W.mDh>5: D%=I̵2"PrvQ5Z^x'9ņjiTw-e^ϠaSͦg7WyfYC`W#Ԗ:/jzGRꝮM?HP3dx3(՝N/iOP{{gP; gu9ԭ2z ߓϢ`@Xďz }[bX)Gᶃ)B3~3kuO GЫqxHDe;#˛^|6?1^,y@D[ԾlF}1Ѷ*SV&,_TB[܏4=T74Fʐ vRtzQ -2bj_k ncD/: >Q篢]hsAħ\:Y DGXlY 5rY.Җ\vnvD|=6ėvK_<,I7U< @ PeR᳅K%^C7'XɎD 0AT/cd覽C abIgJb 8&kF)Ppz-Cz,dv}k( Y'u1R5)|t-|Rs7n!ZAT`BBugVUuiZUlEv)+C6oM{-մSXg0Dc]Gh kQmW5u՜Q%A7P0MS!7%AhCu݀\DC˜+?9]I9,S֪u^v/jՋH&R^p?pt&"-*(GtւPՏpY7e9u!XZZ7 УP%@B {57*Z*֔=tr{ 4+Wi5E(|acr-XQcA (MIr> i* 6:=-~a!fԨ].dVw ƺjmh06VA/)6`r[5BFӹin as9pL[݅t%yԌЍl997?_5&B p/P"e0#cF) Sk"/KpK"P//{r%X,|JD%GN–})cJJ);[Rb`K$r ZΑrŌ"x>dY!ܼ/K,>'4ՙ!ᎶnN6-tm{xnB'=:N-3sT!\S|Zc:z}iU^C!0;v oc (LD`Ah(zFnìf*eK3 LD<^~fr;艎r;蠃:蠃:蠃:蠃:D\9#G l)_ O'ߎΣ'M; ZQ]Y~8]( K nY0&:oy\)#w 9'G1WPp%4O, $(Hy}Җlc .eoײ=(e9Fm`ig6 iO`oN߉N's+Ov!W/ n¼=˝\ְ{( ~zdӯU]zMԇY!α9Ck@OYp↽xԟ]΂N} g D`,AFn'M'(6kb}-C ZS&Y#ڬ\>+u(]( rO􂿼ߋ>.TJ;Vܲos(`v 'r0#NrGWuR7oܓS]}zFhyvy(_EMRK0f`:Zd2#gfZ|g01( f0\yh]@=w إ5#uvDZ c9Ԋɫ0q]YZ݁AdAlN#Ȇ-)VȕǶd{ JT9ǸK>]OH̲A!t@/DAOz#vs (`Ypln4KdOZ!ƶ$ԯA@<Zw_[4u0͗tjn^ =33h__\ϡg@Mf n]PzB\W˺`d8uAmMk;C|8[\K{JnUI%//h^^GUc;sQR̾ QjYU{$6%urU{U0\gAv孕 RU| 4qMUw*ëtA+qWUcXo|?M}arVٽH_0 Zaކ.G#1:ݡ(=],eC!O"HwH{g*=֛+ ^;$"`^zqa&yReM)!T;ujY#}6,wc+ż7:}3f#6Viwu(nid|ۙNd]AgPQP!^m_p}G_ue|!k|\2^0jJï/? ~kb|~O#bq~:蠃:蠃:蠃hM⠹Ec<93@!J^H=.AۖncpA7`Ovh@hV_fˈg%;LmEcM`v5aL$eV]gj+aY N<̖m}" r蚟dK{4M%ؗ *owK/ W}t>"kC{e~wg+#ӈŒ{Ā 0I_t.ll~l? h \O 71ʒ2y[/y~@~, O\g 7/"/__~Z/lz67~e+~~>0.|uǟ3#s ^K:}nm ~yW|ccp-h-A"1"8iA8 Pf5xd f!V"H+ )zJ|u[V R1L k@0 0leAC.}5ޟ:DžhxUe~NJ׷W I`mQ5 o?$o-_K| /_};y xF/a<$8XC|/& 08_OYx"y=󠑴5t^ʥVb4(z[at"}WBEL0'k%JC -!;Pǟ[~͂|5mGa* NIM= FZN>wi;h H b(=qϊֈh9`L/Fց olWʾEʈ'`\cO0Ūc0ưmJ@=i;SM<)Y}~JCU(nnz#.^E>l*@a'g /VBS UDF#X?v 6XbȻvm/u@Un=P77kWݣ3%D>,IQZFǙk{ q9"˙.`c/>q 8f?+2O*yosetATF] 0ОoisR/Z@p1HŽu]u=a 5~#;u`l̝`41͋8-Bwaw:#c1㥮°LN0Ug`D&Z%k=(B ε>:n<̵= gS0/apڌO8E#V3}F뺮kC锎0 6pEa" 4oTڔ5qMD Dt{;rgQg"@ږ0834 "^j+0L-F0+3)G6qJa7tD㥳3W 3ޛz6{hZ`*a0-߅M5CRZn#&%HY_YUCD-/V~a* Ֆ< :y&ؐTmYפ侴@-0#3)7J!B̢[J ]T NaFt3^5zT\0ED1֟obp9!pE32ÅKP[-s*jA4Rw+XcOfZeDy8]d9vJb.zJڱ _w=U3kqfD;}SFi~EGidRnFM^7jɑbxQg@qy1M.Z,۳hhJZ5ٺZo䜄)W"TlYk0ZcgǤi%knDS1a0knLZ`Ff6JֽWtbhܦ/VJPZ9f/?d1nr&|``WR e׃Jʋ)Ye +)"CU`%Z;C԰󦿧d]G3e@[b2#hfo&F1_Z -2&0JUnu,< 0^gK~@P`x} J;FFj@yLj2^`7߃γi%DȨK.NHYSbE@_mlݢ2ߵv7ܨ3 xrhLsgxd1 M'6(d{OV`׀H[mmB.U\(yc ƕD(7p'뵴*B%-; #1LLuy0m5]b Ȣq_O{k*9Y _X{T;fHАZ΃g A E'=|\ %N2nX% CXR/4? XPAh ^W=rbqb2"3\if*z^w>cuQ&8=Ж Xy;Bvuqe)n"TY_rEs.RFA nx XZ~qa] 0!*4֘T $g-4Vh5s4MBaM' C F.Å__eeL㩓Lz;LR=og iȠIENDB`pyromaths/data/images/vignettes/6e-06.png0000644000175000017500000000671711560531274020742 0ustar didrocksdidrocksPNG  IHDR9wi IDATx]903Jc$r*`B (wLטv@O@!Jo# |wR&58]s^b{8)QB&pw85pq!8e/݄wSFs.;ж p15(CYWPFCZWdoYR빋e:^YG*pG뗹cM[+ w4o|P oH+ᱱA0pb&7(#HQ%Cs3CEEIPSeT rYE#$Lk&V.s`OI4d8VZ_T P H 1D4㈆uH,A APyfLL` % a&̄"L`f8Wn=?<,e.5ՂB!ȤѸlԙAV0a썉ѬuQWV@a΄X  w0̅G@ "AhPJ@gԕ(b,UuCU3*PPB@ YTHX6m7&R108d@HQ"ƆYFE#HyB&#aTwTVap"#H`b!cm&64` 4L ,H4jB53%Wn=-x<ϥsJh6<)c9h9̺,bMVlD7PP .5Z4"Eg9S74\іqͩ+h6"'+˫xbesox|ï/8/~?SN+_͙sO?O9x;L_ci7xpپK(R߯^饁Wzi^x^饁Wzi^x^饁/: Wo,E4C6kJ[ɷAD| w^rV6Hby~r g1*McUڦ~44i༾2an"AV8:o2DJ}̎#1Z ,{O-̛ù4 pLE֭p攏g>~,erLcIȿنaTTle MoC{ӹJ2E·E<)y q*c)cFf1qŻ|n@C=_jdE#408qf/SmJqobPNp67XM!O+X́ʻMu20"0 AgH"%YG|1b*[N`ƴ*C#aZ )TaA^bpoY.`aATz@0@!^.˲,˺w0M) ;?*SZcL+a1Y2R:v+K`"F>t8`@b?bC+/4@IS©-0CرSѨ:~'F?'Mqu!d$^@l옿R8):s `pDmg[<Np8pAwH@6@PRQ@c-D<фzŒb Qt `JRI&m_e=Bؿ._`+Yէ1;fGR8j؆p(`s6Tkأ?i5]>/1}nf9f` wщRܺ;0[suxy} ={oeқ_`ݭdxs=yZ|30{;]DC<F//wꁟ}׶~燎l)z6b~Ŏ/\ MS~,o\?ˮW) <_XzG}V"ߑC'o!;Q ?l_<~.ʨvjcm56ŕ'|Oϝj#/'3/W.;?lyPԞȳ,:&c=}ǩC8œd)Iaӆ%8oUxyT c h,aB'|o@z'1ɰ^MsC$9fTy5:Fh0lL '(O1jրS(vTڇmha@ Bz7[ OA^{ }a h!?g2w̳uapD=ijHF56))$39{wT'1' 3T!9B,&1 QRj)̎0x]YM ʤDoqà ilQ5GH<02(#Zjiy:}桦PgBI 2vK0lrs"w B9X40dmzsQR΃_~7(c g-WAt8h$ Xy;Vӆ [D}؃ sq|ɄQb(6{gçTqؤzg1ހuQ4@g~\b>#E\ .(+a^ 󊾵:Ñk^C7턹@kSL#dK9.5aNyBNObvy&oUk\oz^嗟dor>f<0+& +yAB&IENDB`pyromaths/data/images/vignettes/6e-20.png0000644000175000017500000001655511560531274020737 0ustar didrocksdidrocksPNG  IHDRc5`PLTEǽ۹ÑzzonnYYTSS==:99r,MIDATxٖ( +fC P~ /qjZRtAV |!л~)/?O軥HI3Bzw+r~p~-ooNHl_K9`y`W[$a$0, 3M@7-Y "sB6'Oo2I0"aޞO |NX`i<DCkZCsAȭoUש7Ah [[F웇,2}S7!8 xIxEF;Cix@d<{ΧvU 8R~" qP2 D3>.5BVaX`ha؃}n@ߗjN(ƣ̒Re E`dN ̾-00+2 56 B D-aIk[4 !: bb}-({p{7% HBS x eB!)G,~)I>D5Ô{;x RM@!F B,&hh@>G1F~4R}~seRJ^>GHbթWyO&U~n[.s}Ui~qKo2/\S` zd@]P?[:gf"0Y3υU"7Il]mnh c1_LMxg]7ކMMNOp;l.J;&<oƧq/((Z_X/¿1Q/`\1cAͫ!?Xj{0Y*fqzEkk_J9_xy ;3n_Ӂ.nGϽ{u݄͒2-NOܖzd,NB_ܚAmKO%8z0Q` d,9DŽ|V>r @̓;}[(q?~uYkG]9Ąee7ŸHr1Zѫ}OA 5{8})OЧ, ]twv &c"_N'=$c"8d[gd?W!<? 1ofLs}KRl1vH ;_);ƴmBl@L8|gĸ ƴ>]w80i?i1H1mA/t|:O[ഊ)xxEW/K~pðvV&m])g*p<45q3qFRW"S"햚§i,"Ao0~.{?S[RAvJw_jj_@|K4|M|0DUs~&}H~ݴqkg%K}%k[KQoIwx:뺙7BVG.l^ cB8N~ʴ٥na-ME;=,u#/-ƶ6.-} e}Cr8J0þ]eZ.ŷe }SZֹ_v$xEڌ E*/å^k޲ ܤBD|SƳ\FzNuv6B`^C|cƻ󯑞lBn~7˱Ҷ3kΤ_Xs,0Ww[9^cM>c/ISq+|>7~_d|&jC +R^ay`[:㗤]8>{f+C?6/CwvE8>t\?v;Cmgd|x'})%gyƩ\J6}DŽJj r\!ju72';Wƌ}m!x4gw7}#1+ab0I%"c8Jxn ӓaƄj,wc ~ݖ>/6 cBx:[Gu ݴtq8$OgnWwƄcsW@uc]7 2i'6$?33>^!IzeLoc^+ ǛuBxXs;61!O{0⫬Yxl!}:RH3Tse|%W\Kz@$wS}s݆_} e)ΧwIi;${-?.uxע^3ݯi"Mft1'p):R{bEinS]0??14rB~!pnؠ4 ؤ1k{z:~)oaLc/fr &h`LPwFFw pJ{#`>_܋Õ?m[?#<#<#<£%p9=+*>u:W rF/A hCe%t\%,;~"Ȯw&,˟DgoYbLNָ0fH* M:̋^Z`~[Nz@H2 G?p0 -&̻Ŏ:Vgiy5=dvs&dPvyH㙩fbM o35v cn0CD,h|E@a肝×S_z_"w^z>)L!p9O z]qy")Z;o)Zn.0~MoxG Sڙ1K FdױV,TuAK44Q&QU!*zɚ8CX+Ejig5`c\+R -KEZV<_nZCHҋJV"hHJyHQ2@ɚA@om˷qQY֚ ZFӬo6(BY0YEҸaZNN]Ch?\m'r'ZTE RQbi(* xZ%TA+CfiAu:u";*0fǺ&a0(E[@i^u}2E@ffܸO>X`jk4Ⱒ1p~hj|:Ȁ1 ̸}f<ǀ*sݜ|fUX0VhvV$i  -Cs"",pE̊xاZ@+cGHcЊ1}$Z ZEA<S@L?̪{_oP[e 4e4Ԉ)V7U+hD: ݠ oԤuH0Z:pƠـމ¢y.b 41 Hpy(v8L uZExUסJ@[?9+0(XB2TA/̾ɽ˃җ6d0KJD`-<%UZ!b5 YMR $,R!UBfrCH.23Vq cfAjɉls4·yuVCZRN sCS)>7dՊJw7Th-S=B  V0N>kև"j[X "0AHPe}jc1kAg/THέjDi yO5ձMNZXr2K 9ΝU=FZ SXJq^:B+) ev!67q%4۩kAmø#ҙq7- cE`">7Q}T6"*\{U2”yln#Yi=[R dPYrzGeVAϭCzLX"ϝ.YWZUcgY.6?*X%mdz\t32hJhu )Zv*iʴ|u6C^B.)+]eYz"ox]mG?j*v?GzβgW-{c>9ы>[\٬6 3Y>xpWɠ͊Xdbt1z eonf=[mm#gs!̇'M+='3)#):`玷1V}y;ϮKQ~ x$݅ ޷Y!iq-kپ2yv8 q&G(|n,tx:nvhƌ |9Vv1Łl@%DT=gZۤzv9\Z:Z .GPz/3ە1\~0~,H1L+^Ʋ >^= ˿%il B RA Ajŕd`(0CYR+k`dWܜ&ߤuZ2/3ōe[39[d/![iZ}R>z,v?'ܴ83O#Y]*+:4I; Vc,sH.1\{b ڐGF6q7>zW 2vwE\<_AlDTr`SQ]!(ѣ 5hcDޝKA7ύQP,G˨\mh1 D53 X!`G_ZͣoUsE;j"Z?(.5>mrЪoOcm;e-CAχԾRy( f,Uj<r @(R)@# {iAhu(Uv^Juϓf^O$fNƒDTA-wbL߰USᅑM+}g9G}vӫ7/;V&b%Lf6f` -,_;dY-3f=5f""sL6ZG͔d%>[DS'kͻ;?;mt?]8IIENDB`pyromaths/data/images/vignettes/._2e-06.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._3e-03.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG 55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/3e-06.png0000644000175000017500000000264011560531274020726 0ustar didrocksdidrocksPNG  IHDR3/jgIDATh=30XqʉaKD-&@ܠ=JShs8EAC_beyN[ z1D>.Zz?& #ܽQCwTQPdoe,(ܩ\OUdn$6@_jQ  E-+4dߐ5Dۛ}1B ya&4{O;݆܂3S 1;d; m/TvJ7f#nVfo)frC2Gc`"6w؊];jl1^4p1%bLCLTZ zHـxlVdrD\_}'Mglmb'l4LbKfev۳!8J8O1(hWD2Oѹzrx#&o$$La\9dMn1d1s6@馿 려UiPCRVںH`k"rYsf׵U2=FB}Vg1RϗsSEu0_'P=Q;:8?} &:g=.k3kcCd)e#G+wyNvSq\w}2QJ"r7~Ky^7KD[;eRvQDK4*(2E+'afࡋ|CV=aeJF0;=٥Qѡgq`2hy+n)vESBQկw] Tād5sxc xCALc1;hZJ1pbAIY^*k HclKZb`&:Vkn,Z'NxWV{ |4q3ܛ`b͟MVxl zNHrIis$9q ,"J,)KJd?j,!A+-߆~Ӭ7Dv|+a[|, zÎ 3#vUo]>9[m 9uO7NQ9>N,*FGVG-@i!Bsƥ}-'v{qŮ|v~$_Jlw[o[NPfV ;; <:(j*zO`uS槟~)SI\%M@&U'07=O=Pof3h'g4J>BV%8bSɻϢ,1mOI~CV>:;/2q>t{';'IENDB`pyromaths/data/images/vignettes/3e-01.png0000644000175000017500000000757611560531274020736 0ustar didrocksdidrocksPNG  IHDRA"!VEIDATx;*{T AF [`reg Sp]G]"*J<2"$_X~V1[yId7i<)iDyB/W=QDQN\li򴿘?MBOpsA"TWe(@2tlw^urGG!Mk{TYc>fmJe<?EJ>z*CKJvAO } 4sA`r;N(Jݕ/'2;'<ȨEz=čʠ=z )^57)6 vB̻ĻvJuW%r& Hl7e˰kɯl6T3l:-6Ovz BWi 1L pG?X׭epd 5)z3E9.z?;\g1-pe@=.vaufndvfPPvulv0y{\JnfX%rm$C<&i{>̶J/S(մZ&G'؀b!J_!+42Yz?gL2cz0!]o1bGZK޳HMqC|1Lɹ{d1f7ښMvL[x9d1)CPsiCt.M6`o(D&KtUoA(nancxD⭚R15zL_b5DVSLLbM'O/v[c6M'&<ȼ47/YK 4Qk&7e8j-P1 bBnb2NnZ$wnp*'ȩ\[?qexb=džjMpHUs\m 5q6gJ<$z`n\֊>S>-֤R?{޶zwmi(i\ٻB{ͱӉMlSB(7ZzO<;J<7ՖG͚4jF0r-ۗ5~bӷU`7x evR3=unde`ɺ^OY9MVm*%rS؜skFi'ǽ>{xW2˳5t`Knvar5O/dtڂcK뚎]rwKJKkHM䴮Qr+s.Sv#l$jC*Tub=ORҺ G؈I5rEeP2qu1dG6R\Gv1p11ƸQGv#]Wc"rj[%`ɮux1 6<:L=G_Ӫ.6'jb[ >U0Pt†aw•'yD.7J2k,!'CQ.CrvbXG*󙈘u*ӲZSYlK*RZLnΨz%Lح_MgFb2 ŷU^{#tlMYzSqiJ,wnLG \6inY;ͤC7=Ѵ 滖+r?o7q83`05n7MS6pDs9U|Ux{gW͆q2 y9a2@'әL_j#KyGdɍ1 }aX/ƍۗ1)bVQ%frn^ĵMɽǽe::6xn|1ڌ*C(kY22?Jv2='xp.@eG2˺ܮ<<>:;_!d'Y|.Nkh~ ^K BGFrDv)|̟-p#佼ǩRi~ʃG>5#^݈\CQ ,rXPZ=I%F؞%)ㆥKɺW,C3Dt{EM>W\kCTϗa!8>VI?Hg^gLŽ9[>f`^Dݧ8ܲWQsΕ?GUw~5ڊ79v^pJi#?ý EBR['y-]wv#,#(@ xyhvO r}1Rp;ރu^m~?.4vg$E?΍9D^kиmgouJ\CEz'Y LRRQ-j=~,y9C-dd__le943>o>Qd3߰qqϼ`j\}Eq'xNh)v[LH}i;q[Cظ3L+- [ZŮty TAHRJ)Bq n Q|w~lHInOXXYBYl&0ZD }c$"l={ ib fF i3qC] Uv ~F~jM+J>| K$BMv(juf7#_`55nbv1%aҭ>h_>ܨ KLQ׭q#BMynvit,N7R}G;qz%CdR7}mg?c}8hօ(yxW@7W_= ]+"W9kJyq!O+^/)Q*17ouT`ڍ#nY曛ono*S}su77wt?(lZ-IENDB`pyromaths/data/images/vignettes/._4e-02.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG)55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-16.png0000644000175000017500000000031511560531274021142 0ustar didrocksdidrocksMac OS X  2ATTRGE55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._3e-08.png0000644000175000017500000000031511560531274021142 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._2e-01.png0000644000175000017500000000031511560531274021132 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-05.png0000644000175000017500000000031511560531274021142 0ustar didrocksdidrocksMac OS X  2ATTRGi55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-09.png0000644000175000017500000000031511560531274021146 0ustar didrocksdidrocksMac OS X  2ATTRGq55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/2e-02.png0000644000175000017500000000674711560531274020735 0ustar didrocksdidrocksPNG  IHDReEBqJ IDATx\=v,M hh ,SRSR娚3+$΋t03 s׋[.ݗmR[Mo~~_~ˀua.t`$7m*1S9wtפ 蓁L# -`ˎ5}[9a03uہv'-4e@`fPǻ$!#\u M%1 pH+('ftA!*nAa=W7u)#>Ic:c͸=j{Nʃ+ cֵ|͖} 0b:n^PfnEUTaoR[yDt:fq,y/N DU/D'0F~:è}xDQW0jO# U6~*nen|BQgv9V:zM` yx闅:o"m 0a5>N'UQGARM$e6fs6ћHQ"ZDh]B dU"nv4'鸞,`%i$A/`t-r #/֦cB^ĭR@ FqcB)}rw[K;"5ti_׺/Ú38oD:fhvm۱ّuZ5D;NY{?lBښ?Ϝ]a;+rIcwF_ I3?~L|&8ޢ |'DWzbtRtD<ۘݔDw~2Sgnji~bDD_m'Dh%u>ZmpFD"usrv.CoD3Ig~Yq6k3NP3LtۍśAq#~: uc,.Y?(PrylSo 8AbPKfZ4"yUr]$ 3+Tͪ4iȴ/jiÖHN D T 5n刲97_Kg@ :XU !+kDB*<o2uoJiߧP-aAPȂ21BGbܻ.Hz&y 18R1h8em ):#l2 mD%R/j!^'oSE_J bf&|%_C "ޠ;sVFt&'3_x>UI`L~`FݛLW/FqMէjf2%ěs8)δLC_yФQ^C+X?xrRN ӑq(jX&a ù 鲙dagY\9 Q, tIA]r5RXw.)b#3Z}'7 FhG?8)O甍8)V3ɧ J!8]4KqmX%uJ,#o%U>lrRdn},qٛOlu]ensUZ"Q]o,%%G,)t@]Y/pRye1ƞ?P;C88X%BI˭eBܮL*'bI) u2CF*|sE7̹8:E•wGJ5-H7}NIytrƧ~uwv8ui}2`e:} #間5NJol[N 7wnۭ :[ sw)uTAv8)|~D|K;>T>֜4'#O@ξ@ 'm#7]2ߕA? 9)1R\_{+MBj wDEN R)Y#3/ # Ԟ}t׹)xXeh:=A ڹ#5N I,0"r/$Ƃx?VׄYn ú랏!x ~'%[ADFD@'mG*V;$wܔM~MĮ-MfCuQ4$mz6h*vVIAT*13 * ’$[quFXD MIuxPOXD2 \ \n6,[0Դ&/ѪT_(\Ť&IF wtܞf<7%7%:BqIie{L*RR箔 tAkܔh䙔sM)c۰3^Zݿ /qRmQASItm5EM"gEwkdʶ=MqasDʓ"gf_琥KE'e8 J!% (&b .[`*ȋoSܔ![7Ctb"ZGrRVcWvY䅁J~|8N pwL89)"X 7^3XpyH|>o|ǿ?#ߜO{rR8Y?9)/ߍR8)+8)bOl؁⤤]DžoN߇򆳭W߀k5oI!IENDB`pyromaths/data/images/vignettes/4e-00.png0000644000175000017500000001572411560531274020730 0ustar didrocksdidrocksPNG  IHDR,IDATx]=e ^` lEh ځbJ*V@BU_6vg{=Ӟ6.8~Tթ8ͣbD%R2*Z z" 0=2(t%HkcB: fA?+^7%@`Fg@Omώ' N9`zBHRM3! 0 )B42NPR(J$0Ë8>; m`[٢3VB H`Hmh Da}Au$ zF(Eנ@}6ZRCA=4RӐDk  [42KTk zqi31:&{!t@Fq=OƕyZ7 dDТd`:٠==! @miiK-t6:  e%YKj/  IU.ң3bRgM3Rm;tVKf(ol8 s2Yavhc+ |!Sg3lyH0$1A lf@ (z}.6dO)& &ޅRdc0xbZ|4Ob|;^^Va^Z$|_~/%2E `0_` x9~ϧ?As|?As|?ǿNҟG^iFټC m28#]Bߧ\l :\>'Oz|GG[4X^UBf`A.Gmߞ6>dY;GNo giL`xQFRn3~Y ˜5CG Cf$ٍvHl 9q]W]j5D"/lf 5:?otW7/fa9R }z >6y9=331IQr02}e3_PU0"u3L t Fo1 Zh,$ NZ~ͧG몒\iR%ưJkUxPE.Fmӷb^jBSfigO"M, Cb+A\yEt +/8 PTn:{=`D:zӌ40NXYKKy=UUW5hsC>`؆yCvh: B{C7z67ya hȋUuqDi*7͜Rr"Q!]YH_dB%BUfbi'{Ѻ EIC$p[A躔ZꁡFHOӀA.. [uO ͹ɽ**63|K}mndHiOeG]b3y{M^`*$EׯDH,&# R%NڠڨBTkCҀU+f7~`NS6Wם׼_[l3 Lp؇^mfUoFy6që;~6MteufEF/DzTޯ鋳\W7K91F6ӑwpb_b+[w6|?4U|wܵ.@f02wyіs/Ez3 O'lw49V[y w_~OS#zv|0TCLjygfˣcu ž2sY5l5'1.C$[{d<櫧Y6pea`$A}z |0z{ucQ}׽d"""%OMW~l A3bvosLW9N]՟dnͪwg2)ق\9$Ԗx;;fRʂ@!=PG-[f$^\3|}YgM;XB/ =Do0og'Й6*$)/Ǟ=/õ͓j#.. >{V#>b3/MY/"] Wۦ"tuI&i˒y!ڴ#>faC%˷8=iu +*yFh1M9xF-T"HToǂ.wBE4w;c ]P*cQ0yBȅbIKBHx!nE]R9r"^B& ➦ $Ys^l^R9XB:@bq?#@ ^.w ҽAڌ$U/kTFHʫZ1%J҅=F^k=NrR\/<ӌ܌\27P!68E44Uⲏ2=skJhm}L4Jq;.H IJeL#C!},y2O]63) sP[aN8f8}8etؗ`$ǘh-bei"/2Ⱥr,WD7]ʃEM6ۦ2<6ª6BK^;#HE0rZ)HH/N"S\Fڪk[l2$$;}YH]!ɌBHR` 8ߧ/](9 lddyȍWyFׇzs3~]qwY{F~ˌ"hA}6=,(wW~ gw~9l(#cٷ_WDx$vҌv䑝p< U}{oT_C'qYˠqZ npH8-"9 ӟ@cͨ5ĸޟQ?+;}u3ӫNՋ ѐ|T麬OymG_oNUо9#E<(iBO7v}Cߎ]) IӫsrI7}qTj1EdFYU/`~K~zBz,P$L`+ vw4zW%fU>J;dwp=[oY꾳"=`$ui+ ǹT3n\>ZLD0_lӽ󎟎j^( ƪ2ښ}t+azwNZc2Ꝁ M a9e;~:ӵ0i"Z8.X-ұڵg̿!S }Uo0"'jesP( %][L*v lT7>өYV_CƦ 7\wDT443g:cvl`'c,'̥iR]UΨ|5G߅7?Z^;V^^f ːʹLIU]nTbfvs]x9'SUm w-ezFW3Z3cH{{EžB g\кٿto zhc -/բ U&P`\5q&Okb|<]5-]?K^.id.Yw# ܝ!jf'jKDL- ] 5d??ta R~<$MkoWV8ӫK٘n7Y!@_2ƶKWy_hS{Cw#?F vvGsD7QFGc݃J%^Lw/2]Z4J\ hUKGOpYuTUz&3wpF c`J(?=m."ɵ5%VWkD䜴G Jahiw}/J~"n{S#]o)Y]3R5{[v7d҃v{ H2i^Ӿ|dbJڴmw9o I7Oaozϊ *A4jiLv_6%EXo8-j{WGoivN1_^ i/=lo{ֳ=4}&m~. [~ }u7ғ2#Ԅ.}EЅ3btX׭k1(v_-"蔟Ƞ殽̈! ^wlg5d@gVJʾӿ{l/0hC>oVcdԤg^)fN7ϔ -ڀds  陟/T֔K87q=lHuxNSTB6 Hvo\= jz6RoACkq4朽i |dB!$+fty =3-2bL˃b2Ov~3[=flиg^jDV-}7uc;%LQJk1@ +ўWzٻ\Q޻L*;OO!ӈ4΄#y@4nfkL fhݙ1?4ivh<^|S#TLߵ7xZ^>;> [6~ZG_?IENDB`pyromaths/data/images/vignettes/._6e-00.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG_55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-01.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRGa55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-14.png0000644000175000017500000000031511560531274021142 0ustar didrocksdidrocksMac OS X  2ATTRG{55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/3e-00.png0000644000175000017500000001026311560531274020720 0ustar didrocksdidrocksPNG  IHDRWw݀LzIDATx;gAA6 [6) y2#GVFw It[DřS%OB*?:_AA)/jVR'ծ"Q^ϐ}UPӯAQɠtq[[GC#:K^(x+Y,'i#=ZL@ A!eU (Zg=YfGfml5\2 fQUƣͫfMg{;}P=@*t rnwQT6v]߲%5Cu!ӑYXLOjbפ" Jt!٥B;!ը\ zŪҠֺr y\6,L 2((0/ԢJnzlQ`ɢ#uV%[KV]PD6|vf^sY\PIH(k[xplL:TR[[5HpɎMж!ٮQfΥ{.5mm]*Bv]W`c}okBl w*w]+Ŷ-W1}[ ,mo\-(ݠ!Dۙ9vm}4=T]Ѹ*uIm-*Ghboۡخm>Ze*3Jl;;5C Smm.{mlg{}_i0m |zmlhQy\ ,fQ."Z6wב I jo%Z!)"2[fTscKp nX,Ļfֽ=QIA6[ݾR8֍#LJR [Xea̖zo;8|w5Rk !8@:#3^REAΩԹ 6IcnŤMCEewE/fKV_V#*6Ъ)nc5&b;o*kk!&cT] d)LԒ T):7fDgjt]t}wՂm& -&3T~1SlRHb'bjsAip]_EɵbΉeĽ(VU6B¦!93zj]]>cg]gC'Iۦj`l=-vAU_ !8Ld6ܰBVVCNJUǚg2LD€kjk ЮE׭5ӆn4-mMVekd+EM;Lw{}.;4;3ڏ):2w5W # MX-h;8:n5R̪DJAkv{:o .fm6Y]a{ٍ?_!v-M(9[Iْk6nz3*ShT7ҷ' (t|~h%PY*5A*CUc{0T4!jmYhnIX%6ɚ95ND|̀l}BH6$W]5ڍʖ@pMrKg6*֛v\i|J\5jt՜gLmML+8N I]-D;Oo` }ĺ̸=Sn%e Q % P i,y^IQyܗ0˴Hh8%Ǒyd ɹsJ[=qeS.l\,K亙 (:Lias9>,DΛ;z|!CJƪS?gzLOV3=Y}LOV;'ϮN_^\ե_AVQ*6mjW ڲ[#jYkF)?2s*S`~&xbKُUI|'V9Y*CRGK={}oĢYݏ|#[UBn 57Ud&w7}>J a/W"cw7|e(>B?U!4P'ru `gBs'Z;A5Uwuc5y;&̫s9a+V 63~5**jS;&MV%x}эUϳr61whF;=U2[k80J#V<.l 1f V\_kJ{낂;xU%Ut26 D[ +#O|sU(Sy{ I.hKKV$ͪ׼ 5ǹ˛^}[n1[UZ~J]NPUl%/slRj=kcO1f %x?ٚ:!DAeL>m8n ,A2׳ċL u|@ R|bB[]%QF`p^Hd%L7?GaVF;Bz'^\?]GיO&趰o^fU'.~,U -$6Vf#o*]rzEu;/xtR_9&u  >!TP JUJ=.˲,?NW%2 uwD,uEYc⫕x5kNw@Je*6T_6EB<=NH2ZydRJS1ea(0)NR`Fn7Z6(hy'y/ݛ뀰F㋬C41pݷ1}xKà/ r\Wes.9׭œvcQ>`a2ʿcJf^M3| ?-%WGg M];(J7{yX^2̢r-ɥ_KKE+MW@ JDžqXwB$BlN-^ 52Fﮃ7+%/Ksɛ@&?!z哦 V}Y}#l^yѱEhz,7Qҿ kGz-Y"GQK6ocH1T`+=*޼0E)f{wb R%6q"Əշ 䗌g13:{9}%jyaX# _FW,=]Ėì/D8?C|;q:3>ߴ\w^m A*AK8C>~#ŬK1mtδe容#&|!ic_d=ۦc[^g'V gb"tnT_f?᢬S琪 ?cI˓9^Fi4ӣ^/Pb%nxK)zqr `x:9*YuMFy%G5e)8J Y(e{CVw_^58l͔.~3zܞz#]ݞWJjfnjn>26ϣ>Y"~+YIfI? {'CCo=6mhooXUs Y}d)]:ϿDO[#FZ IENDB`pyromaths/data/images/vignettes/6e-21.png0000644000175000017500000000562011560531274020727 0ustar didrocksdidrocksPNG  IHDRB WIDATh1*%d\+p\LE`(D|kHٙ}3ogE+Q *S Yg^߀MVqJRҀc']8ْ1? )@֓y ꏯ2pkU `wslBXC}!.M~g ~]Sw/ҭ xn[.S1nr+X['uh[=xI&;\.URVlLٴVJK/Qgm3t=g@V-IuTE:ΙՂ:h'hЭHJ4f9r{2M@V! %OETT A#^4A=2ƞ2zKUdς$ (vQC%Y1]K-* + 9YjN~^p&C̚0Wڷ imkmh[rcZKnַzcvb)6!+=eƖ5܁meFʏ )_so@[n5zGGFl56~ߴDFoDE/XJ?p).5Ɨ4K?M ovT58_^u"u c, 1(&6Stb #N;/>m d]~ϟ(9g_#_x.37DbJ !N _Q{=^SzzO;mЭYp! Bq~#΁E" ?bu>w3NÙl *LjR&>)'h^"32y`5N79'A mnP*vvr"kFDi ^A~+yRi戫6 Bm^ ޼CW ˜9sfGkm_³jދm7Cb耪S^J]UdEvj4׹hLߓ`jԩ[N)A>{:RlkF%Brѕb1E7l$0 ! >^H$[zL%m1ûVc*1h.#7~Pxƾ:vDu=eoxz(gx}Ň_p}~qQ?, }^񟅿[yVV >q5X.WQK ir/Rrx4QeNBm?y@ 6ei `,!v'pno]-^)1)9 ^s%6bi!5RL::-S=q6R EO#AӣBSF)A.\RbqMm7=g#ʢE~SZZ5F(hρ D;7g.U@Tف7]kRJ9DET?^9y B&v,@ss (8Yh)R0JY*5;IUl*Q氚pR!sFU Ts3+kdMD+A +"2M,Ӗ["]-\oȹ<+}6d"HWj1[[p@hiT V!6ӆm []rEY,.a; hN~J6Dl$d5*{SfMkAS[v=m6Ypq)Z&F]Di7^xq?+#M7/\_p7p}?>/ _>s;z+@N#T)^3p< [7;w쫽>ɖlmf'ga}JMv97]FK*8ONolj2|vSpvugjwa\h}{х1)dh,\R|8҇!6yrYPm6yevdq6nK 26i,HRy+Enϻ)-j!}ք0_b vxPϼ2 @z5%PpSG+7e/teO)M*w Xҙk)ޮq,7_^W7]I\Rep+Tݍ@$Z^ih^@^krT~@ (6W^L֥$.y -6W9ݺ/`K KKj*^"&EpK 2Ksl)vHZ[r20ez=R֯| TRRcuە PpcEX-!v U~5J^#"f{!&G:ߐi*Oy! ""QQȢutPMiQה -_q{:E*A^ <6ߨJ6ȥ"b=x z:W*23Kk1ʥ]IBg_C2i{wQ덕YC=) C$Lɥ 'B]*Q)wv*xNwRn:3,uiֺfB=w&šl]ogf]0)Nv]iۨ7sm9Q30t:Ɔd@FcA~uCkU9)L^S[jk SLmSc|ijtɎtz?3PEw-]H7k\cv[3"38Pu4kivz A'TWLGl0&Nڡ0ޢ}lpfZ.k>6?. s,seٹʜQwY׹rYmY:,eL$g+'҆<Ng iܢ&#U냻cycUޛ<&g32Zحy鯼?k~4Tvwp?`T> "w-d}mt*W䮈 *AU0SOҕ.L85nU>]0`jUg%b0_|/`0_|̯&!l@t! Zf =ƛ 4O2Inekx&LM;^Y}cK/[u_R*7ɛw͓K_1  SUo+&}`|}9 4XGV˲l@BYs8]2>,i` 星!eEXMYk~kUT K\yCHB~bQZ$ZnSL)sQT| O 렄O)ŪRb j9fk`rI1ŸS|dv<l7*OetCˎ T5 ާBXR[2SY3t!;Dkp~Ƭ*2kb!T3gɁi#}G\9Ap-XOl ! W*B1[ >1 F& B>Lo@JrcDnmpq);M¢*cWXt.|v'P3BmFTd>"BG`B֟ΠFzKq}9r͊ npj3"UD9ij;,:rpYϠ'&zH4&ϗrNrPўY"0wk*K0.&ki0P|䩉T G2bk.*؎Mq~?0BpYa1¦#wׂN6պCi،ط=OeRPR 3Ka3"d>',CJͶ8KW`7b[Vʼ-a(>be;B9̨X:/`G;>s.LYq ,JV0D * ^oq}]Ƀo %T^7BiGs!-Hc5`nA]CC?LpyO0>&{xyI1&eXn{̹Y o {o滾_槺xWO-` /`~/`>kF*?P$a$YIENDB`pyromaths/data/images/vignettes/6e-10.png0000644000175000017500000000676511560531274020740 0ustar didrocksdidrocksPNG  IHDR2> IDATx[1䪲5h {`@66>`X,W"d(3![}f޴ν}}?b3RVBP?< BUW˾M`"gUw f+뽥2*ܢl' ,z[@eH?q@˶tU0yߵS8>nAgyx\ၟ%)n:3@爓"2`.IMA3h㘼r٦ *%{Ы@tefʙՖT5IY$D=QGN1N 0:Pnck򰔎~Qxn'v20IB(JE9M p<*)B*Rd(斔Y2 M1-ej\&ǘ}7a'TvJLY x l#:bWd0]jia/צX!wK.cc؃hTr;eZ"'Mx@JS% R958e<({;0z\UɘJnAS8lѤ)l<)S=HZ,bIdYē2I鯦~,edpe>(a+ * e:^LKBѐraoة6\rFQ94YR%fԱ6z0eQs*2$Se +\pfzSrEN+}E ^ Ң yLYӨddN R2MY{I,iܽjYTC ">&!Lrt&,lPr墅 Fx-g#jTI }*؟M \ZisDq!kj'ɵU e9$ָ֖řՎ95jc4}f.;D}X5ec.젵KiKk둻9 [hmmTymRW},/y/2/O0Ef ~^|O |{odҙᙈg.]2ԓlNxd8#r O{5}{'s|sCٿGez?AH~7}s/3Gnx6,B z &ߘ F0zg]gqg\ô$C<)rgZ]s2T8WY$gqh?ƕf67@ 3st!F3B6סi,~u\|_d_~?(C:e_KݱV0+Us-ꪾs2{κkfl;?5;Wij繗 .k)1W^Yb}0*v٘~]##^{q_(;7h*g "y^_"Q6l)cU "s'iug{ b rۡ/)!w  PLC~<$' nѐ%̹rN38Gv~dkƙ 3ضe{1歱W5,%ȶ#usc^!0譳vOkl{3rboڌ/ξC8 f>(eANaqJn[4q$1{:%!Ut.bP -it*2A&9Z;~U)nqee:()˝&xC-:zI/(S2Z*'ჍS.̀:v?{T!\'˧$/*Ju."UC,4͙@,gIm ucjd|HD\ź ]_9g2Qv'Ka+R$'ͪDG:Rf9.y6΀oS62%`%:Dâl4nG F\i0䙋$OjQ>)LEŋ$$o͎1,TLg3^ۻ?v^d̲bV T}dPB".St5EjYץ>,+"Գ㯣r_xuR٫utNd7/r7bs5W|k*u~_29۔K2WItCٿG^_3XTVK]lo~=pѢV@Ov.uԁtNF`UJHyh?0U>p i G<@;<9%/c$6I)G&'nTH8}YG$ЅLˈ4wb) 1x} sNܢv;^UDwD7<@jct}/SL$Nw$n}9q ;r:KKNޠF,⺌D(#FOvzOCޢ 3tPDvj4^6*!5-Cw%yo;cvߨ_Ik1(IENDB`pyromaths/data/images/vignettes/3e-09.png0000644000175000017500000003157111560531274020736 0ustar didrocksdidrocksPNG  IHDRQH`PLTE߽ԻϞʔiM@5zzzbbY.SLL200ZI ϸ2IDATx][w/#ӊ$JHy_ri65#SY lR2{ȲvSn3uqX7na~$ѵɘG.1t$X%01D+IvF9YD.e0a=$88f8,0O %!,F =Y<e00>a>C0N]'~04€C=10 uczk'~Ͼm?5<1+1esp0 1P3&k';i6 4ʅ!8 ~4MӬPɦi#re;s_Wetden2Vx}b6zҰ}mc'rp؇ƛ226cx{lń3|V|}.xڊްTu2>l+n<ҹ&lV:q<1p]*~Ϛ<|ٞc=x| Ĝ~^ ^S׀ Mj]7?n``*'߃cv'@x)'=bF|Wk+>;bF0.;B扁fff+u {ʹq4rc7VIFx8^sT>"fv5:x p|'8zx<x(e{1{9C?[X9q|aX9>^vUv[n ^63u:Ld*c2Bn7qXܸvӶ<3zl=@ GĈ?-1F"|Hz ti+NO |kwcKAO <d8N/K0~A Ƨ<1 e=3O i'9t"wA?"GD~Dcy}J^R ѵX^ۙ<!̱߽zv,dḺu_QKmfKmz5j:lV////׉c9^v"_7> ]Ay8&Uڤ/e,c7nwPō3yL'?ۏ z~]iXb$~$oıj3q M7I끮ڑ1iql'ͺK?`A'o ƋOʗ D.\Pu!k]1#B.$$HvGnuQ`\vׅRt}\كF,DAKI "Zh=;`6|~"8bCL Sh #B3_X حXΏ 0}횐zt^F2MhT4LHOt2{V@ C@xOPEx4p ',éj=X9qxA7m(h'` &;U@Ao־Vd.dE #=EAZjb dhKӔ{dW9BMsF譗>i[/)&$I)YhUX ֳf14?DZ *~w D>oբqٴO! ,&j !=>[!lS рh 1Csd30"T4AzdEv&]@͈.y`ݷo >^so@VdAB$x}DW1s &!0z-^Cp("dRϱX4cmL,*>Iu℁>Bz UmĀ)L_0\`W0,,Gfd2o2r`XP0=|Y{rVX/9-7U{X뢉GhVԇ u.%d֖!{Tr=o?,"Nc~D ˢ0PփahԤׄl4'SĜ@5Xj1$AX栖"%s^Y2%l!޲:Kee%>fI@lbf9e’II;,k ,²ZVICfDS@41&~D7ezFa"/``āy;AKGuєMwExd'\t[,)2댅d9m$l,e[C-#7ES  G4!l#4M4[&a(FDKD#̹|haQ>-K'2qk!frݒ;^xSFdOƱ-w[1}K^䦁n |y\DrA.jKڒþ|%ߨubz_}ݼSrVٴDŽgׄo9Y@\kk\~?z5a!e5mGք2?&|/癇nn<y7{hxr0 1@LwYq0u﫤f<9q 0nY~>7F?E8֘,:l>Uv-zUU%Tz^;ƭv%ɣ/07kN/Xbe[(Yejc"F.l 4&ZV'7irs.q<^xTHWcD粖83+&!le_18z qX|n^`0O?KgrtfF2-B.#X ǜ|"eL&mY3z2=0t3gzywF74F1`c(LjTp4sphEbN^L @II!JD3WNHQ5 [ėߧ>Pɦi#reW͊S:߸p*kOevKo_Yq9ۍ2Y5?x\z7ЌFVы}o<\({ )OBYK' b$B/.fdED& V$=,Kﲗ%sj=?4qsF;Q#]mmzb)^d\y߱]X8ޕq0$T ,C9B@q}Psu:b.@6I 1׀1bĀs) b( gm!dg HV|~V`JK d0KF@v)1J1=ܑtp +yH:&|~P{95 d%|B29$},K>^GU{in[$w"]/Weߛd"QAl.(}YCBs%gQϯ ~g;@p%eٷ:bj2_<b *OhY%,DI-CL#)&RD *D8M)$^$&Q'5)z%]SGp\^z_P/S-ҟX&? {%Lw ٍ)8'Ϗ-+v%c{) p=/4&;!3/F1ar#'rCLlf.]84bc&00 }<}72p8.8o&$~z~%>.jY`̋y[Jz>U%m/|DF*Me4n5蟅nWI;,n\Ořzxr/2\_@qӝu}=POK=fboѲ_q#^]>)hI1!!]2Ũ浺X=tO3j< 4b&xϾhqL3>$kz"7ug|H@ FH^ J&si5d,8֊7E>>bj͉^+YjX|Ȯ[} /_|3_\xaC#`FEC @P~ )X%(Ej),PJ& G0|php< )DEhRt!G%7S}\n#+{wIɐdU[1CyK^,>*5s%fhX.pJD3$VAټf&5XA3Jzyӻ+1F5c`[ч$ ",TzNYjbF4dAEedca&B`4A1L krdj/_ ^1kQգ@z9KMO``_> f$^T4aೖ< ѐiւ)ÌExyq) Qa 5H+ZYJ@ʒ,5d`HL^Fc {e2 LJ &`:d}'Č+2w7!5fYRE#1f34N,`_60/ @ !=GGB;W.^wң 5Y֘ >GtX>ShxǎqyM%yKbci\Lկ8c1P< ,jqK-$h"Y+q$-@sLD0De9 XJ> T-`Q-Ƕ"fd- j}ޟ;R҃|?9v;@y{wLx*Qd"ӏЅ-jN]Z$Hu\7DgFr Ln3y|鰛9{qBoᚌ-cx]u}e2Wdͥxr)I)) 3?(sښ{%QBN@Y&! (h[s!.2_O֫]0lRj^0//׉cv8.nܼ4ixyyyYWetmutvn9I꺌鏜b}\Z6s!uq|\/ A\5a5mZڒe;w&l7e=?q>$p-vR}a{k\>}H~j<\{1Pսcgfo:\@rB f:?;5n87nȠx;Ͼ\q Tb| qy,3D.fׄ_JΠ޹`_ڊga>Yx>?/ykwM}`?՗%w^ÆDU"qk({VGN0DI^=ȴT5q Y+Abq^*>J-ڙLݵصyن᪌ :}oh.m iO~P66d͂s[!;,_>}T,قE/$kϚElnjCJ X"3Dܠ,QS07bAQbjsuz.;mfyK1HC fEޯq`ƾWdP.[5H7XDE@/ #▖A@m, LRR)qJa>I.'qv g~ltݧtt֦ .i/|˳e%Ίw[0ܯXr:-gd/ΝCܯ8ܧMaYܔA$xZGl`9Z2b)qbN08\GJm&DԘPb))lbɲ{Kb ReYaɂ՜\S =@֮ԴR<6'|,z@ )]Fs)]TgeTzE_*Ag6"")j%q?9Q;aff㽣dGZۊ靿>rTb\/ׄ!_ k.ĤO/c}A˯0ș [Y˜a .#BFsbhۆGbp&&^ 1@ s_⇋EKW \S9g1_@1t_P?sݼ<.Ʊ:<m C!}|C2pu"Л熣#.ߥs=rv|"t+hAMqmdvSz[Oq$7D{;[2adqO/1︸q&{S*`Ӹ1-DcF?Ұ~HH:cy8$0:Bеo@2hLh63aL2N_2EN焕15,zE'&Ɯ)ԟt.@;swz !+!m`ILB*fmeKc[lk'7[y.X~C~BכCZ\4 H1؀\ 0c1fg6];wzrnPx046h%w+p$"&"9\w匮[2 ҆ RfTa9Y(h4D"^Eq{b6:2z@a e,>FsX^ /RM%1$01|wG_cr띆Hssix ]گ:fn!\^~QsJ)/su13s$Ѷ8ޖVıg&cu[1WOҷ;z>1vNq;fa=wug2=677.e<_min&#g~"wl;i/ck\`3jC: }9EYn:Hnktݴnphwք  ō@o }T|ްvô(l@_A?l/@׶ls<ɏb`F,Q0ϧkuJ;bY})+_ğ+a5z0!8䬕`9PJ.\AՂnao`5 55O$?ɟNY[ R, Iw i5h͟j.ɒL-ml%Y7u"M Xι<>rY"|\ѿ ‡䬖Mh7s/!b~J&w.^zc!ĵ\ 8O"a TBS}! %)13@\6 f027P=TuϿL G-^e.pnN<Ɲ,(?g! +碹4 βh}%#ڂSBO% RIN>r4Te{ $KFoJs&0߮Fmy}D2q]!dv8VI;k2^ߪeCLq}%n[|:Ɲ_YH:q{ 0pӋգL ', Y},TȔivK ڎ]]ڊc-D<'r9^u?C2vqlw ZrblM6Ksy1֟0v/C#]j2,=̯E7ct-zu~_? yV^ViE2A"0?hLps1g= ~DiG4UH #eXTB˒KjC9 ػdȩASj /!bFhL%}oBfFk!]"DCVȘ~ خ/8~C?~S}ȸIJ}S0d63 PlJ!i@l{Z'+)lKU\z9f%C2ǡw $d9 jk6f$ׇ\/#w;?үۙ2Wd4ͩKqhk2n `XdĨmPjcjd\8 0c b^V u" o >t^@pgDA@ݷrҐ\|!i'sI,I-{˜,eAeXvf%P.'Sf}!fdCL٥\!7M{,Z }qy_/ hd)7)&IHUTI*#/,* IJɆȪRX c A)F)M">xqK  F؈NXy~O o͞ɢN͸Є>p3[1 cձk89_ \mL=bG$Vk.vBa7rRA]-O-IQd)[71|m+)MG8w6>#Bѹ?vMJ~D = ¶-S5.>v7XݼLq$__we{/ֻ㺌RKjw]Yu*'c=cr\ܸn\?1p/￿]~{%vx-W{KF23N00O tJC\\\+ք]ҕ\7ֿ&Râ$!5!=ׄloh;@ީcRO{0In@ E~b࿆BVkݻ(G ቁӒZ>@5 t aw0?/#ü/5}-qF}qsz ~}d:O:јKmz5H^'nۙ㸞86Iz]ae^^V]wCzbY3vn9au\q<1p *y8x_>\xRZ-b9Pd 2= 0,A=p=?/aڪOxILG0vֶ}?FsP_H̏c߇f9(Hn=zn=aL1 bS EЛx'bcX퉁$] j 0@_@އv;nj'2j>vi.}Vi+(Ÿ-!*y1{\4Ā"艁/z]?s㥌p8tu2Npk~5C~<=۳=5Z#cT /  s p&&h{5#D `!riO |_A8PyɮBB]#Ƙ qHjbaWh@PC9PHKV0ED0mbXDV/ Erx߹&)dpgMa&!A[U{C07o\]6"AT6ooaWA@'/;3B e{Bg>mgj tIENDB`pyromaths/data/images/vignettes/._3e-05.png0000644000175000017500000000031511560531274021137 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-02.png0000644000175000017500000001645011560531274020731 0ustar didrocksdidrocksPNG  IHDRt9IDATx]ҽB$@J@ `cccĒ34}vgu?QS[;qIM(DN+JEkqkgBB+#*Ṯ!n;-^ۛ.UVzb x8>H֏4st7X|E),"@5=zi|?=J#hhC{W@@?mua.=f@DXź, [oQ;1{.A8 ak < lՠFOVan4mZxpc35G̲h$O̡?30Ӕ@ԑ]qVVPo)HКB^;NMw5+~аa+АP\A >y!ĀaP omUfr(4suXZy܁\qij :ջj'F@sPuBv:ѱ ij@d a=vF7.R'@yi+k K8 `lH$$-f 9{( -fk%,U)I$5 Yer3cR LVkN>q c5$TmeVSӢ\LIJ+HrIg{Kd7ڥI1L w4kʤ*ɣ͜EFz*Y ZHНi!% "g&Xg*ved 'TkX|NºjdJP:Ń: N;1[ K>sHeP& pQY)u@xSnv;%:Сf(U8B3+E@:D =Xir;ݢ[ =x4\Hp4^=_Bi4T$DN0^BP t8UYޥD7-c*]EGA8ePSh"`+7ɥ2!'U9Y M- %,Mr1@hs@ =Иcz(o}7WQX֧R&*= ) pg$DA}CAʡ<-( $'lNOU`e+z< pv (+4>lbCJ%o p+Du5D 5:faŬP"_ʸNV"ӔO(hiXf 1z mm J`P2$f Fج"iG;:ݐXX=L>MVjxa-@@"̄W/,Z2 uyihf:ɳT*mT<@S,IHLCπecM:v̀; ¬-SS촄 R[3,TmDe mr,82rIb^܌ 62La1o~< MZld(?Arh7y>G1/BZT@:̙F0en n"< w 7媂`'+XՍ aRq| WV+HIk9 eM ׮5^JBX}FrKZK.%~\ PZJҭ~e:E!R٘J2z lJ)%#͂~dK1u/nRJ-}]sАզkɥ\ukμR֖PJ8]V_WJΥq| aqLv BLN ?Ű?m| pk#ZgAt: N݌EcYl{qRGPB|H'tr v1a Ct~Ƙ<]v'=wqR8P B?c;dg Wt:_^~ͽc_g,?tzO']_򿊀zN/qޮ_ p!L ğ?F'lk3Q?qDx>&8Ӟ^3WրP-ӧ%X)4B?DkP gq(^=fCe< =o+/P* #dv=Qױ T?D@s+ЉM5_va& 9K~@OLyM7#?d {_W*PO 8j^LmnY.#CdBTz)*c]:C*jsQg2PmYԜ+QOQ#s)f5?[v@@c x@GbSdJ 3)1+#[c I' olֶ|YيI%IK塈ia,Gw GU 4q/?h#UmzW_Bw@ 6E@D3s jQJ@E,qY—9'#G@j*:\.3Y(efIVY"v3f[ܬ0'a64\f6ɫq+_ǢD8aQIQsC/ڏ7h!49Z Qqk)} >Ej\@(~D&xo ma~1e!|>$WVrFoh~W(& JgY@e;aQIQsC_h?in, =:h7H7u5Qyd>_@="B{q h_j~<_RDIо {kx GQZf~CkO|v!yZOss@YV6WpJ!"VXbIBi+XEK&^Xӑ @@no_>!BXNWrBt@H9m"x-B ru7b^Ӎ mvxs\mT&8'A,k^.PK!߶d)ќ(Ƶ5THj L‚%"q!2! ,!\% Qr$V!%% bmUNhvWQ"!HRd_D132}XuJaC0;:̷EEKb6pI8V@4BALf>_Vƛ ~j0]W׀vc ٕGx5]Y$_">E:K]$mSԨ_&T$ "CT#V‘nZN;xp?_jcGfXnP`TBNd5 %:1B{К+A?a-yM/ANȔ!ڞ$Oম5Z*#8geqfg>#ZaN ^qNc6Pga6cpQcxlY"t 4xDʇOǓAd',vBYQ#J4X1B ?:`sDiGVJ[iF%2ɪhU:[^y 2ڨ*C4BѺJpCT6*OFemTZ^D CTxN@@2OIL&~'stqJ=CǖD <=ڠS|#t}z?wz@9cw$T i"DwGϩgvq\(iEmHր\ʅ\ʅ,2["NE[:2{AB/2~r;Qb"sMş"`8usNPGz L*rQy\-Љ!IFh F#r)3Os@Jul;;UqC|NgWmۉގ,2;_P"DvEiSuLj&㬹+!=R.[' }4{'z'•R[2H@A ʙN'-홤vn3{GX e\FOTYJ+#}$TYl?'{Z^ď 6,2=Np' j,2NCSP, !Ɩ9cCCa!|DD[M:6$9@N"tolo7CӖ 0զYl8AGz-X@^^{AOXīYFލ#'!}N,e.@~ (m0X*Kh4 rPDkEuXل 1]{>};>?1w4v5w~ghh Cm k`KfLW(^s\ H[ynik kL$ف' Rg5 6܎ xIG> :+ rMAK% LhM@c6h3lt]3SYbBt3G@=sv61@4/ f082<V]Hƀİ&F#.`،ҡivL %גk+f@6UTCMj]Z(+si5Bf"YU V$Sl¬ZYMM-6[gUKyXЛR25!(H#g0vY5@ شPXU̳nrt4A wGm FY(^^т P i 341rG(Klғ 30|]hDCr 5VIi^0~dHr#07XP#-L"o}hme B5E>bF#Ku'4P~]S0rORyɖa)ad Zp#A<8cd:vh@lnᵃ#(3S6tEO!6p@gܬ5=#*C~Ea*lp8<"!P;c>Hogx*>{ F)0Q0d=-id'ĖU@Kutej%ז{6>#7sD#q1٬p#Aussj̓=/RM $Iɇe'LY|>Ddu,>9#Y@BaI\%M%KBX*ĉ чr9{̀ чF7m˚cT:hj>β{k)]xbϊ>-yEK F&KN}Cұ!CXLrMojxl.ey,:Zg'mRV?#'x=^vvp >s{Gxw]##=k{G>{~ӯ\LO/ezSe|^ǣ |{zw@` ?97{7@vm#z}hծ !e|w_iS0n}쓺=2Ekǻ |enܭ.Nx]cz @]xɞ^mʽ`E 29y";ꂗ7pϯjA?:~t#O~xEŔi,r_!c.w #F𱙸v{n׆;w>`v.;$bܥ=%.`7d&0ϾMmK/Vd^@侁=pad!|L^nCA~ ‘["qpO v\/" H71\.9B+WCFX^G1lku+jC:"usW'f|T pc}^>|28:.z?q>Q0\3\qE.+ W\1ym^I.+~1v_=ߠ"7!HX[𣿞.O\ifxz~=>jVª^~1%goENOWi%nK@|]_}%!t)==+S.GΣls<_b96k jfrrF~F;tϽ p״σAN;N;N;N;mL/Ec{[?߭Y >?9#1p\ Yk5&g1 ig.p  L1C6Y#.`nrʥр#dÎz :>m_ 5y EmO%D ^7.  T } )eCЊ12IUI0B( hI38Iݰc "@'2*[r1QdP:(!oA "L}:ǑGb`{Ѳt#wUFZE Ya#Ս1 0zոXC}}#c* ٵR:XٵF ˱MFh"̆P^hiC q ׋'-#Ux}tW, \ _ʀE8#Ewڐ{ʥ!IǩԩnAA1r YI :φ@.. m%+fCOy`nqQ"bfPtfʼf5U0U:'\X/e!V@` V4FViPzšb2ujDMRVmzs.Ѣm7U"O[d#^mj@@ewZ.@  "b&f{z+w+vJ}L)t׉>g]7]j] 3J%=8Lc\ץo_b?/heWe{b HBiD`Cf)@PéٳjarvwZC =,щ|0y>&![0U^x{X7kK8ZD@t@205vلw9HRECR0aSYVUV mU+yHQ)f`F1%jk5-&fuj,YZZ#4%Y]P$Uyݛ&DHz[9Orrcѫ!otk0H%F !!=Z 0Bh( =*J1YRh5IVQ ֑{h^*hCKx#4зK5 TRC#hbRO I*/GwQT#KCr>* 2t]Y[<6Icn38؂~3\Rɀ@G&&*G`6VзpW:(3L#'!Ψ3Vb!5 >.1GT\ZVAZTzFF]j~ "֣4ѩgUvߖeXMu '0|=djUҬ%7F KMJUE]n@f ;hBD ×B~Cs!].IRbLA2CX<0e! hI TuEoNU^݃0QECh^̗Rݩ':Hq'-oe~ >qkjd+' t7Hmt_aw}/||>sl0ΐIENDB`pyromaths/data/images/vignettes/3e-14.png0000644000175000017500000002212211560531274020722 0ustar didrocksdidrocksPNG  IHDR Ml$IDATx]([Kp @|<G"H$6A0ORy)V骄f? DkMoWh{|]Zoob@M;Jf" /|8.џ>}IW[$Z@WE~xi͵?i uGPォiM}?@ 񐸈hy4ŏ@> ~\= pGN4_Q7O/Ex@ADW)?HZ@ ?ken(,\:飫>-:/Ў2{dWEN[۫,,u*hv>(E#YTj'0 ! "4@vHVhBA3Z ZbZ @Z6zPuCCE3A #Gc~{RbZ)_7a' {iagkdҍW@['QvrCthhed 2k9{Jo@@ e(\eΓ\er \sl}-VR+ļ*J1;)-C5[i03̌星"y49覤؄qMQjVV& FHr"I5 $Wi3'/+h XmE@@*=ve\/j1 y@I"PhUu3 ;=Or%ZhQZtyJxޢYyqR.eRlAUY,5$7B(lE5|& 6^nƌb/|Fc3i0O|цN&wD zFP8yHgZ:G_:/eSu1ҩ6/Z`f``HgAzj2Ö'7qa /&"qqWqYuqxSɣӦ3i!6e_TT+X5q6 1rm%``Omaa4ntJbfd9m@^鴊]p+#eA0ԳE!s?y`D1ҙ̧ !Ō%M fTna4uϬLbJ"lq8m&aCC; 7j,)&w"B%||ZI{O)!m  ZJ9wZ˻ېREHk)b#RyRDs#*V^<5li@>New6Ej.`uƵjoޣbYy큯 M㲝[,Д[vCD_>Wᣤ-H杁/-'6ϒ/}CY/M]6r4‹Hw&!$<{=nn[Q[9ϳU1YPlAMsJ[ tGAO ұO?'赲.D윗L,z-/}=[[?̕b¡?Ek iϿT[Xj0XG JQ}&e?!tIY '/- 8bGwش?ml@О\5cۚ@jؔu^ (7^n|dAy=lzܔ'B{_:a7lS怖4p)O\5t< LĽ/J u3Y9Lth`cِqN2 f0+LW+ e> ñ9Pef&2 ɘw?Wi KS#-V\*`"7hU.H~tI^_=t*:8y#ſ5j+R#jDuEj{.n$Tky'/M?{N(Ou<]j8O]J I)/A}o9+ mRq.eZ {h% zP쳽 ٻ\zߠ4Xx"=Xqd1:L1V8t=Ad$v i$7nHE_c,p|=-$yF S @2D!LZCX{In@kGPI=0{z:S%`юA@t)jzrwÍ)MPX}h6O%CxV;9%67O{y3NoOG?9]MwtH⽘{۞+@U͊"7W/_H:O<]p7~Ǽǘ^Arɜ~ h-%Pk))g1XrNw{7&%iBOO(K9Ռ1C9Bf hwU@aV`5㼈|q s)Ԡ,/;3,$5(3iX3U'4S4v8h": =FԃH:2 M#%N - 6Υj7_j9 h@ +h}8 jOΐeߦ Ou0` E#R myCCSQ༟ e؁m(N_<ݳ&w~(rII ,bƠjׁyђvw~CdL8YZk}HIUJ:҇-hJ><\PRGjp"x5y3K*KyۏQOܞ>}j?!"8Bb] rYkVJhn;`%D[VΨ@*%V 6@R*\k,@smiG |K9L8I٪vFQ@{n/tBGAS %#gPԂڞbE{\T;+N!(>ኍXK%7xڞQ?4+6mH%KFUn,LkFM%Aϭ(G(P@Y?@#rK Vvj?V :a8 vv|:6[a ]Kd?*b$hrSmæB1;Q5J f?mV eRM˨=Gmbc c maؼbsPڈmC@Cք4d`fk=ps$q+iv@LlJQ֘l DeG?aӦsv37ͣ?~8i l3)8+Ah AWsGY0rݺ gXt>oY;w\J 0^VVUom̥ R,[-C.\d 1K(Z}|ݯAj۟CeΨṰ\ hR; ̽i;aV bA!W1ք<*mVwP,`11tPmm뭝~w5?4걺J0^cJ}|"!=,6t\j}kov=z ޝG1"ԪstM?F_Gbgz˼4ErD.9jx &鮠rUʭ{E ϲ1EegdyN~p`NU?Ċkn3K635j,cg[! X>/aD#7P/0Zg2F~k_Ċ!b[n+G`n@)9C,GB,n<"|,[1:!s35-qvM/rA,6F{5 qcvB8k "KS 4jdWUAHIuLCC5>^D+w O>0+}ǟ!nEGht焞9ωck}O:.O~?¿}߯W.9LvG[*oпNѾ9Qn(\tGր2&37) s0Jmfƿަ`g@z91k}|Tmߕ|lúboBY7+/NMJ'o[wM8ś/>дݕWy_h!Yf&oM*y!;9:(?hy4e (,a6y˱3O!Qt /hGy/_?Ÿ,0H~ԭE89%\t(Ğ/ =Zwם=ODc8UvbQj7Ho_x0G@â?b EiJ,!$HjJĮ ɽ\Zffy 1?a&ݤie`^dk+;d_`KAش3eVy5C 4OM@] W+ܦ]`Y/x0n?W, úYEҐZ`:D兿@<zWl $uJ~>&ѕ$#xwV9m־k9j;> &RIL%^#sdfhl3w8Tͯ_ C;o|k|?ZyߪRڦ/&'χM iƣ!:0ǙCCa&396EaV90.-0Mtt"D QB2nhFݠm6 yHf5.<ۨi6Z;ĿXzlc+(6"hciχqPҎlK( Դg ⩹+%%4Ў"z,;]y㐜JN %\"ȅ-B2Z9D.{EׅQ<^.~v׶"K hX8&1$?-OFl_i .[`*݃~~(&iA@;w8Uƙ|(Nr20 +к 3sx!iBBIaU7b6`{G/h~dF?3_x_|}_#< !8eVE',Q [YWğ1T^-(_웖}\ǯ9:o 17@ٴ/5ٕ ojDzgw=Zꀾ k;!ʚ??\fysLfueF0D]f]ړާ|?x 1=oGoOH oOuArcU vY6{DKYCM}=秎(нZⰬZ E@¢[Q{V #\?@VKZqm6}aɃ`V)VAK{ު? SӚ׌Aׅ'ǸUb *~ GK`52Z˚Of¬`e{?! O?HsQ)«J"H+Vdh%'odiy.{ -|qOip B g M|M| ##cNy@u,EFVR)? }^u֥CЀ0hX~OX@o]?5AoUǒw}Hŷ_aL4Y!HF6T?7r:wgV{` 1ITd ڝ}60c7/qA7LrjqyW 圾A{I@ s/3m/5os-$cDGIENDB`pyromaths/data/images/vignettes/5e-00.png0000644000175000017500000001355411560531274020730 0ustar didrocksdidrocksPNG  IHDRPNB3IDATx흽+Ӷi$A @@㌁U}}ז{Ӟ*Vt@Mo"q( pe%ԮP~i!SvF߿צ^r!|OWOksOWVN4Y,ňE""@ו\}eݷn1Si&y[.<";_sEp 5Y\7~X]+!01I3ޅh/Nl.a " 9IS@8" }} ٖ{S聍tCWplvcC1o]plpS dn)C1n+[[lND3%{!ЭXS7LiӡZ皏[*ޙuc̈́`,㖂6oul~~i~ nbDgîLZq@1J[Fδ՜h;lz'؋|  ڣ :T!VD=+>ڎ apqZ)3k5gv=R[mk{=Z=FOjֵK{4({;Z[7Vk=MZ+-d/Zy#]ok.euQY?Uzqj;oܷ؂-ۼy\7Eзy7{r-2gZ ܞ {\6w=θ+P%'En(UKk/Smyc/e~y _/|_: u|A/9Ġ|Ax?0Z2VkftXDTO ђ#[5 WuNa t fOƱE9sW]_FY76cr]pIvxœ̂ߺ hLZynCoکu)U'lWcke~9'jO[q'䝢La⶗/WB`t7~,Za2,>AN"‚i #@P•+z^G|MDa9Ntcq'g2ykj /PkPr{ /"axC [h L3юAYB 1E#to.Y/+n}ϡ:qc ڗSHOsң |y^u{ gS;f3կ-V<bA0v.ʽ'W;DC,?5 Xkӽ;g1SM0.&8LkOEE> ?$.QtP>Z>y]nBv,? L/6s|=d7,ݦ_T brܭȔߚiv>w7N~'V櫊*|;|kǙ0S./>WG5i"3;Y72_;d/u~A/ywOQV1;{ lV 9p_R3ks~@)FנrGPsFS%]]M>EqhOaq1`?kKb@o<'U(xמX#S:z}oՙSN-jTxW8^2xóNx臰u ^,Þ7 +db5?\Ǫ- b9 nzwo ~!;E%EO_X]ժ/m\Ro'Þ~?5F2gVS#2L @`v3bu5SfOj.]2v`7^$i}&NPPzLHп L\i;1*Pʙlpх-Jt?;au'2 :L처,EDQ3Av(J '@<BT%/i۾nIU-9s N }A߫8p[@ĨIb4~U[OR5L@NwI,?TE@U!0lXUZB gs7R0 bo|WD&7.L Lk{S;BvZ Y%-tǵE]590^~BwoQ* ]>UU/4K,ߊ L'ol7ūۜbb6.:( ܵfAzРv U Ƥ" N:^]eFYs}Ipؐ! ]D>IX7JY΁ ?{G\?W20\4Ȭ:`k#R C 0\&tW(4= lrt]*@Ӯ .`;qRֆ5 C8w٠v+,¾ߝhw)rU]jɱQk\c{|";?EJG xVg3""Ǹ]LFBI仫D??/"smz?!y?n7>1}e4uodg w/| _eY)y~ o%O?qvlB/|6`q ԾOZ?Sb WE*hZ_r~:VַV'dgeu_&){A+,m5$-I2H)E`VgcYLH|d8ک䒚L9v񴗻C2lJ+c=EWJKᢕPU9S|()ZFf%讻'&w^ʬI`O? l#=O*;[/FJ҆oN扦4qiQJŚZ@c?Bq +wIP{.\Zm/m~7&e!w/ R W.f\ 2tbDA`5u.&k0rĻΘ8Y2lEi^ ody:?)ʭxRYb%'n+"ȼ\b &>25\Ȉ*[9~~ŗ5_k 3/ˋL\nG [_q Pen pE T {hgHܻ`Q&6R ;"|Պ?jGtP 8M&7mt!w|~Eq/Wq__fK=yX|mur&zʝ/Tq_Q`vXy\v)}ic}a?|ѯj|g0Pк\C}6'krE ^^ F͏LԈk~icx)kp',ڭ_?R_?UPx m@IENDB`pyromaths/data/images/vignettes/._5e-10.png0000644000175000017500000000031511560531274021135 0ustar didrocksdidrocksMac OS X  2ATTRG[55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-12.png0000644000175000017500000001576011560531274020735 0ustar didrocksdidrocksPNG  IHDRD,`PLTE·|||qqqaaaRRREEE444D`KIDATxr#EcF$P<Pq[F bJ,EwK%k63J9x W%}؝ @ |7> )V&2@+$*h SÜSim3[``(.:7O DtÀ J? h f^3}zM TAZ}y 3SD3&ra`P@a3U_<6'>B ` 5d7B ۆ!'Cu6V =ulmb;4#%VaXQK>73P6m6ЫfHd.U \`蠝61FWEEcJ-26*vrmgOZc gq!Ks|p:{.7)D:o!o~}kڟn nحB7˸u[s tˍin8'D:D"H$D"H$hmC$%3A_d:a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@> R2eUp \uXGch:hc ?; 2 <ضeG\B*t< lоP 7<3[woȡDV@H `8 D€H "a@$ 0 D€H "a@$ 0 D€Hx%b0 U+ttNjVVaѤWswߝXaT WȚ!p+ |tX#`~0gx\ /4YXW€Hx9@>`0  ?6H8܇fMY8ZZAcC8@$,1@f F /\Ad.xq`q<MxZzeꇎ+BN.* G/cCTau~a]eǟo'$QV+_U32!X2730@e>bRƁBՃzj0OL=ްU~پ`ja=",ҦdM(0 D€H "a@$ 0 D€H "a@$ 0 D€H "a@$ |b0 \jFx~r Bu% #F+.$0_ 'ʇεN [,=R}ѱWUұW[lo+ kL""a@$ 0 D€H "a@$ 0 D€H "a@yMD_^a@ \c|~]Gi~tVjdV^m_,)k b♾đp} n.JZ՟Ent4{Vecu9?akPc.90?V/ yL{' V 97- fDܿd5!!.@ȯ?:f7@rGJ>FRo?ʜyvBGH "a@$ 0 D€H "a ~e= S6|87{A+J]/|”07m q_x4iA>pRۇ] "j+LT@]//rnpqiG/F>^x@ m"a@$ 0 D€H "a@$ 0 D€H "a@$ 0 D€H "a@$ 0 D€H "a@$ 0 D€H "a@$ ꈈ=90QOM>xGwUC k^ZWO{9>/"^ϊ5ǁO_7>\˗gz+^OG O ͗t.zr(LL`E&ۦI؛ 3aPF}$>ȅaL/[/ emApTI u HV= Z_^ *o_R=- 7s`14Vw# ]$2m:rS;GBq'8-~jBn: WeDSk$ W<@:{TCE)/pG WylX!U`mЀ-uJE0@(VG,ģ<6-\-}OKbZP]{Sϣ.;[*;7~}o kfOXGX=vw;We34嶫N t0p:NMۺ%w0Bڎ~߃:mKK_@ф[lzFz{.sIւtkh -'#F©ur7B܎zFM^;iOtyԪoxxJγ Xݳo:#ם+ؽdk2pvO y;03̈at:N[ ;V+S}ph;ʥWToKRtH&t)b0St?ݑ.%;} %&53_#\g\ץ=8wӴrգF%7q=aZv4<N7=W23gn 9϶;[tmxE@ܱv葕Hg;Og4jRг2 taٿmK"֎_VA(nxt6%q+ -:Q_Gܑyˤf\a@{j?.F]B7{ލ~'3J:HJGvt:aOh*wʌ1چT:8/ȷN:NNAcX;XR 蝰UlamvR.mڏ)p~v*ѹd@ &ڶ;T{b[A-A=D; fr_^m!5#ם,C=/dg;#G0ܢG}90WFQ3RKf.\ꐫ)57j5qqoSS-sղ_3c5 6Y_ReAZ ֤s:Rՠ]\ًP#j>^%\*XKqO\tR^5GܑH #o=$I!hzεyu*|m{Z !U1HM D7%&ڭKjQy^ﲼIJf%]e#H<; ֢\p[ גsM͝sf_3\:ֈX^LiГn wS_\I* F_L3 fX{]7 uߤ2c||= \gp^3 ޷v j|s||tt?k_?^|#5>?lD/g/l2 _r= 7fzt|ɂgfӍ82s~1kܐOE뗏N';J?} K#}Md@б웼ʟ|IoP 0~d/ Nf:|n/Nv ;Wa[gXYwv@B5X,1 0a0$;Oر-(̗3Z 0XY2>/zlu:8v x0h%L/y|*ۚХSIhA6Y8Ι/# ?LC:pu#Q0'c:v]23]3%&|vyT9.-",t̗ 01Ϋ~~g` avaӇњ^[85V';5ڏl\I}Bl' ɻ0 mǪiY0T t?pX6 ct`@4'vSɌb;)I6050bs&2b>>N ~O\X_ gm #ՙFm=ՙ iӫ%Kse,ۦN?ۆՏlבDK+6s${;j lI\&!XYjWc57m V/ɴ SO\~ՎK׳֙x ML4c*?|lq9P%&ϻb_ q YA .1p.mE!umڟ u;s0;R$޶&/gW~- ?ao;Τcl":,B1nK7wQcuƵgԥ13 5:_Td(X&jxσ(C9r]f~o(j:0Lcxbwc#Fqh Fc#p\J{nANj@PtVP-mlWK9V\hl37,[%6\i([ڐgf-@l~CM9x{1W+`vS+wG=gP%KvE).vp넼{ 2&aP*Y8q -U#5H~\OV~ZOpΞݗVO4_C 04[{e?3ڄ?:M7c1wǹZAy" PN6߷Y4`rzl4wB`O>_~=gӜ'~Z4Fkh @mhyLzl/oHVuچ=l;l͂vb`-KLWو.;ZQ\K8kDbrRGc0[*EC/sU[4o<+_1|7n3#4`h f ^prუ1761ѷ5$_ \B8\ptM^/Kb@ǁѯM^qw BqO> &\~7w{Y],!D0T Q@^/݃q껞dIv])wzY&~8P5gX8@p ^dzy!&9]܄ۭeyĀi BPeC 6o`Ԛ ʦr>l5dMvPmy^.96?=sd3QeUsLءOB6%Zd&-|N~/K2|CG`kѝ=1bZDCyJh]Ld+{zPe Ȁ`X u*\b2 ; dFh kb2\Yۏ߰g8&i=ô PUi%pN4l52s,qZͳ ji gX=߶7,z1 0"(5!8c%7mnc2$dZ?3䧶Ǝdx,\pF^b27É^pdq]^{xϙ{ݱ 3?0 d6x[,3vIENDB`pyromaths/data/images/vignettes/._2e-02.png0000644000175000017500000000031511560531274021133 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._5e-02.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRGK55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-10.png0000644000175000017500000000031511560531274021136 0ustar didrocksdidrocksMac OS X  2ATTRGs55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._6e-16.png0000644000175000017500000000031511560531274021144 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/._4e-10.png0000644000175000017500000000031511560531274021134 0ustar didrocksdidrocksMac OS X  2ATTRG955com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/vignettes/6e-04.png0000644000175000017500000001271611560531274020734 0ustar didrocksdidrocksPNG  IHDRm$IDATx]u.:PC@  BRbRRH p~Hg]}'͂Vsu5ĝ"~çT^@H^~}ܤuVų&Y H A@3 " N]έvv?(PTZpa@g(H  D(Rޡ u/y^PƎ "B)#K׻cTp=@Gkk|2 O^b9z8GgB#$z n@0" bQm#d-@-a;(~1 9@ xc>ٍ '[Dp3 a`ȱ1 (ԯrݣ`H9 i qɞ@5"i3}lGsjXeТW=G&ϼA\7kC;4:Kj+3- BlZ:ZZD ^$H[b=J)ŔJ $@0i>/63r!Y=wbLa1ňdf[}mA~% iۑKa)F(dX,n+bH(ی.ԍrbn)?_P]SBNѷ?NZF[nE)2%KʯGhMt 8r0(r0(r0(r0Y`Qӷuo/e@J r<pU,ʿ70# (P`\3>`ŀa76^wEV)UoѨ%qKP~"t _n {QKL1=vʅK>)xAk3pwms ymMP[8y gCw9rV kd4ZY0k .'8nY*iMŅTX̀jxމYߔYkWo,]ܡnkKPR3 kmd(@sѤʰ7OljKdd(!g!Jj!6`6#a$ʓi XW\̀ Σ@"MDjY Zim*H=P` 0B q&V4D^rQάx6CB%*TcJzCzKƀѬY8!esu[d_=`Jա0,}fB fDARJ)tmT4>儆HԹ"Y Ø[ @5V$| H1:~ ;t]g}WUKH2Lj@@0ofʭDն3x;Ne9` Jȃ]1)Ugv{U0:(,ժ(/Z>;jTLiWb_4tʕxsʀ*.`zet($}skVQm0oeҜkmWr ac EAZk]7N(eOИݖYKC:v֢ JJ84kBba"[[PrՕ8-b+@Y1z5!dJ F2Bs(J{ Zu^Rw =u:j-A2NJ>Z6kqUC(c*FWXvRBgvf#h6" J!T)u*P2u؋ \ Bkt5 j(0k @Nl݂lm8OƠ@N@Ub6*DRhԁ e !\Zemqv&f-d{K$9'dggQ𡓽Ydl~ *N0af&Y$Q'͓~\F7>xd6F H%L}ϭ&l@+}ldq]-~94Ƣrڞl$bU^wRc40LG`\[K߰v۹e@ޏٛ!] }ח?~3D&~l@U2zn3`tp?;x0BA0 p&8c Xܠ1[ ò̗rM_e:{O l}@c7no;0а?Ro. Dž[*҄(_=9f6R⾺UboπoALe#Yw70 /at0A Q?; Ѕ22b|6resdqC D~C)"Eg0nH+]Ec.}4>}}:b!\7HH攀S4u'z*x't|X5c`bՑ=w*AmQL21SWM)W0v`]6 J'Kn= 77]ՎC7;wz#`Νl Ss4RSl{6kԇhKVNF }\7X{έg(;^)Ww^ "xf fqKu%ǣL\UC M0ݴ}^`xkqC7hfZ7m߯7feIQSnP3({w䪘?J,s2]_UOI riL] ${0unE0Ī@ a!"8T/g3^)*u.U)W Da thɽEt F!u7xI&kBz"`]W4jV4(PFh4 uOgNQIl}TD=J78b "YS/N)XGö LȮ6]]l̂*r<`aJJ& |M7&w7umD%oAN2Tŕ{m+=(ӉrEXxZQTuuN&F_w~I|ߚ nh_Իr\_rK թǺ!1`/oSl tuJ9<1.:nr<6 s%>ܩV6%U[Լ 4n B[~ևDfhUd?57]Rb2Gfp X {78<|2!?x\π:S{Z}OfWuu34W׉|&2~>3o6o:atUMWWz#59^kŇO nLVi~#z+~7z )"{nwxy_-|w-<2N'ߵ$<eoyX~)y@zq`gt0`cpɽȷ&ǏU3s4N-b0wo[W?&4T{J>1y1`底bfNYZu&K8?>t 8Oz]bIʝL&.w=a wMOŀ7@waN$Ǹfj)DҁCiYpY!m3e)~o(!tyy}t3UUn7Sb˚ 0:Γ3ΰc`.w|o(Py 0 =F?&h*UX |elYr|P}}7;ljC(p}%j/H`ځ.a\1P~5v Aap\L{x B eXҺQ;y  "ы*F]T4J\ H0Yvq cøeP*0ӏPUcɎC>%0[D2Ѳ=y-2TdwΗ3}lY!i&֡"G*»If>Qb">+U4fjdn D5nЬ #ʗ3/*0[]W]*G$'S*>:8n01UEd=Ά3lM12g]9.[ >:DCz@|#}iG#DKXq˟1>D;ΦNWw4H0B2Ol^$^F܁/G`\@Qs  h8ꯚ>-bBU L|ήДCy3MqkF_ t4@$&6o6Gen}2.LH-&(f^j6B,;$"x.@B RBKXPLҐP %HZZ_GCC4&G)T PB)TBF2kp(2^[K0ҮYVF_} 6lA!xN5PbmQ)[/]Um].[ ZW QdFeWbk¢|KŹE ^O nբmJ9IvRE}toݏ>\} hwH`Qjhz:u#2>z`Es4.j-iP`96{#E߂vӳ~v^[ajݦboݾM+! R 0 \}wbNz^'{fK`0C O¡7e> C\#`E0bbCCob\{ycJU'ߍGAnDdjl,b Z^"O viw4BXJ8>Z@g }wy`<!~B W3`]z~~٪ߥUcG?A%OzIENDB`pyromaths/data/images/._vignettes0000755000175000017500000000031511560531274017626 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/images/pyromaths.png0000644000175000017500000004263211702101415020203 0ustar didrocksdidrocksPNG  IHDR>abKGD pHYsHHFk> vpAg01DIDATxwdusirAD$$E%Ӗ-qe[%^iv]'ٲ-*PK۲EQEQA$afބ_7$;7ԽUIu\kp 5\kp 5\_x?] ÕL0(ŀL@N _p?w1h1*aAXE>$??;3^Eܸ1 sAd `Jx2y_#7;AU;4.s^pg(0ԓ"_miLb߅O[=|C>ioSメ| 0nc) IpwK_햸G+nCױ=8kkj5w[C3^!4~,q]>X>`ʏf,P8ed_3+4PȆZkFF- KbR(jeД}I"ksGs2qde֬V_s٫w槳, ƜdHZиϱ>7 ;4;+lZ05gHuz|Cv1IhѮwP1B6#scPֺ:Beg_0̄ucK_?^$t7?)9 !M0HO yM7:iփLþ@f(u'N Kr?+e>yPk{u [ `B1Q[0ɤLN*K(4L;hڴT k5Ejx_JnZ' "\N(+Xb+7Z̛ݼP C9789 =[ټj0D;/$4~IsAP=\wT?9_ےI~R)ng?+ڟTwǾ#}lH% P ÷P<__\Z㻞ҋw5R lŚ'RRR Ch}z(ô ʍPS*ut:Vj%-i-d^ߓ{ޢ|קjσ \A2/=dK!e4\6OfU#ʂ_xAy[-cTt-|Zk^;5U{{rt-[xOfGO!cSJsxd!պWl1-pMOkml Nzix8;rm}uRV]{6?myX %[^)?o 2E4ZԂR֘XNۊnT_+BS-vbg'MͷRʒd?+U]?DDӯ΁ӕ͛&VdKF7?n-n>s`_O/|O%?|{ٟo˿sN+^~u<裳!vn$lQe9XzF:>ߓF~RqNN|Jmy[(ي`קHr(,%T=Md4;S!ZS,8 BKi[Eyjeߩȼ[ה>lf+:TzրF$c^&Ai#g޴(8ol!,(=ۓBibHyaT `*bݵKi[ۃ)D;P"{u O۷um`X׺iDc<^B2 )amv_^c;&NB+3[<7]elQI*3Zl-@/X#'"[ZS-Ks:Ut[!0B7ӗɴF邅8rhW=juIp 4d!E4hlI d V܁=M#ːw0AY'%oh]ufFj[(P!,>ݣO#?~78 '^}i9jN!+E'QrLEʓoSߚ\8yf~8c̊YL0m#ӷ/ b$@+kȪשƕe$ @L@kA6՗Y4He7hpYa$ΗoXo/oR6|L_q]IJvdBZ3 2c;R }=H,NFlBPZɧ}}>uӝFM޿g>3CN/(*V0/N6b iEO|kJ1^LUBNui2Dfd@ dH[J6sv,h3*Tz^k&}¼fRRkKĕfk JRq.VjZDz> !99ŊkXF)eP jZE<:¶]#}f)QAihE TuB#|-~,إ({h egleiQHYdm0 D̊u*?p+keFs2ݛAĈQ"uذ{lɽ18wbuFsaOƏ`gl|b?cw#vvG/v,10.˭ F6ɬ/-y_l|XMنa wS轟y4s:_{}c~{~FkKB0{> _;[s,s5/,8ȂZk8M,8hK;HS g#5gLݟ(r6~mdfob"ՙ=ujՍN3?9jud{6,vfݼCXJha}~?j9@{miWXpy^~+ _^y׾wSВѵb\ %y{=b]QhSWS <׸'+z?o~o}澑enx٘ޟ3b}w(έ4z3=Ms4<{s_{ċ76wa˰7i~ae:xR<S*NxH)m?ybC D_/ek翱H8X ]#9vT}-,D1u_SR)п퇨2Io!m,^'Lz#3mi{__3o.}uyЁϼ7߻5[2y;]o~s*} +$$L!}%ɺdB/ {6do^[fL/z>x|H[ ٖ=ο㶟eVK<O1}8gNӘAٞ"6a& Ξ8qӳ6k3s,F>#=zTΟ:H6XE9n*ԗ"Wp. 35K!+ٸ!ب!gꜝt l\&3[ 8;2;s/1VE6,hB?Be$EɺdMZg J64g*!5IbehT`b18%0f΃ųc@pO[?z-͔A4Ei+~7l.t!4lԚa,GYV^@MOoR!c ҎA:k1bI@>"ex(/ S+&I"k* Y!!0+;##jNa EO^hL$-)Co={2R*(ց{αf[LAF|ZqL:º9NmSzH/" xE}W,}!T9`Ru cdL57ZGP !@hE<ke5DȯN6 5ϝ:[^8D3zH\#""BSϐFN<}b]×G"BAB}s rY+%\SSpl ND aBh.;ZIbH.ȯ.ō,stk.G^8[#D@Xͷ@im@U'm5řŠ~I 1⛡W~bZЅ6y7a[HO*.\º8Hnm|h8~&ߊXB ]LswaYp#"-A2B0k>קKGak<^>U\CC l~9hƙRCYLgyϹ7BRYm'K 7v=tb/@~:ظ29EE]IK̺.Dм'b'E'/ \G :B6E*l2>CGt6=ܩi †bCs/;P@B2>)GEB^35$!\uNh2qݺ]k9͗qx'dw ra{V# eBXSCI@GKGDM"B+d(;BV#_H3z.T*Αo{9/vѱ[/P?q_"جG\#D4"@!* ):Bب E@e0m'nݷ=iZl0 8^*{MߜIxMX_FW\BXGQ2R(B!-ֈbb,Q@w[ 3fC.ǿ$ZTK>Owp38@H&Hz# Cw1N@q.iE"e{t7?0c]a#p'Xi!`2k JS :!u"O?{ݘE -xҰY^Y aijm9ae_Dk29o O/t:;|?hVJ脮6(WU'~)4f(fZ"r##A+ք~Hبz.A*D1R0=GkoMߠ~5RdGw2~8 `E'ׅ@{A!Hߎt9i9s4i,qx:nWsq ؤ9 C%Jk)fl_"/mn w|/OZvf,Q*wXP^-h 'd~#i@Xi\TV&`hEx22ys0z=hpriz7пyp dzޏ"r?[7ʚ:[XBLtn53 0ћZskm hQXjQ&:n_%!?2D~d-_w;y#uC6=q5D7%Xh|]dS(/Vwd%Z mKeDo$Vy ~.9J#B ]:iM|vHk ֱY1Z%.txwY e:@CiD VMlЗK& 0߂4ki(W]Dlk!I"KdIIP%SKAtG^d40MC È1ȥWozmd'" լ48)pLHaKd[ɠ$:@\ȳ`-BwhX$iEgY;-'KD - Y2!C!EQm@űm,G`H![DSsg.i/}M%0d!cCII>zç7[l)H! |tqt-O}!Œe $5uRhU'9waݐoܟwV- >iv ^JkxaWs~r{nGsϿs.B1arV`S1,?Ìn-`e㉕XR9I:uo⾦-GMO~She[^>Y*Ok8W;@yA߉P 7"1GSbgpS_Nŗ~>(o_W~6HP͵&T-E~2'?46s3sx=B ||Ggs ֦R0lʦfQA)MBT>h(W tt[Kh_!:ee=sIsm*Y CtL.oPÄ兹 62(!hµX|Dg'D4y;aidrWDZ ;@8Iv3{.eLE!/jk(f2L oآb~f͌+(@ׁW,nEtMVF~2{Gc[P+qA}>eFĸN=t'Xmb"rB,ִnx =ի v%&]"&XѬSh֩t\dW/m2|{k<~7>Mn/KV&WǍOx{ ,6ZF:w2DXB "})th"R. SBD&B#S9#D)C(/ rk =Ӏ@!2ˁ0Pg1 mEzH7M̍9yD9#XJ1~q|ip}M/ g|jUgAvڲ"4'mDe%β⢎ R@@E<]sր@@Y@yN"NKX#"ӰႡ%9EdM}h=VD/e-̹z^ \Xw3|K.9y8]se@u)Nr&,}C: UKyCE*@]@:!cѽFԣ,F1 AJi|^}҅ݨR8<ӿ g6ֲֻUDHDn*.(ŐnZN[X Ok}'p P@~'I*,Q!p*bcaoARqyNe*?{Ϟ<޿:h/wS*0jD i4\ D%BD+8 D'й ~g?;>돿g|le׃W_$[h8gXV66hxP"-Vz9U^؛KA!.UKG=ɑށ2"F6m7j ?ikM`'^=ƣda'4?}4/\o,R0)8S f"Ee(1AD~Lz2D@#^ueCwɈtv^'*GuLyrssL;O"~# bB"~4 nxp}6L{5< |g`4x]k':i9 /Z,>KmM]~;Y['兑"|z\Q.V/VUL/Xx!aQeBJFvc1uK2bbuׄ*ow'ΎzG.$E@WץKFRX%A!i*ST&MV~ *d#܉L m_od`P;|%z]v@C@x_z g,qvj])uJtW.= =G;|bE4#Z#511%>$N45HBJCql62rz҅ ]Gje]D!6VD}1{pV@'_*Z҈VwcKhR23OcL}[4;eл޵qTt$C}ߣ|(*ԑy"< kϾֱiYG(m@iRit[혎B{Ha}28lFƙ׏p: =~'|vވa6 ُ1[݁:ӱNk2IϦMXNvZO{ _qlwmrç:|Q 6ƣ|}_yq݇g\&tK㏬ŷ_ě=fI$Xɏm ڪ6H$g)r$ R\߽p H:si=N0!Z"`ԧ5,tLsv!&/cƘ7]Gc8k4vsX,Di9A!PcIqW +_xae+[G8쫜yMK4w2>h-]z]$wwI{ہ+ O~v|PiP QJ^*9nae^P34Ѧa+|M*} @6GCGvm58 >x {h?kiPB d,g~~Mn|R <_DňC4>yADPt\.7pLAɃ3xˁg_Nsd󍱁h z z{>a;/ hIwnys_Mn ٸX:-8bA۱c)0Bv.4|yrvPB-F=ZiPY0_ac,DA(LaHw(Am01uքPA8֘fO=NWvy wm9q6l|d@ڗ$^_waN#L#sl.iG>!E^z s ̭Zl` %d_ =hfw_+#0>zx. 0%YCPᦿcA-DX H4D\2~œ'(n"i0@43M-}ꉷhܺ­5>G#=ˆ5_U}3e;2 ͌GlE2`n$Aͥ:$c ,浣uiѓGFֻ|~o4ퟻ,]t\} w 1Գi+ "L _2O=wA?)B7oz]ّgoEǝBxx;%N5cVjTOV"/龞h2I) L~ap/C_ ז j!pO5mXٝ<`Zt.1mvl];3޼_uvs^S i4$ejahݿ{#°}iKȽ_xt͑)DEMi>Gv}7!!FZci ݸxō^GH.QfS _9O iR)'uX Y<:T{ӱsRjsO=ɺdh-@HBTk3%폫H)ކ2(ark0)-+WL;ھO}5~/=@ udQDϮV|te@:Aeg Ȏ;H^q,gtmWh̖g t.`ѾM X:uǴwBdh|2ZZD \\ɀX>,a푿l_=cbþ9b[6Q "}@ϜlY6D暝_ZG/:#P41mH)_G/dZAԖD -`ْn+ŏ!VHbn>1W(&/Дq񯊮 RV;>!XYw7㎿R!νIfѳp \B@|GB v|IUn?*J; #4u .?w) u2E]x`<đYz/2c}rc.DﶲpJ`ŻB%:f Wo0oag5i*)T;|X]Ԇ;ǢlosdY% cIN0 \\5@{dcu_&; o+뿃}?[j9t "G9\0*w#^$M=\m#RM~HbYpoŰSy{2űKq&Mʟ+D~z+E^30:x%@(n^PqIpع G&y/~lK HCnx"IuAWȔR6OJ \LhɊ풣*" 17~͵<sˮf$Ͷ]ėa0{WGxz]h?E C1{0nMHzw$7pey9R-U:z57GR6H;톭TJs)h]Sv}(퀁['8H4D/rCH0`d 0,Hmfse*%I0"Ѐ0Tz?<ۇ]`ΪuCw!(rmV뼮 כ"^vI,ЈoAcwao}jE~j] (,( B>O8CCPޝ]tz3y% 4?OKK$ρA,Tp>hf&?/|B9.޽ b؜al\ :F--96nXrM)Į*d.q-mȊWV7CXFy;_M__A>ݷ޶ı(w aʦdԒ˙R"svGaB7p s_w4,Ê_Xۖ0Uwx|?~M_y^gy }%w!(V0N I#|Rh|`UoW h@lԶ`Ej+xP)LoӁj@ٯ»;偎rYR0A3g\CC$tsL6;OrbI3Vq)vy{zŐE}P5Чš*(0 Ul,#kfX+Y0!eC_j9u3{6|ϏAPTat(CyXv|ϥ/ ⵬P3QߚI ~(EƚSj 0F};Q_o?slܼwk4y;|+ _;u^x?ṽb1]J;z2F6@{`]6;)ݖ=W- p6 C\7_~j %tEXtcreate-date2009-08-29T11:15:00+02:00ዋ~%tEXtmodify-date2009-08-29T11:15:00+02:00:JIENDB`pyromaths/data/images/pyromaths-banniere.png0000644000175000017500000007126311702101415021766 0ustar didrocksdidrocksPNG  IHDRPfvW pHYs  tIME -Ly IDATx%qgo:ݳ$UI[-D_ " $e0hLtOﯻo[m?TսUumFꊞ7[˩s/Cx}>^z㿴C}x}>x}>^Z>^kx}>^x}/8 '!s-OO+\Y:aKW1^8|s+«a9w`| j=u0Ej7{rrM?1pmgڇyPºo_( 4/-9aFJk{>ե$uEx 5w͟"\+9s oQ;{ W;qA+S/'ּMS+ .)>Ǔq%"L~[dEM 3a #0f"YzͼxV&wKߢSC4]a &>љN dpڃ\)raD&]S W7k溲<3WxI8Έȓ&ҁ宨jQ|[[d.t Ee. o<3yblآv,5ӁêcuK[o=J qXˊ"gUQv\EM&`=SUTH3 <%U݃LH{Nkx2M "^xf6yZى *1c "O)NűE`βVklgM[jZ?/Fb镱\c`IξLT'Lt^7FsqчXߪ<ʯ4:A#%ön8 C+U8+`X&|,d,X,v̬YiшP+ X31|1i&İIqxd^6Q}1_zԝFS8R%~gaJe2k$ :1[ZnK$ ! AD"SŠX*i=W.88I5]a~g֓+G: ~_n HV.I|p'߿^GD0 2Pl ?|efGaJَurZYҫx';QyiUdWfgFۄg9<::j{Gmotsu\ӎ D*'Ǎb69x{'>u~q]lM?w?ɇi;L?6Fk|恵B \5iy3tk.&ʥu`ab фڞ8j`A9wvw.5ٯ]hFyhDX}C }ήv=9)n7}s?oKZzF`bLX3SicL &!;` `  zwmaҌ2B`!eR*a6l?iv߁˿w¼^3!ذ_l6CJ&;AЃw|g\ZHxuǽ&KWպ؊̵;_sgmQR5;o`fU.O5q^"05F<;,8 ̳*?~'eD^NBG,tt)B uJ@^'}jVȢH]YD+!pUf<0•;_5Z `l_8 `ĉ"1r, ddM*yHF޸";B*фWFg3*v<]ss{oDS9Mj h &`-k!1Z``b XBp8UknG~^&k^hU ]t?qٛ H;G}bixLc])&̲qNkbc]N }'jjι9xywXY4"8OAx/ulCO%Kpt?{k5G9ZMS4? y%]-]ױZ aQ~"|3-R?L#mIJqØ<8}۔<A8lIQh1fŜD @1tsaAΰN -sQ-pDvCCi<`S7q[e>>ʴXw77_YNl,$ԺHN\?X,I%CbaȘmj܄RQ0 W]O)Fd%K[ bUsq DrٻtQd a~t_\syRISB摖}ƋLe;m62mbfs5UiIZ`&JdxQjU~&&8 B0A`pcp9.-l,1A5HRɭU'4 )Lr4rpU,XAxF9qA{QIK`3@3Ő$0`H'8L`aC@3&N԰MD:ke6iW'Plʩχ`Nx @d9l`$"*6'E#Hs61\hB+)@+D &G*X  '5$ d[gl-X6Xc93fҶSJNtF!gJ&Bd4 C LL#3m<{c)#c,==^NDpoug #+פv [ Mm<̅ NGk  T$+ 8) qB&22(ɡ<=YaX@Ƞ `e &X"k@ ` @sǷg·@Ċ8!;2!=H,RZ/?ph(Ο}kcAES ^^<~ K-Dw7MOߠElsTR"e/íj?C{]:RJ!D= v\$B!l/­j^8C.{=J )#^vh:-63juZMjxw8ǑbK!qDGְGV SScennoߘȻ|^? _L(DD90d00JM$菌"dUˆl3UR a#L@f0/vkRJ!HߺgHtZbilxuJ#FY_n%5QN -j>F @&v:m Op= 0,7s[:o6mIZk Gm%OUDΌ BB$WIF?{*}CqI;<:H}Gb}[޸*ΜϬzRQ~KD#kG-߾q\W.κoEW/wW/9P-LI8Z;]{2]>/._PKnt[RY l&s7~^Բn;,ҤSJFj `)3utW* 5\] B fJFCoﳕ0;?6dwS+ՋSur)%Xhl 6s|r?_*ժQ=pv57k[_ % 3n~2rUS7gּh 8߼֮Z`L7?\Կv~ ?z0࿍Ν[3W.yo^G_TJ=jx gH~blȈkBbQpGgz/6W>uwxjyktwjyR))RW༪\NFA@NMdJWJӠML鎍ZԵeK3xnw5@j1RAm_8&m l#$^5\*ѯ* |żw..x$8)h=9 @NZ}616C@x/:l1.xwx{E8~sӎ`!y,fIP6&uhb d- ))Adq646xhE5FccíjՋ6 pd; N󓏔+S3|xg>׾qw ʎ5SI574ew]UJ-tY=Z />~te >~p!@w=x|pv>E?PJ; >:ZyZvaxx/v b$RYlܽ7XY ʙ(&W[ύ7??j^mnɟ]Te^ѽo,w>m8Zk3xN:]D}e^QYN"+_}ma^i\]u|  :-ܻ矽㝵kкtx;h^0Ka<5r j?m,Y^V#M^!ʲW[}`AZt sȀk1c@H`IA3+x/T@W=6~x?~a ׾|ۧ( E%DZĽ: HRJB9" 8ў;-w -qUȅ<^VWAĬ i{kÅ^ZnK.tce!Z;gt IDATx?EZ ZyLyP^?s,[B8l+74 4ԋqb/ "0xO>6-,Y8A^hnnڕ^<ϖ(auc@h(` & ԽlQkQv] 4 ȞlۂI9"Tqn›<>Ɯe΍^h4K 4Lʱ6#ưȺKN`>|n(-,]Xo|Z8edYqc\.AH! G\!$ӵãN˥BNKC` jc\IDy2*Dfppn*fM\R%A];ZYXFlGSND{4\7:H8ѝ[y-u/M i#1ŋLjR -NsȘՄF 'R(a"$ զNʵ0Oļk9V*njۻzqVWWGGXffLx̪";$F,\U]cG [)$$Q㵖5@ƭW׻W/ ]2C敏D`@@7RWwȴ'Ð Gلn̪t$'0Ez8o}=/+rY_a쵛ΰPN IJ%%[LJs]ZJS5(`խ,pQ(\ ""9=%q8 =[Ds_~6 ~RR20 Q}$*biXXͣHZP|^8g:,UZLT `Bq DJ={1,J̭0̭f,Vn~>\r儆5~x?ե喓${Jpuu)`AZ!66Mj$~! IZP%X,m3HnmKWw>]\lMF("DB j5U2VPVPbeR&9dp<~F4‘ 'fX@@R W/p͵wEŎl%2OI|L+5pv‡S ׀ySIiDYpg9T1B)Qy̓TKYaѐP,t1㷅u%Usnpʿ:@Z \G y0ŕN^%-&6/vVS/-rxq8R'TAXOSB8RZHO?e̗I8A%pl~ P P{kĈz6IskK8&tu" DNy9$4ͶB3q HhJ jL 0?ie|fpQ<qh 菃  ƉI,"Eݳ3? HՁ(8k!vbI-:%0oybRX1!LB)_+g٢1$d,i)Z#7cu=)d,oGI{Ӗ =s$iQ}Ƈa"ڭȄV4Y|cAJ 4+2#h",DfE"hQFf}ǵä,64hqoC;7[Ru!7hFHJG N*40"8:'O2H[w %UF{CAu$$BgGh6 Ā * 渏&FE, 0LB$L%J0xl΋hy)j4n۶pMr0MVaGp5 `mB2r: I lr@AƴM2;޹|q:9,dؑd (+>k4o}r,tϡAu3F.tDWK^H1x>f8RVx=>< q%aI$6IdMlL&acQNszڛڧs4IFS.d,'d)L@%b#|]`#r>lѥX6Ro46Hˁ#ЕrݠDW?=>RSh\.$ vY9 =ZLM8 _A-ȑ¢]xzBA͖( en+<x <~&w t;IZN0!03^%ЮDqIN2lU+jG}qY.HSL69W1*QtM hZNHKDWT%B(EB"uu Z^me{#녞wTik* %bЀ\l,tF>8FGN^PR=*D-Z ĽH$4e$bh0׌+) p(Ql66)ZJ(!0"'9?HS8Ԟ㵚jMiU)?۟@Hd{Sʸ[%_0Lz-ufq(pG$X(ٔr kfEҖӘ(x4 "6 F iuZ?O5L51v0p/: ( 8(<Q4 LbkyvkX4[NϽͧ.'OzN j6!B ]!0g2_0Kƺ !m;-eBۤ uQ]`MFIDA8ƃa<0D0%v|I<Դ&޿M8[  TZ7rԊUKZIPJ@:E짨ٿ ՠ.%i^ojEgd)sT O.ȩYQl,$c%탃^$q& mƂ|eeҲsY&`` I3f T-6N7WWT/$}3ɂɝY-=]m L@Wx$8}KKJ272 ̬R4nPJN Ls$:uJ6|WZxx5Un90F8J:Y՞e1Ӳ$)a Wm8C+l*Z-KႁW7D(=x' Eg #dC, ,4\j>֕pl3 6W25M=8`_qdMhb [8B7 i5 Hˮ! Ȣ|CϷtͥbLU TR+:sBkC  6afT IC8:0 RtM?LM}GJ3%$Mlqq,~;E"dDtP1[P6T븮ZY I`GaB*O+sXd=d{vMG^{{zpH(z?nH1ݖj5 $e-Np9SX mE{ 2pS8# $}ᯮ~Fp]k , EH)oe& r 5| Z+&'8BSH4]Ǔ%9xspgl w˿ $R`3ډwY 0˝7>tIũF>a+"K+.'l+KE^0kuŐx{lexv0<[ D2Di03+AY8Ayv{];ml 8nilLB )RRk-RZ^,6$\)7< bFZ*OC!<9? Q+UzhmkX&0ҡ,zS\'hR먔Rٹق@0ٗ-Ť$ MBH!!*<@_R|a< BY162—@%k7ܧSg:HT|_W:KQv !vXQCJiz*Z9 2*_&@FOA9 |a0n G.:WL$aDDqh cD c "6.bM.̀}@1Nj$3Ak.s {I#1۰9Wb} I ဣ>0!fttg[W>#L bt[Z9MAU޷!ÍՔDRCg`6iTWPզc8?韽5(}x`đpq)]NQ RTSt"k"`&'[b[^unK 85ĊO7 2 !$)$Ft6pi\-H?Ϋ„HJP_0F!V 8LPjm^֤h:71c%B"iA彅 UЩtQp%Vvlu]RJu7óz0u{+w7V.^O7|r{z'Mr PꪛKe7qu:d{Oʴa 6GQaQ$IVZP];ް0`8ƒc@D1HvR%|ٮ<-QPn̓UJL=JkЩeBkh ho4ޥ l&BL:=/[ݪ5 [/;UbC,V[mugd]{h6e`HbO=2y#, Ӫfi `HPxbI[^KH*z !uct:%Nɔ/@BX A[5(F!R)JIt/NPf`j pu*dLA  !#-RzrɥM=>eA H++Lu6̔I#2_\蔝wЮ:t֚7(s-v;hH<a̍*ekXԳd[@:NEvHU':߽!$gZQi4r%tcۀi-]G4q:o'Ô6wFf7egF{4VzH5tEEPLdH8m{t !!Qit~ OZLa{Q i $`Mbc@Bx QB+1<Ĩx% ̽̉5BG, 9jB$* d 0I HWS66 &0y-rH-7|7,4f_Ó?+W;.,t !@ʜz*#7Ӕ|iYn+Dߋz.l)2cm$w~gcCmL6vI'܅s?W^,HE 4x.BXw"/xpt7IHELkWl8z9dv&J- @gޒvr4 vw8F(IC}tn|B+lX(KUQ`SbN"ETD`ԂVjf }z(%7V*6<{'-8kKq3oF1l 쓎(Oo? ڿێ(@36b6\}ٟs{J&J]J ,j@jx)<&V`ϓ$Y%j-9ko+o~f2BƶZL \q/~E x麔58e폓n`3}/lJFC-,ȕeD=fk5\  7ѡJ&"xMt˒g3pbOQ H_H)QI iS'RrX2 Ω30({Ze-1uI OePd-afDBHMP)CQ8a$R7u',| F%fzYwO| IDATm{#Wm:U36( DqZ(5FH } 0WpexyU H$|uMx6xpʃp[_:zŹ/=1aȉa1rdYz9zH6&tLs6f,Ɇ X ^+@ ȲZ0,x-zW3;ݙݙ~7d7,Xz;"̌Ȍ*B@,VeFFܸs`p"3!)5\;Deo94z6g vwgz?-P$]Z08C[ :aCԂA ZIPWH>t yG,,T4`R)8EƜ FLB8.S&pLJ̅,]w嗣w}%$PHC'v^y&; W>uO ϱ ؄aG͇}BOsd-6yHL`cTvHKR{[+ꪮVUk1k\:݉ۊ"OBJ:3 v׷H&v$` MhhviI\W:F*EB"Qpƻ]àP] ޠ7ػ~5Q,s'%* :bi@d (a@$:5<,GIktڋO-x _<;`b(I{Iq M@bZBSH'}8 )#SFfDЁ>҉Q1T]X޸u*v~ قӧ9N7bE$1w,4)ƗٵCfҎ^^mܗݡp˰& &@~F u?[`!Bԅ6]Hz a.@=8M (D0|ͽz6^^={}-:%!i@X?<͓rfYϣr~n,yo[!_Z+ $"Dݭ{I40.=P^,$>#\@տ{Ɵ_^64ԝ, "qcC#GF )c6PRJ"p՟W޵~/ԟʇ6 L b8R Bk>S 12@uzW~Q S/b΄P!mlgOW+h"`Bʢ?fԏ-#b!$%6,2R`?@P&uk=*fn%S\h$kF#DԀFĉIIy$fmpRQy@ d1|~/fEC]ht $V$9N`\i/`"W+dIPנKK֍ųP&m ZLHDU&H:t!ޡv6V|CUv=l*kː3pBYǭ@)Pk<{QLlqZi}O+0g^PUÄjOȜnO19 n"tq7$!  9!hI gZ$TRg?K%^v6Åi!Ԩ0lzٹކc miAu"]SMD)ZURkRZQS[_wȷ$$N zq>P8"2Y+BGb܌ƌBh-#!I*"k_/n囫Oմ%: y+gl.2~quL]<2qYcYIW"8{(DBO:MoPȴzIfc{fc= t45'Nձ _ =`lDAC)4v+QL.r"M[A+(r:2]z܍{HTm24?W~|"p";UK; o3z<@gLm*_ƜVD icrɽ> Hںf/,4;O^KM楫@L 8W~m?V:ʚ 3ѩ0FI)J7X x _ n~zMWVg4{_pz"k ]oZ;swyƕXyxa17-ʕMPYؒ;VZ~a,!J4]7vk?omWݬ"8/s%wOTL;O|zs魽xyeen0C:ҋ7o}p+¥K`+M ?NKw\_>Y־k\* ;=zONo וh6) 7Ko.ЩW֪kҹ?_+ +RA(FCCK>;5&r]o6_yuխ7z駝J8tdn#@;z: IOdޠ^Y]&D-+B$ckYhᨎ eSIȲߑdjQ{Ί0eDVı\Jz%|3޽%$-< T>(PW+\Xqe)]_j) ig?#$;j "RI1Jܓ4kۗn}֞0믮9i&8 ۿ;9O]yk"IPoH_#Aְ SB&_.-/4bp]2D!2B~R@Bݥ[[o퀯8/]\~߻c.Y\0Өzwۯ$yor B: P;w+ +/ 梬VzqtF-Z{xq),h<]Gz/׮\WWOӟ?T߾rG'=uO_ZL5W\|:v>eo_ _=)}j~P[)^=?aɫ.N5:UMs=[[6;\XUK?ڤNbĘ1cZb!Y/ߔR )CK˗oFy3w@l`smG6?o}KJӿzxIyYfn}LRpi@22 `SE 1.`t˷cR[6}D+$ǃ5,bc;LzֿB.@ *q6˕ OL:`q r Dn-%Ipk~D T@@>6VODX;$ʽ B!5!d_ģz$"): oP]n؇Pou t\ O,5u&)qTZp{`7]NY5qэz"8y2X]J,dL{|xH,-n6;s?P7WҒ\\4:HE^Xںf͏ "U""@W7;&V)X8Qahu{@b0\o.w?CK8*>hژImwnmZ=X[0d2q8 "78\sO6y#U]YX}p{cw;ɷKIwa!8.- ׋t;ڋkr3 u]Ewm[[sMJA)D (J ċ/\yWFh mϿ]|j[ݻrs^X2p ١|GLi>{6I^/"[[7vYx "OLaL)..,4Dmec's04|2Wؑ҅h(=_fyrJA[qf0+:<SU'c)(r83E$@dm!az<@aI, ?ic}gՓU}OKw0BGl7VeAI:yR$FHeJH6"{+V ZŦP$1ȉFTs+U^w{kkqu:`IBBpy9<,-y BZ}ըO&Xqnn€I \.-Es6 S8 nFF(ֵrj%$ҕZ\R՚ iIHW^\ǽ[P6[kGI<ڽ啨JЮEJ'CF' $9VͅI |\0$וA,eRj'V^sua`Ma avW Ң|{v{o;8FN&>' qj-XhVVÕe^מ'&J.wPJt\}_]ƿ?yAj}\LQ,[΃~ssew?TI:|pC$yb9! p BB3S&EѓIL^1XY۽W5۹>;?ՓP=9ʺ{,q?m2s8Ұ(TƘ kA{؊ViSkH%dJ{Q|xo~<7^8u{[FAT'^XƔ>Td\"ABiM+GGSv[~cX+Ө $Q74H RZ;^5Vjڝ~Dk-)cJhFXy`!)%ׄlZ$RzaU+qlNowA+/ cew^t~uC!1qjkajE3K*U(D$Nj ڝA*Z4*(c ӤﻵZy=lX+S+WKB,Hn{vX^>EQtVn:]RV 5QPǃ^?;vv'vh`IJe[ Z-lzݭqD,-fIRI ͥg~I[xf1NhKaC;JN$xk~g~pw}?Xio WQy TdeS2om2͑gES.X4uG*PwT1h3%1gl?@7l$U΂GQIq?,K4pF;#ɡӄcec齏9 ) q/Z}'$quKQTxBݸk?):QX{rtq -#Q/&'(DDuaF~ň4hD)XPXkqT^{AG1[*d7iwOܺ-n~r F'~S#\|Yt[bŧ/*(p@$|4QT9R_✇ƥ^ʔ:Kdv4<2fL6؎F2tXc\L;=8)D:Uk :Ktg=&)45YǙVD$YalJaAgozDdhj.Օa׿s&ǐ6 QS!"@L/bX0" BDz00>Y3v_+st!i ̂?pTL,2$;"/͂š:؂ kA|B"+Qk'3MtSɽ0;Wz"̙U=i2AH}b-;ԃ=ḛ.Vں#7SQx$s5_mFغq5oW(<1 zy'bz$ͽ\PLpD17'- ,.ݾ~^89~?=cφ9۷ϯ TNITDs'D՗8CRiM7\~Pi5VzUKJ 6޼{WVkT"<; 4LoDͺ8"#HQ%b9Q5F$}釢EeR9/7~S 2C.Hx Ca:d=D%C'1Jo~4؜F,ܣq|KlF~a,>1#]q NY7j_#@x o}Ss,82kHMOIc1\H亻qcE=X/z?qcz?iiLu5:{gBM6;~~cU*m^5j>?ɧ͸4ElxJ9"I!S"Hũ7?`S^ji51q :bjriE-- +HJ4zDe4 xħ(' ;Ô7#b[gDrvl (m 6~qCk_ nÂsDpNrcbN&G)ƇVEIx|i.6oӿ[8HnwO}*\Y*8.YN?s~s xaD$ )W ťzw:Hm8l 8N欬kk⒩֔ ҳ#,uav➏q5I -MKbٛdȧ>^>^=al1\ ˒s L)D7Ȃ5O /Bdm_Sw1;ɯ; L .b+b|8+%˰(=?uq_y,3 +j/}׿q?x/W'3'ƵO~_=si}MyC]2 k.U9' 2Tx^Wfnvu8hNAĖI4[fuqjqIIʸ)B!x$h<#X-؝[C3]1{1r,|`rS6|vw;z@7Xb{U(lH1˿kMmPy^|I?'d.CR c8 )Dh0 j~׋$Z$6T+~X+yJkAsJ3qn#rsxTNTg0x7"sQarFgy0#1 )H {@zS% E侑ʺ~Y1TVw7c;IVrx2'n_]ZezbIss Bob?a.y(RY:Qz qGQ̔qXhhɈR t9I򱜵㮳NGxf>G'Aju,ffCa Y)-A:͟?Z/t $?yVLn έ)PAV-XmѬ;OmDvȊ_?ĐF%%TpD5`qKWG~[."0 R=M$Mlb-ĦYRL <'s<#bLcg \egd*feq|c йX>zc> &BYh.r_̺H iN\[oRӄX >j)ϥqNdH~c.GCE߹Ҟ4 Z*LyS(Wx5di9Z`l\oܾug{ J`Ý7b~ t/J!I Q5rQJR9 ǒz0g*"Bh. pZF$f"Ex?OHQoYXSTaa~G%KͲJzď[MKE`f@D!F}"]x? #_r@Rŋ_ճ>m硔spi#zm)|pTxdr _g2G2Q9o0cxqϣq`s2`;s6]~5X/\(?bLBH&y^^/e$0 ٬4n"CYHT0|%|I0$Be`ɺx|8Ά=RR> ,YSPL c^k5f?DDB(m i18#ٲO,w%Vw gF-* KNd2gxi< c,K9D^1WPfYZ9Id̼"aT^#wU\2eqtӾ+qnXpoĴxr?IX-~jS_ܝ{3Q)L9˜'G(wx<#B4M ef("sb Γ*8 |8YYFqs B{w &dG&'qq<3G>? 9{GSyss+GX>s8Ex%e?Ci#<ζ?0}|<>@x|<> xl(<>x||hz:IENDB`pyromaths/data/images/pyromaths.ico0000644000175000017500000020407611702101415020173 0ustar didrocksdidrocks ((     $"),-4092<2>2>2>3?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?3?2>2>2>2<09-3)+$  -8@.G@NQS^WfYjZlZmZm[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[n[nZmZmZlYjWeS\MOF>?,7,#>MY2bMkhqV\ddddeeeeeeeeeeeeeeeeeeeeeeeeeeddddb_NRwdIZ/PF / 0Pd1uOpi`vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvy tMmMr(fX*                                                  7Z0wKn jjo2;~P8z j  !& * , - - -".%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.&/13E;dNkf;C}^i$^ '/,68a)$ 1=(H;RO[acpizmoqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrv~uv}% o.3 CQ+^Dk_wyrkmooooooooooooooooooooooooooooooooooooooooooooooooooooryv , r0@Rb)pE~fpe n v{, t1 Mbp ~<`] |FNtuMMvv+ t1Il{-Q|[08}jjvsd+ t1s :dg>Fhivo4/* t1a#Fz k#{givk+0A<* t1z)Nrehvh/'4k&b* t1,Ts}cgveH%#&^&$) t1/W v#/I)((,bgva}%!}x9) t10Y y4@-(((*`fv]|r&zslfX( t10Z y4A,((()^evZ{/ib\Z( t10Z y3@7&''(~\evWzk_b\RK;s( t11Z y2@X$%&'n[dvSxmklST\98sAA' t11Z y1@##$%[YcvPw/6]qWEFM_zM 1e' t11Z y1?2!"#6|{VWbvMvHx06 1 7 ?H`T'O& t11Z y/?e !"LH.nVbvJuz3!) 0 9I{{{r &Ey{{{{{{{{{{{{{{{& t11Z y/?# ,/$KTavFt~`!+={rssss=Czsssssssssssssss% t11Z y.>M{~Y(wr{m:|R`vBr}vQ ""@jlkkkk+WSlkkkcT`kkkkkkkk% t11Z y->uwz}r(chci?,zP_v?q}vnbLYddddddd={addcH,Icdddddddd% t11Z y,=Fpsvy~R'DYTh!w!uxO_v;p}vnf_\\\\\\\\P\\\Q'@\\\\\\\\\\ $ t11Z y+=jloru(7'o(cJEtccuM^v8o~vog^WTTTTTUTTTTTL$fhknq@*&[N ; 7SSsL_v5nxph_WOMMMMMMMMMMM<"DMMMMMMMMM # s01Z y)'P,8GErM`v2muik]OK==>>====[.>>>>>>=> " p-1Z y(;8631.+((((((((((((((('~ /Hg$]L1Z y$:6_'Q!NLKIJMP6u(#""!!und]WW`fIz -CksLjkuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuux yD;3E: 1Z y#:Bd0T*Q%O MKIHIQ}&""! 3Y3wkIh2J.F.E.E.E-E-E+o `c_YVTTTTTTTTTTTTTTTTTSSSSSSQ=%V5$,! 1Z y"9Gd:W4U/S*P%NLJGH\'"!! M%@{xwvvvuuCc kzc[I@<06*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4'4&3&3&2'1%.#)" 1Z y!9vI`C[=X8V3S.Q)O"LJHH-!! ~TXKp r~Mv0F $  1Z y 9`rQcL_G\AYF*aKjtuuuuuuuuuuuuuuuCu|q; 1Z y6}zwsqqqqqqnZE1 la\YVSPMJHEB ? < : 7 4 17+^YpqqqqqqqqqqqqqAt|r< 1Z y6}yvrommmmmmmmmkf^TJ?4|(kWIC @ = : 7 5 2 /,*)!MUlmmmmmmmmmmm?s|s>W1Z y5|xuqnjiiiiiiiiiiiiiiihf`SC2sQ; 3 0-*'%"#1feiiiiiiiiii19-1''! 1Z y4{wsplhd`]]]]]]]]]]]]]]]]]]]]]]]]\B59y]]]]]]]]6p|whxat_r^q^q^p]oZkWdQXIIA88&." 1Z y4{wsokgd`\YYYYYYYYYYYYYYYYYYYYYYYYYT*cOYYYYYYY3o|yqtg\[BO*C7 1Z y3~ywtkjbb_ZUUUUOSGEUUUUUUUUUUUUUUUUUUUUB,LUUUUUUU1n|~}dpCd'UE1Z y3{||mzc^`U{VMvFnDqHE,QIKM/kLB5yQQQQQQQQQQQQQQQQQQQQQJEVAAAABA&i|9C sn@ *P u1|wrnid_[VSMJE@==;=<>=>>>=;<===>=>=>====>=:>>>==>#h|rD! h%H q '}w{odf`TSRDCC>:?;#m.\(x({5(x.-$m,"g b:9:9::::::9::T99::99]ytE" *| =h{Wz{k_\YRPRE~?yJJ-g6)u\'~J'|T/_25X'~LE6666666666666C666656>uuF"Ts 0Slzsnlgc^UTOJC@:0//,,2222,./,2222222222222222222-|%vckuF"Thv#fN l"|`|wrmid_ZUPKFA<72..............................Mdo}uF#'H Yh-D?^~ytoje`[VQLGB=83.****************************n#mq~uF#(: JL7N 7$Nr}zxvtrpmliheca_][XWTSPNLJHFCB?=;97521.-*(((((((((((((((((((((((((('\sfsuF#+81:H{Iu"##############################################################"["}n}uF#  $*'(v Y|pK[aruF# !E%k5{6}5~5~5~666666666666666679?KK Zjvr|q|q{o{o{o{m{mzmzlz^jQ\jyiyhyhxgxfxfxewdwcvcvbvavavavavauavauavavavavcxh~uF#     1Y&:` sdyuF#  I.hy^tuF#?(m}ruF#&o~tuF#&o~iZ}buF#&o~mHh$< ":`[zuF#&o~_;Z. ;[zylTsuF#&o~yjmvp_Lq7U7  #>>a]fTRs{uF#&o~scVKzBn:c3Y+N%D YCiqmieb^\WSQ3r9SSSSSSSSTSSSSDuF" "(& %o~ncx\plkF[AYWplhd`\YTN.l5|MNNNNNNNNNNNNN?tE"(+@7YAmFyFu@]66*$n~m_qZkulH[E]lnkfc_ZWJ-c7HIIIIIIIIIIIIII;sD! &'8JJrf7(UBy lbpV.D V#j~l\iitL[^rmjeb]VB0dCIEDDDDDDDDDDDDDD7pB (<0Wk"JPqg # ~ uGkR e~nfoZztqlhc]L>?>>?>>?>?>3i=  5VC]=} VzCSe{#Y|vhrsng[MDrIRPJFA>;9887678888777-yc<~ h   +!/" <<|®s{{zswz{{N \u! )+>A@yyxqf\}X{]`[TNIJLMG>868741.+*,021/,+, l`nlTQF17 -#9&@$;,  .:?]KxRsSGP6Kss_+Zr-_sstP _f$2&8JFpRH |r~_lYghxlZs`|t{jVxQubmaMw?fBlVe`P=t/_,]4p9~2v(c!X#c-2/&r_[q'+' vc\l 3 gUWVR^=3%-/C>aK}TXVNwBH2!:INr-]@ wbq_ !&AɽIz, !lllL bi3 d\=:v%Q x e0ZhIqJH0V*9TeKjEz=u8NSpIf=iE*EEiLs8`=v=y&FGzZK1`?|8r.>F*_<|9wB&s/)]%_=KZ "fU4tM>sj"I:v lSlNu t)U=zC9s, u iZ?H#&W !^7p]eU f }h<Y%=MdT beeH e GNde-^ X[opK_eeed-Y/>i|gOdeH&;;kWea71UMdeW7@oDyCbee5lAYeeI:%p+2xVeeBU*sPdeC3i]ee ! y/@`eeee`7 v_jLH)?^^^^)4k[^^^^^^^F jv!jY>QUWWW?| pGJ$0 T&DWWWL2fOWW>{ e9rWWW1c {jV--{'TWWP (TWWW:'SWWW4jRWWW &7WWWKTWWPH@~WWW;v}UWWW{BWWW#K)WWWW1eWWWK-\,6EHHH3e #'P' x kqEHHH !DHHH4h g)THHH?z ~j>Y5jHHH,Y {=vHH1a #IHHH8n =wHHH?GHHA| %HHHC GHHH2c xhwLBHHH oC8oHHH4hGHHH+ #r%MEIHH;s Hf:4+ K/>uA{A{A{8lw#Iq[YVPS=] '6g:m:n:m:m:m:m:n:n8j/4d:n:m:m "F:m:m:m+U m@:m:n:m:m8 oU>)Q:n:m:m'N w(P:m:n+V =:n:n:m:m)R:n:m:m*S8k:m:n4d4d:m:n:m2 %K:m:m:m'O b@4d:m:m:m t@-X:m:m:m9k2`:m:m:m* (P:m:n:n1_ z, B yn u'a] !.X3_3_3_3_3_3_3_3_3_1]1]3_3_3_ 33_3_3_'M s53_3_3_2^+S u\q93_3_3_'M {!C3_3_$H 73_3_3_/Z&#G3_3_3_/Z1]3_3_-W s%J3_3_3_@ 23_3_3_#F ~k lO,U3_3_3_ y\g&J3_3_3_1\&)P3_3_3_(3_3_3_3_ 2.X3_2^ q x&i] 'J,Q,Q,Q)M)L,Q,Q,Q,Q,Q,Q,Q,Q,Q $,Q,Q,Q$F z,,Q,Q,Q>,Q. } l ,Q,Q,Q)M x9,Q,Q8 p2,Q,Q,Q>3;,Q,Q+Q!A "*O,Q,Q%H |b5,Q,Q,Q'J !,Q,Q,Q> v ft$F,Q,Q,Q { i<,Q,Q,Q!A3#D,Q,Q,Q " ,Q,Q,Q)M<,Q,Q*O lY`G\  =%C%C%C97%C%C%C%C%C%C%C%C ! %C$C%C"?  rq$%C%C%C)%C$B${ >%C%C%C  }8%C$B PT-%C%C%C,;2%C%C$B,-$B%C%C8 reH f#A%C%C%C  %C%C%C5 w1"?%C%C%C.. 1%C%C%C. =!>%C%C$C %C%C%C$C3%C%C7]sE25 &o0555/ ,5555555%5555MJ555 .554 &555/'52 =E0#'555%,455/3555%JV<$X+55520555/ c(5555554'555 35551 j jc2555144+vw(,%S&#'''$ u'''&'&"''# DA! ''%  '$ 7<o'''$!s\!  ¼''%  '% ~u WI%'$ SM  ~''% '&!  ri&'''''' i{''' '&"(/"'''$ v5- ? zf    j3* b rB/    lJ?r d3  p  v U9     nM Q"T m2 \^ Y.  "   lJFlxBr" `d  y^J g;'  >  }M8> r;            }FB( W     HPF(      t^_'R   ==&   `N3 jXEM) - u{*. r C |3# . JN)} 5 l  <5    y^$$    ????????????????????????????????????????????????????????????????????????????????????8< ??qa papqCpq?pq 1p<1 1'qF<1 31>b>ws>?pyromaths/data/linux/0000755000175000017500000000000011734627251015352 5ustar didrocksdidrockspyromaths/data/linux/._pyromaths.10000644000175000017500000000031511702101415017656 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/linux/._pyromaths.desktop0000644000175000017500000000031511702412057021176 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/data/linux/pyromaths.10000644000175000017500000000356611702101415017454 0ustar didrocksdidrocks.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH PYROMATHS 1 "November 03, 2010" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME pyromaths \- Exerciseur de mathmatiques crant des fiches LaTeX .SH SYNOPSIS .B pyromaths .br .SH DESCRIPTION This manual page documents briefly the .B pyromaths command. This manual page was written for the Debian GNU/Linux distribution because the original program does not have a manual page. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBpyromaths\fP est un programme qui a pour but de crer des exercices type de mathmatiques niveau collge et lyce ainsi que leur corrig. C'est ce qu'on appelle parfois un exerciseur. Contrairement de nombreux autres projets, \fBPyromaths\fP a pour objectif de proposer une correction vritablement dtaille des exercices proposs et pas seulement une solution. .br Il permet par exemple de proposer des devoirs maison aux lves et de leur distribuer ensuite la correction. Il peut aussi servir des familles afin qu'un lve puisse travailler un point du programme et se corriger ensuite. .SH AUTHOR This manual page was written by Jrme Ortais , for the Debian GNU/Linux system (but may be used by others). pyromaths/data/linux/pyromaths.desktop0000644000175000017500000000043711702412057020766 0ustar didrocksdidrocks[Desktop Entry] Icon=/usr/share/pixmaps/pyromaths.png Version=1.0 Name=Pyromaths Comment=Generator for math worksheets for french college Comment[fr]=Générateur d'exercices de maths Exec=/usr/bin/pyromaths Terminal=false Type=Application Categories=GNOME;Education; StartupNotify=true pyromaths/data/._linux0000755000175000017500000000031511702412057015503 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/._pyromaths0000755000175000017500000000031511702101415015452 0ustar didrocksdidrocksMac OS X  2ATTRGh55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/README0000644000175000017500000000113111702101415014136 0ustar didrocksdidrocksPyromaths est un programme qui a pour but de créer des exercices type de mathématiques niveau collège et lycée ainsi que leur corrigé. C'est ce qu'on appelle parfois un exerciseur. Contrairement à de nombreux autres projets, Pyromaths a pour objectif de proposer une correction véritablement détaillée des exercices proposés et pas seulement une solution. Il permet par exemple de proposer des devoirs maison aux élèves et de leur distribuer ensuite la correction. Il peut aussi servir à des familles afin qu'un élève puisse travailler un point du programme et se corriger ensuite. pyromaths/._setup.cfg0000644000175000017500000000031511702101415015317 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/pyromaths0000755000175000017500000000051711702101415015241 0ustar didrocksdidrocks#!/usr/bin/env python import sys from os.path import dirname, join, realpath from os import chdir try: from pyromaths import pyromaths except ImportError: basedir = dirname(realpath(__file__)) workdir = join(basedir,'src') sys.path.insert(0, basedir) from src import pyromaths chdir(workdir) pyromaths.main() pyromaths/src/0000755000175000017500000000000011702412270014055 5ustar didrocksdidrockspyromaths/src/quatriemes/0000755000175000017500000000000011734627250016247 5ustar didrocksdidrockspyromaths/src/quatriemes/puissances.py0000644000175000017500000003660011702101415020764 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils.Arithmetique import pgcd, valeur_alea from ..outils.Affichage import decimaux, tex_coef from random import choice, randrange import string def tex_proprietes_val(exp_max, nb_max, type): """ Renvoie des valeurs pour l'exercice sur les propriétés des puissances @param exp_max: valeur maximale pour les exposants @type exp_max: Integer @param nb_max: Valeur maximale pour les nombres @type nb_max: integer @param type: 0 : 2 exposants et 1 nombre ; 1 : 1 exposant et 2 nombres @type type: integer """ if type: while 1: nb1 = randrange(2, nb_max) nb2 = randrange(2, nb_max) exp1 = randrange(2, exp_max) exp2 = exp1 if nb1 != nb2: break else: while 1: nb1 = randrange(2, nb_max) nb2 = nb1 exp1 = randrange(2, exp_max) exp2 = randrange(2, exp_max) if exp1 != exp2: break return (nb1, exp1, nb2, exp2) def tex_proprietes(): exo = ["\\exercice", u"Compléter par un nombre de la forme $a^n$ avec $a$ et $n$ entiers :", "\\begin{multicols}{4}", " \\noindent%", " \\begin{enumerate}"] cor = ["\\exercice*", u"Compléter par un nombre de la forme $a^n$ avec $a$ et $n$ entiers :", "\\begin{multicols}{4}", " \\noindent%", " \\begin{enumerate}"] lexos = [0, 1, 2, 3, 0, 1, 2, 3] #0: a^n*a^p ; 1: (a^n)^p ; 2:a^n/a^p ; 3: a^n*b^n for i in range(len(lexos)): j = lexos.pop(randrange(len(lexos))) if j == 3: lval = tex_proprietes_val(12, 12, 1) exo.append("\\item $%s^{%s} \\times %s^{%s} = \\dotfill$" % lval) cor.append("\\item $%s^{%s}\\times%s^{%s}=" % lval) cor.append("%s^{%s}$" % (lval[0] * lval[2], lval[1])) else: lval = tex_proprietes_val(12, 12, 0) if j == 0: exo.append("\\item $%s^{%s}\\times%s^{%s}=\\dotfill$" % lval) cor.append("\\item $%s^{%s}\\times%s^{%s}=" % lval) cor.append("%s^{%s}$" % (lval[0], lval[1] + lval[3])) elif j == 1: exo.append("\\item $(%s^{%s})^{%s}=\\dotfill$" % (lval[0], lval[1], lval[3])) cor.append("\\item $(%s^{%s})^{%s}=" % (lval[0], lval[1], lval[3])) cor.append("%s^{%s}$" % (lval[0], lval[1] * lval[3])) elif j == 2: while lval[1] - lval[3] < 3: lval = tex_proprietes_val(12, 12, 0) exo.append("\\item $\\dfrac{%s^{%s}}{%s^{%s}}=\\dotfill$" % lval) cor.append("\\item $\\dfrac{%s^{%s}}{%s^{%s}}=" % lval) cor.append("%s^{%s}$" % (lval[0], lval[1] - lval[3])) exo.append("\\end{enumerate}") exo.append("\\end{multicols}\n") cor.append("\\end{enumerate}") cor.append("\\end{multicols}\n") return (exo, cor) # ----PROPRIETES AVEC 10 def tex_proprietes_neg_val(exp_max, nb_max, type): """ Renvoie des valeurs pour l'exercice sur les propriétés des puissances @param exp_max: valeur maximale pour les exposants @type exp_max: Integer @param nb_max: Valeur maximale pour les nombres @type nb_max: integer @param type: 0 : 2 exposants et 1 nombre ; 1 : 1 exposant et 2 nombres @type type: integer """ if type: while 1: nb1 = randrange(2, nb_max) nb2 = randrange(2, nb_max) exp1 = randrange(2, exp_max) exp2 = exp1 if nb1 != nb2: break else: while 1: nb1 = randrange(2, nb_max) nb2 = nb1 exp1 = randrange(2, exp_max) exp2 = randrange(2, exp_max) if exp1 != exp2: break return (nb1, exp1, nb2, exp2) def tex_proprietes_neg(): exo = ["\\exercice", u"Écrire sous la forme d'une puissance de 10 puis donner l'écriture", u" décimale de ces nombres :", "\\begin{multicols}{2}", " \\noindent%", " \\begin{enumerate}"] cor = ["\\exercice*", u"Écrire sous la forme d'une puissance de 10 puis donner l'écriture", u" décimale de ces nombres :", "\\begin{multicols}{2}", " \\noindent%", " \\begin{enumerate}"] lexos = [0, 1, 2, 3, 0, 1, 2, 3] #0: a^n*a^p ; 1: (a^n)^p ; 2:a^n/a^p for i in range(len(lexos)): lexp = [randrange(-6, 6) for i in range(2)] j = lexos.pop(randrange(len(lexos))) # FIXME : À finir if j == 0: while abs(lexp[0] + lexp[1]) > 10: lexp = [randrange(-6, 6) for i in range(2)] exo.append("\\item $10^{%s} \\times 10^{%s} = \\dotfill$" % tuple(lexp)) cor.append("\\item $10^{%s}\\times 10^{%s}=" % tuple(lexp)) cor.append("10^{%s+%s}=" % (lexp[0], tex_coef(lexp[1], '', bpn=1))) cor.append("10^{%s}=%s$" % (lexp[0] + lexp[1], decimaux(10 ** (lexp[0] + lexp[1]), 1))) elif j == 1: while abs(lexp[0] * lexp[1]) > 10: lexp = [randrange(-6, 6) for i in range(2)] exo.append("\\item $(10^{%s})^{%s}=\\dotfill$" % (lexp[0], lexp[1])) cor.append("\\item $(10^{%s})^{%s}=" % tuple(lexp)) cor.append("10^{%s \\times %s}=" % (lexp[0], tex_coef(lexp[1], '', bpn=1))) cor.append("10^{%s}=%s$" % (lexp[0] * lexp[1], decimaux(10 ** (lexp[0] * lexp[1]), 1))) elif j == 2: while abs(lexp[0] - lexp[1]) > 10: lexp = [randrange(-6, 6) for i in range(2)] exo.append("\\item $\\dfrac{10^{%s}}{10^{%s}}=\\dotfill$" % tuple(lexp)) cor.append("\\item $\\dfrac{10^{%s}}{10^{%s}}=" % tuple(lexp)) cor.append("10^{%s-%s}=" % (lexp[0], tex_coef(lexp[1], '', bpn=1))) cor.append("10^{%s}=%s$" % (lexp[0] - lexp[1], decimaux(10 ** (lexp[0] - lexp[1]), 1))) exo.append("\\end{enumerate}") exo.append("\\end{multicols}\n") cor.append("\\end{enumerate}") cor.append("\\end{multicols}\n") return (exo, cor) #------------------------------------------------------------------------------ # Écritures scientifiques #------------------------------------------------------------------------------ def val_sc(): while True: a = randrange(10) * 1000 + randrange(10) + randrange(10) * 10 ** \ (randrange(2) + 1) a = a * 10 ** randrange(-9, 6) #a=randrange(1,9999)*10**randrange(-9,6) if a >= 10 or (a < 1 and a >0) : break return a def ecr_sc(): from math import log10, floor exo = ["\\exercice", u"Compléter par le nombre qui convient :", "\\begin{multicols}{3}", " \\noindent%", " \\begin{enumerate}"] cor = ["\\exercice*", u"Compléter par le nombre qui convient :", "\\begin{multicols}{3}", " \\noindent%", " \\begin{enumerate}"] for i in range(6): a = val_sc() exp = int(floor(log10(a))) a_sc = (a * 1.) / 10 ** exp s_a = decimaux(a, 1) s_a_sc = decimaux(a_sc, 1) if randrange(2): # forme : a=a_sc*... exo.append("\\item $%s=%s\\times\\dotfill$" % (s_a, s_a_sc)) cor.append("\\item $%s=%s\\times\\mathbf{10^{%s}}$" % (s_a, s_a_sc, decimaux(exp, 1))) else: # forme : a_sc*...=a exo.append("\\item $%s\\times\\dotfill=%s$" % (s_a_sc, s_a)) cor.append("\\item $%s\\times\\mathbf{10^{%s}}=%s$" % (s_a_sc, decimaux(exp, 1), s_a)) exo.append("\\end{enumerate}") exo.append("\\end{multicols}\n") cor.append("\\end{enumerate}") cor.append("\\end{multicols}\n") return (exo, cor) # ------------------- PUISSANCES de 10 ------------------- def exo_puissances(): from math import floor, log10 sd = string.maketrans('.', ',') # convertit les . en , (separateur decimal) exo = ["\\exercice", u"Calculer les expressions suivantes et donner l'écriture scientifique du résultat.", "\\begin{multicols}{2}", " \\noindent%"] cor = ["\\exercice*", u"Calculer les expressions suivantes et donner l'écriture scientifique du résultat.", "\\begin{multicols}{2}", " \\noindent%"] valeurs = valeurs_puissances() i = randrange(2) exo.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_0(valeurs[i]).translate(sd)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_0(valeurs[i]).translate(sd)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_1(valeurs[i]).translate(sd)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_2(valeurs[i]).translate(sd)) if int(floor(log10(((valeurs[i][0] * valeurs[i][1]) * 1.) / valeurs[i][2]))) != \ 0: cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_3(valeurs[i]).translate(sd)) cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % tex_puissances_4(valeurs[i]).translate(sd)) exo.append("\\columnbreak\\stepcounter{nocalcul}%") cor.append("\\columnbreak\\stepcounter{nocalcul}%") exo.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_0(valeurs[1 - i]).translate(sd)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_0(valeurs[1 - i]).translate(sd)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_1(valeurs[1 - i]).translate(sd)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_2(valeurs[1 - i]).translate(sd)) if int(floor(log10(((valeurs[1 - i][0] * valeurs[1 - i][1]) * 1.) / valeurs[1 - i][2]))) != 0: cor.append("\\[ \\thenocalcul = %s \\]" % tex_puissances_3(valeurs[1 - i]).translate(sd)) cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % tex_puissances_4(valeurs[1 - i]).translate(sd)) exo.append("\\end{multicols}\n") cor.append("\\end{multicols}\n") return (exo, cor) def tex_puissances_0(a): if isinstance(a, tuple): return '\\cfrac{\\nombre{%s} \\times 10^{%s} \\times \\nombre{%s} \\times 10^{%s}}{\\nombre{%s} \\times \\big( 10^{%s} \\big) ^%s}' % \ (a[0], a[3], a[1], a[4], a[2], a[5], a[6]) def tex_puissances_1(a): if isinstance(a, tuple): if a[4] < 0: return '\\cfrac{\\nombre{%s} \\times \\nombre{%s}}{\\nombre{%s}} \\times \\cfrac{10^{%s+(%s)}}{10^{%s \\times %s}}' % \ (a[0], a[1], a[2], a[3], a[4], a[5], a[6]) else: return '\\cfrac{\\nombre{%s} \\times \\nombre{%s}}{\\nombre{%s}} \\times \\cfrac{10^{%s+%s}}{10^{%s \\times %s}}' % \ (a[0], a[1], a[2], a[3], a[4], a[5], a[6]) def tex_puissances_2(a): if isinstance(a, tuple): if ((a[0] * a[1]) * 1.) / a[2] == (a[0] * a[1]) / a[2]: if a[5] * a[6] < 0: return '\\nombre{%s} \\times 10^{%s-(%s)}' % \ verifie_type(((a[0] * a[1]) / a[2], a[3] + a[4], a[5] * a[6])) else: return '\\nombre{%s} \\times 10^{%s-%s}' % verifie_type(((a[0] * a[1]) / a[2], a[3] + a[4], a[5] * a[6])) else: if a[5] * a[6] < 0: return '\\nombre{%s} \\times 10^{%s-(%s)}' % \ verifie_type((((a[0] * a[1]) * 1.) / a[2], a[3] + a[4], a[5] * a[6])) else: return '\\nombre{%s} \\times 10^{%s-%s}' % verifie_type((((a[0] * a[1]) * 1.) / a[2], a[3] + a[4], a[5] * a[6])) def tex_puissances_3(a): from math import floor, log10 b = int(floor(log10(((a[0] * a[1]) * 1.) / a[2]))) if isinstance(a, tuple) and b != 0: return '\\nombre{%s} \\times 10^{%s} \\times 10^{%s}' % \ verifie_type(((((a[0] * a[1]) * 1.) / a[2]) / 10 ** b, b, (a[3] + a[4]) - a[5] * a[6])) def tex_puissances_4(a): from math import floor, log10 b = int(floor(log10(((a[0] * a[1]) * 1.) / a[2]))) if isinstance(a, tuple): return '\\nombre{%s} \\times 10^{%s}' % verifie_type(((((a[0] * a[1]) * 1.) / a[2]) / 10 ** b, (b + a[3] + a[4]) - a[5] * a[6])) def verifie_type(a): # verifie si des nombres reels dans le tuple a sont en fait des nombres entiers et change leur type list = [] for i in range(len(a)): if str(a[i]).endswith('.0'): list.append(int(a[i] + .1)) else: list.append(a[i]) return tuple(list) def valeurs_puissances(): # renvoie un tuple contenant les valeurs pour les deux exercices sur les puissances from math import floor, log10 (max, emax) = (10, 2) while True: (b1, b2) = (valeur_alea(2, max), valeur_alea(2, max)) (b1, b2) = (b1 / pgcd(b1, b2), b2 / pgcd(b1, b2)) if b1 != 1 and b2 != 1: break while True: (n1, n2) = ((b1 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax), (b2 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax)) n3 = ((b1 * b2) * choice((2, 4, 5, 8))) * 10 ** randrange(-emax, emax) if int(floor(log10(((n1 * n2) * 1.) / n3))) != 0 and n1 != 1 and \ n2 != 1 and n3 != 1: break (e1, e2, e3, e4) = (valeur_alea(-10, 10), valeur_alea(-10, 10), valeur_alea(2, 10), valeur_alea(2, 5)) a = verifie_type((n1, n2, n3, e1, e2, e3, e4)) while True: (b1, b2) = (valeur_alea(2, max), valeur_alea(2, max)) (b1, b2) = (b1 / pgcd(b1, b2), b2 / pgcd(b1, b2)) if b1 != 1 and b2 != 1: break (n1, n2) = ((b1 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax + 1), (b2 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax + 1)) n3 = ((b1 * b2) * choice((1, 2, 4, 5, 8))) * 10 ** randrange(-emax, emax + 1) (e1, e2, e3, e4) = (valeur_alea(-10, 10), valeur_alea(-10, 10), valeur_alea(-10, -2), valeur_alea(2, 5)) b = verifie_type((n1, n2, n3, e1, e2, e3, e4)) return (a, b) pyromaths/src/quatriemes/litteral.py0000644000175000017500000001236711702101415020433 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #---------------------------------------------------------------------- # Pyromaths : Initiation au calcul littéral #---------------------------------------------------------------------- from ..outils import Arithmetique from ..outils.Affichage import tex_coef from ..outils.Priorites3 import texify, priorites import random def valeurs_reduire(): """Travail sur les bases du calcul littéral en quatrième""" var = "abcdfghkmnpqrstuvwxyz" var = var[random.randrange(len(var))] op = "+*-*"[random.randrange(4)] if op == "*": deg1 = random.randrange(3) if deg1 == 2: deg2=0 elif deg1 == 1: deg2 = random.randrange(2) else: deg2 = random.randrange(1, 3) else: deg1 = random.randrange(1, 3) deg2 = [i for i in range(3)] deg2.extend([deg1]*7) random.shuffle(deg2) deg2 = deg2.pop(random.randrange(len(deg2))) a1, a2 = 0, 0 while not a1 or not a2: a1 = random.randrange(-10, 11) a2 = random.randrange(-10, 11) p1 = "Polynome(\"%s%s^%s\")" % (a1, var, deg1) p2 = "Polynome(\"%s%s^%s\")" % (a2, var, deg2) return p1 + op + p2 def reduire(): """Travail sur les bases du calcul littéral en quatrième""" exo = ["\\exercice", u"Réduire, si possible, les expressions suivantes :", "\\begin{multicols}{3}\\noindent", " \\begin{enumerate}"] cor = ["\\exercice*", u"Réduire, si possible, les expressions suivantes :", "\\begin{multicols}{3}\\noindent", " \\begin{enumerate}"] for i in range(9): a = valeurs_reduire() solve = [a] exo.append("\\item $\\thenocalcul = " + texify(solve)[0] + "$") cor.append("\\item $\\thenocalcul = " + texify(solve)[0] + "$") solve = priorites(a) solve.insert(0, a) solve = texify(solve) if len(solve)>1: for e in solve[1:]: cor.append("\\[\\thenocalcul = " + e + "\\]") exo.append("\\stepcounter{nocalcul}") cor.append("\\stepcounter{nocalcul}") exo.extend([" \\end{enumerate}", "\\end{multicols}"]) cor.extend([" \\end{enumerate}", "\\end{multicols}"]) return (exo, cor) def valeurs_reduire_somme(): """Réduire une somme de six monômes de degrés 0, 1 et 2""" import random var = "abcdfghkmnpqrstuvwxyz" var = var[random.randrange(len(var))] l=[] for i in range(6): a = 0 degre = i//2 while not a: a = random.randrange(-10, 11) l.append("Polynome(\"%s%s^%s\")" % (a, var, degre)) random.shuffle(l) t = l[0] for i in range(1, len(l)): t += "+-"[random.randrange(2)] + l[i] return t def valeurs_reduire_sommeprod(): """Réduire une expression de six monômes de degrés 0, 1 et 2""" import random var = "abcdfghkmnpqrstuvwxyz" var = var[random.randrange(len(var))] l=[] for i in range(5): a = 0 degre = i//2 while not a: a = random.randrange(-10, 11) l.append("Polynome(\"%s%s^%s\")" % (a, var, degre)) random.shuffle(l) t = l[0] for i in range(1, len(l)): if l[i-1][-3] in "01" and l[i][-3] in "01": t += "*" + l[i] else: t += "+-"[random.randrange(2)] + l[i] return t def reduire_expressions(): """Travail sur les bases du calcul littéral en quatrième""" exo = ["\\exercice", u"Réduire les expressions littérales suivantes :", "\\begin{multicols}{2}\\noindent", " \\begin{enumerate}"] cor = ["\\exercice*", u"Réduire les expressions littérales suivantes :", "\\begin{multicols}{2}\\noindent", " \\begin{enumerate}"] for i in range(6): if i < 3: a = valeurs_reduire_somme() else: a = valeurs_reduire_sommeprod() solve = [a] exo.append("\\item $\\thenocalcul = " + texify(solve)[0] + "$") cor.append("\\item $\\thenocalcul = " + texify(solve)[0] + "$") solve = priorites(a) solve.insert(0, a) solve = texify(solve) if len(solve)>1: for e in solve[1:]: cor.append("\\[\\thenocalcul = " + e + "\\]") exo.append("\\stepcounter{nocalcul}") cor.append("\\stepcounter{nocalcul}") exo.extend([" \\end{enumerate}", "\\end{multicols}"]) cor.extend([" \\end{enumerate}", "\\end{multicols}"]) return (exo, cor) pyromaths/src/quatriemes/._litteral.py0000644000175000017500000000031511702101415020636 0ustar didrocksdidrocksMac OS X  2ATTRGޚ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/calcul_mental.py0000644000175000017500000000705611702101415021415 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #---------------------------------------------------------------------- # Pyromaths : Poser des opérations #---------------------------------------------------------------------- from ..outils import Arithmetique from ..outils.Affichage import tex_coef import random def choix_trou(nb1, nb2, tot, operateur, exo, cor): nbaleatoire = random.randrange(4) if nbaleatoire > 1: exo.append("\\item $%s %s %s = \\ldots\\ldots$" % (nb1, operateur, nb2)) cor.append("\\item $%s %s %s = \\mathbf{%s}$" % (nb1, operateur, nb2, tot)) elif nbaleatoire > 0: exo.append("\\item $%s %s \\ldots\\ldots = %s$" % (nb1, operateur, tot)) cor.append("\\item $%s %s \\mathbf{%s} = %s$" % (nb1, operateur, nb2, tot)) else: exo.append("\\item $\\ldots\\ldots %s %s = %s$" % (operateur, nb2, tot)) cor.append("\\item $\\mathbf{%s} %s %s = %s$" % (nb1, operateur, nb2, tot)) def plus(pyromax): (a, b) = (Arithmetique.valeur_alea(-pyromax, pyromax), Arithmetique.valeur_alea(-pyromax, pyromax)) return (a, b) def moins(pyromax): (a, b) = (Arithmetique.valeur_alea(-pyromax, pyromax), Arithmetique.valeur_alea(-pyromax, pyromax)) return (a + b, a) def div(pyromax): (a, b) = (Arithmetique.valeur_alea(-pyromax, pyromax), Arithmetique.valeur_alea(-pyromax, pyromax)) return (a * b, a) def main(): exo = ["\\exercice", "Effectuer sans calculatrice :", "\\begin{multicols}{3}\\noindent", " \\begin{enumerate}"] cor = ["\\exercice", "Effectuer sans calculatrice :", "\\begin{multicols}{3}\\noindent", " \\begin{enumerate}"] modules = (plus, moins, plus, div) calculs = [i for i in range(20)] for i in range(20): j = random.randrange(0, len(calculs)) (a, b) = modules[calculs[j] // 5](10) if calculs[j] // 5 == 0: choix_trou(a, tex_coef(b, '', bpn=1), a + b, '+', exo, cor) if calculs[j] // 5 == 1: choix_trou(a, tex_coef(b, '', bpn=1), a - b, '-', exo, cor) if calculs[j] // 5 == 2: choix_trou(a, tex_coef(b, '', bpn=1), a * b, '\\times', exo, cor) if calculs[j] // 5 == 3: choix_trou(a, tex_coef(b, '', bpn=1), a // b, '\\div', exo, cor) calculs.pop(j) exo.extend([" \\end{enumerate}", "\\end{multicols}"]) cor.extend([" \\end{enumerate}", "\\end{multicols}"]) return (exo, cor) pyromaths/src/quatriemes/.___init__.py0000644000175000017500000000031511702101415020555 0ustar didrocksdidrocksMac OS X  2ATTRGޕ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/developpements.py0000644000175000017500000005502411702101415021642 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils.Arithmetique import ecrit_tex, valeur_alea, signe from random import randrange # # ------------------- DEVELOPPEMENTS ------------------- def exo_distributivite(): exo = ["\\exercice", u"Développer et réduire les expressions suivantes :", "\\begin{multicols}{2}", " \\noindent%"] cor = ["\\exercice*", u"Développer et réduire les expressions suivantes :", "\\begin{multicols}{2}", " \\noindent%"] for i in range(8): (l1, l2) = tex_developpe1(valeurs_distr(10)) exo.extend(l1) cor.extend(l2) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\\end{multicols}\n") cor.append("\\end{multicols}\n") return (exo, cor) def exo_double_distributivite(): exo = ["\\exercice", u"Développer et réduire les expressions suivantes :", "\\begin{multicols}{2}", " \\noindent%"] cor = ["\\exercice*", u"Développer et réduire les expressions suivantes :", "\\begin{multicols}{2}", " \\noindent%"] for i in range(6): (l1, l2) = tex_developpe1(valeurs_dbldistr(10)) exo.extend(l1) cor.extend(l2) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\\end{multicols}\n") cor.append("\\end{multicols}\n") return (exo, cor) def coef_opposes(a): # renvoie un tuple dont les valeurs sont les opposees de celles de a l = [] for i in range(len(a)): l.append(-a[i]) return tuple(l) def dev(a): # renvoi un tuple avec les 3 coefficients du developpement return (a[0][0] * a[1][0], a[0][0] * a[1][1] + a[0][1] * a[1][0], a[0][1] * a[1][1]) def somme_polynomes(a, b): # renvoie un tuple dont les valeurs sont les sommes des valeurs correspondantes dans a et b l = [] if len(a) > len(b): long = len(a) else: long = len(b) for i in range(int): if (len(a) - i) - 1 < 0: l.append(b[(len(b) - 1) - i]) elif (len(b) - i) - 1 < 0: l.append(a[(len(a) - 1) - i]) else: l.append(a[(len(a) - 1) - i] + b[(len(b) - 1) - i]) l.reverse() return tuple(l) def tex_coef(coef, var, bplus=0, bpn=0, bpc=0): # coef est le coefficient à écrire devant la variable var # bplus est un booleen : s'il est vrai, il faut ecrire le signe + # bpn est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef est negatif. # bpc est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef =! 0 ou 1 et var est non vide if coef != 0 and abs(coef) != 1: if var == '': if abs(coef) >= 1000: a = '\\nombre{%s}' % coef else: a = '%s' % coef else: if abs(coef) >= 1000: a = '\\nombre{%s}\\,%s' % (coef, var) else: a = '%s\\,%s' % (coef, var) if bplus and coef > 0: a = '+' + a elif coef == 1: if var == '': a = '1' else: a = '%s' % var if bplus: a = '+' + a elif coef == 0: a = '' elif coef == -1: if var == '': a = '-1' else: a = '-%s' % var if bpn and coef < 0 or bpc and coef != 0 and coef != 1 and var != '': a = '\\left( ' + a + '\\right)' return a def tex_dev0(a, bplus=0): # renvoi (a+b)², (a-b)² ou (a+b)(c+d) ou a(c+d) ou (a+b)*c # a est de la forme ((3, 2), (3, 2)) pour (3x+2)(3x+2) (ca, cb, cc, cd) = (a[0][0], a[0][1], a[1][0], a[1][1]) # coefficients a, b, c et d if ca == 0 and cb == 0 or cc == 0 and cd == 0: return '0' elif a[0] == a[1]: # (a+b)² ou (a-b)² if ca == 0: return '%s^2' % tex_coef(cb, '', bpn=1) elif cb == 0: return '%s^2' % tex_coef(ca, 'x', bpc=1) else: return '(%s%s)^2' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=1)) else: # (a+b)(c+d) if ca == 0 or cb == 0: if cc == 0 or cd == 0: return '%s%s\\times %s%s' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=ca != 0), tex_coef(cc, 'x', bpn=1), tex_coef(cd, '', bplus=cc != 0, bpn=1)) else: return '%s%s\\,(%s%s)' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=ca != 0), tex_coef(cc, 'x'), tex_coef(cd, '', bplus=cc != 0)) elif cc == 0 or cd == 0: if cc == 0 and cd == 1: return '%s%s' % (tex_coef(ca, 'x', bplus=bplus), tex_coef(cb, '', bplus=ca != 0)) else: return '(%s%s)\\times %s%s' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=ca != 0), tex_coef(cc, 'x', bpn=1), tex_coef(cd, '', bplus=cc != 0, bpn= 1)) else: return '(%s%s)\\,(%s%s)' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=1), tex_coef(cc, 'x'), tex_coef(cd, '', bplus=1)) def tex_dev1(a, bplus=0, bpar=0, bpn=0): # renvoi le developpement (a)²+2*a*b+(b)², (a)²-2*a*b+(b)², (a)²-(b)² ou a*c+a*d+b*c+b*d # a est de la forme ((3, 2)(3, 2)) pour (3x+2)(3x+2) (ca, cb, cc, cd) = (a[0][0], a[0][1], a[1][0], a[1][1]) # coefficients a, b, c et d if a[0] == a[1]: # (a+b)² ou (a-b)² if signe(ca) == signe(cb): # (a+b)² (ca, cb) = (abs(ca), abs(cb)) texte = '%s^2+2\\times %s\\times %s+%s^2' % (tex_coef(ca, 'x', bpc=1), tex_coef(ca, 'x', bpn=1), tex_coef(cb, '', bpn=1), tex_coef(cb, '', bpn=1, bpc=1)) if bpar: return '(' + texte + ')' else: return texte else: # (a-b)² (ca, cb) = (abs(ca), abs(cb)) texte = '%s^2-2\\times %s\\times %s+%s^2' % (tex_coef(ca, 'x', bpc=1), tex_coef(ca, 'x', bpn=1), tex_coef(cb, '', bpn=1), tex_coef(cb, '', bpn=1, bpc=1)) if bpar: return '(' + texte + ')' else: return texte if abs(ca) == abs(cc) and abs(cb) == abs(cd): # (a+b)(a-b) ou (a+b)(-a+b) if ca == cc: # (a+b)(a-b) texte = '%s^2-%s^2' % (tex_coef(ca, 'x', bpc=1), tex_coef(abs(cb), '')) if bpar: return '(' + texte + ')' else: return texte else: # (a+b)(-a+b) texte = '%s^2-%s^2' % (tex_coef(cb, '', bpn=1), tex_coef(abs(ca), 'x', bpc=1)) if bpar: return '(' + texte + ')' else: return texte else: # (a+b)(c+d) if cc == 0 and cd == 1: texte = '%s%s' % (tex_coef(ca, 'x', bplus=bplus), tex_coef(cb, '', bplus=ca != 0)) if bpar: return '(' + texte + ')' else: return texte elif ca == 0 or cb == 0 or cc == 0 or cd == 0: if ca == 0: texte = '%s\\times %s+%s\\times %s' % (tex_coef(cb, '', bpn=bpn), tex_coef(cc, 'x', bpn=1), tex_coef(cb, '', bpn=1), tex_coef(cd, '', bpn=1)) elif cb == 0: texte = '%s\\times %s+%s\\times %s' % (tex_coef(ca, 'x', bpn=bpn), tex_coef(cc, 'x', bpn=1), tex_coef(ca, 'x', bpn=1), tex_coef(cd, '', bpn=1)) elif cc == 0: texte = '%s\\times %s+%s\\times %s' % (tex_coef(cd, '', bpn=bpn), tex_coef(ca, 'x', bpn=1), tex_coef(cd, '', bpn=1), tex_coef(cb, '', bpn=1)) else: texte = '%s\\times %s+%s\\times %s' % (tex_coef(cc, 'x', bpn=bpn), tex_coef(ca, 'x', bpn=1), tex_coef(cc, 'x', bpn=1), tex_coef(cb, '', bpn=1)) return texte else: texte = '%s+%s+%s+%s' % (tex_coef(ca * cc, 'x^2', bpn=bpn), tex_coef(ca * cd, 'x', bpn=1), tex_coef(cb * cc, 'x', bpn=1), tex_coef(cb * cd, '', bpn=1)) if bpar: return '(' + texte + ')' else: return texte def tex_developpe1(a): # developpe l'expression a (exo, cor) = ([], []) exo.append("\\[ \\thenocalcul = %s \\]" % tex_dev0(a)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_dev0(a)) cor.append("\\[ \\thenocalcul = %s \\]" % tex_dev1(a)) cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % tex_trinome(dev(a))) return (exo, cor) def tex_developpe2(a, nega, b, negb, f1, f0=None, tabs=1): # developpe l'expression a plus l'expression b. if nega: if negb: if b[1][0] == 0 and b[1][1] == 1: if f0: ecrit_tex(f0, '-' + tex_dev0(a) + '-(' + tex_dev0(b) + ')', tabs=2) ecrit_tex(f1, '-' + tex_dev0(a) + '-(' + tex_dev0(b) + ')', tabs=tabs) elif a[1][0] == 0 and a[1][1] == 1: if f0: ecrit_tex(f0, '-(' + tex_dev0(a) + ')-' + tex_dev0(b), tabs=2) ecrit_tex(f1, '-(' + tex_dev0(a) + ')-' + tex_dev0(b), tabs=tabs) else: if f0: ecrit_tex(f0, '-' + tex_dev0(a) + '-' + tex_dev0(b), tabs=2) ecrit_tex(f1, '-' + tex_dev0(a) + '-' + tex_dev0(b), tabs=tabs) ecrit_tex(f1, '-(' + tex_dev1(a) + ')-(' + tex_dev1(b) + ')', tabs=tabs) ecrit_tex(f1, '-(' + tex_trinome(dev(a)) + ')-(' + tex_trinome(dev(b)) + ')', tabs=tabs) ecrit_tex(f1, tex_trinome(coef_opposes(dev(a))) + tex_trinome(coef_opposes(dev(b)), bplus=1), tabs= tabs) ecrit_tex(f1, tex_trinome(somme_polynomes(coef_opposes(dev(a)), coef_opposes(dev(b)))), cadre=True, tabs=tabs) else: if a[1][0] == 0 and a[1][1] == 1: if f0: ecrit_tex(f0, '-(' + tex_dev0(a) + ')+' + tex_dev0(b), tabs=2) ecrit_tex(f1, '-(' + tex_dev0(a) + ')+' + tex_dev0(b), tabs=tabs) ecrit_tex(f1, '-(' + tex_dev1(a) + ')+' + tex_dev1(b, bpn=1), tabs=tabs) ecrit_tex(f1, '-(' + tex_trinome(dev(a)) + ')+' + tex_trinome(dev(b)), tabs=tabs) elif b[1][0] == 0 and b[1][1] == 1: if f0: ecrit_tex(f0, '-' + tex_dev0(a) + tex_dev0(b, bplus= 1), tabs=2) ecrit_tex(f1, '-' + tex_dev0(a) + tex_dev0(b, bplus=1), tabs=tabs) ecrit_tex(f1, '-(' + tex_dev1(a) + ')' + tex_dev1(b, bplus=1), tabs=tabs) ecrit_tex(f1, '-(' + tex_trinome(dev(a)) + ')' + tex_trinome(dev(b), bplus=1), tabs=tabs) else: if f0: ecrit_tex(f0, '-' + tex_dev0(a) + '+' + tex_dev0(b), tabs=2) ecrit_tex(f1, '-' + tex_dev0(a) + '+' + tex_dev0(b), tabs=tabs) ecrit_tex(f1, '-(' + tex_dev1(a) + ')+' + tex_dev1(b, bpn=1), tabs=tabs) ecrit_tex(f1, '-(' + tex_trinome(dev(a)) + ')' + tex_trinome(dev(b), bplus=1), tabs=tabs) ecrit_tex(f1, tex_trinome(coef_opposes(dev(a))) + tex_trinome(dev(b), bplus=1), tabs=tabs) ecrit_tex(f1, tex_trinome(somme_polynomes(coef_opposes(dev(a)), dev(b))), cadre=True, tabs=tabs) elif negb: if b[1][0] == 0 and b[1][1] == 1: if f0: ecrit_tex(f0, tex_dev0(a) + '-(' + tex_dev0(b) + ')', tabs=2) ecrit_tex(f1, tex_dev0(a) + '-(' + tex_dev0(b) + ')', tabs= tabs) else: if f0: ecrit_tex(f0, tex_dev0(a) + '-' + tex_dev0(b), tabs=2) ecrit_tex(f1, tex_dev0(a) + '-' + tex_dev0(b), tabs=tabs) ecrit_tex(f1, tex_dev1(a) + '-(' + tex_dev1(b) + ')', tabs=tabs) ecrit_tex(f1, tex_trinome(dev(a)) + '-(' + tex_trinome(dev(b)) + ')', tabs=tabs) ecrit_tex(f1, tex_trinome(dev(a)) + tex_trinome(coef_opposes(dev(b)), bplus=1), tabs=tabs) ecrit_tex(f1, tex_trinome(somme_polynomes(dev(a), coef_opposes(dev(b)))), cadre=True, tabs=tabs) else: if b[1][0] == 0 and b[1][1] == 1: if f0: ecrit_tex(f0, tex_dev0(a) + tex_dev0(b, bplus=1), tabs=2) ecrit_tex(f1, tex_dev0(a) + tex_dev0(b, bplus=1), tabs=tabs) ecrit_tex(f1, tex_dev1(a) + tex_dev1(b, bplus=1), tabs=tabs) else: if f0: ecrit_tex(f0, tex_dev0(a) + '+' + tex_dev0(b), tabs=2) ecrit_tex(f1, tex_dev0(a) + '+' + tex_dev0(b), tabs=tabs) ecrit_tex(f1, tex_dev1(a) + '+' + tex_dev1(b), tabs=tabs) ecrit_tex(f1, tex_trinome(dev(a)) + tex_trinome(dev(b), bplus=1), tabs=tabs) ecrit_tex(f1, tex_trinome(somme_polynomes(dev(a), dev(b))), cadre=True, tabs=tabs) def tex_trinome(a, bplus=0, bpar=0): # renvoi le trinome ax²+bx+c # bplus est un booleen : s'il est vrai, le premier terme est precede d'un signe + si son coefficient est positif. # bpar est un booleen : s'il est vrai, ecrit des parentheses autour du trinome si deux valeurs au moins ne sont pas nulles ou si la valeur est - texte = '%s%s%s' % (tex_coef(a[0], 'x^2', bplus=bplus), tex_coef(a[1], 'x', bplus=bplus or a[0] != 0), tex_coef(a[2], '', bplus=bplus or a[0] != 0 or a[1] != 0)) if bpar: v0 = 0 for i in range(3): # compte le nombre de valeurs nulles if a[i] == 0: v0 = v0 + 1 if v0 == 2: # une seule valeur non nulle (on suppose que les trois coef ne sont pas nuls) if a[0] < 0 or a[1] < 0 or a[2] < 0: # le coefficient non nul est negatif, il faut donc des parentheses return '(' + texte + ')' else: return texte else: return '(' + texte + ')' else: return texte def valeurs_apb2(pyromax): # renvoie un tuple contenant ((3,5),(3,5)) a = valeur_alea(1, pyromax) b = valeur_alea(1, pyromax) return ((a, b), (a, b)) def valeurs_amb2(pyromax): # renvoie un tuple contenant ((3,-5),(3-5)) a = valeur_alea(1, pyromax) b = valeur_alea(-pyromax, -1) return ((a, b), (a, b)) def valeurs_apbamb(pyromax): # renvoie un tuple contenant ((3,-5),(3,+5)) a = valeur_alea(-pyromax, pyromax) b = valeur_alea(-pyromax, pyromax) if randrange(2) == 0: return ((a, b), (-a, b)) else: return ((a, b), (a, -b)) def valeurs_distr(pyromax): # renvoie in tuple contenant ((a,b),(c,d)) avec a != c ou b != d (en valeur absolue) et a, b, c ou d nul. while True: a = valeur_alea(-pyromax, pyromax) b = valeur_alea(-pyromax, pyromax) c = valeur_alea(-pyromax, pyromax) l = [a, b, c] l.insert(randrange(4), 0) if abs(l[1]) != 1 and abs(l[3]) != 1: break #Pour qu'il y ait quelque chose à développer. return ((l[0], l[1]), (l[2], l[3])) def valeurs_dbldistr(pyromax): # renvoie in tuple contenant ((a,b),(c,d)) avec a != c ou b != d (en valeur absolue) a = valeur_alea(-pyromax, pyromax) b = valeur_alea(-pyromax, pyromax) c = valeur_alea(-pyromax, pyromax) d = valeur_alea(-pyromax, pyromax) while abs(a) == abs(c) and abs(b) == abs(d): c = valeur_alea(-pyromax, pyromax) d = valeur_alea(-pyromax, pyromax) return ((a, b), (c, d)) #=============================================================================== # Développements #=============================================================================== def def_vals(): lexp = [0, 1, 2, 0, 1, 2] expr = [] for i in range(6): a = valeur_alea(-10, 10) e = lexp.pop(randrange(len(lexp))) expr.append([a, 'x', e]) return expr def def_vals2(): expr = [] loper = ['+', '-', '\\times', '+', '-', '\\times', '+', '-'] for i in range(8): a = valeur_alea(-10, 10) e = randrange(3) o = loper.pop(randrange(len(loper))) expr.append([a, 'x', e, o]) return expr def def_vals3(): expr = [] lsgn = ['+', '-', '+', '-'] for i in range(9): if i % 3 == 0: sgn = lsgn.pop(randrange(len(lsgn))) if i > 0 or sgn == '-': expr.append(sgn) expr.append(" (") elif i % 3 == 1: a = valeur_alea(-10, 10) e = randrange(3) expr.append([a, 'x', e]) else: a = valeur_alea(-10, 10) e = randrange(3) while e == expr[-1][2]: e = randrange(3) expr.append([a, 'x', e]) expr.append(') ') return expr def def_vals4(): expr = [] for i in range(9): a = valeur_alea(-10, 10) e = randrange(3) if i % 3 == 0: expr.append([a, 'x', e]) expr.append(' \,(') elif i % 3 == 1: expr.append([a, 'x', e]) else: while e == expr[-1][2]: e = randrange(3) expr.append([a, 'x', e]) expr.append(') ') return expr def def_vals5(): expr = [] for i in range(8): a = valeur_alea(-10, 10) e = randrange(3) if i % 2 == 0: if i % 4 == 0: expr.append(" (") else: expr.append(' \,(') expr.append([a, 'x', e]) else: while e == expr[-1][2]: e = randrange(3) expr.append([a, 'x', e]) expr.append(') ') if i == 3: expr.append(['+', '+', '-'].pop(randrange(3))) return expr def monome(coef, var, exposant, bplus=0, bpn=0, bpc=0): # coef est le coefficient à écrire devant la variable var # bplus est un booleen : s'il est vrai, il faut ecrire le signe + # bpn est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef est negatif. # bpc est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef =! 0 ou 1 et var est non vide if exposant == 0: var = '' elif exposant > 1: var = '%s^{%s}' % (var, exposant) if coef != 0 and abs(coef) != 1: if var == '': if abs(coef) >= 1000: a = '\\nombre{%s}' % coef else: a = '%s' % coef else: if abs(coef) >= 1000: a = '\\nombre{%s}\\,%s' % (coef, var) else: a = '%s\\,%s' % (coef, var) if bplus and coef > 0: a = '+' + a elif coef == 1: if var == '': a = '1' else: a = '%s' % var if bplus: a = '+' + a elif coef == 0: a = '' elif coef == -1: if var == '': a = '-1' else: a = '-%s' % var if bpn and coef < 0 or bpc and coef != 0 and coef != 1 and var != '': a = '\\left( ' + a + '\\right)' return a def print_expr(expr): text = '$' for i in range(len(expr)): coef = expr[i][0] var = expr[i][1] exposant = expr[i][2] if i > 0: text = '%s%s' % (text, monome(coef, var, exposant, bplus=1)) else: text = '%s%s' % (text, monome(coef, var, exposant)) return '%s$' % text def print_expr2(expr): text = '$' for i in range(len(expr)): coef = expr[i][0] var = expr[i][1] exposant = expr[i][2] if i > 0: text = '%s %s %s' % (text, expr[i - 1][3], monome(coef, var, exposant, bpn=1)) else: text = '%s%s' % (text, monome(coef, var, exposant)) return '%s$' % text def print_expr3(expr): text = '$' for i in range(len(expr)): if isinstance(expr[i], list): coef = expr[i][0] var = expr[i][1] exposant = expr[i][2] if expr[i - 1] == " (": text = '%s %s' % (text, monome(coef, var, exposant)) else: text = '%s %s' % (text, monome(coef, var, exposant, bplus=1)) else: text = '%s%s' % (text, expr[i]) return '%s$' % text def print_expr4(expr): text = '$' for i in range(len(expr)): if isinstance(expr[i], list): coef = expr[i][0] var = expr[i][1] exposant = expr[i][2] if i == 0 or expr[i - 1] == " (": text = '%s %s' % (text, monome(coef, var, exposant)) else: text = '%s %s' % (text, monome(coef, var, exposant, bplus=1)) else: text = '%s%s' % (text, expr[i]) return '%s$' % text pyromaths/src/quatriemes/fractions.py0000644000175000017500000003305311702101415020576 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils import Arithmetique from ..outils.Priorites import OperateurPrioritaire from ..outils.TeXMiseEnForme import Affichage import random from ..classes.Fractions import Fractions #Classe Fractions de pyromaths def sommes_fractions_4e(op, level): '''Choisit des valeurs aléatoires pour effectuer une somme ou une différence de fractions en fonction du niveau de difficulté souhaité (de 1 à 4) et renvoie l'énoncé et le corrigé au format TeX @param op: '+' ou '-' @param level: niveau de difficulté : 1- Fractions positives et dénominateur de l'une multiple de l'autre 2- Fractions positives et dénominateurs non multiples 3- Fractions avec des nombres relatifs 4- Fractions avec des nombres relatifs et résultats simplifiable ''' while True: (n1, d1, n2, d2) = (2, 2, 2, 2) # import pdb; pdb.set_trace() while True: if level == 1: n1 = random.randrange(1, 16) d1 = random.randrange(1, 9) n2 = random.randrange(1, 16) d2 = d1*random.randrange(2, 11) if random.randrange(2): d1, d2 = d2, d1 elif level == 2: n1 = Arithmetique.valeur_alea(1, 16) d1 = Arithmetique.valeur_alea(1, 40) n2 = Arithmetique.valeur_alea(1, 16) d2 = Arithmetique.valeur_alea(1, 40) else: while True: neg=[(-1,1)[random.randrange(2)] for x in range(4)] if neg[0]<0 or neg[1]<0 or neg[2]<0 or neg[3]<0: break n1 = random.randrange(1, 16)*neg[0] d1 = random.randrange(1, 40)*neg[1] n2 = random.randrange(1, 16)*neg[2] d2 = random.randrange(1, 40)*neg[3] fr1 = Fractions(n1, d1) fr2 = Fractions(n2, d2) if Arithmetique.pgcd(fr1.n, fr1.d) == 1 and \ Arithmetique.pgcd(fr2.n, fr2.d) == 1 and \ (level == 1 or (Arithmetique.pgcd(fr1.d, fr2.d) != abs(fr1.d) \ and Arithmetique.pgcd(fr1.d, fr2.d) != abs(fr2.d))): if op == "+": simplifiable = abs(fr1.d * fr2.d) != \ abs(Fractions.simplifie(fr1 + fr2).d) else: simplifiable = abs(fr1.d * fr2.d) != \ abs(Fractions.simplifie(fr1 - fr2).d) if level == 1 or (simplifiable and level == 4) or \ (not simplifiable and level < 4): break l = [fr1, op, fr2] (cor, res, niveau) = OperateurPrioritaire(l, 4, solution=[]) if niveau >= 4: break fr1 = Fractions(n1, d1) fr2 = Fractions(n2, d2) return ([fr1, op, fr2], cor, res) def produits_fractions_4e(op, level): '''Choisit des valeurs aléatoires pour effectuer un produit ou un quotient de fractions en fonction du niveau de difficulté souhaité (de 1 à 4) et renvoie l'énoncé et le corrigé au format TeX @param op: '*' ou '/' @param level: niveau de difficulté : 1- Fractions positives non décomposables 2- Fractions avec des nombres relatifs non décomposables 3- Fractions positives à décomposer 4- Fractions avec des nombres relatifs à décomposer ''' while True: (n1, d1, n2, d2) = (2, 2, 2, 2) while True: n1=d1=n2=d2=a=b=2 if level == 3 or level == 4: while Arithmetique.pgcd(a,b)>1: a=random.randrange(2,11) b=random.randrange(2,11) else: a, b = 1, 1 if op == "*": if level == 1 or level == 3: while Arithmetique.pgcd(n1*a,d1*b)>1: n1=random.randrange(1,11) d1=random.randrange(2,11) while Arithmetique.pgcd(n2*b,d2*a)>1: n2=random.randrange(1,11) d2=random.randrange(2,11) elif level == 2 or level == 4: while True: neg=[(-1,-1,1)[random.randrange(3)] for x in range(4)] if neg[0]<0 or neg[1]<0 or neg[2]<0 or neg[3]<0: break while Arithmetique.pgcd(n1*a,d1*b)>1: n1=random.randrange(1,11)*neg[0] d1=random.randrange(2,11)*neg[1] while Arithmetique.pgcd(n2*b,d2*a)>1: n2=random.randrange(1,11)*neg[2] d2=random.randrange(2,11)*neg[3] fr1 = Fractions(n1*a, d1*b) fr2 = Fractions(n2*b, d2*a) simplifiable = abs(fr1.d * fr2.d) != Fractions.simplifie(fr1 * fr2).d else: if level == 1 or level == 3: while Arithmetique.pgcd(n1*a,d1*b)>1: n1=random.randrange(1,11) d1=random.randrange(2,11) while Arithmetique.pgcd(n2*a,d2*b)>1: n2=random.randrange(1,11) d2=random.randrange(2,11) else: while Arithmetique.pgcd(n1*a,d1*b)>1: n1=random.randrange(-11,11) d1=random.randrange(2,11)*(-1,1)[random.randrange(2)] while Arithmetique.pgcd(n2*a,d2*b)>1: n2=random.randrange(1,11)*(-1,1)[random.randrange(2)] d2=random.randrange(2,11)*(-1,1)[random.randrange(2)] fr1 = Fractions(n1*a, d1*b) fr2 = Fractions(n2*a, d2*b) simplifiable = abs(fr1.d * fr2.n) != \ Fractions.simplifie(fr1 / fr2).d if (simplifiable and level>2) or (not simplifiable and level<=2): break l = [fr1, op, fr2] (cor, res, niveau) = OperateurPrioritaire(l, 4, solution=[]) if niveau >= 4: break return (l, cor, res) def valeurs_priorites_fractions(nb, entier=1): # renvoie les 2 listes contenant les opérateurs et les opérandes. listoperateurs = [ "+", "*", "-", "/", '(', '(', '(', '(', ')', ')', ')', ')', ] loperateurs = [] loperandes = [] i = 0 #nombre d'opérateurs créés p = 0 #nombre de parenthèses ouvertes cpt = 0 #compteur pour éviter que le programme ne boucle. while i < nb - 1: cpt = cpt + 1 if cpt > 10: #On recommence (cpt, i, p, loperateurs) = (0, 0, 0, []) if p: if loperateurs[-1] == '(': # On n'écrit pas 2 parenthèses à suivre operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(12)] elif loperateurs == []: # On ne commence pas par une parenthèse operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(8)] if nb > 3: test = ('-*/').find(operateur) >= 0 and loperateurs.count(operateur) < \ 1 or operateur == "+" and loperateurs.count(operateur) < \ 2 else: test = ('-*/+').find(operateur) >= 0 and loperateurs.count(operateur) < \ 1 if test: #On n'accepte pas plus de 1 produit, différence, quotient et de 2 sommes ou parenthèses par calcul. if i == 0 or loperateurs[-1] != '(' or ('*/').find(operateur) < \ 0: #pas de * ou / dans une parenthèse. i = i + 1 loperateurs.append(operateur) elif operateur == '(' and (')+').find(loperateurs[-1]) < 0: #Il ne peut y avoir de ( après une ) ou après un + p = p + 1 loperateurs.append(operateur) elif operateur == ')': p = p - 1 loperateurs.append(operateur) while p > 0: loperateurs.append(')') p = p - 1 loperandes = [] for i in range(nb): (n, d) = (2, 2) while Arithmetique.pgcd(n, d) != 1 or abs(d) == 1: n = Arithmetique.valeur_alea(-16, 16) d = -Arithmetique.valeur_alea(-40, 40) loperandes.append(Fractions(n, d)) exercice = [loperandes[0]] i = 1 j = 0 while i < len(loperandes) or j < len(loperateurs): if j < len(loperateurs): exercice.append(loperateurs[j]) j = j + 1 while j < len(loperateurs) and (loperateurs[j] == '(' or loperateurs[j - 1] == ')'): exercice.append(loperateurs[j]) j = j + 1 if i < len(loperandes): exercice.append(loperandes[i]) i = i + 1 return exercice def exo_sommes_fractions(): exo = ["\\exercice", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent%"] cor = ["\\exercice*", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent%"] op = ["+", "-","+", "-","+", "-","+", "-"] for i in range(8): if i%2: (l, sol, res) = sommes_fractions_4e(op.pop(0), i//2+1) else: (l, sol, res) = sommes_fractions_4e(op.pop(random.randrange(2)), i//2+1) exo.append("\\[\\thenocalcul = %s\\]" % Affichage(l)) cor.append("\\[\\thenocalcul = %s\\]" % Affichage(l)) for l in sol: if l == sol[-1]: cor.append("\\[\\boxed{\\thenocalcul = %s}\\]" % l) else: cor.append("\\[\\thenocalcul = %s\\]" % l) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\\end{multicols}\n") cor.append("\\end{multicols}\n") return (exo, cor) def exo_produits_fractions(): exo = ["\\exercice", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent%"] cor = ["\\exercice*", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent%"] op = ["*", "/","*", "/","*", "/","*", "/"] for i in range(8): if i%2: (l, sol, res) = produits_fractions_4e(op.pop(0), i//2+1) else: (l, sol, res) = produits_fractions_4e(op.pop(random.randrange(2)), i//2+1) exo.append("\\[\\thenocalcul = %s\\]" % Affichage(l)) cor.append("\\[\\thenocalcul = %s\\]" % Affichage(l)) for l in sol: if l == sol[-1]: cor.append("\\[\\boxed{\\thenocalcul = %s}\\]" % l) else: cor.append("\\[\\thenocalcul = %s\\]" % l) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\\end{multicols}\n") cor.append("\\end{multicols}\n") return (exo, cor) def exo_priorites_fractions(): exo = ["\\exercice", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{3}", " \\noindent%"] cor = ["\\exercice*", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{3}", " \\noindent%"] for i in range(6): while True: l = valeurs_priorites_fractions(3) (sol, res, niveau) = OperateurPrioritaire(l, 4, solution=[]) if niveau >= 4: break exo.append("\\[\\thenocalcul = %s\\]" % Affichage(l)) cor.append("\\[\\thenocalcul = %s\\]" % Affichage(l)) for l in sol: if l == sol[-1]: cor.append("\\[\\boxed{\\thenocalcul = %s}\\]" % l) else: cor.append("\\[\\thenocalcul = %s\\]" % l) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\\end{multicols}\n") cor.append("\\end{multicols}\n") return (exo, cor) exo_sommes_fractions() pyromaths/src/quatriemes/._quatriemes.py0000644000175000017500000000031511702101415021175 0ustar didrocksdidrocksMac OS X  2ATTRGޜ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/._geometrie.py0000644000175000017500000000031511702101415020776 0ustar didrocksdidrocksMac OS X  2ATTRGޙ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/__init__.py0000644000175000017500000000171511702101415020345 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/quatriemes/._calcul_mental.py0000644000175000017500000000031511702101415021621 0ustar didrocksdidrocksMac OS X  2ATTRGޖ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/._puissances.py0000644000175000017500000000031511702101415021173 0ustar didrocksdidrocksMac OS X  2ATTRGޛ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/._fractions.py0000644000175000017500000000031511702101415021006 0ustar didrocksdidrocksMac OS X  2ATTRGޘ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/quatriemes.py0000644000175000017500000000362011702101415020762 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from . import puissances, developpements, calcul_mental, fractions, geometrie from . import litteral def write(f0, f1, exos): f0.write("\n") f1.write("\n") f0.writelines(x + "\n" for x in exos[0]) f1.writelines(x + "\n" for x in exos[1]) def main(exo, f0, f1): modules = ( calcul_mental.main, fractions.exo_sommes_fractions, fractions.exo_produits_fractions, fractions.exo_priorites_fractions, litteral.reduire, litteral.reduire_expressions, puissances.tex_proprietes, puissances.tex_proprietes_neg, puissances.ecr_sc, puissances.exo_puissances, developpements.exo_distributivite, developpements.exo_double_distributivite, geometrie.exo_pythagore, geometrie.exo_reciproque_pythagore, geometrie.exo_triangle_cercle, geometrie.exo_thales, geometrie.exo_trigo, ) write(f0, f1, modules[exo]()) pyromaths/src/quatriemes/._developpements.py0000644000175000017500000000031511702101415022050 0ustar didrocksdidrocksMac OS X  2ATTRGޗ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/quatriemes/geometrie.py0000644000175000017500000007271211702101415020573 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random from math import acos, asin, atan, pi, sin, cos, tan from ..outils.Geometrie import couples_pythagore, choix_points # # ------------------- THEOREME DE PYTHAGORE ------------------- def fig_tr_rect(lg): # renvoie les angles au centre des trois sommets du triangle ABC rectange en C a = random.randrange(360) if a < 180: b = a + 180 else: b = a - 180 c = (int((180 - ((2 * acos((lg[1] * 1.0) / lg[2])) * 180) / pi) * 100) * 1.0) / 100 + a if c < 0: c = c + 360 return (str(a), str(b), str(c)) def enonce_pythagore(noms, angles, longueurs, cotes, nom_tr, long0, long1, diam=0): if diam: return ( noms[0], angles[0], angles[0], noms[1], angles[1], angles[1], noms[2], angles[2], angles[2], int(float(angles[0]) - 90), cotes[2], noms[2], cotes[long0], nombre(longueurs[long0]), cotes[long1], nombre(longueurs[long1]), cotes[(3 - long0) - long1], ) else: return ( nom_tr, noms[2], cotes[long0], nombre(longueurs[long0]), cotes[long1], nombre(longueurs[long1]), cotes[(3 - long0) - long1], ) def exo_pythagore(): types_exercice = [[2, random.randrange(2)], [0, 1]] random.shuffle(types_exercice) random.shuffle(types_exercice[0]) random.shuffle(types_exercice[1]) exo = ["\\exercice\n\\begin{multicols}{2}\n \\begin{enumerate}"] cor = ["\\exercice*\n\\begin{multicols}{2}\n \\begin{enumerate}"] for j in range(2): while True: longueurs = couples_pythagore[random.randrange(len(couples_pythagore))] longueurs = [longueurs[i] / 10.0 for i in range(3)] if inegalite_triangulaire(longueurs): break noms = choix_points(3) angles = fig_tr_rect(longueurs) nom_tr = nom_triangle(noms) long0 , long1 = types_exercice[j] cotes = cotes_sommets(noms) enonce = \ """ \\item Soit $%s$ un triangle rectangle en $%s$ tel que :\\par $%s=\\unit[%s]{cm} \\text{ et }%s=\\unit[%s]{cm}$.\\par Calculer la longueur $%s$.""" % \ enonce_pythagore(noms, angles, longueurs, cotes, nom_tr, long0, long1) exo.append(enonce) cor.append(enonce) cor.append("\\par\\dotfill{}\\par\n") cor.append(u"Le triangle $%s$ est rectangle en $%s$.\\par" % \ (nom_tr, noms[2])) cor.append(u"Son hypoténuse est $[%s]$.\\par" % (cotes[2])) cor.append(u"D'après le \\textbf{théorème de Pythagore} :" ) cor.append("\\[%s^2=%s^2+%s^2\\]" % (cotes[2], cotes[0], cotes[1] )) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s^2-%s^2\\kern1cm\\text{(On cherche }%s)\\]" % (cotes[(3 - long0) - long1], cotes[2], cotes[((4 - long0) - long1) % 2], cotes[(3 - long0) - long1])) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s^2-%s^2\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2]), nombre(longueurs[((4 - long0) - long1) % 2]))) else: cor.append("\\[%s^2=%s^2+%s^2\\]" % (cotes[2], nombre(longueurs[0]), nombre(longueurs[1]))) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s-%s\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2] ** 2), nombre(longueurs[((4 - long0) - long1) % 2] ** 2))) else: cor.append("\\[%s^2=%s+%s\\]" % (cotes[2], nombre(longueurs[0] ** 2), nombre(longueurs[1] ** 2))) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2] ** 2 - longueurs[((4 - long0) - long1) % 2] ** 2))) else: cor.append("\\[%s^2=%s\\]" % (cotes[2], nombre(longueurs[0] ** 2 + longueurs[1] ** 2))) if long0 == 2 or long1 == 2: cor.append("\\[ \\boxed{\\text{Donc }%s=\\sqrt{%s}=\\unit[%s]{cm}}\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2] ** 2 - longueurs[((4 - long0) - long1) % 2] ** 2), nombre(longueurs[(3 - long0) - long1]))) else: cor.append("\\[\\boxed{\\text{Donc }%s=\\sqrt{%s}=\\unit[%s]{cm}}\\]" % (cotes[2], nombre(longueurs[0] ** 2 + longueurs[1] ** 2), nombre(longueurs[2]))) if j == 0: exo.append("\\columnbreak") cor.append("\\columnbreak") exo.append("\\end{enumerate}\n\\end{multicols}\n") cor.append("\\end{enumerate}\n\\end{multicols}\n") return (exo, cor) def nom_triangle(noms): # renvoie le nom du triangle dans un ordre aleatoire a = random.randrange(3) b = (random.randrange(2) + 1 + a) % 3 c = (3 - a) - b return '%s%s%s' % (noms[a], noms[b], noms[c]) def cotes_sommets(noms): # renvoie les noms des 3 cotes du triangle en finissant par l'hypotenuse return (noms[1] + noms[2], noms[0] + noms[2], noms[0] + noms[1]) # # ------------------- CERCLE ET THEOREME DE PYTHAGORE ------------------- # def exo_triangle_cercle(): exo = ["\\exercice"] cor = ["\\exercice*"] while True: longueurs = couples_pythagore[random.randrange(len(couples_pythagore))] longueurs = [longueurs[i] / 10.0 for i in range(3)] if inegalite_triangulaire(longueurs): break noms = choix_points(3) angles = fig_tr_rect(longueurs) nom_tr = nom_triangle(noms) long0 = random.randrange(3) long1 = (random.randrange(2) + 1 + long0) % 3 cotes = cotes_sommets(noms) enonce = \ u"""\\begin{minipage}{4cm} \\begin{pspicture}(-2,-2)(2,2) \\SpecialCoor\\psset{PointSymbol=x} \\pstGeonode[PointName=%s,PosAngle=%s](1.5;%s){a} \\pstGeonode[PointName=%s,PosAngle=%s](1.5;%s){b} \\pstGeonode[PointName=%s,PosAngle=%s](1.5;%s){c} \\pspolygon(a)(b)(c)\\pscircle(0,0){1.5} \\rput(1.8;%s){$\\big(\\mathcal{C}\\big)$} \\end{pspicture} \\end{minipage}\\hfill \\begin{minipage}{13cm} $\\big(\\mathcal{C}\\big)$ est un cercle de diamètre $[%s]$ et $%s$ est un point de $\\big(\\mathcal{C}\\big)$.\\par On donne $%s=\\unit[%s]{cm}\\text{ et }%s=\\unit[%s]{cm}$.\\par Calculer la longueur $%s$.""" % \ enonce_pythagore(noms, angles, longueurs, cotes, nom_tr, long0, long1, diam=1) exo.append(enonce) cor.append(enonce) cor.append("\\par\\dotfill{}\\\\\n") cor.append(u"$[%s]$ est le diamètre du cercle circonscrit au triangle $%s$.\\par" % (cotes[2], nom_tr)) cor.append("\\fbox{Donc le triangle %s est rectangle en %s.}\\\\\n" % (nom_tr, noms[2])) cor.append(u"D'après le \\textbf{théorème de Pythagore} :") cor.append(u"\\[%s^2=%s^2+%s^2\\kern1cm\\text{(car }[%s]\\text{ est \\emph{l'hypoténuse})}\\]" % (cotes[2], cotes[0], cotes[1], cotes[2])) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s^2-%s^2\\kern1cm\\text{(On cherche }%s)\\]" % (cotes[(3 - long0) - long1], cotes[2], cotes[((4 - long0) - long1) % 2], cotes[(3 - long0) - long1])) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s^2-%s^2\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2]), nombre(longueurs[((4 - long0) - long1) % 2]))) else: cor.append("\\[%s^2=%s^2+%s^2\\]" % (cotes[2], nombre(longueurs[0]), nombre(longueurs[1]))) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s-%s\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2] ** 2), nombre(longueurs[((4 - long0) - long1) % 2] ** 2))) else: cor.append("\\[%s^2=%s+%s\\]" % (cotes[2], nombre(longueurs[0] ** 2), nombre(longueurs[1] ** 2))) if long0 == 2 or long1 == 2: cor.append("\\[%s^2=%s\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2] ** 2 - longueurs[((4 - long0) - long1) % 2] ** 2))) else: cor.append("\\[%s^2=%s\\]" % (cotes[2], nombre(longueurs[0] ** 2 + longueurs[1] ** 2))) if long0 == 2 or long1 == 2: cor.append("\\[\\boxed{\\text{Donc }%s=\\sqrt{%s}=\\unit[%s]{cm}}\\]" % (cotes[(3 - long0) - long1], nombre(longueurs[2] ** 2 - longueurs[((4 - long0) - long1) % 2] ** 2), nombre(longueurs[(3 - long0) - long1]))) else: cor.append("\\[\\boxed{\\text{Donc }%s=\\sqrt{%s}=\\unit[%s]{cm}}\\]" % (cotes[2], nombre(longueurs[0] ** 2 + longueurs[1] ** 2), nombre(longueurs[2]))) exo.append("\\end{minipage}\n") cor.append("\\end{minipage}\n") return (exo, cor) # # ------------------- RECIPROQUE DU THEOREME DE PYTHAGORE ------------------- # def exo_reciproque_pythagore(): exo = ["\\exercice"] cor = ["\\exercice*"] while True: longueurs = couples_pythagore[random.randrange(len(couples_pythagore))] longueurs = [longueurs[i] / 10.0 for i in range(3)] if inegalite_triangulaire(longueurs): break noms = choix_points(3) nom_tr = nom_triangle(noms) l = [i for i in range(3)] n = [l.pop(random.randrange(3 - i)) for i in range(3)] c = cotes_sommets(noms) recip = (nom_tr, c[n[0]], nombre(longueurs[n[0]]), c[n[1]], nombre(longueurs[n[1]]), c[n[2]], nombre(longueurs[n[2]]), nom_tr) enonce = \ """Soit $%s$ un triangle tel que : $\\quad %s=\\unit[%s]{cm}\\quad$, $\\quad %s=\\unit[%s]{cm}\\quad$ et $\\quad %s=\\unit[%s]{cm}$.\\par Quelle est la nature du triangle $%s$? """ % \ recip exo.append(enonce) cor.append(enonce) cor.append("\\par\\dotfill{}\\\\\n") cor.append(u"Le triangle %s n'est ni isocèle, ni équilatéral.\\par\n" % nom_tr) cor.append("$\\left.") cor.append("\\renewcommand{\\arraystretch}{2}") cor.append("\\begin{array}{l}") cor.append(u"\\bullet %s^2=%s^2=%s\\qquad\\text{(}[%s]\\text{ est le plus grand côté.)}\\\\\n" % (c[2], nombre(longueurs[2]), nombre(longueurs[2] ** 2), c[2])) cor.append("\\bullet %s^2+%s^2=%s^2+%s^2=%s \n" % (c[0], c[1], nombre(longueurs[0]), nombre(longueurs[1]), nombre(longueurs[0] ** 2 + longueurs[1] ** 2))) cor.append("\\end{array}") cor.append("\\right\\rbrace$") cor.append(u"""Donc $%s^2=%s^2+%s^2$.\\par D'après la \\textbf{réciproque du théorème de Pythagore}, \\fbox{le triangle $%s$ est rectangle en $%s$.}""" % (c[2], c[0], c[1], nom_tr, noms[2])) return (exo, cor) # # ------------------- THEOREME DE THALES ------------------- # def valeurs_thales(pyromax): liste = [0, 0, 0, 0, 0, 0, 0, 0] while liste == [0, 0, 0, 0, 0, 0, 0, 0]: for i in range(3): liste[i] = random.randrange(2) a = random.randrange(liste.count(1)) for i in range(3): if liste[i]: if not a: liste[i + 3] = 1 a = a - 1 else: liste[i + 3] = 1 # on doit connaitre le numeratuer ou le denominateur for i in range(2): # AB et AE ou AB et BE ou AE et EB if liste[i] and liste[i + 3]: # i est le rapport complet. On choisit une des 3 formes ci-dessus a = random.randrange(2) liste[i + 6] = 1 liste[i + 3 * a] = 0 rapport = [i + 3 * ((a + 1) % 3), i + 3 * ((a + 2) % 3)] rapport.sort() if liste[2] and liste[5]: rapport = [2, 5] valeurs = [0, 0, 0, 0, 0, 0, 0, 0] for i in range(3): if liste[i]: valeurs[i] = random.randrange(15, pyromax) / 10.0 if liste[i + 3] and liste[i]: valeurs[i + 3] = random.randrange(5, valeurs[i] * 10 - 9) / \ 10.0 elif liste[i + 3]: valeurs[i + 3] = random.randrange(5, pyromax) / 10.0 if liste[6]: valeurs[6] = random.randrange(5, pyromax) / 10.0 if liste[7]: valeurs[7] = random.randrange(5, pyromax) / 10.0 #-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #type_thales=valeur_alea(-1,1) # -1 si papillon, 1 si triangle type_thales = 1 valeurs.append((rapport, type_thales)) if test_valeurs_thales(valeurs, rapport, type_thales): return valeurs else: return 0 def test_valeurs_thales(valeurs, rapport, type_thales): v = [valeurs[i] for i in range(8)] if rapport[0] // 3 == 0 and rapport[1] // 3 == 2: # On donne AB et EB v[rapport[0] + 3] = (v[rapport[0]] - v[rapport[1]]) * \ type_thales elif rapport[0] // 3 == 1 and rapport[1] // 3 == 2: # On donne AE et EB v[rapport[0] - 3] = v[rapport[0]] * type_thales + v[rapport[1]] if v[rapport[0] % 3]: # rapport est AE/AB rapp = (v[rapport[0] % 3 + 3] * 1.0) / v[rapport[0] % 3] else: rapp = 0 for i in range(3): if not v[i] and rapp: v[i] = v[i + 3] / rapp elif not v[i + 3]: v[i + 3] = v[i] * rapp if inegalite_triangulaire(v[0:3]) and inegalite_triangulaire(v[3:6]) and \ .3 < rapp < .7: return v else: return 0 def inegalite_triangulaire(a): # renvoie 1 si c'est un triangle, 0 sinon vrai = 0 coef = 1.2 # evite les triangles trop ecrases if a[0] > a[1] and a[0] > a[2]: if a[1] + a[2] > coef * a[0]: vrai = 1 elif a[1] > a[0] and a[1] > a[2]: if a[0] + a[2] > coef * a[1]: vrai = 1 elif a[2] > a[0] and a[2] > a[1]: if a[0] + a[1] > coef * a[2]: vrai = 1 return vrai def exo_thales(): exo = ["\\exercice"] cor = ["\\exercice*"] noms = choix_points(5) # les noms des sommets while True: valeurs = valeurs_thales(70) # les longueurs en mm if valeurs: break exo.append(tex_fig_thales(noms, valeurs)) exo.append(tex_enonce_thales(noms, valeurs)) cor.append(tex_fig_thales(noms, valeurs)) cor.append(tex_enonce_thales(noms, valeurs)) cor.append(tex_resolution_thales0(noms, valeurs)) cor.append(tex_resolution_thales1(noms, valeurs)) cor.append(tex_resolution_thales2(noms, valeurs)) cor.append(tex_resolution_thales3(noms, valeurs)) return (exo, cor) def long_val(noms, valeurs): # renvoie un tuple contenant les noms des segments et leur longueur puis les noms des longueurs a calculer liste = [] for i in range(8): if valeurs[i]: liste.append(creer_noms(noms, i)) liste.append(nombre(valeurs[i])) for i in range(6): if not valeurs[i] and valeurs[8][0][0] % 3 != i % 3: liste.append(creer_noms(noms, i)) return liste def lAB(a): # renvoie AB return str(a[0]) + str(a[1]) def nombre(a): texte = str(a).replace('.', ',') if a >= 1000 or a <= 0.0001: return '\\nombre{%s}' % texte else: if texte.count(',') and len(texte) - texte.find(',0') == 2: return texte.replace(',', '{,}').replace('{,}0', '') elif texte.count(','): return texte.replace(',', '{,}') else: return texte def creer_noms(noms, i): if i == 0: return str(noms[0]) + str(noms[1]) elif i == 1: return str(noms[0]) + str(noms[2]) elif i == 2: return str(noms[1]) + str(noms[2]) elif i == 3: return str(noms[0]) + str(noms[3]) elif i == 4: return str(noms[0]) + str(noms[4]) elif i == 5: return str(noms[3]) + str(noms[4]) elif i == 6: return str(noms[3]) + str(noms[1]) elif i == 7: return str(noms[4]) + str(noms[2]) def tex_enonce_thales(noms, valeurs): texte = \ u'{Sur la figure ci-contre, les droites $(%s)\\text{ et }(%s)$ sont parallèles.\\par\n' % \ (lAB(noms[1:3]), lAB(noms[3:5])) liste = long_val(noms, valeurs) texte = texte + \ 'On donne $%s=\\unit[%s]{cm},\\quad %s=\\unit[%s]{cm}, \\quad %s=\\unit[%s]{cm}\\quad\\text{et}\\quad %s~=~\\unit[%s]{cm}$.\\par\n' % \ tuple(liste[0:8]) texte = texte + 'Calculer $%s\\text{ et }%s$.}\n' % tuple(liste[8:10]) return texte def tex_resolution_thales0(n, v): return u"""Dans le triangle $%s$,~ $%s$ est sur le côté $[%s]$,~ $%s$ est sur le côté $[%s]$ et les droites $(%s)$ et $(%s)$ sont parallèles.\\par D'après le \\textbf{théorème de Thalès} : $\\qquad\\mathbf{\\cfrac{%s}{%s}=\\cfrac{%s}{%s}=\\cfrac{%s}{%s}}$""" % \ ( n[0] + n[1] + n[2], n[3], n[0] + n[1], n[4], n[0] + n[2], n[1] + n[2], n[3] + n[4], creer_noms(n, 0), creer_noms(n, 3), creer_noms(n, 1), creer_noms(n, 4), creer_noms(n, 2), creer_noms(n, 5), ) def tex_resolution_thales1(n, v): r = v[8][0][0] % 3 # grand rapport if v[8][1] == 1: sgn = '+' else: sgn = '-' if v[r] and v[r + 3]: # on connait les deux rapports donnees = 0 elif v[r + 3]: # on connait le petit rapport, mais pas le grand v[r] = v[r + 6] + v[r + 3] * v[8][1] donnees = (creer_noms(n, r), creer_noms(n, r + 6), sgn, creer_noms(n, r + 3), nombre(v[r])) else: v[r + 3] = (v[r] - v[r + 6]) * v[8][1] if sgn == '+': donnees = (creer_noms(n, r + 3), creer_noms(n, r), '-', creer_noms(n, r + 6), nombre(v[r + 3])) else: donnees = (creer_noms(n, r + 3), creer_noms(n, r + 6), '-', creer_noms(n, r), nombre(v[r + 3])) if donnees: return '\\vspace{1ex}\\par De plus $%s=%s%s%s=\\unit[%s]{cm}$\n' % \ donnees else: return '' def tex_resolution_thales2(n, v): donnees = [] for i in range(3): if v[i]: donnees.append(nombre(v[i])) else: donnees.append(creer_noms(n, i)) if v[i + 3]: donnees.append(nombre(v[i + 3])) else: donnees.append(creer_noms(n, i + 3)) return '\\[\\frac{%s}{%s}=\\frac{%s}{%s}=\\frac{%s}{%s}\\]' % tuple(donnees) def nom_ou_valeur(n, v, i): if v[i]: return nombre(v[i]) else: return creer_noms(n, i) def valeur_exacte(a, approx=3, unit=1): nb = nombre(a) if unit: if nb.count(',') and (len(nb) - nb.find(',')) - 1 > approx: return '\\simeq\\unit[' + nombre(int(1000.0 * a) / 1000.0) + \ ']{cm}' else: return '=\\unit[' + nombre(a) + ']{cm}' else: if nb.count(',') and (len(nb) - nb.find(',')) - 1 > approx: return '\\simeq' + nombre(int(1000.0 * a) / 1000.0) else: return '=' + nombre(a) def tex_resolution_thales3(n, v): r = v[8][0][0] % 3 # grand rapport donnees = [] for i in range(3): if i != r: donnees.extend([nom_ou_valeur(n, v, r), nom_ou_valeur(n, v, r + 3), nom_ou_valeur(n, v, i), nom_ou_valeur(n, v, i + 3)]) if v[i]: # on cherche i+3 donnees.extend([creer_noms(n, i + 3), nombre(v[i]), nombre(v[r + 3]), nombre(v[r]), valeur_exacte(((v[i] * 1.0) * v[r + 3]) / v[r])]) else: donnees.extend([creer_noms(n, i), nombre(v[i + 3]), nombre(v[r]), nombre(v[r + 3]), valeur_exacte(((v[r] * 1.0) * v[i + 3]) / v[r + 3])]) texte = \ '$\\cfrac{%s}{%s}=\\cfrac{%s}{%s}\\quad$ donc $\\quad \\boxed{%s=\\cfrac{%s\\times %s}{%s}%s}$\\par\n ' % tuple(donnees[0:9]) texte = texte + \ '$\\cfrac{%s}{%s}=\\cfrac{%s}{%s}\\quad$ donc $\\quad\\boxed{%s=\\cfrac{%s\\times %s}{%s}%s}$\\par\n' % tuple(donnees[9:18]) return texte #def pyromax(a): # maxi = a[0] # for i in xrange(len(a)): # if a[i] > maxi: # maxi = a[i] # return maxi # # #def pyromin(a): # mini = a[0] # for i in xrange(len(a)): # if a[i] < mini: # mini = a[i] # return mini def fig_thales(noms, valeurs): v = test_valeurs_thales(valeurs[0:8], valeurs[8][0], valeurs[8][1]) type_thales = valeurs[8][1] angle = int(((100.0 * acos(((v[0] ** 2 + v[1] ** 2) - v[2] ** 2) / ((2 * v[0]) * v[1]))) * 180) / pi) / 100.0 v = [int(v[i] * 100) / 100.0 for i in range(8)] mini_x = int(100.0 * min(0, v[1] * cos((angle * pi) / 180), v[3] * type_thales, (v[4] * cos((angle * pi) / 180)) * type_thales)) / 100.0 - 1.5 mini_y = int(100.0 * min(0, (v[4] * sin((angle * pi) / 180)) * type_thales)) / 100.0 - 1.5 maxi_x = int(100.0 * max(v[0], v[1] * cos((angle * pi) / 180))) / \ 100.0 + 1.5 maxi_y = int((100.0 * v[1]) * sin((angle * pi) / 180)) / 100.0 + .5 echelle = int(400 / max(abs(mini_x) + maxi_x, abs(mini_y) + maxi_y)) / \ 100.0 if type_thales == 1: return ( echelle, mini_x, mini_y, maxi_x, maxi_y, 225, angle + 45, noms[0], noms[1], noms[2], v[0], v[1], angle, -45, angle + 90, noms[3], noms[4], v[3], v[4], angle, ) else: return ( echelle, mini_x, mini_y, maxi_x, maxi_y, 135, angle + 45, noms[0], noms[1], noms[2], v[0], v[1], angle, 135, angle + 180, noms[3], noms[4], -v[3], -v[4], angle, ) def tex_fig_thales(noms, valeurs): donnees = fig_thales(noms, valeurs) enonce = \ '''\\figureadroite{ \\psset{PointSymbol=x,unit=%s} \\begin{pspicture}(%s,%s)(%s,%s) \\SpecialCoor \\pstTriangle[PosAngleA=%s,PosAngleB=-45,PosAngleC=%s,PointNameA=%s, PointNameB=%s,PointNameC=%s](0,0){a}(%s,0){b}(%s;%s){c} \\pstTriangle[PosAngleB=%s,PosAngleC=%s,PointSymbolA=none, PointName=none,PointNameB=%s,PointNameC=%s](0,0){a}(%s,0){b}(%s;%s){c} \\end{pspicture} }''' % \ donnees return enonce # # ------------------- TRIGONOMETRIE ------------------- # def exo_trigo(): exo = ["\\exercice"] cor = ["\\exercice*"] s = choix_points(6) n1 = cotes_sommets(s[0:3]) n2 = cotes_sommets(s[3:6]) v = valeurs_trigo() (l1, l2) = enonce_trigo(((s[0:3], n1, v[0]), (s[3:6], n2, v[1]))) exo.extend(l1) cor.extend(l2) return (exo, cor) def enonce_trigo(v): (exo, cor) = ([], []) (l, lt) = ([], []) for j in range(2): f = (('\\sin', 1, 0), ('\\cos', 2, 0), ('\\tan', 1, 2))[v[j][2][0]] for i in range(2): l.append(v[j][1][f[i + 1]]) l.append(v[j][2][i + 1]) l.append(angle(v[j][0], 1)) l.append(v[j][2][3]) for j in range(2): tmp = [] for i in range(3): if len(l[2 * i + 6 * j]) < 3: if l[2 * i + 6 * j + 1]: lt.append('$%s=\\unit[%s]{cm}$' % (l[2 * i + 6 * j], nombre(l[2 * i + 6 * j + 1]))) else: tmp = 'la longueur $%s$' % l[2 * i + 6 * j] elif l[2 * i + 6 * j + 1]: lt.append('$%s=%s\\degres$' % (l[2 * i + 6 * j], l[2 * i + 6 * j + 1])) else: lt.append('la mesure de l\'angle $%s$' % l[2 * i + 6 * j]) if tmp: lt.append(tmp) exo.append('\\begin{multicols}{2}') exo.append('\\begin{enumerate}') cor.append('\\begin{multicols}{2}') cor.append('\\begin{enumerate}') tr = nom_triangle(v[0][0]) exo.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par' % (tr, v[0][0][0])) exo.append('%s et %s.\\par\nCalculer %s.\\par' % tuple(lt[0:3])) cor.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par' % (tr, v[0][0][0])) cor.append('%s et %s.\\par\nCalculer %s.\\par' % tuple(lt[0:3])) cor.append('Dans le triangle $%s$ rectangle en $%s$,' % (tr, v[0][0][0])) # résolution v2 = (v[0][1], v[0][2]) l2 = l[0:6] cor.extend(resolution_trigo(v2, l2)) tr = nom_triangle(v[1][0]) exo.append('\\columnbreak') cor.append('\\columnbreak') exo.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par' % (tr, v[1][0][0])) exo.append('''%s et %s.\\par Calculer %s.\\par''' % tuple(lt[3:6])) cor.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par' % (tr, v[1][0][0])) cor.append('%s et %s.\\par\nCalculer %s.\\par' % tuple(lt[3:6])) # cor.append("""\\dotfill{}\\par\\vspace{2ex}") cor.append('Dans le triangle $%s$ rectangle en $%s$,' % (tr, v[1][0][0])) # résolution v2 = (v[1][1], v[1][2]) l2 = l[6:12] cor.extend(resolution_trigo(v2, l2)) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) def resolution_trigo(v2, l2): cor = [] f = (('\\sin', 1, 0), ('\\cos', 2, 0), ('\\tan', 1, 2))[v2[1][0]] cor.append('\\[ %s%s=\\cfrac{%s}{%s} \\]' % (f[0], l2[4], v2[0][f[1]], v2[0][f[2]])) if not v2[1][3]: cor.append('\\[ %s%s=\\cfrac{%s}{%s} \\]' % (f[0], l2[4], nombre(v2[1][1]), nombre(v2[1][2]))) if f[0] == '\\sin': r = (asin(v2[1][1] / v2[1][2]) * 180) / pi elif f[0] == '\\cos': r = (acos(v2[1][1] / v2[1][2]) * 180) / pi else: r = (atan(v2[1][1] / v2[1][2]) * 180) / pi cor.append('\\[ \\boxed{%s=%s^{-1}\\left(\\cfrac{%s}{%s}\\right)\\simeq%s\\degres} \\]' % (l2[4], f[0], nombre(v2[1][1]), nombre(v2[1][2]), nombre(int(r * 10) / 10.0))) elif not v2[1][1]: cor.append('\\[ %s%s=\\cfrac{%s}{%s} \\]' % (f[0], v2[1][3], v2[0][f[1]], nombre(v2[1][2]))) if f[0] == '\\sin': r = sin((v2[1][3] * pi) / 180) elif f[0] == '\\cos': r = cos((v2[1][3] * pi) / 180) else: r = tan((v2[1][3] * pi) / 180) r = r * v2[1][2] cor.append('\\[ \\boxed{%s=%s%s\\times %s\\simeq\\unit[%s]{cm}} \\]' % (v2[0][f[1]], f[0], v2[1][3], nombre(v2[1][2]), nombre(int(r * 100) / 100.0))) else: cor.append('\\[ %s%s=\\cfrac{%s}{%s} \\]' % (f[0], v2[1][3], nombre(v2[1][1]), v2[0][f[2]])) if f[0] == '\\sin': r = sin((v2[1][3] * pi) / 180) elif f[0] == '\\cos': r = cos((v2[1][3] * pi) / 180) else: r = tan((v2[1][3] * pi) / 180) r = v2[1][1] / r cor.append('\\[ \\boxed{%s=\\cfrac{%s}{%s%s}\\simeq\\unit[%s]{cm}} \\]' % (v2[0][f[2]], nombre(v2[1][1]), f[0], v2[1][3], nombre(int(r * 100) / 100.0))) return cor def angle(s, n): # renvoie \\widehat{ABC} où s est la liste des 3 sommets du triangle et n est le rang du sommet de l'angle dans cette liste return '\\widehat{%s%s%s}' % (s[(n + 2) % 3], s[n], s[(n + 1) % 3]) def valeurs_trigo(): l = [random.randrange(10, 121) / 10.0 for i in range(3)] l.sort() l.append(random.randrange(15, 76)) trigo = 1 if random.randrange(2): # on choisit en 1er une longueur et un angle if random.randrange(2): # on connait la première des deux longueurs v = (trigo, l[0], 0, l[3]) else: v = (trigo, 0, l[0], l[3]) v = (v, (trigo, l[1], l[2], 0)) else: # on choisit en 1er deux longueurs v = (trigo, l[1], l[2], 0) if random.randrange(2): # on connait la première des deux longueurs v = (v, (trigo, l[0], 0, l[3])) else: v = (v, (trigo, 0, l[0], l[3])) return v pyromaths/src/.___init__.pyc0000644000175000017500000000031511702412270016545 0ustar didrocksdidrocksMac OS X  2ATTRGm55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._interface.py0000644000175000017500000000031511702412057016606 0ustar didrocksdidrocksMac OS X  2ATTRGp55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._outils0000755000175000017500000000031511702412270015536 0ustar didrocksdidrocksMac OS X  2ATTRGs55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/.___init__.py0000644000175000017500000000031511702101415016376 0ustar didrocksdidrocksMac OS X  2ATTRGl55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._troisiemes0000755000175000017500000000031511702101415016376 0ustar didrocksdidrocksMac OS X  2ATTRGx55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._pyromaths.py0000755000175000017500000000031511702101415016670 0ustar didrocksdidrocksMac OS X  2ATTRGt55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._Values.py0000644000175000017500000000031511702412057016105 0ustar didrocksdidrocksMac OS X  2ATTRGy55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/0000755000175000017500000000000011734627250016253 5ustar didrocksdidrockspyromaths/src/troisiemes/proportionnalite.py0000644000175000017500000001246711702101415022230 0ustar didrocksdidrocks# -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from random import randint, shuffle, randrange from ..outils.decimaux import decimaux import math from ..outils.Geometrie import cotation, cotation_h def choix_valeurs(min_prct, max_prct, min_nbre, max_nbre): while 1: decomp100 = [2,2,5,5,1,1] shuffle(decomp100) prct = decomp100[0] * decomp100[1] * decomp100[2] # qui donne 2, 4, 5, 10, 20, 25 ou 50 tot = decomp100[3] * decomp100[4] * decomp100[5] if (max_prct / prct != 0) and (max_nbre / tot != 0): break prct = randint(max(min_prct / prct, 1 ), (max_prct / prct )) * prct tot = tot * randint( max(min_nbre / tot,1) , (max_nbre / tot )) return prct, tot def proportionnalite_3eme(): #choix exercice i = randrange(2) #choix valeurs [min_prct, max_prct, min_nbre, max_nbre] = [[40, 80, 40, 65], [40, 80, 65, 90]][i] #choisit les valeurs du groupe A #prctA : pourcentage d'individu dans le groupe A entre 40% et 80% #totA : nombre total du groupe A entre 40 et 70 prctA, totA = choix_valeurs(min_prct = 40, max_prct = 80, min_nbre = 40, max_nbre = 65) #On choisit B avec des valeurs différentes while 1: prctB, totB = choix_valeurs(min_prct = 40, max_prct = 80, min_nbre = 40, max_nbre = 65) if prctA != prctB and totB != totA: break Total = totA + totB #calcul nbA = (prctA * totA / 100) nbB = (prctB * totB / 100) nbTotal = ((nbA + nbB)) prct_final = (100.0*nbTotal/Total) prct_final_arrondi = round(100.0*nbTotal/Total, 1) if prct_final == prct_final_arrondi: approx = "=" else: approx = "\\approx" #La situation texte = [u"Lors d'un voyage scolaire, les élèves sont répartis dans deux bus :", u"Au collège Dubois, il y a $%s$ élèves en quatrièmes et $%s$ élèves en troisièmes."%(totA,totB)][i] #Les deux groupes ligne1 = [u"\\item Bus A : %s élèves dont %s %s de garçons."%(totA, prctA,"\\%"), u"\\item $%s$ %s des élèves de quatrièmes possèdent un ordinateur ;"%(prctA,"\\%")][i] ligne2 = [u"\\item Bus A : %s élèves dont %s %s de garçons."%(totB, prctB,"\\%"), u"\\item $%s$ %s des élèves de troisièmes possèdent un ordinateur ;"%(prctB,"\\%")][i] #La question question = [u"Quel est, sur l'ensemble des deux bus, le pourcentage de garçons ?\\par", u"Quel est le pourcentage des élèves qui possèdent un ordinateur ?\\par"][i] #La correction correction =[#Dans le bus [u"Dans le bus A, il y a $\\cfrac{%s \\times %s}{100} = %s$ garçons.\\par"%(prctA, totA, decimaux(nbA)), u"Dans le bus B, il y a $\\cfrac{%s \\times %s}{100} = %s$ garçons.\\par"%(prctB, totB, decimaux(nbB)), u"On en déduit qu'il y a $%s + %s = %s$ garçons sur un total de $%s + %s = %s $ élèves.\\par" %(decimaux(nbA), decimaux(nbB), nbTotal, totA, totB, Total), u" Le pourcentage de garçons sur l'ensemble des deux bus est donc de $\\cfrac{%s}{%s}\\times 100 %s %s%s$" %(nbTotal, Total, approx, decimaux(prct_final_arrondi), "\,\\%")], #À l'ordinateurs [u"En quatrièmes, $\\cfrac{%s \\times %s}{100} = %s$ élèves possèdent un ordinateur.\\par"%(prctA, totA, decimaux(nbA)), u"En troisièmes, $\\cfrac{%s \\times %s}{100} = %s$ élèves possèdent un ordinateur.\\par"%(prctB, totB, decimaux(nbB)), u"On en déduit qu'il y a $%s + %s = %s$ élèves qui possèdent un ordinateur sur un total de $%s + %s = %s $ élèves.\\par" %(decimaux(nbA), decimaux(nbB), nbTotal, totA, totB, Total), u" Le pourcentage d'élèves possédant un ordinateur est donc de $\\cfrac{%s}{%s}\\times 100 %s %s%s$" %(nbTotal, Total, approx, decimaux(prct_final_arrondi), "\,\\%")], ][i] exo = ["\\exercice", texte, "\\begin{itemize}", ligne1, ligne2, "\\end{itemize}", question, ] cor = ["\\exercice*", texte, "\\begin{itemize}", ligne1, ligne2, "\\end{itemize}", question, "\\dotfill\\par" ] + correction return (exo,cor) pyromaths/src/troisiemes/puissances.py0000644000175000017500000001643111702101415020770 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils.Arithmetique import pgcd, valeur_alea from random import choice, randrange import string, math # # ------------------- PUISSANCES ------------------- def tex_puissances_0(a): if isinstance(a, tuple): return '\\cfrac{\\nombre{%s} \\times 10^{%s} \\times \\nombre{%s} \\times 10^{%s}}{\\nombre{%s} \\times \\big( 10^{%s} \\big) ^%s}' % \ (a[0], a[3], a[1], a[4], a[2], a[5], a[6]) def tex_puissances_1(a): if isinstance(a, tuple): if a[4] < 0: return '\\cfrac{\\nombre{%s} \\times \\nombre{%s}}{\\nombre{%s}} \\times \\cfrac{10^{%s+(%s)}}{10^{%s \\times %s}}' % \ (a[0], a[1], a[2], a[3], a[4], a[5], a[6]) else: return '\\cfrac{\\nombre{%s} \\times \\nombre{%s}}{\\nombre{%s}} \\times \\cfrac{10^{%s+%s}}{10^{%s \\times %s}}' % \ (a[0], a[1], a[2], a[3], a[4], a[5], a[6]) def tex_puissances_2(a): if isinstance(a, tuple): if ((a[0] * a[1]) * 1.) / a[2] == (a[0] * a[1]) / a[2]: if a[5] * a[6] < 0: return '\\nombre{%s} \\times 10^{%s-(%s)}' % \ verifie_type(((a[0] * a[1]) / a[2], a[3] + a[4], a[5] * a[6])) else: return '\\nombre{%s} \\times 10^{%s-%s}' % verifie_type(((a[0] * a[1]) / a[2], a[3] + a[4], a[5] * a[6])) else: if a[5] * a[6] < 0: return '\\nombre{%s} \\times 10^{%s-(%s)}' % \ verifie_type((((a[0] * a[1]) * 1.) / a[2], a[3] + a[4], a[5] * a[6])) else: return '\\nombre{%s} \\times 10^{%s-%s}' % verifie_type((((a[0] * a[1]) * 1.) / a[2], a[3] + a[4], a[5] * a[6])) def tex_puissances_3(a): from math import floor, log10 b = int(floor(log10(((a[0] * a[1]) * 1.) / a[2]))) if isinstance(a, tuple) and b != 0: return '\\nombre{%s} \\times 10^{%s} \\times 10^{%s}' % \ verifie_type(((((a[0] * a[1]) * 1.) / a[2]) / 10 ** b, b, (a[3] + a[4]) - a[5] * a[6])) def tex_puissances_4(a): from math import floor, log10 b = int(floor(log10(((a[0] * a[1]) * 1.) / a[2]))) if isinstance(a, tuple): return '\\nombre{%s} \\times 10^{%s}' % verifie_type(((((a[0] * a[1]) * 1.) / a[2]) / 10 ** b, (b + a[3] + a[4]) - a[5] * a[6])) def verifie_type(a): # verifie si des nombres reels dans le tuple a sont en fait des nombres entiers et change leur type list = [] for i in range(len(a)): if str(a[i]).endswith('.0'): list.append(int(a[i] + .1)) else: list.append(a[i]) return tuple(list) def valeurs_puissances(): # renvoie un tuple contenant les valeurs pour les deux exercices sur les puissances from math import floor, log10 (max, emax) = (10, 2) while True: (b1, b2) = (valeur_alea(2, max), valeur_alea(2, max)) (b1, b2) = (b1 / pgcd(b1, b2), b2 / pgcd(b1, b2)) if b1 != 1 and b2 != 1: break while True: (n1, n2) = ((b1 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax), (b2 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax)) n3 = ((b1 * b2) * choice((2, 4, 5, 8))) * 10 ** randrange(-emax, emax) if int(floor(log10(((n1 * n2) * 1.) / n3))) != 0 and n1 != 1 and \ n2 != 1 and n3 != 1: break (e1, e2, e3, e4) = (valeur_alea(-10, 10), valeur_alea(-10, 10), valeur_alea(2, 10), valeur_alea(2, 5)) a = verifie_type((n1, n2, n3, e1, e2, e3, e4)) while True: (b1, b2) = (valeur_alea(2, max), valeur_alea(2, max)) (b1, b2) = (b1 / pgcd(b1, b2), b2 / pgcd(b1, b2)) if b1 != 1 and b2 != 1: break (n1, n2) = ((b1 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax + 1), (b2 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax + 1)) n3 = ((b1 * b2) * choice((1, 2, 4, 5, 8))) * 10 ** randrange(-emax, emax + 1) (e1, e2, e3, e4) = (valeur_alea(-10, 10), valeur_alea(-10, 10), valeur_alea(-10, -2), valeur_alea(2, 5)) b = verifie_type((n1, n2, n3, e1, e2, e3, e4)) return (a, b) def tex_puissances(): sd = string.maketrans('.', ',') # convertit les . en , (separateur decimal) valeurs = valeurs_puissances() i = randrange(2) exo = ['\\exercice''', u"Calculer les expressions suivantes et donner l'écriture scientifique du résultat."] exo.append('\\begin{multicols}{2}\\noindent') cor = ['\\exercice*''', u"Calculer les expressions suivantes et donner l'écriture scientifique du résultat."] cor.append('\\begin{multicols}{2}\\noindent') exo.append(u'\\[ \\thenocalcul = ' + tex_puissances_0(valeurs[i]).translate(sd) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_0(valeurs[i]).translate(sd) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_1(valeurs[i]).translate(sd) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_2(valeurs[i]).translate(sd) + '\\] ') if int(math.floor(math.log10(((valeurs[i][0] * valeurs[i][1]) * 1.) / valeurs[i][2]))) != \ 0: cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_3(valeurs[i]).translate(sd) + '\\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_puissances_4(valeurs[i]).translate(sd) + '} \\] ') exo.append('\\columnbreak\\stepcounter{nocalcul}%') cor.append('\\columnbreak\\stepcounter{nocalcul}%') exo.append(u'\\[ \\thenocalcul = ' + tex_puissances_0(valeurs[1 - i]).translate(sd) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_0(valeurs[1 - i]).translate(sd) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_1(valeurs[1 - i]).translate(sd) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_2(valeurs[1 - i]).translate(sd) + '\\] ') if int(math.floor(math.log10(((valeurs[1 - i][0] * valeurs[1 - i][1]) * 1.) / valeurs[1 - i][2]))) != 0: cor.append(u'\\[ \\thenocalcul = ' + tex_puissances_3(valeurs[1 - i]).translate(sd) + '\\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_puissances_4(valeurs[1 - i]).translate(sd) + '} \\] ') exo.append('\\end{multicols}') cor.append('\\end{multicols}') return (exo, cor) pyromaths/src/troisiemes/._troisiemes.py0000644000175000017500000000031511702101415021205 0ustar didrocksdidrocksMac OS X  2ATTRGވ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._systemes.py0000644000175000017500000000031511702101415020676 0ustar didrocksdidrocksMac OS X  2ATTRGއ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/.___init__.py0000644000175000017500000000031511702101415020561 0ustar didrocksdidrocksMac OS X  2ATTRG{55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/developpements.py0000644000175000017500000013036211702101415021645 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from .fractions import tex_frac, simplifie, tex_decomp_prod, decomp_prod, \ produit, den_com0 from ..outils.Arithmetique import valeur_alea, signe, pgcd import random # # ------------------- DEVELOPPEMENTS ------------------- def coef_opposes(a): # renvoie un tuple dont les valeurs sont les opposees de celles de a l = [] for i in range(len(a)): l.append(-a[i]) return tuple(l) def dev(a): # renvoi un tuple avec les 3 coefficients du developpement return (a[0][0] * a[1][0], a[0][0] * a[1][1] + a[0][1] * a[1][0], a[0][1] * a[1][1]) def somme_polynomes(a, b): # renvoie un tuple dont les valeurs sont les sommes des valeurs correspondantes dans a et b l = [] if len(a) > len(b): long = len(a) else: long = len(b) for i in range(long): if (len(a) - i) - 1 < 0: l.append(b[(len(b) - 1) - i]) elif (len(b) - i) - 1 < 0: l.append(a[(len(a) - 1) - i]) else: l.append(a[(len(a) - 1) - i] + b[(len(b) - 1) - i]) l.reverse() return tuple(l) def tex_coef(coef, var, bplus=0, bpn=0, bpc=0): # coef est le coefficient à écrire devant la variable var # bplus est un booleen : s'il est vrai, il faut ecrire le signe + # bpn est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef est negatif. # bpc est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef =! 0 ou 1 et var est non vide if coef != 0 and abs(coef) != 1: if var == '': if abs(coef) >= 1000: a = '\\nombre{%s}' % coef else: a = '%s' % coef else: if abs(coef) >= 1000: a = '\\nombre{%s}\\,%s' % (coef, var) else: a = '%s\\,%s' % (coef, var) if bplus and coef > 0: a = '+' + a elif coef == 1: if var == '': a = '1' else: a = '%s' % var if bplus: a = '+' + a elif coef == 0: a = '' elif coef == -1: if var == '': a = '-1' else: a = '-%s' % var if bpn and coef < 0 or bpc and coef != 0 and coef != 1 and var != '': a = '\\left( ' + a + '\\right)' return a def tex_dev0(a, bplus=0): # renvoi (a+b)², (a-b)² ou (a+b)(c+d) ou a(c+d) ou (a+b)*c # a est de la forme ((3, 2), (3, 2)) pour (3x+2)(3x+2) (ca, cb, cc, cd) = (a[0][0], a[0][1], a[1][0], a[1][1]) # coefficients a, b, c et d if ca == 0 and cb == 0 or cc == 0 and cd == 0: return '0' elif a[0] == a[1]: # (a+b)² ou (a-b)² if ca == 0: return '%s^2' % tex_coef(cb, '', bpn=1) elif cb == 0: return '%s^2' % tex_coef(ca, 'x', bpc=1) else: return '(%s%s)^2' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=1)) else: # (a+b)(c+d) if ca == 0 or cb == 0: if cc == 0 or cd == 0: return '%s%s\\times %s%s' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=ca != 0), tex_coef(cc, 'x', bpn=1), tex_coef(cd, '', bplus=cc != 0, bpn=1)) else: return '%s%s\\,(%s%s)' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=ca != 0), tex_coef(cc, 'x'), tex_coef(cd, '', bplus=cc != 0)) elif cc == 0 or cd == 0: if cc == 0 and cd == 1: return '%s%s' % (tex_coef(ca, 'x', bplus=bplus), tex_coef(cb, '', bplus=ca != 0)) else: return '(%s%s)\\times %s%s' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=ca != 0), tex_coef(cc, 'x', bpn=1), tex_coef(cd, '', bplus=cc != 0, bpn= 1)) else: return '(%s%s)\\,(%s%s)' % (tex_coef(ca, 'x'), tex_coef(cb, '', bplus=1), tex_coef(cc, 'x'), tex_coef(cd, '', bplus=1)) def tex_dev1(a, bplus=0, bpar=0, bpn=0): # renvoi le developpement (a)²+2*a*b+(b)², (a)²-2*a*b+(b)², (a)²-(b)² ou a*c+a*d+b*c+b*d # a est de la forme ((3, 2)(3, 2)) pour (3x+2)(3x+2) (ca, cb, cc, cd) = (a[0][0], a[0][1], a[1][0], a[1][1]) # coefficients a, b, c et d if a[0] == a[1]: # (a+b)² ou (a-b)² if signe(ca) == signe(cb): # (a+b)² (ca, cb) = (abs(ca), abs(cb)) texte = '%s^2+2\\times %s\\times %s+%s^2' % (tex_coef(ca, 'x', bpc=1), tex_coef(ca, 'x', bpn=1), tex_coef(cb, '', bpn=1), tex_coef(cb, '', bpn=1, bpc=1)) if bpar: return '(' + texte + ')' else: return texte else: # (a-b)² (ca, cb) = (abs(ca), abs(cb)) texte = '%s^2-2\\times %s\\times %s+%s^2' % (tex_coef(ca, 'x', bpc=1), tex_coef(ca, 'x', bpn=1), tex_coef(cb, '', bpn=1), tex_coef(cb, '', bpn=1, bpc=1)) if bpar: return '(' + texte + ')' else: return texte if abs(ca) == abs(cc) and abs(cb) == abs(cd): # (a+b)(a-b) ou (a+b)(-a+b) if ca == cc: # (a+b)(a-b) texte = '%s^2-%s^2' % (tex_coef(ca, 'x', bpc=1), tex_coef(abs(cb), '')) if bpar: return '(' + texte + ')' else: return texte else: # (a+b)(-a+b) texte = '%s^2-%s^2' % (tex_coef(cb, '', bpn=1), tex_coef(abs(ca), 'x', bpc=1)) if bpar: return '(' + texte + ')' else: return texte else: # (a+b)(c+d) if cc == 0 and cd == 1: texte = '%s%s' % (tex_coef(ca, 'x', bplus=bplus), tex_coef(cb, '', bplus=ca != 0)) if bpar: return '(' + texte + ')' else: return texte else: texte = '%s+%s+%s+%s' % (tex_coef(ca * cc, 'x^2', bpn=bpn), tex_coef(ca * cd, 'x', bpn=1), tex_coef(cb * cc, 'x', bpn=1), tex_coef(cb * cd, '', bpn=1)) if bpar: return '(' + texte + ')' else: return texte def tex_developpe1(a, exo, cor): # developpe l'expression a exo.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev1(a) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(dev(a)) + '} \\]') def tex_developpe2(a, nega, b, negb, cor, exo=None): # developpe l'expression a plus l'expression b. if nega: if negb: if b[1][0] == 0 and b[1][1] == 1: if exo: exo.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + '-(' + tex_dev0(b) + ')' + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + '-(' + tex_dev0(b) + ')' + '\\]') elif a[1][0] == 0 and a[1][1] == 1: if exo: exo.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev0(a) + ')-' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev0(a) + ')-' + tex_dev0(b) + '\\]') else: if exo: exo.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + '-' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + '-' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev1(a) + ')-(' + tex_dev1(b) + ')' + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_trinome(dev(a)) + ')-(' + tex_trinome(dev(b)) + ')' + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(coef_opposes(dev(a))) + tex_trinome(coef_opposes(dev(b)), bplus=1) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(somme_polynomes(coef_opposes(dev(a)), coef_opposes(dev(b)))) + '} \\]') else: if a[1][0] == 0 and a[1][1] == 1: if exo: exo.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev0(a) + ')+' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev0(a) + ')+' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev1(a) + ')+' + tex_dev1(b, bpn=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_trinome(dev(a)) + ')+' + tex_trinome(dev(b)) + '\\]') elif b[1][0] == 0 and b[1][1] == 1: if exo: exo.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + tex_dev0(b, bplus= 1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + tex_dev0(b, bplus=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev1(a) + ')' + tex_dev1(b, bplus=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_trinome(dev(a)) + ')' + tex_trinome(dev(b), bplus=1) + '\\]') else: if exo: exo.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + '+' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-' + tex_dev0(a) + '+' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_dev1(a) + ')+' + tex_dev1(b, bpn=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '-(' + tex_trinome(dev(a)) + ')' + tex_trinome(dev(b), bplus=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(coef_opposes(dev(a))) + tex_trinome(dev(b), bplus=1) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(somme_polynomes(coef_opposes(dev(a)), dev(b))) + '} \\]') elif negb: if b[1][0] == 0 and b[1][1] == 1: if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '-(' + tex_dev0(b) + ')' + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '-(' + tex_dev0(b) + ')' + '\\]') else: if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '-' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '-' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev1(a) + '-(' + tex_dev1(b) + ')' + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(dev(a)) + '-(' + tex_trinome(dev(b)) + ')' + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(dev(a)) + tex_trinome(coef_opposes(dev(b)), bplus=1) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(somme_polynomes(dev(a), coef_opposes(dev(b)))) + '} \\]') else: if b[1][0] == 0 and b[1][1] == 1: if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + tex_dev0(b, bplus=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + tex_dev0(b, bplus=1) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev1(a) + tex_dev1(b, bplus=1) + '\\]') else: if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '+' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev0(a) + '+' + tex_dev0(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev1(a) + '+' + tex_dev1(b) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(dev(a)) + tex_trinome(dev(b), bplus=1) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(somme_polynomes(dev(a), dev(b))) + '} \\]') def tex_trinome(a, bplus=0, bpar=0): # renvoi le trinome ax²+bx+c # bplus est un booleen : s'il est vrai, le premier terme est precede d'un signe + si son coefficient est positif. # bpar est un booleen : s'il est vrai, ecrit des parentheses autour du trinome si deux valeurs au moins ne sont pas nulles ou si la valeur est - texte = '%s%s%s' % (tex_coef(a[0], 'x^2', bplus=bplus), tex_coef(a[1], 'x', bplus=bplus or a[0] != 0), tex_coef(a[2], '', bplus=bplus or a[0] != 0 or a[1] != 0)) if bpar: v0 = 0 for i in range(3): # compte le nombre de valeurs nulles if a[i] == 0: v0 = v0 + 1 if v0 == 2: # une seule valeur non nulle (on suppose que les trois coef ne sont pas nuls) if a[0] < 0 or a[1] < 0 or a[2] < 0: # le coefficient non nul est negatif, il faut donc des parentheses return '(' + texte + ')' else: return texte else: return '(' + texte + ')' else: return texte def valeurs_apb2(pyromax): # renvoie un tuple contenant ((3,5),(3,5)) a = valeur_alea(1, pyromax) b = valeur_alea(1, pyromax) return ((a, b), (a, b)) def valeurs_amb2(pyromax): # renvoie un tuple contenant ((3,-5),(3,-5)) a = valeur_alea(1, pyromax) b = valeur_alea(-pyromax, -1) return ((a, b), (a, b)) def valeurs_apbamb(pyromax): # renvoie un tuple contenant ((3,-5),(3,+5)) a = valeur_alea(1, pyromax) b = valeur_alea(1, pyromax) if random.randrange(2): return ((a, -b), (a, b)) else: return ((a, b), (a, -b)) def valeurs_distr(pyromax): # renvoie in tuple contenant ((a,b),(c,d)) avec a != c ou b != d (en valeur # absolue) a = valeur_alea(-pyromax, pyromax) b = valeur_alea(-pyromax, pyromax) c = valeur_alea(-pyromax, pyromax) d = valeur_alea(-pyromax, pyromax) while abs(a) == abs(c) and abs(b) == abs(d): c = valeur_alea(-pyromax, pyromax) d = valeur_alea(-pyromax, pyromax) return ((a, b), (c, d)) # # ------------------- FACTORISATIONS ------------------- def facteur_commun(a, b): #renvoie le facteur commun et les les deux autres binomes if a[0] == b[0]: # recherche le facteur commun et le nomme f0, f1 et f2 etant les deux autres facteurs (f0, f1, f2) = (a[0], a[1], b[1]) elif a[0] == b[1]: (f0, f1, f2) = (a[0], a[1], b[0]) elif a[1] == b[0]: (f0, f1, f2) = (a[1], a[0], b[1]) elif a[1] == b[1]: (f0, f1, f2) = (a[1], a[0], b[0]) return (f0, f1, f2) def facteur_commun2(f, nega, negb): # renvoie (2x+3)(4x+5+6x+7) sous la forme ((2,3),(4,5),(6,7)) if nega: if negb: return (f[0], coef_opposes(f[1]), coef_opposes(f[2])) else: return (f[0], coef_opposes(f[1]), f[2]) elif negb: return (f[0], f[1], coef_opposes(f[2])) else: return (f[0], f[1], f[2]) def facteur_commun3(f, nega, negb): # renvoie un tuple contenant les deux binomes finaux de la mise en facteur if nega and negb: return (f[0], somme_polynomes(coef_opposes(f[1]), coef_opposes(f[2]))) elif nega: return (f[0], somme_polynomes(coef_opposes(f[1]), f[2])) elif negb: return (f[0], somme_polynomes(f[1], coef_opposes(f[2]))) else: return (f[0], somme_polynomes(f[1], f[2])) def tex_binome(a, bplus=0, bpar=0): # renvoi le binome ax+b # bplus est un booleen : s'il est vrai, le premier terme est precede d'un signe + si son coefficient est positif. # bpar est un booleen : s'il est vrai, ecrit des parentheses autour du binome si les deux coef ne sont pas nuls ou si le seul coef est - texte = '%s%s' % (tex_coef(a[0], 'x', bplus=bplus), tex_coef(a[1], '', bplus=bplus or a[0] != 0)) if bpar: if (a[0] != 0 or a[1] < 0) and (a[1] != 0 or a[0] < 0): texte = '(' + texte + ')' return texte def tex_trinome_alea(a, bplus=0): # renvoi le trinome ax²+bx+c dans le desordre valeurs = [tex_coef(a[0], 'x^2', bplus=1), tex_coef(a[1], 'x', bplus= 1), tex_coef(a[2], '', bplus=1)] ordre1 = [] while ordre1 == [] or ordre1 == [0, 1, 2]: ordre0 = [i for i in range(3)] ordre1 = [ordre0.pop(random.randrange(3 - i)) for i in range(3)] liste = [valeurs[ordre1[i]] for i in range(3)] if not bplus and liste[0].startswith('+'): liste[0] = liste[0].replace('+', '', 1) return '%s%s%s' % tuple(liste) def tex_facteur_commun0(a): #renvoie -(2x+3)(x+5)+(2x+3)(3x+6) if a[2]: if a[3]: return '-' + tex_dev0(a[0]) + '-' + tex_dev0(a[1]) else: return '-' + tex_dev0(a[0]) + '+' + tex_dev0(a[1]) elif a[3]: return tex_dev0(a[0]) + '-' + tex_dev0(a[1]) else: return tex_dev0(a[0]) + '+' + tex_dev0(a[1]) def tex_facteur_commun1(f, nega, negb): # renvoie (2x+3)(-(x+5)+3x+6) texte = tex_binome(f[0], bpar=1) if nega or negb: texte = texte + '\\,\\big( ' else: texte = texte + '\\,(' if nega: texte = texte + '-' + tex_binome(f[1], bpar=1) else: texte = texte + tex_binome(f[1], bpar=0) if negb: texte = texte + '-' + tex_binome(f[2], bpar=1) else: texte = texte + tex_binome(f[2], bplus=1) if nega or negb: texte = texte + '\\big)' else: texte = texte + ')' return texte def tex_facteur_commun2(a): # renvoie renvoie (2x+3)(-x-5+3x+6) return tex_binome(a[0], bpar=1) + '\\,(' + tex_binome(a[1]) + \ tex_binome(a[2], bplus=1) + ')' def tex_a2moinsb2_0(a): # renvoie 16-(2x+3)² if a[0][0] == 0: return '%s-%s^2' % (a[0][1] ** 2, tex_binome(a[1], bpar=1)) else: return '%s^2-%s' % (tex_binome(a[0], bpar=1), a[1][1] ** 2) def tex_a2moinsb2_2(a): # renvoie (4+2x+3)(4-(2x+3)) if a[0][0] == 0: return '(%s%s)\\,\\big( %s-%s\\big)' % (tex_binome(a[0]), tex_binome(a[1], bplus=1), tex_binome(a[0]), tex_binome(a[1], bpar=1)) else: return '(%s%s)\\,(%s-%s)' % (tex_binome(a[0]), tex_binome(a[1], bplus=1), tex_binome(a[0]), tex_binome(a[1], bpar=1)) def tex_a2moinsb2_3(a): # renvoie (4+2x+3)(4-2x-3) if a[0][0] == 0: return '(%s%s)\\,(%s%s)' % (tex_binome(a[0]), tex_binome(a[1], bplus=1), tex_binome(a[0]), tex_binome(coef_opposes(a[1]), bplus= 1)) else: return '' def tex_facteur_commun(valeurs, cor, exo=None): # ecrit toutes les etapes de la factorisation (a, b, nega, negb) = valeurs f = facteur_commun(a, b) if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_facteur_commun0(valeurs) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_facteur_commun0(valeurs) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_facteur_commun1(f, nega, negb) + '\\]') f2 = facteur_commun2(f, nega, negb) if nega and f2[1][0] != 0 and f2[1][1] != 0 or negb and f2[2][0] != \ 0 and f2[2][0] != 0: cor.append(u'\\[ \\thenocalcul = ' + tex_facteur_commun2(f2) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_dev0((f2[0], somme_polynomes(f2[1], f2[2]))) + '} \\]') def tex_a2moinsb2(valeurs, cor, exo): # ecrit toutes les etapes de la factorisation if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_a2moinsb2_0(valeurs) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_a2moinsb2_0(valeurs) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + '%s^2-%s^2' % (tex_binome(valeurs[0], bpar=1), tex_binome(valeurs[1], bpar=1)) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_a2moinsb2_2(valeurs) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_a2moinsb2_3(valeurs) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_dev0((somme_polynomes(valeurs[0], valeurs[1]), somme_polynomes(valeurs[0], coef_opposes(valeurs[1])))) + '} \\]') def valeurs_facteur_commun(pyromax): # renvoie les valeurs pour obtenir un facteur commun. a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) while a[0] == a[1]: # on refuse un carre a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) if random.randrange(2) == 0: while True: b = (a[random.randrange(2)], (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) if b[0] != b[1]: break else: while True: b = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), a[random.randrange(2)]) if b[0] != b[1]: break (nega, negb) = (random.randrange(2), random.randrange(2)) return (a, b, nega, negb) def valeurs_facteur1(pyromax): # renvoie les valeurs pour obtenir un facteur commun facteur de 1 a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) while a[0] == a[1]: # on refuse un carre a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) b = (a[random.randrange(2)], (0, 1)) if random.randrange(2) == 1: # le 1 est dans le deuxieme terme return (a, b, random.randrange(2), random.randrange(2)) else: return (b, a, random.randrange(2), random.randrange(2)) def valeurs_facteurcarre(pyromax): # renvoie les valeurs pour obtenir un facteur commun au carre a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) while a[0] == a[1]: # on refuse un carre a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) if random.randrange(2) == 0: b = (a[0], a[0]) else: b = (a[1], a[1]) if random.randrange(2) == 0: # le carre est en premier return (b, a, 0, random.randrange(2)) else: return (a, b, random.randrange(2), 0) def valeurs_facteura2mb2(pyromax): # renvoie (((a,b),(a,-b)),((a,b),(c,d));nega,negb) a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) while a[0] == a[1]: # on refuse un carre a = ((valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)), (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax))) if random.randrange(2) == 0: a = ((abs(a[0][0]), a[0][1]), a[1]) b = (a[0], (a[0][0], -a[0][1])) else: a = (a[0], (abs(a[1][0]), a[1][1])) b = (a[1], (a[1][0], -a[1][1])) if random.randrange(2) == 0: # le a²-b² est en premier return (b, a, 0, random.randrange(2)) else: return (a, b, random.randrange(2), 0) def valeurs_a2moinsb2(pyromax): # renvoie les valeurs pour obtenir a²-(bx+c)² a = (0, valeur_alea(1, pyromax)) b = (valeur_alea(-pyromax, pyromax), valeur_alea(-pyromax, pyromax)) if random.randrange(2) == 0: # le nombre est en premier return (a, b) else: return (b, a) def factorisation0(cor, exo=None, valeurs=None): # factorise (ax+b)(cx+d)+(ax+b)(ex+f) if not valeurs: valeurs = valeurs_facteur_commun(10) tex_facteur_commun(valeurs, cor, exo) def tex_factorisation1(valeurs): # renvoie la premiere etape de la factorisation 1 if valeurs[2] == 0: siga = '' else: siga = '-' if valeurs[3] == 0: sigb = '+' else: sigb = '-' if valeurs[0][1][0] == 0 and valeurs[0][1][1] == 1: # le 1 est dans la premiere partie return '%s%s%s%s' % (siga, tex_trinome(dev(valeurs[0]), bpar=1), sigb, tex_dev0(valeurs[1])) else: return '%s%s%s%s' % (siga, tex_dev0(valeurs[0]), sigb, tex_trinome(dev(valeurs[1]), bpar=1)) def factorisation1(cor, exo=None, valeurs=None): # factorise (ax+b)(cx+d)+(ax+b) if not valeurs: valeurs = valeurs_facteur1(10) if valeurs[2] == 0: siga = '' else: siga = '-' if valeurs[3] == 0: sigb = '+' else: sigb = '-' if valeurs[0][1][0] == 0 and valeurs[0][1][1] == 1: # le 1 est dans la premiere partie texte = '%s%s%s%s' % (siga, tex_trinome(dev(valeurs[0]), bpar=1), sigb, tex_dev0(valeurs[1])) cor.append(u'\\[ \\thenocalcul = ' + texte + '\\]') if exo: exo.append(u'\\[ \\thenocalcul = ' + texte + '\\]') texte = '%s%s\\times1%s%s' % (siga, tex_trinome(dev(valeurs[0]), bpar=1), sigb, tex_dev0(valeurs[1])) cor.append(u'\\[ \\thenocalcul = ' + texte + '\\]') else: texte = '%s%s%s%s' % (siga, tex_dev0(valeurs[0]), sigb, tex_trinome(dev(valeurs[1]), bpar=1)) cor.append(u'\\[ \\thenocalcul = ' + texte + '\\]') if exo: exo.append(u'\\[ \\thenocalcul = ' + texte + '\\]') texte = '%s%s%s%s\\times1' % (siga, tex_dev0(valeurs[0]), sigb, tex_trinome(dev(valeurs[1]), bpar=1)) cor.append(u'\\[ \\thenocalcul = ' + texte + '\\]') f = facteur_commun(valeurs[0], valeurs[1]) cor.append(u'\\[ \\thenocalcul = ' + tex_facteur_commun1(f, valeurs[2], valeurs[3]) + '\\]') f2 = facteur_commun2(f, valeurs[2], valeurs[3]) if valeurs[2] and f2[1][0] != 0 and f2[1][1] != 0 or valeurs[3] and \ f2[2][0] != 0 and f2[2][0] != 0: cor.append(u'\\[ \\thenocalcul = ' + tex_facteur_commun2(f2) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_dev0((f2[0], somme_polynomes(f2[1], f2[2]))) + '} \\]') def factorisation2(cor, exo=None, valeurs=None): # factorise (ax+b)(cx+d)+(ax+b)² if not valeurs: valeurs = valeurs_facteurcarre(10) tex_facteur_commun(valeurs, cor, exo) def tex_factorisation3(valeurs): # renvoie les deux premieres etapes de la factorisation 3 if valeurs[2] == 0: nega = '' else: nega = '-' if valeurs[3] == 0: negb = '+' else: negb = '-' if valeurs[0][0][0] == valeurs[0][1][0] and valeurs[0][0][1] == -valeurs[0][1][1]: return ('%s%s%s%s' % (nega, tex_trinome(dev(valeurs[0])), negb, tex_dev0(valeurs[1])), '%s%s%s%s' % (nega, tex_dev1(valeurs[0]), negb, tex_dev0(valeurs[1]))) else: return ('%s%s%s%s' % (nega, tex_dev0(valeurs[0]), negb, tex_trinome(dev(valeurs[1]))), '%s%s%s%s' % (nega, tex_dev0(valeurs[0]), negb, tex_dev1(valeurs[1]))) def factorisation3(cor, exo=None, valeurs=None): # factorise (ax+b)(cx+d)+(ax)²-b² if not valeurs: valeurs = valeurs_facteura2mb2(10) textes = tex_factorisation3(valeurs) if exo: exo.append(u'\\[ \\thenocalcul = ' + textes[0] + '\\]') cor.append(u'\\[ \\thenocalcul = ' + textes[0] + '\\]') cor.append(u'\\[ \\thenocalcul = ' + textes[1] + '\\]') tex_facteur_commun(valeurs, cor) def factorisation4(cor, exo=None, valeurs=None): #factorise 64-(x-5)² if not valeurs: valeurs = valeurs_a2moinsb2(10) tex_a2moinsb2(valeurs, cor, exo) def factorisation5(cor, exo=None, valeurs=None): # factorise a²-b² if not valeurs: valeurs = valeurs_apbamb(10) if valeurs[0][0] == -valeurs[1][0]: valeurs = ((valeurs[0][0], abs(valeurs[0][1])), (valeurs[1][0], abs(valeurs[1][1]))) else: valeurs = ((abs(valeurs[0][0]), valeurs[0][1]), (abs(valeurs[1][0]), valeurs[1][1])) if exo: exo.append(u'\\[ \\thenocalcul = ' + tex_trinome(dev(valeurs)) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(dev(valeurs)) + '\\]') cor.append(u'\\[ \\thenocalcul = ' + tex_dev1(valeurs) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_dev0(valeurs) + '} \\]') def tex_factorisation6(valeurs): # renvoie les deux premieres etapes de la factorisation 6 if valeurs[0][0] == valeurs[0][1]: # le carre est en premier if valeurs[3] == 0: # on insere un signe + return (tex_trinome_alea(dev(valeurs[0])) + '+' + tex_dev0(valeurs[1]), tex_trinome(dev(valeurs[0])) + '+' + tex_dev0(valeurs[1])) else: return (tex_trinome_alea(dev(valeurs[0])) + '-' + tex_dev0(valeurs[1]), tex_trinome(dev(valeurs[0])) + '-' + tex_dev0(valeurs[1])) else: if valeurs[2] == 0: # on insere un signe + return (tex_dev0(valeurs[0]) + tex_trinome_alea(dev(valeurs[1]), bplus=1), tex_dev0(valeurs[0]) + tex_trinome(dev(valeurs[1]), bplus=1)) else: return ('-' + tex_dev0(valeurs[0]) + tex_trinome_alea(dev(valeurs[1]), bplus=1), '-' + tex_dev0(valeurs[0]) + tex_trinome(dev(valeurs[1]), bplus=1)) def factorisation6(cor, exo=None, valeurs=None): # factorise (ax+b)(cx+d)+2abx+a²x²+b² if not valeurs: valeurs = valeurs_facteurcarre(10) textes = tex_factorisation6(valeurs) if exo: exo.append(u'\\[ \\thenocalcul = ' + textes[0] + '\\]') cor.append(u'\\[ \\thenocalcul = ' + textes[0] + '\\]') cor.append(u'\\[ \\thenocalcul = ' + textes[1] + '\\]') tex_facteur_commun((valeurs[0], valeurs[1], valeurs[2], valeurs[3]), cor) # # ------------------- DEV-FACT-EQUAT ------------------- def choix_exo(a): # renvoie un tuple contenant les valeurs if a == 0: return valeurs_facteur_commun(10) elif a == 1: return valeurs_facteur1(10) elif a == 2: return valeurs_facteurcarre(10) elif a == 3: return valeurs_facteura2mb2(10) else: return valeurs_facteurcarre(10) def valeur_quotient(): # renvoie un tuple contenant la valeur du quotient à calculer (a, b) = (random.randrange(-10, 1), random.randrange(1, 11)) return (a // pgcd(a, b), b // pgcd(a, b)) def tex_initial(exos, a): # renvoie l'écriture de l'expression A if exos == 0 or exos == 2: return tex_facteur_commun0(a) elif exos == 1: return tex_factorisation1(a) elif exos == 3: return tex_factorisation3(a)[0] else: return tex_factorisation6(a)[0] def fin_fact(a): # renvoie un tuple contenant la version factorisee de a return facteur_commun3(facteur_commun(a[0], a[1]), a[2], a[3]) def tex_equations(fact, cor): # renvoie un tuple contenant les deux binomes egaux a 0 cor.append(u'Nous savons que $A=%s$. Nous devons donc résoudre $%s=0$.\\par' % (tex_dev0(fact), tex_dev0(fact))) cor.append('Un produit de facteurs est nul signifie qu\'un des facteurs est nul. Donc :') cor.append('\\[%s=0 \\qquad\\text{ou}\\qquad %s=0\\]' % (tex_binome(fact[0]), tex_binome(fact[1]))) eq = equations1(fact) if not isinstance(eq, tuple): cor.append("\\fbox{Cette équation n'admet aucune solution.}") elif not isinstance(eq[0], tuple): cor.append('\\[ %s=%s \\]' % (tex_coef(eq[1][0], 'x'), eq[1][1])) if eq[1][0] != 1: cor.append('\\[ x=%s \\]' % tex_frac(equations2(eq)[1])) cor.append(u'\\fbox{La solution de cette équation est \\,$%s$\\,.}' % tex_frac(equations3(eq)[1])) elif not isinstance(eq[1], tuple): cor.append('\\[ %s=%s \\]' % (tex_coef(eq[0][0], 'x'), eq[0][1])) if eq[0][0] != 1: cor.append('\\[ x=%s \\]' % tex_frac(equations2(eq)[0])) cor.append(u'\\fbox{La solution de cette équation est \\,$%s$\\,.}' % tex_frac(equations3(eq)[0])) else: cor.append('\\[%s=%s \\qquad\\text{ou}\\qquad %s=%s\\]' % (tex_coef(eq[0][0], 'x'), eq[0][1], tex_coef(eq[1][0], 'x'), eq[1][1])) if eq[0][0] != 1 or eq[1][0] != 1: cor.append('\\[x=%s \\qquad\\text{ou}\\qquad x=%s\\]' % (tex_frac(equations2(eq)[0]), tex_frac(equations2(eq)[1]))) cor.append(u'\\fbox{Les solutions de cette équation sont \\,$%s\\,\\text{ et }\\,%s$\\,.}' % (tex_frac(equations3(eq)[0]), tex_frac(equations3(eq)[1]))) def equations1(a): #renvoie ((9,5),(3,-7)) pour pouvoir ecrire 9x=5 ou 3x=-7 if a[0][0] == 0: if a[1][0] == 0: return '' else: return ('', (a[1][0], -a[1][1])) elif a[1][0] == 0: return ((a[0][0], -a[0][1]), '') else: return ((a[0][0], -a[0][1]), (a[1][0], -a[1][1])) def equations2(a): # renvoie ((5,9),(-7,3)) pour pouvoir ecrire x=5/9 ou x=-7/3 if not isinstance(a, tuple): return '' elif not isinstance(a[0], tuple): return ('', (a[1][1], a[1][0])) elif not isinstance(a[1], tuple): return ((a[0][1], a[0][0]), '') else: return ((a[0][1], a[0][0]), (a[1][1], a[1][0])) def equations3(a): # renvoie les solutions éventuellement simplifiée a = equations2(a) if not isinstance(a, tuple): return '' elif not isinstance(a[0], tuple): if simplifie(a[1]): return ('', simplifie(a[1])) else: return a elif not isinstance(a[1], tuple): if simplifie(a[0]): return (simplifie(a[0]), '') else: return a else: if simplifie(a[0]): if simplifie(a[1]): return (simplifie(a[0]), simplifie(a[1])) else: return (simplifie(a[0]), a[1]) elif simplifie(a[1]): return (a[0], simplifie(a[1])) else: return a def developpements(expr, exos, cor): # effectue les developpements if exos != 3 and exos != 6: tex_developpe2(expr[0], expr[2], expr[1], expr[3], cor) elif exos == 6 and expr[0][0] == expr[0][1] or exos == 3 and expr[0][0][0] == \ expr[0][1][0] and expr[0][0][1] == -expr[0][1][1]: cor.append(u'\\[ \\thenocalcul = ' + tex_initial(exos, expr) + '\\]') if expr[2]: siga = '-' else: siga = '' if expr[3]: sigb = '-' else: sigb = '' cor.append(u'\\[ \\thenocalcul = ' + '%s%s%s%s' % (siga, tex_trinome(dev(expr[0])), sigb, tex_dev1(expr[1], bpar=expr[3], bplus=expr[3] - 1)) + '\\]') if expr[2]: a = coef_opposes(dev(expr[0])) else: a = dev(expr[0]) if expr[3]: b = coef_opposes(dev(expr[1])) else: b = dev(expr[1]) cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(a) + tex_trinome(b, bplus=1) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(somme_polynomes(a, b)) + '} \\]') else: cor.append(u'\\[ \\thenocalcul = ' + tex_initial(exos, expr) + '\\]') if expr[2]: siga = '-' else: siga = '' if expr[3]: sigb = '-' else: sigb = '' cor.append(u'\\[ \\thenocalcul = ' + '%s%s%s%s' % (siga, tex_dev1(expr[0], bpar=expr[2], bplus=expr[2] - 1), sigb, tex_trinome(dev(expr[1]), bpar=expr[3], bplus=expr[3] - 1)) + '\\]') if expr[2]: a = coef_opposes(dev(expr[0])) else: a = dev(expr[0]) if expr[3]: b = coef_opposes(dev(expr[1])) else: b = dev(expr[1]) cor.append(u'\\[ \\thenocalcul = ' + tex_trinome(a) + tex_trinome(b, bplus=1) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_trinome(somme_polynomes(a, b)) + '} \\]') def version_developpee(expr): # renvoie la version developpe de A if expr[2]: a = coef_opposes(dev(expr[0])) else: a = dev(expr[0]) if expr[3]: b = coef_opposes(dev(expr[1])) else: b = dev(expr[1]) return somme_polynomes(a, b) def tex_fractions(expr, nb, cor): # repond a la question sur la valeur de x a = version_developpee(expr) cor.append('Nous savons que $A=%s$\\,. Donc pour $x=%s$\\, : ' % (tex_trinome(a), tex_frac(nb))) cor.append(u'\\[ \\thenocalcul = ' + tex_valeurx0(a, nb) + '\\]') if nb == (0, 1): cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_valeurx1(a, nb) + '} \\]') else: cor.append(u'\\[ \\thenocalcul = ' + tex_valeurx1(a, nb) + '\\]') b = decomp_prod((a[0], 1), (nb[0] ** 2, nb[1] ** 2))[0:2] c = decomp_prod((a[1], 1), (nb[0], nb[1]))[0:2] a = (produit(b[0], b[1]), produit(c[0], c[1]), (a[2], 1)) if a[0][1] == a[1][1] == 1: cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_valeurx2(a, nb) + '} \\]') else: cor.append(u'\\[ \\thenocalcul = ' + tex_valeurx2(a, nb) + '\\]') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_valeurx3(a, nb) + '} \\]') def tex_valeurx0(a, nb): if nb == (0, 1): return '%s%s%s' % (tex_coef(a[0], '\\times %s^2' % tex_frac(nb)), tex_coef(a[1], '\\times %s' % tex_frac(nb), bplus=a[0]), tex_coef(a[2], '', bplus=a[0] or a[1])) else: return '%s%s%s' % (tex_coef(a[0], '\\times\\left(%s\\right)^2' % tex_frac(nb)), tex_coef(a[1], '\\times\\left(%s\\right)' % tex_frac(nb), bplus=a[0]), tex_coef(a[2], '', bplus=a[0] or a[1])) def tex_valeurx1(a, nb): if nb == (0, 1): return tex_coef(a[2], '') elif nb[1] == 1: return tex_coef(a[0] * nb[0] ** 2, '') + tex_coef(a[1] * nb[0], '', bplus=a[0]) + tex_coef(a[2], '', bplus=a[0] or a[1]) else: texte = '' if a[0] != 0: a0 = ((a[0], 1), (nb[0] ** 2, nb[1] ** 2)) if isinstance(decomp_prod(a0[0], a0[1])[2], tuple): texte = tex_coef(1, tex_decomp_prod(decomp_prod(a0[0], a0[1]))) else: texte = tex_coef(1, tex_frac(produit(a0[0], a0[1]))) if a[1] != 0: a1 = ((a[1], 1), (nb[0], nb[1])) if isinstance(decomp_prod(a1[0], a1[1])[2], tuple): texte = texte + tex_coef(1, tex_decomp_prod(decomp_prod(a1[0], a1[1])), bplus=a[0]) else: texte = texte + tex_coef(1, tex_frac(produit(a1[0], a1[1])), bplus=a[0]) texte = texte + tex_coef(a[2], '', bplus=1) return texte def tex_valeurx2(a, nb): if nb == (0, 1): return '' else: if a[0][1] == a[1][1] == 1: return tex_coef(a[0][0] + a[1][0] + a[2][0], '') else: c = den_com0(a[0], a[1]) texte = '' if a[0][0] != 0: texte = tex_coef(1, tex_frac((a[0][0] * c[0], a[0][1] * c[0]))) if a[1][0] != 0: texte = texte + tex_coef(1, tex_frac((a[1][0] * c[1], a[1][1] * c[1])), bplus=texte) if a[2][0] != 0: texte = texte + tex_coef(1, tex_frac(((a[2][0] * a[0][1]) * c[0], a[0][1] * c[0])), bplus=texte) return texte def tex_valeurx3(a, nb): if nb == (0, 1) or a[0][1] == a[1][1] == 1: return '' else: c = den_com0(a[0], a[1]) b = (a[0][0] * c[0] + a[1][0] * c[1] + (a[2][0] * a[0][1]) * c[0], a[0][1] * c[0]) if simplifie(b): return tex_frac(b) + '=' + tex_frac(simplifie(b)) else: return tex_frac(b) def tex_devfacteq(): exos = [0, 1, 2, 3, 6][random.randrange(5)] expr = choix_exo(exos) valeurx = valeur_quotient() fact = fin_fact(expr) exo = ['\\exercice'] exo.append('On donne $A=%s$\\,.' % tex_initial(exos, expr)) exo.append('\\begin{enumerate}') exo.append(u'\\item Développer et réduire $A$\\,.') exo.append('\\item Factoriser $A$\\,.') exo.append('\\item Calculer $A$ pour $x=%s$\\,.' % \ tex_frac(valeurx)) exo.append(u"\\item Résoudre l'équation $A=0$\\,.") # % tex_dev0(fact)) exo.append('\\end{enumerate}') cor = ['\\exercice*'] cor.append('On donne $A=%s$\\,.' % tex_initial(exos, expr)) cor.append('\\begin{enumerate}') cor.append(u'\\item Développer et réduire $A$\\,.') developpements(expr, exos, cor) cor.append('\\item Factoriser $A$\\,.') exec('factorisation' + str(exos) + '(cor,valeurs=expr)') cor.append('\\item Calculer $A$ pour $x=%s$\\,.\\par' % \ tex_frac(valeurx)) tex_fractions(expr, valeurx, cor) cor.append(u"\\item Résoudre l'équation $A=0$\\,.\\par") # % tex_dev0(fact)) tex_equations(fact, cor) cor.append('\\end{enumerate}') return (exo, cor) def tex_developpements(): nb_exos = 4 liste_exos = (valeurs_apb2, valeurs_amb2, valeurs_apbamb, valeurs_distr) exos = [] ordre_exos = [i for i in range(nb_exos)] for i in range(nb_exos): a = random.randrange(nb_exos - i) exos.append(liste_exos[ordre_exos.pop(a)](10)) exo = ['\\exercice'] exo.append(u'Développer et réduire les expressions suivantes.') exo.append('\\begin{multicols}{2}\\noindent') cor = ['\\exercice*'] cor.append(u'Développer et réduire les expressions suivantes.') cor.append('\\begin{multicols}{2}\\noindent') tex_developpe1(exos[0], exo, cor) exo.append('\\stepcounter{nocalcul}%') cor.append('\\stepcounter{nocalcul}%') tex_developpe1(exos[1], exo, cor) exo.append('\\stepcounter{nocalcul}%') cor.append('\\columnbreak\\stepcounter{nocalcul}%') tex_developpe1(exos[2], exo, cor) exo.append('\\stepcounter{nocalcul}%') cor.append('\\stepcounter{nocalcul}%') tex_developpe1(exos[3], exo, cor) cor.append('\\end{multicols}%') exos = [] sig = [random.randrange(2) for i in range(4)] ordre_exos = [i for i in range(nb_exos)] for i in range(nb_exos): a = random.randrange(nb_exos - i) exos.append(liste_exos[ordre_exos.pop(a)](10)) exo.append('\\stepcounter{nocalcul}%') cor.append('\\stepcounter{nocalcul}%') tex_developpe2(exos[0], sig[0], exos[1], sig[1], cor, exo) exo.append('\\stepcounter{nocalcul}%') cor.append('\\stepcounter{nocalcul}%') tex_developpe2(exos[2], sig[2], exos[3], sig[3], cor, exo) exo.append('\\end{multicols}') return (exo, cor) def tex_factorisations(): (nb_exos, ordre_exos, ordre) = (6, [], []) for i in range(nb_exos): ordre.append(str(i)) for i in range(nb_exos): ordre_exos.append(ordre.pop(random.randrange(nb_exos - i))) del ordre exo = ['\\exercice'] exo.append('Factoriser les expressions suivantes.') exo.append('\\begin{multicols}{2}\\noindent') cor = ['\\exercice*'] cor.append('Factoriser les expressions suivantes.') cor.append('\\begin{multicols}{2}\\noindent') for i in range(nb_exos): exec('factorisation' + str(ordre_exos[i]) + \ '(cor,exo)') exo.append('\\stepcounter{nocalcul}%') cor.append('\\stepcounter{nocalcul}%') exo.append('\\end{multicols}') cor.append('\\end{multicols}') return (exo, cor) pyromaths/src/troisiemes/fractions.py0000644000175000017500000004274311702101415020610 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils.Arithmetique import ppcm, pgcd, signe, valeur_alea from random import randrange # # ------------------- FRACTIONS ------------------- def den_com0(a, b): #renvoie un tuple contenant les 2 nombres par lesquels multiplier les deux denominateurs pour obtenir leur ppcm c = ppcm(a[1], b[1]) return (abs(c // a[1]), abs(c // b[1])) def den_com1(a, b): #renvoie un tuple contenant les fractions a et b avec le meme denominateur c = den_com0(a, b) sgn1 = signe(a[1]) sgn2 = signe(b[1]) return (((a[0] * c[0]) * sgn1, (a[1] * c[0]) * sgn1), ((b[0] * c[1]) * sgn2, (b[1] * c[1]) * sgn2)) def somme(a, b, sgn): #renvoie un tuple contenant la somme des fractions a et b ayant pour denominateur le ppcm de leurs denominateurs c = den_com1(a, b) if sgn == '+': return (c[0][0] + c[1][0], c[0][1]) else: return (c[0][0] - c[1][0], c[0][1]) def simplifie(a): #renvoie la fraction a simplifiee b = pgcd(a[0], a[1]) if b != 1: return (a[0] // b, a[1] // b) else: return '' def decomp_prod(a, b): #renvoie un tuple contenant les deux fractions apres simplification et un tuple contenant les nb par lesquels on #simplifie le produit de fractions c = pgcd(a[0], b[1]) d = pgcd(a[1], b[0]) sgn1 = signe(a[1]) sgn2 = signe(b[1]) if c == d == 1: return (((sgn1 * a[0]) // c, (sgn1 * a[1]) // d), ((sgn2 * b[0]) // d, (sgn2 * b[1]) // c), '') else: return (((sgn1 * a[0]) // c, (sgn1 * a[1]) // d), ((sgn2 * b[0]) // d, (sgn2 * b[1]) // c), (c, d)) def produit(a, b): #renvoie un tuple contenant le produit des fractions a et b sgn1 = signe(a[1] * b[1]) return ((sgn1 * a[0]) * b[0], (sgn1 * a[1]) * b[1]) def inverse(a): #renvoie l'inverse de la fraction a sgn1 = signe(a[0]) return (sgn1 * a[1], sgn1 * a[0]) def tex_frac(a): #renvoie l'ecriture au format tex de la fraction a if not isinstance(a, tuple): return '' else: a = ((a[0] * a[1]) // abs(a[1]), abs(a[1])) if a[1] == 1: if abs(a[1]) >= 1000: return '\nombre{%i}' % a[0] else: return '%i' % a[0] else: if abs(a[0]) >= 1000: if abs(a[1]) >= 1000: return '\cfrac{\\nombre{%s}}{\\nombre{%s}}' % a else: return '\cfrac{\\nombre{%s}}{%s}' % a elif abs(a[1]) >= 1000: return '\cfrac{%s}{\\nombre{%s}}' % a else: return '\cfrac{%s}{%s}' % a def OOo_frac(a): #renvoie l'ecriture au format OOo de la fraction a if not isinstance(a, tuple): return '' else: if a[1] == 1: return a[0] else: return '{{%s} over {%s}}' % a def tex_decomp_prod(a): #renvoie l'ecriture au format tex de la decomposition d'un produit if not isinstance(a[2], tuple): # pas de decomposition possible return '' elif a[2][0] == 1: # decomposition que du denominateur b = (a[0][0], a[0][1], a[2][1], a[1][0], a[2][1], a[1][1]) return '\cfrac{%s}{%s\\times\\bcancel{%s}}\\times\\cfrac{%s\\times\\bcancel{%s}}{%s}' % \ b elif a[2][1] == 1: b = (a[0][0], a[2][0], a[0][1], a[1][0], a[1][1], a[2][0]) # decomposition que du numerateur return '\cfrac{%s\\times\\cancel{%s}}{%s}\\times\\cfrac{%s}{%s\\times\\cancel{%s}}' % \ b else: # decomposition du numerateur et du denominateur b = (a[0][0], a[2][0], a[0][1], a[2][1], a[1][0], a[2][1], a[1][1], a[2][0]) return '\\cfrac{%s\\times\\cancel{%s}}{%s\\times\\bcancel{%s}}\\times\\cfrac{%s\\times\\bcancel{%s}}{%s\\times\\cancel{%s}}' % \ b def OOo_decomp_prod(a): #renvoie l'ecriture au format OOo de la decomposition du produit if a[2][0] == 1: if a[2][1] == 1: # pas de decomposition b = (a[0][0], a[2][1], a[1][0], a[1][1]) return '{{%s}over{%s}}times{{%s}over{%s}}' % b else: # decomposition que du denominateur b = (a[0][0], a[0][1], a[2][1], a[1][0], a[2][1], a[1][1]) return '{{%s}over{{%s}times overstrike{%s}}}times{{{%s}times overstrike{%s}}over{%s}}' % \ b elif a[2][1] == 1: b = (a[0][0], a[2][0], a[0][1], a[1][0], a[1][1], a[2][0]) # decomposition que du numerateur return '{{{%s}times overstrike{%s}}over{%s}}times{{%s}over{{%s}times overstrike{%s}}}' % \ b else: # decomposition du numerateur et du denominateur b = (a[0][0], a[2][0], a[0][1], a[2][1], a[1][0], a[2][1], a[1][1], a[2][0]) return '{{{%s}times overstrike{%s}}over{{%s}times overstrike{%s}}}times{{{%s}times overstrike{%s}}over{{%s}times overstrike{%s}}}' % \ b def tex_den_com0(a, b, c, sgn): # renvoie l'ecriture au format tex de la mise au meme denominateur des fraction a et b if not isinstance(c, tuple): # les deux fractions ont deja le meme denominateur return '' else: (sgn1, sgn2) = (signe(a[1]), signe(b[1])) if c[0] == 1: if c[1] == 1: d = (a[0] * sgn1, a[1] * sgn1, b[0] * sgn2, b[1] * sgn2) return '' else: d = (a[0] * sgn1, a[1] * sgn1, sgn, b[0] * sgn2, c[1], b[1] * sgn2, c[1]) return '\dfrac{%s}{%s}%s\\dfrac{%s_{\\times %s}}{%s_{\\times %s}}' % \ d elif c[1] == 1: d = (a[0] * sgn1, c[0], a[1] * sgn1, c[0], sgn, b[0] * sgn2, b[1] * sgn2) return '\dfrac{%s_{\\times %s}}{%s_{\\times %s}}%s\\dfrac{%s}{%s}' % \ d else: d = ( a[0] * sgn1, c[0], a[1] * sgn1, c[0], sgn, b[0] * sgn2, c[1], b[1] * sgn2, c[1], ) return '\dfrac{%s_{\\times %s}}{%s_{\\times %s}}%s\\dfrac{%s_{\\times %s}}{%s_{\\times %s}}' % \ d def tex_den_com1(a, sgn): # renvoie l'ecriture au format tex de la somme des fractions au meme denominateur if not isinstance(a, tuple): # les deux fractions ont deja le meme denominateur return '' else: (sgn1, sgn2) = (signe(a[0][1]), signe(a[1][1])) b = (a[0][0] * sgn1, a[0][1] * sgn1, sgn, a[1][0] * sgn2, a[1][1] * sgn2) return '\dfrac{%s}{%s}%s\\dfrac{%s}{%s}' % b def tex_somme_prod(valeurs, exo, cor): # calcul du type a+b*c, d contenant (+,*) (a, b, c, d) = (valeurs[0], valeurs[1], valeurs[2], valeurs[3]) if d[1] == '*': exo.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_frac(b) + '\\times' + tex_frac(c) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_frac(b) + '\\times' + tex_frac(c) + '\\] ') e = decomp_prod(b, c) if e[2] != '': cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_decomp_prod(decomp_prod(b, c)) + '\\] ') else: exo.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_frac(b) + '\\div' + tex_frac(c) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_frac(b) + '\\div' + tex_frac(c) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_frac(b) + '\\times' + tex_frac(inverse(c)) + '\\] ') e = decomp_prod(b, inverse(c)) if e[2] != '': cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_decomp_prod(decomp_prod(b, inverse(c))) + '\\] ') f = produit(e[0], e[1]) cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + d[0] + tex_frac(f) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_den_com0(a, f, den_com0(a, f), d[0]) + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_den_com1(den_com1(a, f), d[0]) + '\\] ') g = somme(a, f, d[0]) if isinstance(simplifie(g), tuple): cor.append(u'\\[ \\thenocalcul = ' + tex_frac(g) + '\\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_frac(simplifie(g)) + '} \\] ') else: cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_frac(g) + '} \\] ') def tex_prod_parenth(valeurs, exo, cor): # calcul du type a*(b+c), d contenant (*,+) (a, b, c, d) = (valeurs[0], valeurs[1], valeurs[2], valeurs[3]) if d[0] == '*': exo.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times\\left(' + tex_frac(b) + d[1] + tex_frac(c) + '\\right) \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times\\left(' + tex_frac(b) + d[1] + tex_frac(c) + '\\right) \\] ') if isinstance(den_com0(b, c), tuple): cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times\\left(' + tex_den_com0(b, c, den_com0(b, c), d[1]) + '\\right) \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times\\left(' + tex_den_com1(den_com1(b, c), d[1]) + '\\right) \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times' + tex_frac(somme(b, c, d[1])) + '\\] ') if isinstance(simplifie(somme(b, c, d[1])), tuple): e = simplifie(somme(b, c, d[1])) cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times' + tex_frac(e) + '\\] ') else: e = somme(b, c, d[1]) else: exo.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\div\\left(' + tex_frac(b) + d[1] + tex_frac(c) + '\\right) \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\div\\left(' + tex_frac(b) + d[1] + tex_frac(c) + '\\right) \\] ') if isinstance(den_com0(b, c), tuple): cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\div\\left(' + tex_den_com0(b, c, den_com0(b, c), d[1]) + '\\right) \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\div\\left(' + tex_den_com1(den_com1(b, c), d[1]) + '\\right) \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\div' + tex_frac(somme(b, c, d[1])) + '\\] ') if isinstance(simplifie(somme(b, c, d[1])), tuple): e = simplifie(inverse(somme(b, c, d[1]))) cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\div' + tex_frac(inverse(e)) + '\\] ') else: e = inverse(somme(b, c, d[1])) cor.append(u'\\[ \\thenocalcul = ' + tex_frac(a) + '\\times' + tex_frac(e) + '\\] ') f = decomp_prod(a, e) cor.append(u'\\[ \\thenocalcul = ' + tex_decomp_prod(f) + '\\] ') if isinstance(simplifie(produit(f[0], f[1])), tuple): cor.append(u'\\[ \\thenocalcul = ' + tex_frac(produit(f[0], f[1])) + '\\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_frac(simplifie(produit(f[0], f[1]))) + '} \\] ') else: cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_frac(produit(f[0], f[1])) + '} \\] ') def tex_quotient_frac(valeurs, exo, cor): # effectue le quotient {a+b}/{c+d}, e contenant (+,+) (a, b, c, d, e) = (valeurs[0], valeurs[1], valeurs[2], valeurs[3], valeurs[4]) exo.append(u'\\[ \\thenocalcul = \cfrac{' + tex_frac(a) + e[0] + tex_frac(b) + '}{' + tex_frac(c) + e[1] + tex_frac(d) + '} \\] ') cor.append(u'\\[ \\thenocalcul = \cfrac{' + tex_frac(a) + e[0] + tex_frac(b) + '}{' + tex_frac(c) + e[1] + tex_frac(d) + '} \\] ') cor.append(u'\\[ \\thenocalcul = \cfrac{' + tex_den_com0(a, b, den_com0(a, b), e[0]) + '}{' + tex_den_com0(c, d, den_com0(c, d), e[1]) + '} \\] ') cor.append(u'\\[ \\thenocalcul = \cfrac{' + tex_den_com1(den_com1(a, b), e[0]) + '}{' + tex_den_com1(den_com1(c, d), e[1]) + '} \\] ') #ecrit_tex(f1,'\\cfrac{'+tex_frac(somme(a,b,e[0]))+'}{'+tex_frac(somme(c,d,e[1]))+'}') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(somme(a, b, e[0])) + '\\div' + tex_frac(somme(c, d, e[1])) + ' \\] ') cor.append(u'\\[ \\thenocalcul = ' + tex_frac(somme(a, b, e[0])) + '\\times' + tex_frac(inverse(somme(c, d, e[1]))) + ' \\] ') f = decomp_prod(somme(a, b, e[0]), inverse(somme(c, d, e[1]))) cor.append(u'\\[ \\thenocalcul = ' + tex_decomp_prod(f) + ' \\] ') if isinstance(simplifie(produit(f[0], f[1])), tuple): cor.append(u'\\[ \\thenocalcul = ' + tex_frac(produit(f[0], f[1])) + ' \\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_frac(simplifie(produit(f[0], f[1]))) + '} \\] ') else: cor.append(u'\\[ \\boxed{\\thenocalcul = ' + tex_frac(produit(f[0], f[1])) + '} \\] ') def valeurs_somme_prod(): #cree 3 fractions et un tuple de signes (+,*) while True: (base1, base2) = (valeur_alea(-13, 13), valeur_alea(-13, 13)) lepgcd = pgcd(base1, base2) (base1, base2) = (base1 // lepgcd, base2 // lepgcd) if base1 != 1 and base2 != 1: break (n2, d2) = (base1 * valeur_alea(-10, 10), abs(base2 * valeur_alea(2, 10))) lepgcd = pgcd(n2, d2) (n2, d2) = (n2 // lepgcd, d2 // lepgcd) (n3, d3) = (base2 * valeur_alea(-10, 10), abs(base1 * valeur_alea(2, 10))) lepgcd = pgcd(n3, d3) (n3, d3) = (n3 // lepgcd, d3 // lepgcd) (n1, d1) = (base1 * valeur_alea(-10, 10), abs(pgcd(d2, base2 * valeur_alea(2, 10)))) lepgcd = pgcd(n1, d1) (n1, d1) = (n1 // lepgcd, d1 // lepgcd) if randrange(2) == 0: s1 = '+' else: s1 = '-' if randrange(2) == 0: s2 = '*' else: s2 = ':' if s2 == '*': return ((n1, d1), (n2, d2), (n3, d3), (s1, s2)) else: return ((n1, d1), (n2, d2), (d3, n3), (s1, s2)) def valeurs_prod_parenth(): # cree 3 fractions et un tuple de signes (*,+) while True: (base1, base2) = (valeur_alea(2, 13), valeur_alea(2, 13)) lepgcd = pgcd(base1, base2) (base1, base2) = (base1 // lepgcd, base2 // lepgcd) if base1 != 1 and base2 != 1: break while True: n2 = valeur_alea(-13, 13) lepgcd = pgcd(n2, base1) if lepgcd == 1: break while True: n3 = valeur_alea(-13, 13) lepgcd = pgcd(n3, base2) if lepgcd == 1: break while True: (n1, d1) = (valeur_alea(-10, 10), valeur_alea(2, 10)) lepgcd = pgcd(n1, d1) if lepgcd != n1 and lepgcd != d1: break (n1, d1) = (n1 // lepgcd, d1 // lepgcd) if randrange(2) == 0: s1 = '*' else: s1 = ':' if randrange(2) == 0: s2 = '+' else: s2 = '-' return ((n1, d1), (n2, base1), (n3, base2), (s1, s2)) def valeurs_quotient_frac(): # cree 4 fractions et un tuple de signes (+,+) while True: (n1, d1) = (valeur_alea(-10, 10), valeur_alea(2, 10)) lepgcd = pgcd(n1, d1) if lepgcd != n1 and lepgcd != d1: break (n1, d1) = (n1 // lepgcd, d1 // lepgcd) while True: (n3, d3) = (valeur_alea(-10, 10), valeur_alea(2, 10)) lepgcd = pgcd(n3, d3) if lepgcd != n3 and lepgcd != d3: break (n3, d3) = (n3 // lepgcd, d3 // lepgcd) (n2, n4) = (valeur_alea(1, 10), valeur_alea(1, 10)) if randrange(2) == 0: s1 = '+' else: s1 = '-' if randrange(2) == 0: s2 = '+' else: s2 = '-' return ((n1, d1), (n2, 1), (n3, d3), (n4, 1), (s1, s2)) def tex_fractions(): nb_exos = 3 tex_exos = (tex_somme_prod, tex_prod_parenth, tex_quotient_frac) valeurs_exos = (valeurs_somme_prod, valeurs_prod_parenth, valeurs_quotient_frac) ordre_exos = [i for i in range(nb_exos)] exo = ['''\n\\exercice''', u"Calculer les expressions suivantes et donner le résultat sous la forme d'une fraction irréductible."] exo.append('\\begin{multicols}{3}\\noindent') cor = ['''\\exercice*''', u"Calculer les expressions suivantes et donner le résultat sous la forme d'une fraction irréductible."] cor.append('\\begin{multicols}{3}\\noindent') for i in range(nb_exos): a = randrange(nb_exos - i) tex_exos[ordre_exos[a]](valeurs_exos[ordre_exos.pop(a)](), exo, cor) if i < nb_exos - 1: exo.append('\\columnbreak\\stepcounter{nocalcul}') cor.append('\\columnbreak\\stepcounter{nocalcul}') else: exo.append('\\end{multicols}') cor.append('\\end{multicols}') return (exo, cor) pyromaths/src/troisiemes/._affine.py0000644000175000017500000000031511702101415020252 0ustar didrocksdidrocksMac OS X  2ATTRG|55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._geometrie.py0000644000175000017500000000031511702101415021002 0ustar didrocksdidrocksMac OS X  2ATTRGށ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._racines.py0000644000175000017500000000031511702101415020446 0ustar didrocksdidrocksMac OS X  2ATTRGކ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/__init__.py0000644000175000017500000000171511702101415020351 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/troisiemes/equations.py0000644000175000017500000001607011702101415020622 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils import Arithmetique from . import fractions from . import developpements # # ------------------- ÉQUATIONS ------------------- def valeurs(pyromax): # crée les valeurs aléatoires pour l'équation while True: coefs = [Arithmetique.valeur_alea(-pyromax, pyromax) for i in range(6)] sgn = Arithmetique.valeur_alea(-1, 1) if sgn > 0: signe = "+" else: signe = "-" while True: while True: dens = [Arithmetique.valeur_alea(2, 9) for i in range(3)] if dens[0] != dens[1] and dens[0] != dens[2] and dens[1] != \ dens[2]: break ppcm = Arithmetique.ppcm(dens[0], Arithmetique.ppcm(dens[1], dens[2])) densprim = [ppcm // dens[i] for i in range(3)] if densprim[0] < 10 and densprim[1] < 10 and densprim[2] < \ 10: break nvxcoefs = [coefs[i] * densprim[i // 2] for i in range(6)] if (nvxcoefs[0] + nvxcoefs[2] * sgn) - nvxcoefs[4] != 0: break return (tuple(coefs), tuple(dens), tuple(densprim), (signe, sgn), tuple(nvxcoefs)) def tex_quotient0(a, b, c): # renvoie l'ecriture d'un quotient de l'enonce return '\\cfrac{%s}{%s}' % (developpements.tex_binome((a, b)), c) def tex_quotient1(a, b, c, d): # renvoie l'ecriture de la mise au meme denominateur d'un quotient if d == 1: return tex_quotient0(a, b, c) else: return '\\cfrac{%s_{\\times%s}}{%s_{\\times%s}}' % (developpements.tex_binome((a, b), bpar=1), d, c, d) def tex_equation0(valeurs): # renvoie l'ecriture des quotients de l'enonce texte = '' for i in range(3): texte = texte + tex_quotient0(valeurs[0][i * 2], valeurs[0][i * 2 + 1], valeurs[1][i]) if i == 0: texte = texte + valeurs[3][0] elif i == 1: texte = texte + '=' return texte def tex_equation1(valeurs): # renvoie l'ecriture de la mise au meme denominateur des quotients texte = '' for i in range(3): texte = texte + tex_quotient1(valeurs[0][i * 2], valeurs[0][i * 2 + 1], valeurs[1][i], valeurs[2][i]) if i == 0: texte = texte + valeurs[3][0] elif i == 1: texte = texte + '=' return texte def tex_equation2(valeurs): # renvoie l'ecriture des quotients au meme denominateur texte = '\\cfrac{' for i in range(3): texte = texte + developpements.tex_binome((valeurs[4][i * 2], valeurs[4][i * 2 + 1]), bplus=i == 1 and valeurs[3][1] > 0, bpar=i == 1 and valeurs[3][1] < 0) if i == 0 and valeurs[3][1] < 0: texte = texte + valeurs[3][0] elif i == 1: texte = texte + '}{\\cancel{%s}}=\cfrac{' % (valeurs[1][0] * valeurs[2][0]) texte = texte + '}{\\cancel{%s}}' % (valeurs[1][0] * valeurs[2][0]) return texte def tex_equation2bis(valeurs): # renvoie l'ecriture des quotients au meme denominateur sans les parentheses eventuelles texte = developpements.tex_binome((valeurs[4][0], valeurs[4][1])) texte = texte + developpements.tex_binome((valeurs[4][2] * valeurs[3][1], valeurs[4][3] * valeurs[3][1]), bplus=1) texte = texte + '=' + developpements.tex_binome((valeurs[4][4], valeurs[4][5])) return texte def tex_equation3(valeurs): # renvoie l'ecriture reduite de l'equation sans denominateur texte = developpements.tex_binome((valeurs[4][0] + valeurs[4][2] * valeurs[3][1], valeurs[4][1] + valeurs[4][3] * valeurs[3][1])) texte = texte + '=' + developpements.tex_binome((valeurs[4][4], valeurs[4][5])) return texte def tex_equation4(valeurs): # renvoie l'ecriture de l'equation avec l'inconnue d'un cote de l'egalite texte = developpements.tex_coef(valeurs[4][0] + valeurs[4][2] * valeurs[3][1], 'x') + developpements.tex_coef(-valeurs[4][4], 'x', bplus=1) texte = texte + '=' + developpements.tex_coef(valeurs[4][5], '') + \ developpements.tex_coef(-valeurs[4][1] - valeurs[4][3] * valeurs[3][1], '', bplus=1) return texte def tex_equation5(valeurs): # renvoie l'ecriture reduite de l'equation avec l'inconnue d'un cote de l'egalite texte = developpements.tex_coef((valeurs[4][0] + valeurs[4][2] * valeurs[3][1]) - valeurs[4][4], 'x') texte = texte + '=' + developpements.tex_coef((valeurs[4][5] - valeurs[4][1]) - valeurs[4][3] * valeurs[3][1], '') return texte def tex_equation6(valeurs): # renvoie la solution de l'equation frac = ((valeurs[4][5] - valeurs[4][1]) - valeurs[4][3] * valeurs[3][1], (valeurs[4][0] + valeurs[4][2] * valeurs[3][1]) - valeurs[4][4]) if (valeurs[4][0] + valeurs[4][2] * valeurs[3][1]) - valeurs[4][4] == \ 1: texte = '' else: texte = 'x=' + fractions.tex_frac(frac) simpl = fractions.simplifie(frac) if isinstance(simpl, tuple): texte = texte + '=' + fractions.tex_frac(simpl) return texte def equations(exo, cor, valeurs): #resolution d'une equation exo.append(u"Résoudre l'équation : ") exo.append(u'\\[ ' + tex_equation0(valeurs) + '\\] ') cor.append(u"Résoudre l'équation : ") for i in range(7): exec('cor.append(u\'\\\\[\' + tex_equation' + str(i) + '(valeurs) + \'\\\\] \')') if i == 2 and valeurs[3][1] < 0: cor.append(u'\\[ ' + tex_equation2bis(valeurs) + '\\] ') frac = ((valeurs[4][5] - valeurs[4][1]) - valeurs[4][3] * valeurs[3][1], (valeurs[4][0] + valeurs[4][2] * valeurs[3][1]) - valeurs[4][4]) simpl = fractions.simplifie(frac) if isinstance(simpl, tuple): sol = fractions.tex_frac(simpl) else: sol = fractions.tex_frac(frac) cor.append(u'\\fbox{La solution de cette équation est $%s$\\,.}' % sol) def tex_equations(): vals = valeurs(10) exo = ['\\exercice'] cor = ['\\exercice*'] equations(exo, cor, vals) return (exo, cor) pyromaths/src/troisiemes/arithmetique.py0000644000175000017500000002766611702101415021330 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils.Arithmetique import pgcd, ppcm, premier, factoriseTex, carrerise from ..outils.Affichage import decimaux from random import randint, shuffle premiers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997] ## Liste de longueur 168 def Arithmetique(): """Exercice de décomposition de nombres en facteurs premiers, puis de recherche du PGCD et du PPCM, et d'applications aux fractions""" ### Question 1 exo = ["\\exercice", '\\begin{enumerate}', u"\\item Donner la décomposition" + u" en facteurs premiers des nombres suivants, et préciser quand il" + u" s\'agit d\'un nombre premier :\\par"] cor = ["\\exercice*", '\\begin{enumerate}', u"\\item Donner la décomposition" + u" en facteurs premiers des nombres suivants, et préciser quand il" + u" s\'agit d\'un nombre premier :\\par"] prime = premiers[randint(10,167)] fauxpgcd = randint(1,101) fauxpgcdfactor = factoriseTex(fauxpgcd)[0] complementaires = [randint(6,50), randint(6,50)] pgcdcompl = pgcd(complementaires[0], complementaires[1]) pgcdcomplfact = factoriseTex(pgcdcompl)[0] if pgcdcompl != 1: facteurs = pgcdcomplfact + fauxpgcdfactor facteurs.sort() else: facteurs = fauxpgcdfactor autresnombres = [randint(51,999), randint(51,999)] listenombres = [prime, complementaires[0] * fauxpgcd, complementaires[1] * fauxpgcd, ] + autresnombres melange = [prime, complementaires[0] * fauxpgcd, complementaires[1] * fauxpgcd, ] + autresnombres shuffle(melange) exo.append(decimaux(melange[0]) + " ; " + decimaux(melange[1]) + " ; " + decimaux(melange[2]) + " ; " + decimaux(melange[3]) + " ; " + decimaux(melange[4]) + " ;") cor.append("\\begin{multicols}{2}") for i in range(5): cor += factoriseTex(melange[i])[1] cor.append("\\end{multicols}") ### Question 2 exo.append(u'\\item En déduire le PGCD et le PPCM des nombres ' + decimaux(listenombres[1]) + " et " + decimaux(listenombres[2]) + ".") cor.append(u'\\item En déduire le PGCD et le PPCM des nombres ' + decimaux(listenombres[1]) + " et " + decimaux(listenombres[2]) + ".\\par") cor.append(u"D'après la question 1), on sait que les nombres " + decimaux(listenombres[1]) + " et " + decimaux(listenombres[2]) + " ont comme facteurs premiers communs : ") for j in range(len(facteurs)): if j == 0: temp = "$" if j != len(facteurs)-1: temp += decimaux(facteurs[j]) + " , " else: temp += decimaux(facteurs[j]) + "$.\\par" cor.append(temp) cor.append(u"On en déduit que le PGCD des nombres " + decimaux(listenombres[1]) + " et " + decimaux(listenombres[2]) + " est : ") temp = "$" if len(facteurs) > 1: for j in range(len(facteurs)): if j != len(facteurs)-1: temp += decimaux(facteurs[j]) + " \\times " else: temp += decimaux(facteurs[j]) + " = " temp+= decimaux(fauxpgcd * pgcdcompl) + ".$\\par" cor.append(temp) vraippcm = (listenombres[1] * listenombres[2]) / (fauxpgcd * pgcdcompl) if (listenombres[1] % listenombres[2] == 0): cor.append(decimaux(listenombres[1]) + u" est un multiple de " + decimaux(listenombres[2]) + u", donc leur PPCM est directement " + decimaux(listenombres[1]) + ".") elif (listenombres[2] % listenombres[1] == 0): cor.append(decimaux(listenombres[2]) + u" est un multiple de " + decimaux(listenombres[1]) + u", donc leur PPCM est directement " + decimaux(listenombres[2]) + ".") else: cor.append(u"Il existe plusieurs méthodes pour calculer le PPCM de " + decimaux(listenombres[1]) + " et de " + decimaux(listenombres[2]) + ".\\par" ) cor.append(u"En voici deux :") cor.append("\\begin{enumerate}") cor.append(u"\\item On peut simplement utiliser la formule :") cor.append(u"$a \\times b = PGCD(a;~b) \\times PPCM(a;~b)$.\\par") cor.append(u"Donc : $PPCM(" + decimaux(listenombres[1]) + ";~" + decimaux(listenombres[2]) + ") = " + "\\dfrac{" + decimaux(listenombres[1]) + "\\times" + decimaux(listenombres[2]) + "}{" + decimaux(fauxpgcd * pgcdcompl) + "} = " + decimaux(vraippcm) + ".$") cor.append(u"\\item On peut aussi multiplier un nombre par les \"facteurs " + u"complémentaires\" de l'autre.\n" + u"Ces \"facteurs " + u"complémentaires\" sont les facteurs qui complètent le PGCD pour " + u"former le nombre.\\par") temp = u"Comme $PGCD(" + decimaux(listenombres[1]) + ";~" +\ decimaux(listenombres[2]) + ") = " + decimaux(fauxpgcd * pgcdcompl) if len(facteurs) > 1: temp += " = " for j in range(len(facteurs)): if j != len(facteurs)-1: temp += decimaux(facteurs[j]) + " \\times " else: temp += decimaux(facteurs[j]) factornb1 = factoriseTex(listenombres[1])[0] if len(factornb1) > 1: textcompl = u"$, alors les \"facteurs complémentaires\" de $" else: textcompl = u"$, alors le \"facteur complémentaire\" de $" temp += textcompl + decimaux(listenombres[1]) + " = " for j in range(len(factornb1)): if j != len(factornb1)-1: temp += decimaux(factornb1[j]) + " \\times " else: temp += decimaux(factornb1[j]) factcompl = factoriseTex(listenombres[1] / (fauxpgcd * pgcdcompl))[0] if len(factcompl) == 1: temp += u"$ est : " else: temp += u"$ sont : " for j in range(len(factcompl)): if j != len(factcompl)-1: temp += decimaux(factcompl[j]) + " , " else: temp += decimaux(factcompl[j]) + ".\n" temp += u"On en déduit que $PPCM(" + decimaux(listenombres[1]) + ";~" +\ decimaux(listenombres[2]) + ") = " + decimaux(listenombres[2]) +\ " \\times " for j in range(len(factcompl)): if j != len(factcompl)-1: temp += decimaux(factcompl[j]) + " \\times " else: temp += decimaux(factcompl[j]) + " = " temp += decimaux(vraippcm) + ".$" cor.append(temp) cor.append("\\end{enumerate}") ### Question 3 exo.append(u"\\item Quel est le plus petit nombre par lequel il faut " + u"multiplier " + decimaux(autresnombres[0]) + u" pour obtenir un carré parfait ?") cor.append(u" \\item Pour obtenir un carré parfait, il faut que sa " + u"décomposition en facteurs premiers ne contienne que des facteurs " + u"apparaissant un nombre pair de fois. D'après la question 1, " + u"la décomposition en facteurs premiers de " + decimaux(autresnombres[0])) decompautre = factoriseTex(autresnombres[0])[1] if len(decompautre) == 1: cor.append(u" est lui-même, car c'est un nombre premier.") else: cor.append(" est : \\par\n$" + decimaux(autresnombres[0]) + " = " + decompautre[-2][5:-2] + ".$\\par") cor.append(u"Il faut donc encore multiplier ce nombre par ") carre = carrerise(autresnombres[0]) factsup = factoriseTex(carre)[0] if len(factsup)==1: cor.append(" le facteur ") else: cor.append(" les facteurs ") for j in range(len(factsup)): if (j != len(factsup)-1) and (j != len(factsup)-2): cor.append(decimaux(factsup[j]) + " , ") elif (j == len(factsup)-2): cor.append(decimaux(factsup[j]) + " et ") else: cor.append(decimaux(factsup[j]) + ".\\par") cor.append(u"Le nombre cherché est par conséquent " + decimaux(carre) + u" et le carré parfait obtenu est " + decimaux(carre * autresnombres[0]) + ".") ### Question 4 exo.append(u"\\item Rendre la fraction $\\dfrac{" + decimaux(listenombres[1]) + "}{" + decimaux(listenombres[2]) + u"}$ irréductible.") cor.append(u"\\item Le moyen le plus rapide de simplifier cette fraction est" + u"de diviser le numérateur et le dénominateur par leur PGCD." + u" D'après la question 2), PGCD(" + decimaux(listenombres[1]) + ";~" + decimaux(listenombres[2]) + ") = " + decimaux(fauxpgcd * pgcdcompl) + ", donc on obtient :\\par") cor.append(u"$\dfrac{" + decimaux(listenombres[1]) + "{\\scriptstyle \\div " + decimaux(fauxpgcd * pgcdcompl) + "}}{" + decimaux(listenombres[2]) + "{\\scriptstyle \\div " + decimaux(fauxpgcd * pgcdcompl) + "}} = \dfrac{" + decimaux(listenombres[1] / (fauxpgcd * pgcdcompl)) + "}{" + decimaux(listenombres[2] / (fauxpgcd * pgcdcompl)) + "}.$") ### Question 5 num = [randint(6,50), randint(6,50)] exo.append(u"\\item Calculer $\\dfrac{" + decimaux(num[0]) + "}{" + decimaux(listenombres[1]) + "} + \\dfrac{" + decimaux(num[1]) + "}{" + decimaux(listenombres[2]) + "}$.") mult1 = vraippcm / listenombres[1] mult2 = vraippcm / listenombres[2] num1 = mult1 * num[0] num2 = mult2 * num[1] simplfin = pgcd(num1+num2,vraippcm) if simplfin != 1: simpl = "{\\scriptstyle \\div " + decimaux(simplfin) + "}" result = " = \\dfrac{" + decimaux((num1+num2)/simplfin) + "}{" + \ decimaux((vraippcm)/simplfin) + "}" else: simpl = "" result = "" cor.append(u"\\item Il faut mettre les fractions au même dénominateur. Grâce" + u"à la question 2), nous avons déjà un dénominateur commun : " + u"le PPCM des nombres " + decimaux(listenombres[1]) + " et " + decimaux(listenombres[2]) + u", qui est par définition le plus petit" + u"multiple commun de ces deux nombres.\\par") cor.append(u"$\\dfrac{" + decimaux(num[0]) + "{\\scriptstyle \\times " + decimaux(mult1) + "}}{" + decimaux(listenombres[1]) + "{\\scriptstyle \\times " + decimaux(mult1) + "}} + \\dfrac{" + decimaux(num[1]) + "{\\scriptstyle \\times " + decimaux(mult2) + "}}{" + decimaux(listenombres[2]) + "{\\scriptstyle \\times " + decimaux(mult2) + "}} = \\dfrac{" + decimaux(num1) + "}{" + decimaux(vraippcm) + "} + \\dfrac{" + decimaux(num2) + "}{" + decimaux(vraippcm) + "} = \\dfrac{" + decimaux(num1+num2) + simpl + "}{" + decimaux(vraippcm) + simpl + "}" + result + ".$") exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return (exo,cor) pyromaths/src/troisiemes/systemes.py0000644000175000017500000002245111702101415020466 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils import Arithmetique from . import developpements ## ##------------------- MÉTHODE PAR COMBINAISON ------------------- def choix_valeurs(m): # crée les valeurs du systeme de la forme a1.x+b1.y=c1 ; a2.x+b2.y=c2 et renvoie ((a1, b1, c1), (a2, b2, c2), (x, y)) while True: c = [Arithmetique.valeur_alea(-m, m) for i in range(6)] if c[0] * c[3] - c[1] * c[2] and abs(c[0]) - 1 and abs(c[1]) - 1 and \ abs(c[2]) - 1 and abs(c[3]) - 1 and abs(c[1] * c[2] - c[0] * c[3]) - 1 and abs(c[0]) - abs(c[2]) and abs(c[1]) - abs(c[3]) and \ c[4] and c[5]: break # supprime des cas particuliers return ((c[0], c[1], c[0] * c[4] + c[1] * c[5]), (c[2], c[3], c[2] * c[4] + c[3] * c[5]), (c[4], c[5])) def signe(a): # retourne '+' si a est positif, '-' si a est négatif, '' si a est nul if a > 0: return '+' elif a < 0: return '-' else: return '' def tex_systeme(v, p=None): # renvoie l'écriture au format tex d'un système d'équations. v[] est de la forme ((a0, b0, c0), (a1, b1, c1), (x,y)) if p == None: tv = (developpements.tex_coef(v[0][0], 'x'), signe(v[0][1]), developpements.tex_coef(abs(v[0][1]), 'y'), v[0][2], developpements.tex_coef(v[1][0], 'x'), signe(v[1][1]), developpements.tex_coef(abs(v[1][1]), 'y'), v[1][2]) return '''\\left\\lbrace \\begin{array}{rcrcl} %s & %s & %s & = & %s \\\\\n %s & %s & %s & = & %s \\end{array} \\right.''' % \ tv else: tv = ( developpements.tex_coef(v[0][0], 'x'), signe(v[0][1]), developpements.tex_coef(abs(v[0][1]), 'y'), v[0][2], '\\qquad\\hbox{\\footnotesize$\\mathit{(\\times %s)}$}' % developpements.tex_coef(p[0], '', bpn=1), developpements.tex_coef(v[1][0], 'x'), signe(v[1][1]), developpements.tex_coef(abs(v[1][1]), 'y'), v[1][2], '\\qquad\\hbox{\\footnotesize$\\mathit{(\\times %s)}$}' % developpements.tex_coef(p[1], '', bpn=1), ) return '''\\left\\lbrace \\begin{array}{rcrcll} %s & %s & %s & = & %s & %s \\\\\n %s & %s & %s & = & %s & %s \\end{array} \\right.''' % \ tv def combinaison1(v, a0, a1): return ((v[0][0] * a0, v[0][1] * a0, v[0][2] * a0), (v[1][0] * a1, v[1][1] * a1, v[1][2] * a1)) def combinaison2(v): # renvoie les coefficients pour la somme des deux lignes return (v[0][0] + v[1][0], v[0][1] + v[1][1], v[0][2] + v[1][2]) def tex_comb2(v, c): if c[0]: tv = (developpements.tex_coef(v[0][0], 'x'), '\\cancel{' + developpements.tex_coef(v[0][1], 'y', bplus=1) + '}', developpements.tex_coef(v[1][0], 'x', bplus=1), '\\cancel{' + developpements.tex_coef(v[1][1], 'y', bplus= 1) + '}', developpements.tex_coef(v[0][2], ''), developpements.tex_coef(v[1][2], '', bplus=1)) else: tv = ('\\cancel{' + developpements.tex_coef(v[0][0], 'x') + '}', developpements.tex_coef(v[0][1], 'y', bplus=1), '\\cancel{' + developpements.tex_coef(v[1][0], 'x', bplus= 1) + '}', developpements.tex_coef(v[1][1], 'y', bplus=1), developpements.tex_coef(v[0][2], ''), developpements.tex_coef(v[1][2], '', bplus=1)) return '%s%s%s%s=%s%s' % tv def tex_comb3(v): if v[0]: tv = (developpements.tex_coef(v[0], 'x'), developpements.tex_coef(v[2], '')) else: tv = (developpements.tex_coef(v[1], 'y'), developpements.tex_coef(v[2], '')) return '%s=%s' % tv def tex_comb4(v): if v[0]: tv = (developpements.tex_coef(1, 'x'), v[2], v[0], developpements.tex_coef(v[2] // v[0], '')) else: tv = (developpements.tex_coef(1, 'y'), v[2], v[1], developpements.tex_coef(v[2] // v[1], '')) return '%s=\\frac{%s}{%s}=%s' % tv def tex_equation(v, c): tv = (developpements.tex_coef(v[0][0], 'x'), developpements.tex_coef(v[0][1], 'y', bplus=1), v[0][2]) t = '$%s%s=%s\\quad\\text{et}\\quad ' % tv if c[0]: t = t + 'x=%s\\quad\\text{donc :}$\n' % v[2][0] tv = (developpements.tex_coef(v[0][0], ''), developpements.tex_coef(v[2][0], '', bpn=1), developpements.tex_coef(v[0][1], 'y', bplus=1), v[0][2]) t = t + '\\[%s\\times %s %s=%s\\]\n' % tv else: t = t + 'y=%s\\quad\\text{donc :}$\n' % v[2][1] tv = (developpements.tex_coef(v[0][0], 'x'), developpements.tex_coef(v[0][1], '', bplus=1), developpements.tex_coef(v[2][1], '', bpn=1), v[0][2]) t = t + '\\[%s %s\\times %s=%s\\]\n' % tv return t def tex_eq2(v, c): if c[0]: tv = (developpements.tex_coef(v[0][1], 'y'), developpements.tex_coef(v[0][2], ''), developpements.tex_coef(-v[0][0] * v[2][0], '', bplus= 1)) t = '%s=%s%s' % tv else: tv = (developpements.tex_coef(v[0][0], 'x'), developpements.tex_coef(v[0][2], ''), developpements.tex_coef(-v[0][1] * v[2][1], '', bplus= 1)) t = '%s=%s%s' % tv return t def tex_eq3(v, c): if c[0]: tv = (developpements.tex_coef(1, 'y'), developpements.tex_coef(v[0][2] - v[0][0] * v[2][0], ''), developpements.tex_coef(v[0][1], ''), developpements.tex_coef(v[2][1], '')) t = '%s=\\frac{%s}{%s}=%s' % tv else: tv = (developpements.tex_coef(1, 'x'), developpements.tex_coef(v[0][2] - v[0][1] * v[2][1], ''), developpements.tex_coef(v[0][0], ''), developpements.tex_coef(v[2][0], '')) t = '%s=\\frac{%s}{%s}=%s' % tv return t def tex_verification(v): # renvoie la vérification de lasolution du système d'équations. tv = ( developpements.tex_coef(v[0][0], '\\times %s' % developpements.tex_coef(v[2][0], '', bpn=1)), developpements.tex_coef(v[0][1], '\\times %s' % developpements.tex_coef(v[2][1], '', bpn=1), bplus=1), developpements.tex_coef(v[0][0] * v[2][0], ''), developpements.tex_coef(v[0][1] * v[2][1], '', bplus=1), v[0][2], developpements.tex_coef(v[1][0], '\\times %s' % developpements.tex_coef(v[2][0], '', bpn=1)), developpements.tex_coef(v[1][1], '\\times %s' % developpements.tex_coef(v[2][1], '', bpn=1), bplus=1), developpements.tex_coef(v[1][0] * v[2][0], ''), developpements.tex_coef(v[1][1] * v[2][1], '', bplus=1), v[1][2], ) return '''\\left\\lbrace \\begin{array}{l} %s %s=%s %s=%s \\\\\n %s %s=%s %s=%s \\end{array} \\right.''' % \ tv def systemes(exo, cor, v): a = Arithmetique.ppcm(v[0][0], v[1][0]) b = Arithmetique.ppcm(v[0][1], v[1][1]) (a0, a1, b0, b1) = (a // v[0][0], -a // v[1][0], b // v[0][1], -b // v[1][1]) if a0 < 0: (a0, a1) = (-a0, -a1) if b0 < 0: (b0, b1) = (-b0, -b1) if min(abs(a0), abs(a1)) > min(abs(b0), abs(b1)): (a0, a1) = (b0, b1) exo.append('$%s$' % tex_systeme(v)) cor.append('$%s$' % tex_systeme(v, (a0, a1))) c1 = combinaison1(v, a0, a1) cor.append('''\\vspace{2ex} \\begin{multicols}{2}\\noindent ''') cor.append(u'\\[ ' + tex_systeme(c1) + '\\quad\\text{\\footnotesize On ajoute les deux lignes}' + '\\] ') c2 = combinaison2(c1) cor.append(u'\\[ ' + tex_comb2(c1, c2) + '\\] ') cor.append(u'\\[ ' + tex_comb3(c2) + '\\] ') cor.append(u'\\[ \\boxed{' + tex_comb4(c2) + '} \\] ') cor.append('\\columnbreak\\par') cor.append(tex_equation(v, c2)) cor.append(u'\\[ ' + tex_eq2(v, c2) + '\\] ') cor.append(u'\\[ \\boxed{' + tex_eq3(v, c2) + '} \\] ') cor.append('\\end{multicols}') cor.append(u"\\underline{La solution de ce système d'équations est $(x;~y)=(%s;~%s)$.}\\par" % v[2]) cor.append(u'{Vérification : $' + tex_verification(v) + '$}') def tex_systemes( ): valeurs = choix_valeurs(10) exo = ['\\exercice', u"Résoudre le système d'équations suivant :"] cor = ['\\exercice*', u"Résoudre le système d'équations suivant :"] systemes(exo, cor, valeurs) return (exo, cor) pyromaths/src/troisiemes/troisiemes.py0000644000175000017500000000346411702101415021000 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from . import fractions, puissances, pgcd, developpements, equations, racines from . import systemes, proba, affine, geometrie, arithmetique def write(f0, f1, exos): f0.write("\n") f1.write("\n") f0.writelines(x + "\n" for x in exos[0]) f1.writelines(x + "\n" for x in exos[1]) def main(exo, f0, f1): modules = ( fractions.tex_fractions, puissances.tex_puissances, pgcd.tex_pgcd, developpements.tex_developpements, developpements.tex_factorisations, developpements.tex_devfacteq, equations.tex_equations, racines.tex_racines, systemes.tex_systemes, affine.affine, proba.tex_proba, geometrie.tex_thales, geometrie.tex_reciproque_thales, geometrie.tex_trigo, arithmetique.Arithmetique ) write(f0, f1, modules[exo]()) pyromaths/src/troisiemes/._proportionnalite.py0000644000175000017500000000031511702101415022432 0ustar didrocksdidrocksMac OS X  2ATTRGބ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._puissances.py0000644000175000017500000000031511702101415021177 0ustar didrocksdidrocksMac OS X  2ATTRGޅ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._proba.py0000644000175000017500000000031511702101415020125 0ustar didrocksdidrocksMac OS X  2ATTRGރ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._fractions.py0000644000175000017500000000031511702101415021012 0ustar didrocksdidrocksMac OS X  2ATTRGހ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/affine.py0000644000175000017500000003656411702101415020054 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #fonction affine 3e import random from math import * from ..outils.Affichage import decimaux from ..outils.Fractions import Fractions #fractions pyromaths def extreme(a,b,xmin,xmax,ymin,ymax): #donne les extremités de la droite passant par a et b (coordonnées) res=[] x1=float(a[0]) x2=float(b[0]) y1=float(a[1]) y2=float(b[1]) coef=float((y1-y2)/(x1-x2)) if coef != 0: xsort1=float(x1+(ymin-y1)/coef) #abscisse du point d'ordonnée ymin if xsort1 >=xmin and xsort1<=xmax and not(xsort1,ymin) in res: res.append((xsort1,ymin)) xsort2=float(x2+(ymax-y2)/coef) #abscisse du point d'ordonnée ymax if xsort2>=xmin and xsort2<=xmax and not(xsort2,ymax) in res: res.append((xsort2,ymax)) ysort1=float(y1+coef*(xmin-x1)) #ordonnée du point d'abscisse xmin if ysort1 >=ymin and ysort1<=ymax and not (xmin,ysort1)in res: res.append((xmin,ysort1)) ysort2=float(y2+coef*(xmax-x2)) #ordonnée du point d'abscisse xmax if ysort2 >=ymin and ysort2<=ymax and not(xmax,ysort2) in res: res.append((xmax,ysort2)) else: res=[(xmin,y1),(xmax,y1)] return res def vecdir(A,B): #retourne sous forme de liste le vecteur directeur normé de la droite (AB) norm= sqrt((B[0]-A[0])**2+(B[1]-A[1])**2) u=[(B[0]-A[0])/norm,(B[1]-A[1])/norm] if u[0]<0: u[0]=-u[0] u[1]=-u[1] return u def validedroite(A,B): #valide le choix du couple A B pour qu'ils ne soient pas "collés", # la droite (AB) ne sera ni horizontale ni verticale rep=True if abs(A[0]-B[0])<=1 and abs(A[1]-B[1])<=1: rep=False if A[0]==B[0] or A[1]==B[1]: rep=False if abs(A[0]-B[0])<1 or abs(A[1]-B[1])<1: rep=False return rep def validec(A,B): #valide le choix du couple A B pour qu'ils ne soient pas "collés" rep=True if abs(A[0]-B[0])<=1 and abs(A[1]-B[1])<=1: rep=False return rep def doublefleche(A,B): #trace une flèche "double" de justification en pointillés mid=(float((A[0]+B[0]))/2,float((A[1]+B[1]))/2) res1="\\psline[linestyle=dashed,linewidth=1.1pt]{->}"+str(A)+str(mid)+'\n ' res2="\\psline[linestyle=dashed,linewidth=1.1pt]{->}"+str(mid)+str(B) res=res1+res2 if A==B: res="" return res def couple () : A=(float(random.randrange(-8,9))/2,float(random.randrange(-8,9))/2) B=(float(random.randrange(-8,9))/2,float(random.randrange(-8,9))/2) while not validec(A,B): B=(float(random.randrange(-8,9))/2,float(random.randrange(-8,9))/2) return (A,B) def coupletrace () : A=(0,float(random.randrange(-4,5))) B=(float(random.randrange(-4,5)),float(random.randrange(-4,5))) while not validec(A,B): B=(float(random.randrange(-4,5)),float(random.randrange(-4,5))) return (A,B) def couples (): #génère 6 points. Chaque couple correspondra a une droite ( (AB)(CD)(EF)). A=(float(random.randrange(-8,9))/2,float(random.randrange(-8,9))/2) B=(float(random.randrange(-8,9))/2,float(random.randrange(-8,9))/2) while not validedroite(A,B): B=(float(random.randrange(-8,9))/2,float(random.randrange(-8,9))/2) C=(0,float(random.randrange(-4,5))) while not (validec(A,C) and validec(B,C)): C=(0,float(random.randrange(-4,5))) D=(float(random.randrange(-4,5)),float(random.randrange(-4,5))) while not (validec(A,D) and validec(B,D) and validedroite(C,D)) : D=(float(random.randrange(-4,5)),float(random.randrange(-4,5))) E=(0,float(random.randrange(-8,9))/2) while not (validec(A,E) and validec(B,E) and validec(C,E) and validec(D,E)): E=(0,float(random.randrange(-8,9))/2) F=(float(random.randrange(-4,5)),float(random.randrange(-4,5))) while not (validec(A,F) and validec(B,F) and validec(C,F) and validec(D,F)and validedroite(E,F)): F=(float(random.randrange(-4,5)),float(random.randrange(-4,5))) return (A,B,C,D,E,F) def tracedroite(A,B,xmin,xmax,ymin,ymax): #trace la droite (AB) l=extreme(A,B,xmin,xmax,ymin,ymax) return "\\psline "+str(l[0])+str(l[1]) def dansrep(A,xmin,xmax,ymin,ymax): #Si le points est dans le repère res= False if A[0]>xmin and A[0]ymin and A[1]=0: b='+'+decimaux(str(A[1])) else: b=decimaux(str(A[1])) if u[1]==1: coef=decimaux(str(u[0])) if u[0]==-1: coef='-' if u[0]==1: coef='' x1=decimaux(str(B[0])) y1=decimaux(str(B[1])) u[0]=u[0]*B[0] else: B=(u[1],u[0]+float(A[1])) if not dansrep(B,xmin,xmax,ymin,ymax): B=(-u[1],-u[0]+float(A[1])) x1=decimaux(str(B[0])) y1=decimaux(str(B[1])) if u[0]>0: coef='\\dfrac{'+decimaux(str(u[0]))+'}{'+decimaux(str(u[1]))+'}' else: coef='-\\dfrac{'+decimaux(str(abs(u[0])))+'}{'+decimaux(str(u[1]))+'}' x0='0' y0=b if coef=='' or (coef=='-' and B[0]>0) : st='On sait que $'+f+'(0)='+decimaux(str(A[1]))+'$ et $'+f+'('+x1+')='+coef+x1+b+'='+y1+'$.' elif coef=='-' and B[0]<0: st='On sait que $'+f+'(0)='+decimaux(str(A[1]))+'$ et $'+f+'('+x1+')='+coef+'('+x1+')'+b+'='+y1+'$.' elif B[0]<0: st='On sait que $'+f+'(0)='+decimaux(str(A[1]))+'$ et $'+f+'('+x1+')='+coef+' \\times ('+x1+')'+b+'='+decimaux(str(u[0]))+b+'='+y1+'$.' else: st='On sait que $'+f+'(0)='+decimaux(str(A[1]))+'$ et $'+f+'('+x1+')='+coef+' \\times '+x1+b+'='+decimaux(str(u[0]))+b+'='+y1+'$.' l=[u'Tracer la droite représentative ($d_'+str(i)+'$) de la fonction $'+f+':x\\longmapsto '+coef+'x'+b+'$.', st, '\\psdot [dotsize=4.5pt,dotstyle=x]'+str(A), '\\psdot [dotsize=4.5pt,dotstyle=x]'+str(B), ] return l def exprfonc(f,i,A,B): #Génère la 3e question. #A est sur l'axe des ordonnées, f est le nom de la fonction u=coefdir(A,B) if A[1]>=0: b='+'+decimaux(str(A[1])) else: b=decimaux(str(A[1])) if u[1]==1: coef=decimaux(str(u[0])) if u[0]==-1: coef='-' #utilisé dans l'expression de la fonction if u[0]==1: coef='' coefres=decimaux(str(u[0])) #résultat utilisé pour a else: if u[0]>0: coef='\\dfrac{'+decimaux(str(u[0]))+'}{'+decimaux(str(u[1]))+'}' else: coef='-\\dfrac{'+decimaux(str(abs(u[0])))+'}{'+decimaux(str(u[1]))+'}' coefres=coef if A[1]-B[1]>0: deltay='+'+decimaux(str(A[1]-B[1])) else : deltay=decimaux(str(A[1]-B[1])) if A[0]-B[0]>0: deltax='+'+decimaux(str(A[0]-B[0])) else: deltax=decimaux(str(A[0]-B[0])) if float(B[0])<0 : mid11=float(B[0])-0.75 mid12=float((B[1]+A[1]))/2 #milieu de la flèche verticale else: mid11=float(B[0])+0.75 mid12=float((B[1]+A[1]))/2 if float(B[0])*float(u[1]/u[0])>0 : mid21=float((A[0]+B[0]))/2 mid22=A[1]-0.6 #milieu de la flèche horizontale else : mid21=float((A[0]+B[0]))/2 mid22=A[1]+0.5 if mid12 < 0 and mid12 >-0.8: mid12=-1 if mid12 >= 0 and mid12 < 0.5: mid12=0.5 if mid11 < 0 and mid11 >-0.8: mid11=-1 if mid11 >=0 and mid11 < 0.5: mid11=0.5 if mid21 < 0 and mid21 >-0.8: mid21=-1 if mid21 >=0 and mid21 < 0.5: mid21=0.5 if mid22 < 0 and mid22 >-0.8: mid22=-1 if mid22 >= 0 and mid22 < 0.5: mid22=0.5 mid1=(mid11,mid12) mid2=(mid21,mid22) l=[u'Déterminer l\'expression de la fonction $'+f+u'$ représentée ci-contre par la droite ($d_'+str(i)+'$).', u'On lit l\'ordonnée à l\'origine et le coefficient de la fonction affine sur le graphique.\\\ ', '$'+f+'(x)=ax+b$ ' +'avec $b='+ decimaux(str(A[1]))+'$ et $a='+'\\dfrac{'+deltay+'}{'+deltax+'}='+coefres+'$.\\\ ', 'L\'expression de la fonction $'+f+'$ est $'+f+'(x)='+coef+'x'+b+'$.', doublefleche(B,(B[0],A[1])), doublefleche((B[0],A[1]),A), '\\rput'+str(mid1)+'{('+deltay+')}', '\\rput'+str(mid2)+'{('+deltax+')}'] return l def affine(): #Génère l'exercice xmin,xmax,ymin,ymax=-5,5,-5,5 f=['f','g','h','k','l','u'] rgfonc1=random.randrange(0,6) fonc1=f[rgfonc1] (A,B,C,D,E,F)=couples() l=anteimage(fonc1,A,B) #lecture d'image d'antécédent fonc2=f[(rgfonc1+1)%6] l2=tracefonc(fonc2,2,C,D,xmin,xmax,ymin,ymax) #représenter une fonction fonc3=f[(rgfonc1+2)%6] l3=exprfonc(fonc3,3,E,F) noms=nom3droites(A,B,C,D,E,F,xmin,xmax,ymin,ymax) exo=["\\exercice", "\\parbox{0.5\\linewidth}{", u"($d_1$) est la droite représentative de la fonction $"+fonc1+"$.", "\\begin{enumerate}", "\\item "+l[0], "\\item "+l[4], "\\item "+l2[0], "\\item "+l3[0], "\\end{enumerate}}\\hfill", "\\parbox{0.45\\linewidth}{", "\\psset{unit=0.8cm}", "\\begin{pspicture}"+str((xmin,ymin))+str((xmax,ymax)), "\\psgrid[subgriddiv=2, gridlabels=8pt](0,0)"+str((xmin,ymin))+str((xmax,ymax)), "\\psline[linewidth=1.2pt]{->}"+str((xmin,0))+str((xmax,0)), "\\psline[linewidth=1.2pt]{->}"+str((0,ymin))+str((0,ymax)), tracedroite(A,B,xmin,xmax,ymin,ymax), noms[0], tracedroite(E,F,xmin,xmax,ymin,ymax), noms[2], "\\end{pspicture}}"] cor=["\\exercice*", "\\setlength{\\columnsep}{2mm}", "\\begin{multicols}{2}\\noindent \\small", u"($d_1$) est la droite représentative de la fonction $"+fonc1+"$.", "\\begin{enumerate}", "\\item "+l[1], "\\item "+l[5], "\\item\n\\begin{flushleft}\n"+l2[1]+"\n\\end{flushleft}", "\\item\n\\begin{flushleft}\n"+l3[1], l3[2], l3[3]+"\n\\end{flushleft}", "\\end{enumerate}", "\\end{multicols}", "\\vspace{0.45cm}", "\\begin{minipage}{0.5\\linewidth}", "\\psset{unit=0.7cm}", "\\begin{center}", "\\begin{pspicture}"+str((xmin,ymin))+str((xmax,ymax)), "\\psgrid[subgriddiv=2, gridlabels=8pt](0,0)"+str((xmin,ymin))+str((xmax,ymax)), "\\psline[linewidth=1.2pt]{->}"+str((xmin,0))+str((xmax,0)), "\\psline[linewidth=1.2pt]{->}"+str((0,ymin))+str((0,ymax)), tracedroite(A,B,xmin,xmax,ymin,ymax), noms[0], tracedroite(C,D,xmin,xmax,ymin,ymax), noms[1], l[2], l[3], l[6], l[7], l2[2], l2[3], "\\end{pspicture}", "\\end{center}", "\\end{minipage}", "\\begin{minipage}{0.5\\linewidth}", "\\psset{unit=0.7cm}", "\\begin{center}", "\\begin{pspicture}"+str((xmin,ymin))+str((xmax,ymax)), "\\psgrid[subgriddiv=2, gridlabels=8pt](0,0)"+str((xmin,ymin))+str((xmax,ymax)), "\\psline[linewidth=1.2pt]{->}"+str((xmin,0))+str((xmax,0)), "\\psline[linewidth=1.2pt]{->}"+str((0,ymin))+str((0,ymax)), tracedroite(E,F,xmin,xmax,ymin,ymax), noms[2], l3[4], l3[5], l3[6], l3[7], "\\end{pspicture}", "\\end{center}", "\\end{minipage}", "\\vspace{0.45cm}"] return exo,cor def tex_affine(): return affine() pyromaths/src/troisiemes/._arithmetique.py0000644000175000017500000000031511702101415021523 0ustar didrocksdidrocksMac OS X  2ATTRG}55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/racines.py0000644000175000017500000002550011702101415020234 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils import Arithmetique import random from .developpements import tex_coef #carres=[2,3,5,6,7,10,11,13,15,17,19] carres = [2, 3, 5, 6, 7, 10] #,11,13,15,17,19] def exoaRb0(exo, cor, v): a = (tex_coef(v[0], '\\sqrt{%s}' % (v[6] * v[3] ** 2)), tex_coef(v[1], '\\sqrt{%s}' % (v[6] * v[4] ** 2), bplus=1), tex_coef(v[2], '\\sqrt{%s}' % (v[6] * v[5] ** 2), bplus=1)) exo.append(u'\\[ \\thenocalcul = ' + '%s%s%s' % a + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + '%s%s%s' % a + '\\] ') a = (tex_coef(v[0], '\\sqrt{%s}' % v[3] ** 2), v[6], tex_coef(v[1], '\\sqrt{%s}' % v[4] ** 2, bplus=1), v[6], tex_coef(v[2], '\\sqrt{%s}' % v[5] ** 2, bplus=1), v[6]) cor.append(u'\\[ \\thenocalcul = ' + '%s\\times\\sqrt{%s}%s\\times\\sqrt{%s}%s\\times\\sqrt{%s}' % a + '\\] ') a = ( tex_coef(v[0], ''), v[3], v[6], tex_coef(v[1], '', bplus=1), v[4], v[6], tex_coef(v[2], '', bplus=1), v[5], v[6], ) cor.append(u'\\[ \\thenocalcul = ' + '%s\\times%s\\times\\sqrt{%s}%s\\times%s\\times\\sqrt{%s}%s\\times%s\\times\\sqrt{%s}' % a + '\\] ') a = (tex_coef(v[0] * v[3], '\\sqrt{%s}' % v[6]), tex_coef(v[1] * v[4], '\\sqrt{%s}' % v[6], bplus=1), tex_coef(v[2] * v[5], '\\sqrt{%s}' % v[6], bplus=1)) cor.append(u'\\[ \\thenocalcul = ' + '%s%s%s' % a + '\\] ') del a cor.append(u'\\[ \\boxed{\\thenocalcul = ' + '%s' % tex_coef(v[0] * v[3] + v[1] * v[4] + v[2] * v[5], '\\sqrt{%s}' % v[6]) + '} \\] ') def valeurs_aRb0(pyromax): # renvoie (coef0, coef1, coef2, carre0, carre1, carre2, b) a = carres l = [Arithmetique.valeur_alea(-pyromax, pyromax) for i in range(3)] while True: t = [random.randrange(2, pyromax) for i in range(3)] if pyromax < 4 or t[0] != t[1] and t[0] != t[2] and t[1] != t[2]: break l.extend(t) l.append(a[random.randrange(len(a))]) return tuple(l) def exoaRb1(exo, cor, v): a = (v[3] * v[0] ** 2, v[3] * v[1] ** 2, v[3] * v[2] ** 2) exo.append(u'\\[ \\thenocalcul = ' + '\\sqrt{%s}\\times\\sqrt{%s}\\times\\sqrt{%s}' % a + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + '\\sqrt{%s}\\times\\sqrt{%s}\\times\\sqrt{%s}' % a + '\\] ') a = (v[0] ** 2, v[3], v[1] ** 2, v[3], v[2] ** 2, v[3]) cor.append(u'\\[ \\thenocalcul = ' + '\\sqrt{%s}\\times\\sqrt{%s}\\times\\sqrt{%s}\\times\\sqrt{%s}\\times\\sqrt{%s}\\times\\sqrt{%s}' % a + '\\] ') a = (v[0], v[3], v[1], v[3], v[2], v[3]) cor.append(u'\\[ \\thenocalcul = ' + '%s\\times\\sqrt{%s}\\times%s\\times\\sqrt{%s}\\times%s\\times\\sqrt{%s}' % a+ '\\] ') a = ((v[0] * v[1]) * v[2], v[3], v[3]) cor.append(u'\\[ \\thenocalcul = ' + '%s\\times\\left(\\sqrt{%s}\\right)^2\\times\\sqrt{%s}' % a + '\\] ') a = ((v[0] * v[1]) * v[2], v[3], v[3]) cor.append(u'\\[ \\thenocalcul = ' + '%s\\times%s\\times\\sqrt{%s}' % a + '\\] ') del a cor.append(u'\\[ \\boxed{\\thenocalcul = ' + '%s' % tex_coef(((v[0] * v[1]) * v[2]) * v[3], '\\sqrt{%s}' % v[3]) + '} \\] ') def valeurs_aRb1(pyromax): # renvoie (coef0, coef1, coef2, carre0, carre1, carre2, b) a = carres while True: l = [random.randrange(2, pyromax) for i in range(3)] if pyromax < 4 or l[0] != l[1] and l[0] != l[2] and l[1] != l[2]: break l.append(a[random.randrange(len(a))]) return tuple(l) def valeurs_aPbRc(pyromax): # renvoie (coef0, coef1, coef2, carre0, carre1, carre2, b) while True: a = carres[random.randrange(len(carres))] b = carres[random.randrange(len(carres))] if a != b and Arithmetique.pgcd(a, b) != min(a, b): break while True: c = random.randrange(2, pyromax) d = Arithmetique.valeur_alea(-pyromax, pyromax) if c != d: break return (c, a, d, b) def exo_aPbRc(exo, cor, v): a = (tex_coef(v[0], '\\sqrt{%s}' % v[1]), tex_coef(v[2], '\\sqrt{%s}' % v[3], bplus=1)) exo.append(u'\\[ \\thenocalcul = ' + '\\left( %s%s \\right)^2' % a + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + '\\left( %s%s \\right)^2' % a + '\\] ') if v[2] > 0: sgn = '+' else: sgn = '-' a = (tex_coef(v[0], '\\sqrt{%s}' % v[1], bpc=1), sgn, tex_coef(v[0], '\\sqrt{%s}' % v[1]), tex_coef(abs(v[2]), '\\sqrt{%s}' % v[3]), tex_coef(abs(v[2]), '\\sqrt{%s}' % v[3], bpc=1)) cor.append(u'\\[ \\thenocalcul = ' + '%s^2%s2\\times%s\\times%s+%s^2' % a + '\\] ') a = (v[0] ** 2, v[1], tex_coef((2 * v[0]) * v[2], '\\sqrt{%s}' % (v[1] * v[3]), bplus=1), v[2] ** 2, v[3]) cor.append(u'\\[ \\thenocalcul = ' + '%s\\times %s %s+%s\\times %s' % a + '\\] ') a = (v[0] ** 2 * v[1] + v[2] ** 2 * v[3], tex_coef((2 * v[0]) * v[2], '\\sqrt{%s}' % (v[1] * v[3]), bplus=1)) cor.append(u'\\[ \\boxed{\\thenocalcul = ' + '%s%s' % a + '} \\] ') def valeurs_entier0(pyromax): # renvoie (coef0, coef1, coef2, carre0, carre1, carre2, b) a = carres[random.randrange(len(carres))] while True: b = random.randrange(2, pyromax) c = Arithmetique.valeur_alea(-pyromax, pyromax) if b != c and abs(c) != 1: break return (b, c, a) def exo_entier0(exo, cor, v): a = (v[0], tex_coef(v[1], '\\sqrt{%s}' % v[2], bplus=1), v[0], tex_coef(-v[1], '\\sqrt{%s}' % v[2], bplus=1)) exo.append(u'\\[ \\thenocalcul = ' + '\\left( %s%s \\right)\\left( %s%s \\right)' % a + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + '\\left( %s%s \\right)\\left( %s%s \\right)' % a + '\\] ') a = (tex_coef(v[0], '', bpc=1), tex_coef(abs(v[1]), '\\sqrt{%s}' % v[2], bpc=1)) cor.append(u'\\[ \\thenocalcul = ' + '%s^2-%s^2' % a + '\\] ') a = (v[0] ** 2, v[1] ** 2, v[2]) cor.append(u'\\[ \\thenocalcul = ' + '%s-%s\\times %s' % a + '\\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + '%s' % (v[0] ** 2 - v[1] ** 2 * v[2]) + '} \\] ') def valeurs_entier1(pyromax): # renvoie (coef0, coef1, coef2, carre0, carre1, carre2, b) a = carres[random.randrange(len(carres))] while True: v0 = random.randrange(2, pyromax) v1 = random.randrange(2, pyromax) b0 = random.randrange(2, pyromax) b1 = random.randrange(2, pyromax) a0 = (b1 * v0) * v1 a1 = v1 * b0 if b0 < b1 and Arithmetique.pgcd(a0, a1) != a1: break return (a0, b0, a1, b1, a) def exo_entier1(exo, cor, v): a = (tex_coef(v[0], '\\sqrt{%s}' % (v[1] ** 2 * v[4])), tex_coef(v[2], '\\sqrt{%s}' % (v[3] ** 2 * v[4]))) exo.append(u'\\[ \\thenocalcul = ' + '\\frac{%s}{%s}' % a + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + '\\frac{%s}{%s}' % a + '\\] ') a = (v[0], v[1] ** 2, v[4], v[2], v[3] ** 2, v[4]) cor.append(u'\\[ \\thenocalcul = ' + '\\frac{%s\\times\\sqrt{%s}\\times\\cancel{\\sqrt{%s}}}{%s\\times\\sqrt{%s}\\times\\cancel{\\sqrt{%s}}}' % a + '\\] ') cor.append(u'\\[ \\thenocalcul = ' + '\\frac{%s\\times %s}{%s\\times %s}' % v[0:4] + '\\] ') cor.append(u'\\[ \\boxed{\\thenocalcul = ' + '%s' % (((v[0] * v[1]) // v[2]) // v[3]) + '} \\] ') def tex_racines(): exo = ['\\exercice'] exo.append('\\begin{enumerate}') exo.append(u'\\item Calculer les expressions suivantes et donner le résultat sous la forme $a\\,\\sqrt{b}$ avec $a$ et $b$ entiers, $b$ le plus petit possible.') exo.append('\\begin{multicols}{2}\\noindent') cor = ['\\exercice*'] cor.append('\\begin{enumerate}') cor.append(u'\\item Calculer les expressions suivantes et donner le résultat sous la forme $a\\,\\sqrt{b}$ avec $a$ et $b$ entiers, $b$ le plus petit possible.') mymax = 5 cor.append('\\begin{multicols}{2}\\noindent') valeurs = valeurs_aRb0(mymax) exoaRb0(exo, cor, valeurs) exo.append('\\columnbreak\\stepcounter{nocalcul}%') cor.append('\\columnbreak\\stepcounter{nocalcul}%') valeurs = valeurs_aRb1(mymax) exoaRb1(exo, cor, valeurs) exo.append('\\end{multicols}\\vspace{-3ex}') cor.append('\\end{multicols}') exo.append(u'\\item Calculer les expressions suivantes et donner le résultat sous la forme $a+b\\,\\sqrt{c}$ avec $a$, $b$ et $c$ entiers.') exo.append('''\\stepcounter{nocalcul}% \\begin{multicols}{2}\\noindent''') cor.append(u'\\item Calculer les expressions suivantes et donner le résultat sous la forme $a+b\\,\\sqrt{c}$ avec $a$, $b$ et $c$ entiers.') cor.append('''\\stepcounter{nocalcul}% \\begin{multicols}{2}\\noindent''') valeurs = valeurs_aPbRc(mymax) exo_aPbRc(exo, cor, valeurs) exo.append('\\columnbreak\\stepcounter{nocalcul}%') cor.append('\\columnbreak\\stepcounter{nocalcul}%') valeurs = valeurs_aPbRc(mymax) exo_aPbRc(exo, cor, valeurs) exo.append('\\end{multicols}\\vspace{-3ex}') cor.append('\\end{multicols}') exo.append(u"\\item Calculer les expressions suivantes et donner le résultat sous la forme d'un nombre entier.\n") exo.append('''\\stepcounter{nocalcul}% \\begin{multicols}{2}\\noindent''') cor.append(u"\\item Calculer les expressions suivantes et donner le résultat sous la forme d'un nombre entier.\n") cor.append('''\\stepcounter{nocalcul}% \\begin{multicols}{2}\\noindent''') valeurs = valeurs_entier0(mymax) exo_entier0(exo, cor, valeurs) exo.append('\\columnbreak\\stepcounter{nocalcul}%') cor.append('\\columnbreak\\stepcounter{nocalcul}%') valeurs = valeurs_entier1(mymax) exo_entier1(exo, cor, valeurs) exo.append('\\end{multicols}\\vspace{-3ex}') exo.append('\\end{enumerate}') cor.append('\\end{multicols}') cor.append('\\end{enumerate}') return (exo, cor) pyromaths/src/troisiemes/pgcd.py0000644000175000017500000001440611702101415017530 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random # # ------------------- PGCD ------------------- def tex_trouve_diviseur(a): # trouve si les nombres dans le tuple a sont divisible par 10, 2, 5, 9 ou 3 (dans cet ordre) if a[0] % 10 == 0 and a[1] % 10 == 0: return '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ u'} se terminent tous les deux par zéro donc ils sont divisibles par 10.\\par\n' + \ '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ '} ne sont donc pas premiers entre eux' elif a[0] % 2 == 0 and a[1] % 2 == 0: return '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ '} sont deux nombres pairs donc ils sont divisibles par 2.\\par\n' + \ '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ '} ne sont donc pas premiers entre eux' elif a[0] % 5 == 0 and a[1] % 5 == 0: return '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ u'} se terminent tous les deux par zéro ou cinq donc ils sont divisibles par 5.\\par\n' + \ '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ '} ne sont donc pas premiers entre eux' elif a[0] % 9 == 0 and a[1] % 9 == 0: return 'La somme des chiffres de \\nombre{' + str(a[0]) + \ '} et celle de \\nombre{' + str(a[1]) + \ '} sont divisibles par neuf donc ils sont divisibles par 9.\\par\n' + \ '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ '} ne sont donc pas premiers entre eux' elif a[0] % 3 == 0 and a[1] % 3 == 0: return 'La somme des chiffres de \\nombre{' + str(a[0]) + \ '} et celle de \\nombre{' + str(a[1]) + \ '} sont divisibles par trois donc ils sont divisibles par 3.\\par\n' + \ '\\nombre{' + str(a[0]) + '} et \\nombre{' + str(a[1]) + \ '} ne sont donc pas premiers entre eux' def valeurs_pgcd(): # creer un tuple contenant les deux nombres dont on cherche le pgcd reste = random.choice((2, 3, 5, 9, 10)) * random.choice((7, 11, 13, 17, 19, 23, 31)) diviseur = reste * random.randrange(1, 10) for i in range(random.randrange(2, 5)): (diviseur, reste) = (diviseur * random.randrange(1, 10) + reste, diviseur) return (diviseur, reste) def algo_euclide(a): # renvoi une liste contenant (dividende,diviseur,quotient,reste) pour chaque etape liste = [] if a[0] > a[1]: (dividende, diviseur) = (a[0], a[1]) else: (dividende, diviseur) = (a[1], a[0]) (quotient, reste) = (dividende // diviseur, dividende % diviseur) liste.append((dividende, diviseur, quotient, reste)) while reste != 0: (dividende, diviseur) = (diviseur, reste) (quotient, reste) = (dividende // diviseur, dividende % diviseur) liste.append((dividende, diviseur, quotient, reste)) return liste def simplifie_fraction_pgcd(l): # renvoie le nombre par lequel on peut simplifier la fraction et la fraction simplifiée (pgcd, n0, d0) = (l[len(l) - 1][1], l[0][0], l[0][1]) (n1, d1) = (l[0][0] // pgcd, l[0][1] // pgcd) return (n0, d0, n0, pgcd, d0, pgcd, n1, d1) def tex_algo_euclide(l): # renvoie l'ecriture au format tex de l'algorithme d'Euclide lignes = [] for i in range(len(l)): lignes.append('\\nombre{%s}=\\nombre{%s}\\times\\nombre{%s}+\\nombre{%s}' % l[i]) lignes.append('\\fbox{Donc le \\textsc{pgcd} de \\nombre{%s} et \\nombre{%s} est %s}.\n' % (l[0][0], l[0][1], l[len(l) - 1][1])) return lignes def tex_simplifie_fraction_pgcd(a): # renvoie l'ecriture au format tex de la simplification de la fraction return '''\\begin{align*} \\cfrac{\\nombre{%s}}{\\nombre{%s}} &= \\cfrac{\\nombre{%s}\\div%s}{\\nombre{%s}\\div%s}\\\\\n &= \\boxed{\\cfrac{\\nombre{%s}}{\\nombre{%s}}} \\end{align*}''' % a def tex_pgcd(): nombres = valeurs_pgcd() exo = ['\\exercice'] exo.append('\\begin{enumerate}') exo.append('\\item Les nombres \\nombre{%s} et \\nombre{%s} sont-ils premiers entre eux ? ' % nombres) exo.append('\\item Calculer le plus grand commun diviseur (\\textsc{pgcd}) de \\nombre{%s} et \\nombre{%s}.' % nombres) exo.append(u'\\item Simplifier la fraction $\\cfrac{\\nombre{%s}}{\\nombre{%s}}$ pour la rendre irréductible en indiquant la méthode.\n' % nombres) exo.append('\\end{enumerate}') cor = ['\\exercice*'] cor.append('\\begin{enumerate}') cor.append('\\item Les nombres \\nombre{%s} et \\nombre{%s} sont-ils premiers entre eux ?\\par ' % nombres) cor.append(tex_trouve_diviseur(nombres)) cor.append('\\item Calculer le plus grand commun diviseur (\\textsc{pgcd}) de \\nombre{%s} et \\nombre{%s}.\\par' % nombres) cor.append('On calcule le \\textsc{pgcd} des nombres \\nombre{%s} et \\nombre{%s} en utilisant l\'algorithme d\'Euclide.' % nombres) l = algo_euclide(nombres) tex_liste = tex_algo_euclide(l) for i in range(len(l)): cor.append(u'\\[ %s' % tex_liste[i] + '\\] ') cor.append(tex_liste[len(l)]) cor.append(u'\\item Simplifier la fraction $\\cfrac{\\nombre{%s}}{\\nombre{%s}}$ pour la rendre irréductible en indiquant la méthode.' % nombres) cor.append(tex_simplifie_fraction_pgcd(simplifie_fraction_pgcd(l))) cor.append('\\end{enumerate}') return (exo, cor) pyromaths/src/troisiemes/._pgcd.py0000644000175000017500000000031511702101415017737 0ustar didrocksdidrocksMac OS X  2ATTRGނ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/proba.py0000644000175000017500000001411711702101415017715 0ustar didrocksdidrocks# -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random from math import * from ..outils.Fractions import Fractions def proba(exo, cor): couleur=['bleue','rouge','jaune','verte','marron','orange'] initiale=['B','R','J','V','M','O'] #Choix des 3 couleurs et du nombre de boule rg=random.randrange(0,4) c1,i1,n1=couleur[rg],initiale[rg],random.randrange(1,6) #1ere couleur, son initiale et le nombre #2e couleur diférente de la première rg2=(rg+random.randrange(1,5))%6 c2,i2,n2=couleur[rg2],initiale[rg2],random.randrange(1,6) #3e couleur différente des précédentes c3,i3,n3=couleur[(rg2+1)%6],initiale[(rg2+1)%6],random.randrange(1,6) if n1>1: plur1="s" else : plur1="" if n2>1: plur2="s" else : plur2="" if n3>1: plur3="s" else : plur3="" exos=[u"Dans une urne, il y a %s boule%s %s%s (%s), %s boule%s %s%s (%s) et %s boule%s %s%s (%s), indiscernables au toucher. On tire successivement et sans remise deux boules."%(n1,plur1,c1,plur1,i1,n2,plur2,c2,plur2,i2,n3,plur3,c3,plur3,i3), "\\begin{enumerate}", u"\\item Quelle est la probabilité de tirer une boule %s au premier tirage?" %c2, u"\\item Construire un arbre des probabilités décrivant l'expérience aléatoire.", u"\\item Quelle est la probabilité que la première boule soit %s et la deuxième soit %s?"%(c3,c2), u"\\item Quelle est la probabilité que la deuxième boule soit %s ?"%c1, "\\end{enumerate}"] tot=n1+n2+n3 #calculs intermédiaires pour la question 4 p41="\\dfrac{%s}{%s}\\times \\dfrac{%s}{%s}+"%(n1,tot,n1-1,tot-1) p42="\\dfrac{%s}{%s}\\times \\dfrac{%s}{%s}+"%(n2,tot,n1,tot-1) p43="\\dfrac{%s}{%s}\\times \\dfrac{%s}{%s}="%(n3,tot,n1,tot-1) result4="\\dfrac{%s}{%s}"%(n1*(n1-1+n2+n3),tot*(tot-1)) #resultat non simplifié de la question 4 cors=[u"Dans une urne, il y a %s boule%s %s%s (%s), %s boule%s %s%s (%s) et %s boule%s %s%s (%s), indiscernables au toucher. On tire successivement et sans remise deux boules."%(n1,plur1,c1,plur1,i1,n2,plur2,c2,plur2,i2,n3,plur3,c3,plur3,i3), "\\begin{enumerate}", u"\\item Quelle est la probabilité de tirer une boule %s au premier tirage?\\par " %c2, "Il y a %s boules dans l'urne dont %s boule%s %s%s. \\par"%(tot,n2,plur2,c2,plur2), u" La probabilité de tirer une boule %s au premier tirage est donc $\\dfrac{%s}{%s}$."%(c2,n2,tot), u"\\item Construire un arbre des probabilités décrivant l'expérience aléatoire.\\\ [0,3cm] ", "\\psset{unit=1 mm}", "\\psset{linewidth=0.3,dotsep=1,hatchwidth=0.3,hatchsep=1.5,shadowsize=1,dimen=middle}", "\\psset{dotsize=0.7 2.5,dotscale=1 1,fillcolor=black}", "\\psset{arrowsize=1 2,arrowlength=1,arrowinset=0.25,tbarsize=0.7 5,bracketlength=0.15,rbracketlength=0.15}", "\\begin{pspicture}(0,0)(80,53)", "\\psline(0,3)(10,23)", "\\psline(10,3)(10,23)", "\\psline(20,3)(10,23)", "\\psline(30,3)(40,23)", "\\psline(40,3)(40,23)", "\\psline(50,3)(40,23)", "\\psline(60,3)(70,23)", "\\psline(80,3)(70,23)", "\\psline(70,3)(70,23)", "\\psline(15,28)(40,53)", "\\psline(40,53)(65,28)", "\\psline(40,53)(40,28)", "\\rput(20,40){$\\dfrac{%s}{%s}$} \\rput(37,40){$\\dfrac{%s}{%s}$} \\rput(60,40){$\\dfrac{%s}{%s}$}"%(n1,tot,n2,tot,n3,tot), "\\rput(10,26){%s} \\rput(40,26){%s} \\rput(70,26){%s}"%(i1,i2,i3), "\\rput(0,10){$\\dfrac{%s}{%s}$} \\rput(7,10){$\\dfrac{%s}{%s}$} \\rput(20,10){$\\dfrac{%s}{%s}$}"%(n1-1,tot-1,n2,tot-1,n3,tot-1), "\\rput(0,0){%s} \\rput(10,0){%s} \\rput(20,0){%s}"%(i1,i2,i3), "\\rput(30,10){$\\dfrac{%s}{%s}$} \\rput(37,10){$\\dfrac{%s}{%s}$} \\rput(50,10){$\\dfrac{%s}{%s}$}"%(n1,tot-1,n2-1,tot-1,n3,tot-1), "\\rput(30,0){%s} \\rput(40,0){%s} \\rput(50,0){%s}"%(i1,i2,i3), "\\rput(60,10){$\\dfrac{%s}{%s}$} \\rput(67,10){$\\dfrac{%s}{%s}$} \\rput(80,10){$\\dfrac{%s}{%s}$}"%(n1,tot-1,n2,tot-1,n3-1,tot-1), "\\rput(60,0){%s} \\rput(70,0){%s} \\rput(80,0){%s}"%(i1,i2,i3), "\\end{pspicture}", "\\vspace{0.3cm}", u"\\item Quelle est la probabilité que la première boule soit %s et la deuxième soit %s?\\par"%(c3,c2), u"On utilise l'arbre construit précédemment.\\par", "$p(%s,%s)=%s \\times %s = %s$\\par" % \ (i3,i2,Fractions.TeX(Fractions(n3,tot)), Fractions.TeX(Fractions(n2,tot-1)), Fractions.TeX(Fractions(n3*n2,tot*(tot-1)))), u"La probabilité que la première boule soit %s et la deuxième soit %s est égale à $\\dfrac{%s}{%s}$."%(c3,c2,n3*n2,tot*(tot-1)), u"\\item Quelle est la probabilité que la deuxième boule soit %s ?\\par"%c1, u"On note (?, %s) l'évènement: la deuxième boule tirée est %s. \\par"%(i1,c1), "$p(?,%s)=p(%s,%s)+p(%s,%s)+p(%s,%s,)="%(i1,i1,i1,i2,i1,i3,i1)+p41+p42+p43+result4+"$", "\\end{enumerate}"] for st in exos: exo.append(st) for st in cors: cor.append(st) def tex_proba(): exo=['\\exercice'] cor=['\\exercice*'] proba(exo,cor) return (exo, cor) pyromaths/src/troisiemes/._equations.py0000644000175000017500000000031511702101415021032 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/._developpements.py0000644000175000017500000000031511702101415022054 0ustar didrocksdidrocksMac OS X  2ATTRG~55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/troisiemes/geometrie.py0000644000175000017500000006512711702101415020601 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random from math import acos, asin, atan, pi, sin, cos, tan from . import fractions from ..outils.Arithmetique import valeur_alea, pgcd from ..outils.Geometrie import choix_points #--------------------------------------------------------------------- #- THÉORÈME DE THALÈS - #--------------------------------------------------------------------- def cotes_sommets(noms): # renvoie les noms des 3 cotes du triangle en finissant par l'hypotenuse return (noms[1] + noms[2], noms[0] + noms[2], noms[0] + noms[1]) def nom_triangle(noms): # renvoie le nom du triangle dans un ordre aleatoire a = random.randrange(3) b = (random.randrange(2) + 1 + a) % 3 c = (3 - a) - b return '%s%s%s' % (noms[a], noms[b], noms[c]) def valeurs_thales(valeurmax, type): """type est égal à 1 pour la version triangle, -1 pour la version papillon""" liste = [0, 0, 0, 0, 0, 0, 0, 0] while liste == [0, 0, 0, 0, 0, 0, 0, 0]: for i in range(3): liste[i] = random.randrange(2) a = random.randrange(liste.count(1)) for i in range(3): if liste[i]: if not a: liste[i + 3] = 1 a = a - 1 else: liste[i + 3] = 1 # on doit connaitre le numeratuer ou le denominateur for i in range(2): # AB et AE ou AB et BE ou AE et EB if liste[i] and liste[i + 3]: # i est le rapport complet. On choisit une des 3 formes ci-dessus a = random.randrange(2) liste[i + 6] = 1 liste[i + 3 * a] = 0 rapport = [i + 3 * ((a + 1) % 3), i + 3 * ((a + 2) % 3)] rapport.sort() if liste[2] and liste[5]: rapport = [2, 5] valeurs = [0, 0, 0, 0, 0, 0, 0, 0] for i in range(3): if liste[i]: valeurs[i] = random.randrange(15, valeurmax) / 10.0 if liste[i + 3] and liste[i]: valeurs[i + 3] = random.randrange(5, valeurs[i] * 10 - 9) / \ 10.0 elif liste[i + 3]: valeurs[i + 3] = random.randrange(5, valeurmax) / 10.0 if liste[6]: valeurs[6] = random.randrange(5, valeurmax) / 10.0 if liste[7]: valeurs[7] = random.randrange(5, valeurmax) / 10.0 valeurs.append((rapport, type)) if test_valeurs_thales(valeurs, rapport, type): return valeurs else: return 0 def test_valeurs_thales(valeurs, rapport, type_thales): v = [valeurs[i] for i in range(8)] if rapport[0] // 3 == 0 and rapport[1] // 3 == 2: # On donne AB et EB v[rapport[0] + 3] = (v[rapport[0]] - v[rapport[1]]) * \ type_thales elif rapport[0] // 3 == 1 and rapport[1] // 3 == 2: # On donne AE et EB v[rapport[0] - 3] = v[rapport[0]] * type_thales + v[rapport[1]] if v[rapport[0] % 3]: # rapport est AE/AB rapp = (v[rapport[0] % 3 + 3] * 1.0) / v[rapport[0] % 3] else: rapp = 0 for i in range(3): if not v[i] and rapp: v[i] = v[i + 3] / rapp elif not v[i + 3]: v[i + 3] = v[i] * rapp if inegalite_triangulaire(v[0:3]) and inegalite_triangulaire(v[3:6]) and \ .3 < rapp < .7: return v else: return 0 def inegalite_triangulaire(a): # renvoie 1 si c'est un triangle, 0 sinon vrai = 0 coef = 1.2 # evite les triangles trop ecrases if a[0] > a[1] and a[0] > a[2]: if a[1] + a[2] > coef * a[0]: vrai = 1 elif a[1] > a[0] and a[1] > a[2]: if a[0] + a[2] > coef * a[1]: vrai = 1 elif a[2] > a[0] and a[2] > a[1]: if a[0] + a[1] > coef * a[2]: vrai = 1 return vrai def thales(exo, cor): type = [-1, 1] random.shuffle(type) exo.append("\\begin{multicols}{2}") cor.append("\\begin{multicols}{2}") for i in range(2): noms = choix_points(5) # les noms des sommets while True: valeurs = valeurs_thales(70, type[i]) # les longueurs en mm if valeurs: break exo.append(tex_enonce_thales(noms, valeurs)) exo.append(tex_fig_thales(noms, valeurs)) cor.append(tex_enonce_thales(noms, valeurs)) cor.append(tex_fig_thales(noms, valeurs) + "\n\\par\\dotfill{}") cor.append(tex_resolution_thales0(noms)) cor.append(tex_resolution_thales1(noms, valeurs)) cor.append(tex_resolution_thales2(noms, valeurs)) cor.append(tex_resolution_thales3(noms, valeurs)) if not i: exo.append("\\columnbreak") cor.append("\\columnbreak") else: exo.append("\\end{multicols}") cor.append("\\end{multicols}") def long_val(noms, valeurs): # renvoie un tuple contenant les noms des segments et leur longueur puis les noms des longueurs a calculer liste = [] for i in range(8): if valeurs[i]: liste.append(creer_noms(noms, i)) liste.append(nombre(valeurs[i])) for i in range(6): if not valeurs[i] and valeurs[8][0][0] % 3 != i % 3: liste.append(creer_noms(noms, i)) return liste def lAB(a): # renvoie AB return str(a[0]) + str(a[1]) def nombre(a): texte = str(a).replace('.', ',') if a >= 1000 or a <= 0.0001: return '\\nombre{%s}' % texte else: if texte.count(',') and len(texte) - texte.find(',0') == 2: return texte.replace(',', '{,}').replace('{,}0', '') elif texte.count(','): return texte.replace(',', '{,}') else: return texte def creer_noms(noms, i): if i == 0: return str(noms[0]) + str(noms[1]) elif i == 1: return str(noms[0]) + str(noms[2]) elif i == 2: return str(noms[1]) + str(noms[2]) elif i == 3: return str(noms[0]) + str(noms[3]) elif i == 4: return str(noms[0]) + str(noms[4]) elif i == 5: return str(noms[3]) + str(noms[4]) elif i == 6: return str(noms[3]) + str(noms[1]) elif i == 7: return str(noms[4]) + str(noms[2]) def tex_enonce_thales(noms, valeurs): texte = \ u'Sur la figure ci-dessous, les droites $(%s)\\text{ et }(%s)$ sont parallèles.\\par\n' % \ (lAB(noms[1:3]), lAB(noms[3:5])) liste = long_val(noms, valeurs) texte = texte + \ 'On donne $%s=\\unit[%s]{cm},\\quad %s=\\unit[%s]{cm}, \\quad %s=\\unit[%s]{cm}\\quad\\text{et}\\quad %s~=~\\unit[%s]{cm}$.\\par\n' % \ tuple(liste[0:8]) texte = texte + 'Calculer $%s\\text{ et }%s$.' % tuple(liste[8:10]) return texte def tex_resolution_thales0(n): return u"""Les points $%s$,~ $%s$,~ $%s$ et $%s$, $%s$, $%s$ sont alignés et les droites $(%s)$ et $(%s)$ sont parallèles.\\par D'après le \\textbf{théorème de Thalès} : $\\qquad\\mathbf{\\cfrac{%s}{%s}=\\cfrac{%s}{%s}=\\cfrac{%s}{%s}}$ """ % \ ( n[0], n[3], n[1], n[0], n[4], n[2], n[1] + n[2], n[3] + n[4], creer_noms(n, 0), creer_noms(n, 3), creer_noms(n, 1), creer_noms(n, 4), creer_noms(n, 2), creer_noms(n, 5), ) def tex_resolution_thales1(n, v): r = v[8][0][0] % 3 # grand rapport if v[8][1] == 1: sgn = '+' else: sgn = '-' if v[r] and v[r + 3]: # on connait les deux rapports donnees = 0 elif v[r + 3]: # on connait le petit rapport, mais pas le grand v[r] = v[r + 6] + v[r + 3] * v[8][1] donnees = (creer_noms(n, r), creer_noms(n, r + 6), sgn, creer_noms(n, r + 3), nombre(v[r])) else: v[r + 3] = (v[r] - v[r + 6]) * v[8][1] if sgn == '+': donnees = (creer_noms(n, r + 3), creer_noms(n, r), '-', creer_noms(n, r + 6), nombre(v[r + 3])) else: donnees = (creer_noms(n, r + 3), creer_noms(n, r + 6), '-', creer_noms(n, r), nombre(v[r + 3])) if donnees: return '\\vspace{1ex}\\par\nDe plus $%s=%s%s%s=\\unit[%s]{cm}$' % \ donnees else: return '' def tex_resolution_thales2(n, v): donnees = [] for i in range(3): if v[i]: donnees.append(nombre(v[i])) else: donnees.append(creer_noms(n, i)) if v[i + 3]: donnees.append(nombre(v[i + 3])) else: donnees.append(creer_noms(n, i + 3)) return '\\[\\frac{%s}{%s}=\\frac{%s}{%s}=\\frac{%s}{%s}\\]' % \ tuple(donnees) def nom_ou_valeur(n, v, i): if v[i]: return nombre(v[i]) else: return creer_noms(n, i) def valeur_exacte(a, approx=3, unit=1): nb = nombre(a) if unit: if nb.count(',') and (len(nb) - nb.find(',')) - 1 > approx: return '\\simeq\\unit[' + nombre(int(1000.0 * a) / 1000.0) + \ ']{cm}' else: return '=\\unit[' + nombre(a) + ']{cm}' else: if nb.count(',') and (len(nb) - nb.find(',')) - 1 > approx: return '\\simeq' + nombre(int(1000.0 * a) / 1000.0) else: return '=' + nombre(a) def tex_resolution_thales3(n, v): r = v[8][0][0] % 3 # grand rapport donnees = [] for i in range(3): if i != r: donnees.extend([nom_ou_valeur(n, v, r), nom_ou_valeur(n, v, r + 3), nom_ou_valeur(n, v, i), nom_ou_valeur(n, v, i + 3)]) if v[i]: # on cherche i+3 donnees.extend([creer_noms(n, i + 3), nombre(v[i]), nombre(v[r + 3]), nombre(v[r]), valeur_exacte(((v[i] * 1.0) * v[r + 3]) / v[r])]) else: donnees.extend([creer_noms(n, i), nombre(v[i + 3]), nombre(v[r]), nombre(v[r + 3]), valeur_exacte(((v[r] * 1.0) * v[i + 3]) / v[r + 3])]) texte = \ '$\\cfrac{%s}{%s}=\\cfrac{%s}{%s}\\quad$ donc $\\quad\\boxed{%s=\\cfrac{%s\\times %s}{%s}%s}$\\par\n' % \ tuple(donnees[0:9]) texte = texte + \ '$\\cfrac{%s}{%s}=\\cfrac{%s}{%s}\\quad$ donc $\\quad\\boxed{%s=\\cfrac{%s\\times %s}{%s}%s}$\\par\n' % \ tuple(donnees[9:18]) return texte def fig_thales(noms, valeurs): v = test_valeurs_thales(valeurs[0:8], valeurs[8][0], valeurs[8][1]) type_thales = valeurs[8][1] angle = int(((100.0 * acos(((v[0] ** 2 + v[1] ** 2) - v[2] ** 2) / ((2 * v[0]) * v[1]))) * 180) / pi) / 100.0 v = [int(v[i] * 100) / 100.0 for i in range(8)] mini_x = int(100.0 * min(0, v[1] * cos((angle * pi) / 180), v[3] * type_thales, (v[4] * cos((angle * pi) / 180)) * type_thales)) / 100.0 - 1.5 mini_y = int(100.0 * min(0, (v[4] * sin((angle * pi) / 180)) * type_thales)) / 100.0 - 1.5 maxi_x = int(100.0 * max(v[0], v[1] * cos((angle * pi) / 180))) / \ 100.0 + 1.5 maxi_y = int((100.0 * v[1]) * sin((angle * pi) / 180)) / 100.0 + .5 echelle = int(400 / max(abs(mini_x) + maxi_x, abs(mini_y) + maxi_y)) / \ 100.0 if type_thales == 1: return ( echelle, mini_x, mini_y, maxi_x, maxi_y, 225, angle + 45, noms[0], noms[1], noms[2], v[0], v[1], angle, -45, angle + 90, noms[3], noms[4], v[3], v[4], angle, ) else: return ( echelle, mini_x, mini_y, maxi_x, maxi_y, 135, angle + 45, noms[0], noms[1], noms[2], v[0], v[1], angle, 135, angle + 180, noms[3], noms[4], -v[3], -v[4], angle, ) def tex_fig_thales(noms, valeurs): donnees = fig_thales(noms, valeurs) enonce = \ '''\\begin{center} \\psset{PointSymbol=x,unit=%s} \\begin{pspicture}(%s,%s)(%s,%s) \\SpecialCoor \\pstTriangle[PosAngleA=%s, PosAngleB=-45, PosAngleC=%s, PointNameA=%s, PointNameB=%s, PointNameC=%s](0,0){a}(%s,0){b}(%s;%s){c} \\pstTriangle[PosAngleB=%s, PosAngleC=%s, PointSymbolA=none, PointNameA=none, PointNameB=%s, PointNameC=%s](0,0){a}(%s,0){b}(%s;%s){c} \\end{pspicture} \\end{center} ''' % donnees return enonce def tex_thales(): exo = ['\\exercice'] cor = ['\\exercice*'] thales(exo, cor) return (exo, cor) # # ------------------- RECIPROQUE DU THEOREME DE THALES ------------------- # def valeurs_reciproque_thales(): while True: (a, b, c, d) = (random.randrange(2, 50), random.randrange(2, 50), random.randrange(2, 20), random.randrange(2, 20)) p1 = pgcd(a, b) (a, b) = (a / p1, b / p1) if c < d: (c, d) = (d, c) if a != b and int(c / d) != (c * 1.0) / d and 10 < a * c < 200 and \ 10 < a * d < 200 and 10 < b * c < 200 and 10 < b * d < 200 and \ .3 < (d * 1.0) / c < .7: break t = valeur_alea(-1, 1) # -1 si papillon, 1 si triangle r = random.randrange(5) while r == 2: r = random.randrange(5) angle = random.randrange(15, 105) valeurs = ( (a * c) / 10.0, (b * c) / 10.0, 0, (a * d) / 10.0, (b * d) / 10.0, 0, (a * c - (t * a) * d) / 10.0, (b * c - (t * b) * d) / 10.0, angle, t, r, ) return valeurs def fig_rec_thales(noms, v): type_thales = v[9] angle = v[8] mini_x = int(100.0 * min(0, v[1] * cos((angle * pi) / 180), v[3] * type_thales, (v[4] * cos((angle * pi) / 180)) * type_thales)) / 100.0 - 1.5 mini_y = int(100.0 * min(0, (v[4] * sin((angle * pi) / 180)) * type_thales)) / 100.0 - 1.5 maxi_x = int(100.0 * max(v[0], v[1] * cos((angle * pi) / 180))) / \ 100.0 + 1.5 maxi_y = int((100.0 * v[1]) * sin((angle * pi) / 180)) / 100.0 + .5 echelle = int(400 / max(abs(mini_x) + maxi_x, abs(mini_y) + maxi_y)) / \ 100.0 if type_thales == 1: return ( echelle, mini_x, mini_y, maxi_x, maxi_y, 225, angle + 45, noms[0], noms[1], noms[2], v[0], v[1], angle, -45, angle + 90, noms[3], noms[4], v[3], v[4], angle, ) else: return ( echelle, mini_x, mini_y, maxi_x, maxi_y, 135, angle + 45, noms[0], noms[1], noms[2], v[0], v[1], angle, 135, angle + 180, noms[3], noms[4], -v[3], -v[4], angle, ) def tex_fig_rec_thales(noms, valeurs): donnees = fig_rec_thales(noms, valeurs) enonce = \ '''{\\begin{wrapfigure}{r}{4cm} \\psset{PointSymbol=x,unit=%s} \\begin{pspicture}(%s,%s)(%s,%s) \\SpecialCoor \\pstTriangle[PosAngleA=%s,PosAngleB=-45,PosAngleC=%s,PointNameA=%s,PointNameB=%s,PointNameC=%s](0,0){a}(%s,0){b}(%s;%s){c} \\pstTriangle[PosAngleB=%s,PosAngleC=%s,PointSymbolA=none,PointNameA=none,PointNameB=%s,PointNameC=%s](0,0){a}(%s,0){b}(%s;%s){c} \\end{pspicture} \\end{wrapfigure}\\par ''' % \ donnees return enonce def rec_thales(exo, cor): noms = choix_points(5) # les noms des sommets valeurs = valeurs_reciproque_thales() exo.append(tex_fig_rec_thales(noms, valeurs)) exo.append(tex_enonce_rec_thales(noms, valeurs) + '\\vspace{2cm}}') #le dernier '}' ferme le bloc exercice cor.append(tex_fig_rec_thales(noms, valeurs)) cor.append(tex_enonce_rec_thales(noms, valeurs) + "\\par\\dotfill{}\\\\}\n") cor.append(tex_resolution_rec_thales0(noms, valeurs)) cor.append(tex_resolution_rec_thales1(noms, valeurs)) # cor.append(tex_resolution_rec_thales2(noms, valeurs)) # cor.append(tex_resolution_rec_thales3(noms, valeurs)) def enonce_rec_thales(n, v): (r, l) = (v[10], []) for i in range(5): if i != 2: if i == r: l.extend([creer_noms(n, 6 + i % 3), nombre(v[6 + i % 3])]) else: l.extend([creer_noms(n, i), nombre(v[i])]) l1 = [i for i in range(4)] l2 = [] for i in range(4): a = l1.pop(random.randrange(4 - i)) l2.extend([l[2 * a], l[2 * a + 1]]) l2.extend([creer_noms(n, 2), creer_noms(n, 5)]) return tuple(l2) def tex_enonce_rec_thales(n, v): d = enonce_rec_thales(n, v) texte = \ u'''Sur la figure ci-contre, on donne $%s=\\unit[%s]{cm}$, $%s=\\unit[%s]{cm}$, $%s=\\unit[%s]{cm}$ et $%s=\\unit[%s]{cm}$.\\par Démontrer que les droites $(%s)$ et $(%s)$ sont parallèles. ''' % \ d return texte def resolution_rec_thales0(n, v): t = v[9] r = v[10] if t > 0: d = [n[0], n[3], n[1], n[0], n[4], n[2], creer_noms(n, r)] else: d = [n[3], n[0], n[1], n[4], n[0], n[2], creer_noms(n, r)] if r < 2: if t > 0: d.extend([creer_noms(n, r + 6), '+', creer_noms(n, r + 3), nombre(v[r])]) else: d.extend([creer_noms(n, r + 6), '-', creer_noms(n, r + 3), nombre(v[r])]) else: if t > 0: d.extend([creer_noms(n, r - 3), '-', creer_noms(n, r + 3), nombre(v[r])]) else: d.extend([creer_noms(n, r + 3), '-', creer_noms(n, r - 3), nombre(v[r])]) return tuple(d) def tex_resolution_rec_thales0(n, v): return u"""Les points $%s$, $%s$, $%s$~ et $%s$, $%s$, $%s$ sont alignés dans le même ordre.\\par De plus $%s=%s%s%s=\\unit[%s]{cm}$.\\par """ % \ resolution_rec_thales0(n, v) def resolution_rec_thales1(n, v): (d, t) = ([], '') for i in range(2): d.extend([creer_noms(n, i), creer_noms(n, i + 3), nombre(v[i]), nombre(v[i + 3])]) if valeur_exacte(v[i] / v[i + 3], approx=5).count('='): d.append(valeur_exacte(v[i] / v[i + 3], approx=5, unit=0)) else: if v[i] != int(v[i]) or v[i + 3] != int(v[i + 3]): p = pgcd(int(v[i] * 10), int(v[i + 3] * 10)) if p == 1: t = '=\\cfrac{%s}{%s}' % (nombre(v[i] * 10), nombre(v[i + 3] * 10)) else: t = '=\\cfrac{%s_{\\div%s}}{%s_{\\div%s}}' % (nombre(v[i] * 10), p, nombre(v[i + 3] * 10), p) if fractions.simplifie((int(v[i] * 10), int(v[i + 3] * 10))): d.append(t + '=' + fractions.tex_frac(fractions.simplifie((int(v[i] * 10), int(v[i + 3] * 10))))) else: d.append(t + '=' + fractions.tex_frac((int(v[i] * 10), int(v[i + 3] * 10)))) d.extend([creer_noms(n, 0), creer_noms(n, 3), creer_noms(n, 1), creer_noms(n, 4), creer_noms(n, 2), creer_noms(n, 5)]) return tuple(d) def tex_resolution_rec_thales1(n, v): d = resolution_rec_thales1(n, v) return u"""$\\left. \\renewcommand{\\arraystretch}{2} \\begin{array}{l} \\bullet\\cfrac{%s}{%s}=\\cfrac{%s}{%s}%s\\\\\n \\bullet\\cfrac{%s}{%s}=\\cfrac{%s}{%s}%s \\end{array} \\right\\rbrace$ Donc $\\cfrac{%s}{%s}=\\cfrac{%s}{%s}$\\,.\\par D'après la \\textbf{réciproque du théorème de Thalès}, \\fbox{les droites $(%s)$ et $(%s)$ sont parallèles.} """ % \ d def tex_reciproque_thales(): exo = ['\\exercice'] cor = ['\\exercice*'] rec_thales(exo, cor) return (exo, cor) # # ------------------- TRIGONOMETRIE ------------------- # def trigo_init(exo, cor): s = choix_points(6) n1 = cotes_sommets(s[0:3]) n2 = cotes_sommets(s[3:6]) v = valeurs_trigo() enonce_trigo(exo, cor, ((s[0:3], n1, v[0]), (s[3:6], n2, v[1]))) def enonce_trigo(exo, cor, v): (l, lt) = ([], []) for j in range(2): f = (('\\sin', 1, 0), ('\\cos', 2, 0), ('\\tan', 1, 2))[v[j][2][0]] for i in range(2): l.append(v[j][1][f[i + 1]]) l.append(v[j][2][i + 1]) l.append(tex_angle(v[j][0], 1)) l.append(v[j][2][3]) for j in range(2): tmp = [] for i in range(3): if len(l[2 * i + 6 * j]) < 3: if l[2 * i + 6 * j + 1]: lt.append('$%s=\\unit[%s]{cm}$' % (l[2 * i + 6 * j], nombre(l[2 * i + 6 * j + 1]))) else: tmp = 'la longueur $%s$' % l[2 * i + 6 * j] elif l[2 * i + 6 * j + 1]: lt.append('$%s=%s\\degres$' % (l[2 * i + 6 * j], l[2 * i + 6 * j + 1])) else: lt.append('la mesure de l\'angle $%s$' % l[2 * i + 6 * j]) if tmp: lt.append(tmp) exo.append('\\begin{multicols}{2}') exo.append('\\begin{enumerate}') cor.append('\\begin{multicols}{2}') cor.append('\\begin{enumerate}') tr = nom_triangle(v[0][0]) exo.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par ' % (tr, v[0][0][0])) exo.append('''%s et %s.\\par Calculer %s.\\par ''' % tuple(lt[0:3])) cor.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par ' % (tr, v[0][0][0])) cor.append('''%s et %s.\\par Calculer %s.\\par ''' % tuple(lt[0:3])) cor.append("\\dotfill{}\\par\\vspace{2ex}") cor.append('Dans le triangle $%s$ rectangle en $%s$,' % (tr, v[0][0][0])) # résolution v2 = (v[0][1], v[0][2]) l2 = l[0:6] resolution_trigo(cor, v2, l2) tr = nom_triangle(v[1][0]) exo.append('\\columnbreak') cor.append('\\columnbreak') exo.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par' % (tr, v[1][0][0])) exo.append('''%s et %s.\\par Calculer %s.\\par ''' % tuple(lt[3:6])) cor.append('\\item $%s$ est un triangle rectangle en $%s$ tel que :\\par' % (tr, v[1][0][0])) cor.append('''%s et %s.\\par Calculer %s.\\par ''' % tuple(lt[3:6])) cor.append("\\dotfill{}\\par\\vspace{2ex}") cor.append('Dans le triangle $%s$ rectangle en $%s$,' % (tr, v[1][0][0])) # résolution v2 = (v[1][1], v[1][2]) l2 = l[6:12] resolution_trigo(cor, v2, l2) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') def resolution_trigo(cor, v2, l2): f = (('\\sin', 1, 0), ('\\cos', 2, 0), ('\\tan', 1, 2))[v2[1][0]] cor.append(u'\\[%s%s=\\cfrac{%s}{%s}' % (f[0], l2[4], v2[0][f[1]], v2[0][f[2]]) + '\\] ') if not v2[1][3]: cor.append(u'\\[ %s%s=\\cfrac{%s}{%s}' % (f[0], l2[4], nombre(v2[1][1]), nombre(v2[1][2])) + '\\] ') if f[0] == '\\sin': r = (asin(v2[1][1] / v2[1][2]) * 180) / pi elif f[0] == '\\cos': r = (acos(v2[1][1] / v2[1][2]) * 180) / pi else: r = (atan(v2[1][1] / v2[1][2]) * 180) / pi cor.append(u'\\[ %s=%s^{-1}\\left(\\cfrac{%s}{%s}\\right)\\simeq%s\\degres' % (l2[4], f[0], nombre(v2[1][1]), nombre(v2[1][2]), nombre(int(r * 10) / 10.0)) + '\\] ') elif not v2[1][1]: cor.append(u'\\[ %s%s=\\cfrac{%s}{%s}' % (f[0], v2[1][3], v2[0][f[1]], nombre(v2[1][2])) + '\\] ') if f[0] == '\\sin': r = sin((v2[1][3] * pi) / 180) elif f[0] == '\\cos': r = cos((v2[1][3] * pi) / 180) else: r = tan((v2[1][3] * pi) / 180) r = r * v2[1][2] cor.append(u'\\[ %s=%s%s\\times %s\\simeq\\unit[%s]{cm}' % (v2[0][f[1]], f[0], v2[1][3], nombre(v2[1][2]), nombre(int(r * 100) / 100.0)) + '\\] ') else: cor.append(u'\\[ %s%s=\\cfrac{%s}{%s}' % (f[0], v2[1][3], nombre(v2[1][1]), v2[0][f[2]]) + '\\] ') if f[0] == '\\sin': r = sin((v2[1][3] * pi) / 180) elif f[0] == '\\cos': r = cos((v2[1][3] * pi) / 180) else: r = tan((v2[1][3] * pi) / 180) r = v2[1][1] / r cor.append(u'\\[ %s=\\cfrac{%s}{%s%s}\\simeq\\unit[%s]{cm}' % (v2[0][f[2]], nombre(v2[1][1]), f[0], v2[1][3], nombre(int(r * 100) / 100.0)) + '\\] ') def tex_angle(s, n): # renvoie \\widehat{ABC} où s est la liste des 3 sommets du triangle et n est le rang du sommet de l'angle dans cette liste return '\\widehat{%s%s%s}' % (s[(n + 2) % 3], s[n], s[(n + 1) % 3]) def valeurs_trigo(): l = [random.randrange(10, 121) / 10.0 for i in range(3)] l.sort() l.append(random.randrange(15, 76)) trigo = random.randrange(3) if random.randrange(2): # on choisit en 1er une longueur et un angle if random.randrange(2): # on connait la première des deux longueurs v = (trigo, l[0], 0, l[3]) else: v = (trigo, 0, l[0], l[3]) trigo = (trigo + 1 + random.randrange(2)) % 3 v = (v, (trigo, l[1], l[2], 0)) else: # on choisit en 1er deux longueurs v = (trigo, l[1], l[2], 0) trigo = (trigo + 1 + random.randrange(2)) % 3 if random.randrange(2): # on connait la première des deux longueurs v = (v, (trigo, l[0], 0, l[3])) else: v = (v, (trigo, 0, l[0], l[3])) return v def tex_trigo(): exo = ['\\exercice'] cor = ['\\exercice*'] trigo_init(exo, cor) return (exo, cor) pyromaths/src/__init__.py0000644000175000017500000000171511702101415016166 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/outils/0000755000175000017500000000000011734627250015407 5ustar didrocksdidrockspyromaths/src/outils/TeXMiseEnForme.py0000644000175000017500000001425011702101415020536 0ustar didrocksdidrocks# -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from . import Arithmetique import string import math import os from .Conversions import radians, degres from ..classes.Fractions import Fractions class TeXMiseEnForme: def __init__(self, text): self.text = text def monome(self, coef, var, bplus=0, bpn=0, bpc=0): # coef est le coefficient à écrire devant la variable var # bplus est un booleen : s'il est vrai, il faut ecrire le signe + # bpn est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef est negatif. # bpc est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'ecriture si coef =! 0 ou 1 et var est non vide if coef != 0 and abs(coef) != 1: if var == "": if abs(coef) >= 1000: a = '\\nombre{%s}' % coef else: a = "%s" % coef else: if abs(coef) >= 1000: a = '\\nombre{%s}\\,%s' % (coef, var) else: a = '%s\\,%s' % (coef, var) if bplus and coef > 0: a = '+' + a elif coef == 1: if var == "": a = '1' else: a = "%s" % var if bplus: a = '+' + a elif coef == 0: a = "" elif coef == -1: if var == "": a = '-1' else: a = '-%s' % var if bpn and coef < 0 or bpc and coef != 0 and coef != 1 and var != \ "": a = '\\left( ' + a + '\\right)' return a def sepmilliers(self, nb, mathenvironment=0): # Insère les espaces fines pour séparer les milliers et remplace le point # décimal par une virgule dec = [str(nb)[i] for i in range(len(str(nb)))] if dec.count('e'): #nb ecrit en notation scientifique exposant = int(("").join(dec[dec.index('e') + 1:])) dec = dec[:dec.index('e')] lg = len(dec) if dec.count('.'): virg = dec.index('.') dec.remove('.') else: virg = len(dec) if virg + exposant < 0: #L'ecriture decimale du nombre commence par 0,... dec2 = ["0", '.'] for i in range(-virg - exposant): dec2.append("0") dec2.extend(dec) dec = dec2 elif virg + exposant > lg: #L'ecriture decimale du nombre finit par des 0 for i in range(-((lg - virg) - 1) + exposant): dec.append("0") dec2 = [] if dec.count('.'): lavtvirg = dec.index('.') laprvirg = (len(dec) - dec.index('.')) - 1 else: lavtvirg = len(dec) laprvirg = 0 nbsep = lavtvirg // 3 + 1 if lavtvirg > 3: cpt = lavtvirg % 3 if cpt: dec2 = dec[0:cpt] dec2.append('\\,') nbsep = nbsep - 1 for i in range(nbsep): dec2.extend(dec[cpt:cpt + 3]) if nbsep - i > 1: dec2.append('\\,') cpt = cpt + 3 else: if dec.count('.'): dec2 = dec[0:dec.index('.')] else: dec2 = dec if dec.count('.'): cpt = dec.index('.') else: cpt = len(dec) if laprvirg <= 3: dec2.extend(dec[cpt:]) else: nbsep = laprvirg // 3 - 1 dec2.extend(dec[cpt:cpt + 4]) dec2.append('\\,') cpt = cpt + 4 for i in range(nbsep): dec2.extend(dec[cpt:cpt + 3]) if cpt + 3 < len(dec): dec2.append('\\,') cpt = cpt + 3 dec2.extend(dec[cpt:]) nb = ("").join(dec2) if nb.endswith('.0'): nb = string.rsplit(nb, '.0')[0] if mathenvironment: return string.join(string.rsplit(nb, sep='.'), '{,}') else: return string.join(string.rsplit(nb, sep='.'), ',') sepmilliers=TeXMiseEnForme("").sepmilliers def Affichage(l): """\xc3\x89crit une expressions contenant des d\xc3\xa9cimaux et des fractions au format TeX @param l: liste contenant l'expression [3, '+', 5, '*', 2] """ expr = "" # résultat for i in range(len(l)): # on parcourt la liste if ["+", "-", "*", "/", '(', ')'].count(l[i]): # Un opérateur if l[i] == "*": expr = expr + " \\times " elif l[i] == "/": expr = expr + " \\div " elif l[i] == ")" and type(l[i-1]) == type(Fractions(1, 1)): expr = expr + " \\big) " elif i 0: if int(exposant) < len(decimale): entiere = entiere + decimale[:int(exposant)] decimale = decimale[int(exposant):] else: entiere = entiere + decimale + "0"*(int(exposant)-len(decimale)) decimale = '' else: if -int(exposant) < len(entiere): decimale = entiere[len(entiere)+int(exposant):] + decimale entiere = entiere[:len(entiere)+int(exposant)] else: decimale = "0"*(-int(exposant)-len(entiere)) + str(abs(int(entiere))) + decimale.rstrip("0") if entiere[0]=="-": entiere = "-0" else: entiere = "0" pattern = re.compile(r"^(-?\d{1,3}?)" + "(\d{3})" * \ ((len(entiere) - 1 - (entiere[0]=='-')) // 3) + "$") partie_entiere = pattern.search(entiere).groups() if decimale and int(decimale): """Vérifie si la partie décimale existe et si elle est différente de zéro""" pattern = re.compile(r"^" + "(\d{3})" * ((len(decimale) - 1) // 3) + \ "(\d{1,3})?$") partie_decimale = pattern.search(decimale).groups() if mathenv: return "{,}".join(("\,".join(partie_entiere), "\,".join(partie_decimale))) else: return ",".join(("\,".join(partie_entiere), "\,".join(partie_decimale))) else: return "\,".join(partie_entiere) pyromaths/src/outils/TexFiles.py0000644000175000017500000001026511702101415017471 0ustar didrocksdidrocks# -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import codecs def mise_en_forme(file): """ \begin => +2 espaces si pas \begin{document} \item => +2 espaces après sauf si c'est \item \end => -2 espaces avant sauf si \end{document} Si longueur de ligne >80, retour ligne au dernier espace précédent et indentation de la ligne suivante. Couper la ligne après un \\begin{}[]{} ou un \\end{} lline : last line cline : current line """ f = codecs.open(file, encoding='utf-8', mode='r') old_tex = f.readlines() new_tex=[] indent = 0 item = False for cline in old_tex: if new_tex: lline = new_tex[-1] else: lline = "" cline = cline.strip() indent = trouve_indentation(cline, indent, lline) if indent < 0: print "problème" if cline: chaine, indent = traite_chaine(cline, indent) new_tex.extend(chaine) else: new_tex.append("") f.close() f = codecs.open(file, encoding='utf-8', mode='w') f.write("\n".join(new_tex)) f.close() def trouve_indentation(cline, indent, lline): if lline.find(r"\begin{")>=0: "indente tout ce qui suit \begin{...}" indent += 2 if cline.find(r"\end{")==0: "desindente tout ce qui suit \end{...}" indent -= 2 # if lline.find(r"\begin{enumerate}")>=0 or lline.find(r"\begin{itemize}")>=0: # "n'indente pas ce qui suit un environnement itemize" # indent -= 2 # if cline.find(r"\item") == 0 and lline.find(r"\begin{enumerate}") < 0 \ # and lline.find(r"\begin{itemize}") < 0: # indent -= 2 if cline.find(r"\item") == 0 : indent -= 2 if lline.find(r"\item") >= 0: indent += 2 indent += compte_paires_ouvertes(lline) return indent def traite_chaine(cline, indent): """indente la chaine txt en fonction du paramètre indent""" list = [] cline = " "*indent + cline list.append(cline) while len(list[-1]) > 80: if list[-1].rfind(" ", indent + 1, 80) > 0: for i in range(79, indent, -1): if list[-1][i] == " ": list.append(list[-1][:i]) indent = trouve_indentation(list[-2][i+1:], indent, list[-1]) list.append(" "*indent + list[-2][i+1:]) list.pop(-3) break else: break return list, indent def trouve_paire(txt): """Trouve le caractère fermant pour les symboles {, [, ( qui est le 1er caractère de txt""" ouvrant = ["{", "[", "("] fermant = ["}", "]", ")"] index = ouvrant.index(txt[0]) compte = 0 for i in range(len(txt)): if txt[i] == ouvrant[index]: compte += 1 elif txt[i] == fermant[index]: compte -= 1 if compte == 0: return i return None def compte_paires_ouvertes(txt): """Compte le nombres de paires {...}, \[...\] qui ne sont pas fermées dans la string txt""" diff = 0 for i in ["{", r"\["]: diff += txt.count(i) for i in ["}", r"\]"]: diff -= txt.count(i) return 2*diff #mise_en_forme("/home/jerome/Documents/projets/pyromaths/exemples/3e-corrige.tex") #mise_en_forme("/tmp/4e.tex") pyromaths/src/outils/.___init__.pyc0000644000175000017500000000031511702412270020064 0ustar didrocksdidrocksMac OS X  2ATTRGޞ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/Polynomes.py0000644000175000017500000001360311702101415017732 0ustar didrocksdidrocks# -*- coding: utf-8 -*- from ..classes.Polynome import Polynome from .Arithmetique import pgcd from random import randint,randrange from math import * #--------------outils pour la class Polynome---------------------- def TeX_division(dividende,diviseur): '''renvoie une chaine de caractere TeX pour afficher la division en détail''' quotient=Polynome({0:0}) texquotient,restera= dividende/diviseur reste=dividende diviseur_degre=diviseur.deg sauve=min(dividende.puiss+restera.puiss) longueur=dividende.degre_max-sauve string= "$$\\renewcommand\\arraycolsep{0cm}\n\\begin{array}{c" for i in range(longueur): string+= "c" string+= "|c}\n" string+=tab_print(dividende,longueur+1) string+= str(diviseur)+ "\\\\\n" string+= "\\cline{"+str(dividende.deg+2-sauve)+"-"+str(dividende.deg+2-sauve)+"}\n" i=0 while reste.deg>=diviseur.deg: for k in range(i): string+= " &" ajout_quotient_deg=reste.deg-diviseur_degre facteur= reste.dictio[max(0,reste.deg)]/diviseur.dictio[diviseur.deg] ajout_quotient=Polynome({ajout_quotient_deg:facteur},var=dividende.var) soustrait_reste=ajout_quotient*diviseur string +=tab_print(soustrait_reste,diviseur_degre+1-sauve,parenthese=True) for k in range(longueur-i-diviseur.deg+sauve): string+= " & " if i ==0: string+= str(texquotient) string+= "\\\\\n" string+= "\\cline{"+str(i+1) +"-"+str(i+diviseur.deg+1-sauve) +"}\n" avant=reste.deg reste=reste-soustrait_reste delta=avant-reste.degre_max for k in range(i): string+= " &" i=i+delta prochain=1 string +=tab_print(reste,min(diviseur.deg+1,reste.degre_max+1)+delta-sauve,debut=delta) #fait descendre les monome du dividende for k in range(longueur-i-diviseur.deg+sauve): string+= " & " string+= "\\\\ \n" string+= "\\end{array}\n$$" string+="\n On a $$"+dividende.TeX()+" = \\left(" + texquotient.TeX()+"\\right) \\times \\left("+diviseur.TeX()+"\\right)" if restera!=Polynome(0): if len(restera.puiss)==1 and restera[restera.deg]>0:#monome string +="+"+restera.TeX() else: string+="+\\left("+restera.TeX()+"\\right)" string+="$$" return string def tab_print(polynome,longueur=0,parenthese=False,debut=0): '''utilisé par TeX_division pour décaler le reste dans la partie gauche''' degre=polynome.degre_max+debut string='' if parenthese: string = "-(" fin=")" else: fin="" if polynome==0: string += "+"+str(0)+ " &" else: for i in range(longueur): k=degre-i coeff=polynome.dictio.get(k,0) if coeff>=0: string+= "+" string += str(coeff) if k!=0: string+= polynome.var if k != 1 and k!=0: string+= u"^" + str(k) if longueur-i==1: string+= fin string+= " & " return string ######################################################## # # construction de polynôme de degré 2 # X est un Polynome # X=Polynome("x","x") donnera un polynome de degré 2 # X=Polynome("x^2",x) donnera un polynôme bicarrée # ######################################################## def poly_racines_quelconques(abs_a,abs_b,abs_c,X): '''renvoie un polynome de degré 2''' '''abs_a,abs_b,abs_c sont des entiers positifs majorant les valeurs absolues de a, b ,c''' a3=(2*randrange(2)-1)*randrange(1,abs_a+1) b3=randrange(abs_b) c3=randrange(-abs_c,abs_c) return a3*X**2+b3*X+c3 def poly_racines_fractionnaires(rac_min,rac_max,denom1,X): '''renvoie un polynome de degré2 à racines fractionnaires ''' '''les racines sont comprises entre rac_min et rac_max''' '''denom1 majore le dénominateur des racines''' while 1: #pour éviter P=77x^2 a2=2*randrange(2)-1 #a2=-1 ou 1 p2facteur=[randint(1,denom1)*X-randint(rac_min,rac_max)for i in range(2)] pol2=a2*p2facteur[0]*p2facteur[1] if pol2[1]!=0 and pol2[0]!=0: break pol2=pol2.simplifie() simplifie=abs(pgcd(pgcd(int(pol2[0]),int(pol2[1])),int(pol2[2]))) pol2= pol2/simplifie return pol2.simplifie() def poly_racines_entieres(rac_min,rac_max,X,a1=1): while 1: p1facteur=[X-randrange(rac_min,rac_max) for i in range(2)] pol1=a1*p1facteur[0]*p1facteur[1] if pol1[1]!=0 or pol1[1]!=0: break return pol1 def poly_id_remarquables(rac_min,rac_max,X): '''Renvoie un polynome obtenu par une identité remarquable''' '''et sgns -2 => (a-b)² +2 => (a+b)² 0 => (a-b)(a+b)''' a=randint(1,10) while 1: coeff=randrange(rac_min,rac_max) racine=randrange(rac_min,rac_max) if coeff!=0 and racine!=0: break sgns=[[-1,1][randrange(2)]for i in range(2)] p1facteur=[coeff*X+sgns[i]*racine for i in range(2)] return a*p1facteur[0]*p1facteur[1],sum(sgns) #sum(sgns) permet de connaître l'identité remarquable # -2 => (a-b)² # +2 => (a+b)² # 0 => (a-b)(a+b) #----------polynome de degré 3------------- def poly_degre3_racines_entieres(rac_min,rac_max,X,racines=[-2,-1,0,1,2]): racine_evidente=racines[randrange(len(racines))] return (X-racine_evidente)*poly_racines_entieres(rac_min,rac_max,X) def poly_degre3_racines_fractionnaires(rac_min,rac_max,denom1,X,racines=[-2,-1,0,1,2]): racine_evidente=racines[randrange(len(racines))] return (X-racine_evidente)*poly_racines_fractionnaires(rac_min,rac_max,denom1,X) def poly_degre3_racines_quelconques(abs_a,abs_b,abs_c,X,racines=[-2,-1,0,1,2]): racine_evidente=racines[randrange(len(racines))] return (X-racine_evidente)*poly_racines_quelconques(abs_a=1,abs_b=10,abs_c=10,X=X) pyromaths/src/outils/.___init__.py0000644000175000017500000000031511702101415017715 0ustar didrocksdidrocksMac OS X  2ATTRGޝ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/TestEnv.pyc0000644000175000017500000000123711702412270017504 0ustar didrocksdidrocks Oc@s#ddklZlZdZdS(i(tisfiletjoincCs;ddkl}tt|dp|idndS(Ni(t CONFIGDIRs pyromaths.xmluImpossible de lire le fichier de configuration.Veuillez vérifier ce dernier ou faire remonter l'erreur sur le forum de Pyromaths.(tValuesRRRterreur_critique(tguiR((s=/Users/administrateur/Desktop/pyromaths/src/outils/TestEnv.pyttest#sN(tos.pathRRR(((s=/Users/administrateur/Desktop/pyromaths/src/outils/TestEnv.pyt!spyromaths/src/outils/TestEnv.py0000644000175000017500000000306211702101415017333 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # ### Pour tester la boite de dialogue ## Fichier à compléter par les tests d'environnement ### Tests à faire ? # installation d'une distribution latex # installation des bonnes extensions latex # lecture de pyromaths.xml # écriture dans le dossier de destination from os.path import isfile, join def test(gui): from ..Values import CONFIGDIR if not isfile(join(CONFIGDIR, "pyromaths.xml")): gui.erreur_critique(u"Impossible de lire le fichier de configuration." \ u"Veuillez vérifier ce dernier ou faire remonter l'erreur " \ u"sur le forum de Pyromaths.") pyromaths/src/outils/__init__.py0000644000175000017500000000171511702101415017505 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/outils/TexFiles.pyc0000644000175000017500000000650011702412270017635 0ustar didrocksdidrocks Oc@s=ddkZdZdZdZdZdZdS(iNc Csti|dddd}|i}g}d}t}x|D]}|o|d}nd}|i}t|||}|djo dGHn|o&t||\}}|i|q@|idq@W|i ti|dddd }|i d i ||i d S( sx egin => +2 espaces si pas egin{document} \item => +2 espaces après sauf si c'est \item \end => -2 espaces avant sauf si \end{document} Si longueur de ligne >80, retour ligne au dernier espace précédent et indentation de la ligne suivante. Couper la ligne après un \begin{}[]{} ou un \end{} lline : last line cline : current line tencodingsutf-8tmodetriits problèmetws N( tcodecstopent readlinestFalsetstripttrouve_indentationt traite_chainetextendtappendtclosetwritetjoin( tfiletftold_textnew_textindenttitemtclinetllinetchaine((s>/Users/administrateur/Desktop/pyromaths/src/outils/TexFiles.pyt mise_en_formes,      cCs|iddjo|d7}n|iddjo|d8}n|iddjo|d8}n|iddjo|d7}n|t|7}|S(Ns\begin{iis\end{s\item(tfindtcompte_paires_ouvertes(RRR((s>/Users/administrateur/Desktop/pyromaths/src/outils/TexFiles.pyR :scCsg}d||}|i|xt|ddjo|did|dddjoxtd|dD]}|d|djoj|i|d| t|d|d||d}|id||d|d|idPqrqrWq$Pq$W||fS( s6indente la chaine txt en fonction du paramètre indentt iiPiiiOii(R tlentrfindtrangeR tpop(RRtlistti((s>/Users/administrateur/Desktop/pyromaths/src/outils/TexFiles.pyR Ns  $"!  cCsdddg}dddg}|i|d}d}xrtt|D]^}||||jo|d7}n$||||jo|d8}n|djo|SqJWd S( s[Trouve le caractère fermant pour les symboles {, [, ( qui est le 1er caractère de txtt{t[t(t}t]t)iiN(tindexR RtNone(ttxttouvranttfermantR*tcompteR#((s>/Users/administrateur/Desktop/pyromaths/src/outils/TexFiles.pyt trouve_paire`s  cCsbd}x'ddgD]}||i|7}qWx'ddgD]}||i|8}q=Wd|S(sZCompte le nombres de paires {...}, \[...\] qui ne sont pas fermées dans la string txtiR$s\[R's\]i(tcount(R,tdiffR#((s>/Users/administrateur/Desktop/pyromaths/src/outils/TexFiles.pyRps  (RRR R R0R(((s>/Users/administrateur/Desktop/pyromaths/src/outils/TexFiles.pyts  #   pyromaths/src/outils/._Conversions.py0000644000175000017500000000031511702101415020466 0ustar didrocksdidrocksMac OS X  2ATTRGޡ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/Priorites.py0000644000175000017500000005344211702101415017732 0ustar didrocksdidrocks# -*- coding: utf-8 -*- import re, sys from Affichage import decimaux from . import Arithmetique, Affichage import math from .Fractions import EffectueSommeFractions, EffectueQuotientFractions, EffectueProduitFractions def EffectueCalcul(op, nb1, nb2, pre="", post=""): denominateur_max = 20 programme = 6 # Faisable pour toutes les classes fr = Fractions(1, 1) # Une fraction type pour vérifier le type de nb1 et nb2 bfr = type(nb1) == type(nb2) == type(fr) # bfr est vrai si on calcul avec des fractions if type(nb1) == type(fr) and type(nb2) != type(fr): nb2 = Fractions(nb2) bfr = True if type(nb2) == type(fr) and type(nb1) != type(fr): nb1 = Fractions(nb1) bfr = True if not bfr and pre.rstrip().endswith('(') and post.lstrip().startswith(')'): pre = pre.rstrip()[:len(pre.rstrip()) - 1] post = post.lstrip()[1:] if op == "+": if bfr: l = EffectueSommeFractions(nb1, nb2, op, pre, post) resultat = Fractions.simplifie(nb1 + nb2) if abs(resultat.d) > denominateur_max: programme = 2 else: l = ["%s%s%s" % (pre, Affichage.decimaux(nb1 + nb2, 1), post)] resultat = nb1 + nb2 elif op == "-": if bfr: l = EffectueSommeFractions(nb1, nb2, op, pre, post) resultat = Fractions.simplifie(nb1 - nb2) n = nb1 - nb2 if n.n < 0: programme = 4 if resultat.n * resultat.d < 0: programme = 4 if abs(resultat.d) > denominateur_max: programme = 2 else: l = ["%s%s%s" % (pre, Affichage.decimaux(nb1 - nb2, 1), post)] resultat = nb1 - nb2 if resultat < 0: programme = 4 elif op == "*": if bfr: l = EffectueProduitFractions(nb1, nb2, pre, post) resultat = Fractions.simplifie(nb1 * nb2) if abs(resultat.d) > denominateur_max: programme = 2 else: l = ["%s%s%s" % (pre, Affichage.decimaux(nb1 * nb2, 1), post)] resultat = nb1 * nb2 else: if bfr: if nb2.n: # Pas de division par zéro l = EffectueQuotientFractions(nb1, nb2, pre, post) resultat = Fractions.simplifie(nb1 / nb2) if abs(resultat.d) > denominateur_max: programme = 2 else: (l, resultat, programme) = ([], 1, 1) else: if nb2 == 0: # division par zéro (l, resultat, programme) = ([], 1, 1) else: l = ["%s%s%s" % (pre, Affichage.decimaux((nb1 * 1.0) / nb2, 1), post)] resultat = (nb1 * 1.0) / nb2 if resultat - math.floor(resultat) == 0.0: programme = 6 elif resultat * 100 - math.floor(resultat * 100) == 0.0: programme = 5 else: programme = 2 return (l, resultat, programme) def split_calc(calcul): """Test de gestion et affichage des priorités de calcul, détaillées. PAS FINI.""" liste_op = [] liste_result = [] init = calcul # Sauvegarde du calcul de départ # Construction d'une liste comportant la liste de toutes les opérations i = 0 while calcul.count('(') > 0: current = 'l' + str(i) liste_op.append(re.search('\(\w+[\+\-/\*]\w+\)', calcul).group().strip('()')) calcul = re.sub('\(\w+[\+\-/\*]\w+\)', current, calcul, 1) i += 1 liste_op.append(re.search('\w+[\+\-/\*]\w+', calcul).group()) # Calcul des différentes opérations contenues dans liste_op et # enregistrement des résultats dans liste_result for index in range(len(liste_op)): element = liste_op[index] m = re.findall('l(\d+)', element) for k in range(len(m)): motif = 'liste_result[' + m[k] + ']' element = re.sub('l\d+', motif , element, 1) liste_op[index] = element liste_result.append(eval(liste_op[index])) print liste_op print liste_result, liste_result[0] # On sert de la sauvegarde pour afficher le déroulement du calcul j = 0 print init, " = ", longueur = len(init) + 2 while init.count('(') > 0: current = 'l' + str(i) init = re.sub('\(\w+[\+\-/\*]\w+\)', str(eval(liste_op[j])), init, 1) j += 1 print(init + "\n" + " " * longueur + "= ",) # Afficher le résultat du calcul print(liste_result[-1]) #a=testfraction.fraction(5,7) #b=testfraction.fraction(4,3) #c=testfraction.fraction(8,9) # # #c=split_calc('(a+b)*c') #calcul = raw_input("Un autre calcul ?\nIl faut mettre des parenthèses à chaque opération, même si inutiles.\n") #split_calc(calcul) #TODO : étendre à des nombres avec plusieurs chiffres #--------------------------------------------------------------------- #autre version des priorités #--------------------------------------------------------------------- import re def priorites(calcul, pre = "", post = "", solution = []): if not solution: solution = [calcul] recherche_parentheses = r""" ^(.*) #des calculs dans le groupe 0 ( #début du groupe 1 \( #commence par une parenthèse ouvrante (?: #regroupement 0 (non groupe) [\+\-]? #un éventuel signe (?: #regroupement 1 (non groupe) \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant \) #une parenthèse fermante | #ou \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 1 [\+\-\*/]+ #un opérateur )+ #fin du regroupement 0 (présent au moins #un fois) [\+\-]? #un éventuel signe (?: #regroupement 0 (non groupe) \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant \) #une parenthèse fermante | #ou \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 0 présent une seule fois \) #fini par une parenthèse fermante ) #fin du groupe 1 (.*)$ #des calculs pour finir """ test = re.search(recherche_parentheses, calcul, re.VERBOSE) while test: sous_calcul = test.groups() (calcul, solution) = priorites_operations(sous_calcul[1], sous_calcul[0], sous_calcul[2], solution) calcul = solution[-1] test = re.search(recherche_parentheses, calcul, re.VERBOSE) calcul, solution = priorites_operations(calcul, pre, post, solution) return(solution) def traite_operation(operateur, calcul, pre, post, solution): pattern = r""" ( #groupe 0 ^\(* #le calcul est au début (aux parenthèses près) #les signes +/- font parti du groupe 2 | #ou ^.*?[\+\-]? #il y a des calculs avant, le 1er signe +/- #est un opérateur ) #fin du groupe 0 ( #groupe 1 (?: #regroupement 1 (non groupe) [\+\-]? #un éventuel signe \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant \) #une parenthèse fermante | #ou [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 1 {0} #opération (?: #regroupement 2 (non groupe) [\+\-]? #un éventuel signe \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant \) #une parenthèse fermante | #ou [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 2 ) #fin du groupe 1 (.*?)$ #tout le reste """.format(operateur) test = re.search(pattern, calcul, re.VERBOSE) while test: sous_calcul = test.groups() print(sous_calcul) print(pre, post) sous_resultat = eval(sous_calcul[1]) if isinstance(sous_resultat, list): for element in sous_resultat: solution.extend([pre + sous_calcul[0] + str(element) + sous_calcul[2] + post]) a = sous_resultat[-1] sous_resultat = 'a' elif (sous_calcul[0] and sous_calcul[0][-1] == '(') and \ (sous_calcul[2][0] and sous_calcul[2][0] == ')') and \ (post[:2] != '**' or sous_resultat > 0): #permet de supprimer les parenthèses solution.extend([pre + sous_calcul[0][:-1] + decimaux(sous_resultat, True) + sous_calcul[2][1:] + post]) else: solution.extend([pre + sous_calcul[0] + decimaux(sous_resultat, True) + sous_calcul[2] + post]) calcul = sous_calcul[0] + decimaux(sous_resultat, True) + sous_calcul[2] test = re.search(pattern, calcul, re.VERBOSE) return (calcul, pre, post, solution) def priorites_operations(calcul, pre = "", post = "", solution = []): for string in ["\*\*", "[\*/]", "[\+\-]"]: calcul, pre, post, solution = traite_operation(string, calcul, pre, post, solution) #calcul, pre, post, solution = traite_operation("\*\*", calcul, pre, #post, solution) #calcul, pre, post, solution = traite_operation("[\*/]", calcul, pre, #post, solution) #calcul, pre, post, solution = traite_operation("[\+\-]", calcul, pre, #post, solution) return (calcul, solution) ## ##print(priorites("(12-15)**2+(15-12)**3")) ##print("_" * 40) ###print(priorites("((-(-1)+-2)++3)")) ###print("_" * 40) ###print(priorites("4-((-1+-2)+3)")) ###print("_" * 40) ###print(priorites('8-(-5*(2-4))')) ###print("_" * 40) ##print(priorites("1+2+3+4")) ##print("_" * 40) ###print(priorites("-3**+2")) ###print("_" * 40) ###print(priorites("9+8*7")) ###print("_" * 40) ###print(priorites("8+1.3e+2")) ###print("_" * 40) ##a, b, c = Racine(5), Racine(5, 3), Racine(5, 2) ##print(priorites("2*(a+b+c)")) ##print("_" * 40) ##a, b = Racine(5), Racine(5, 3) ##print(priorites("a*b*2")) ###print("_" * 40) ###c, d = Terme(5, 2), Terme(-6, 2) ###print(priorites("c*d")) ###print("_" * 40) ##print(priorites("8+1.3e+2")) ##print(priorites("755*(12-15)**2+(15-12)**3")) ##print(priorites("((-(-1)+-2)++3)")) ##print(priorites("4-((-1+-2)+3)")) ##print(priorites('8-(-5*(2-4))')) ##print(priorites("1+2+3+4")) ##print(priorites("-3**+2")) ##print(priorites("9+8*7")) from ..classes.Fractions import Fractions from . import Arithmetique, Affichage import random import math from TeXMiseEnForme import Affichage #=============================================================================== # Gère les priorités opératoires pour le calcul décimal et fractionnaire #=============================================================================== def OperateurPrioritaire(exercice, niveau, pre="", post="", solution=[]): '''Renvoie un tuple contenant : - la liste solution contenant la liste des instructions TeX \xc3\xa0 \xc3\xa9crire dans le corrig\xc3\xa9 - le r\xc3\xa9sultat de l\'expression. La liste exercice peut contenir des nombres ou des objets Fractions. Ex : OperateurPrioritaire([3,"+",5,"*",2]) => [\'3 + 10\', \'13\'] , 13 Ex : OperateurPrioritaire([Fractions(15,4),\'*\',Fractions(14,25),\'-\',Fractions(3,2)]) => [ \'\\dfrac{3 \\times \\cancel{5}}{2 \\times \\bcancel{2}} \\times \\dfrac{7 \\times \\bcancel{2}}{5 \\times \\cancel{5}} - \\dfrac{3}{2}\', \'\\dfrac{21}{10} - \\dfrac{3}{2}\', \'\\dfrac{21}{10}-\\dfrac{3_{\\times 5}}{2_{\\times 5}}\', \'\\dfrac{3_{\\times 2}}{5_{\\times 2}}\', \'\\dfrac{3}{5}\' ], (Fractions(3,5)) @param exercice: liste contenant la succession d\'op\xc3\xa9rations [3, \'+\', 5, \'*\', 2] @param niveau: niveau auquel doit se situer l\'exercice : 6: entiers, 5: d\xc3\xa9cimaux positifs, 4: d\xc3\xa9cimaux relatifs @param pre: chaine contenant ce qui doit \xc3\xaatre ajouter avant la solution @param post: chaine contenant ce qui doit \xc3\xaatre ajouter apr\xc3\xa8s la solution @param solution: liste contenant chaque ligne \xc3\xa0 \xc3\xa9crire dans le fichier TeX pour le corrig\xc3\xa9 ''' if len(exercice) == 1: # il ne reste plus qu'un nombre (le résultat) donc c'est fini return (solution, exercice[0], niveau) else: # Trouvons l'opérateur prioritaire : nbpar = exercice.count('(') nbmul = exercice.count("*") nbdiv = exercice.count("/") if nbpar: # Des parenthèses oui, mais y-a-t-il des parenthèses à l'intérieur des parenthèses ? i0 = TrouveParentheseInterieure(exercice) i1 = exercice[i0:].index(')') + i0 pre1 = Affichage(exercice[:i0 + 1]) post1 = Affichage(exercice[i1:]) (cor, res, programme) = OperateurPrioritaire(exercice[i0 + 1:i1], niveau, pre + pre1, post + post1, solution) suite_exo = exercice[:i0] suite_exo.append(res) suite_exo.extend(exercice[i1 + 1:]) return OperateurPrioritaire(suite_exo, programme, pre, post, solution) else: if nbmul or nbdiv: # Priorité à la multiplication et à la division if nbmul and not nbdiv: i0 = exercice.index("*") elif nbdiv and not nbmul: i0 = exercice.index("/") elif exercice.index("*") < exercice.index("/"): i0 = exercice.index("*") else: i0 = exercice.index("/") else: # Il ne reste que des additions et des soustractions nbadd = exercice.count("+") nbsub = exercice.count("-") if nbadd and not nbsub: i0 = exercice.index("+") elif nbsub and not nbadd: i0 = exercice.index("-") elif exercice.index("+") < exercice.index("-"): i0 = exercice.index("+") else: i0 = exercice.index("-") pre1 = Affichage(exercice[:i0 - 1]) # Ce qui est avant le calcul en cours post1 = Affichage(exercice[i0 + 2:]) # Ce qui est après le calcul en cours (l, res, programme) = EffectueCalcul(exercice[i0], exercice[i0 - 1], exercice[i0 + 1], pre + pre1, post + post1) for i in l: solution.append(i) suite_exo = exercice[:i0 - 1] suite_exo.append(res) suite_exo.extend(exercice[i0 + 2:]) programme = min(programme, niveau) return OperateurPrioritaire(suite_exo, programme, pre, post, solution) def TrouveParentheseInterieure(l): """Trouve la position de la parenth\xc3\xa8se la plus \xc3\xa0 l'int\xc3\xa9rieur @param l: liste d'op\xc3\xa9rations """ nbpar = l.count('(') if nbpar > 1: if l[l.index('(') + 1:].index('(') < l[l.index('(') + 1:].index(')'): # Il existe une parenthèse dans les parenthèses return l.index('(') + 1 + TrouveParentheseInterieure(l[l.index('(') + 1:]) else: return l.index('(') else: return l.index('(') def valeurs_priorites_decimaux(nb, entier=1): # renvoie les 2 listes contenant les opérateurs et les opérandes. listoperateurs = [ "+", "*", "-", "/", '(', '(', '(', '(', ')', ')', ')', ')', ] loperateurs = [] loperandes = [] i = 0 #nombre d'opérateurs créés p = 0 #nombre de parenthèses ouvertes cpt = 0 #compteur pour éviter que le programme ne boucle. while i < nb - 1: cpt = cpt + 1 if cpt > 10: #On recommence (cpt, i, p, loperateurs) = (0, 0, 0, []) if p: if loperateurs[-1] == '(': # On n'écrit pas 2 parenthèses à suivre operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(12)] elif loperateurs == []: # On ne commence pas par une parenthèse operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(8)] if nb > 3: test = ('-*/').find(operateur) >= 0 and loperateurs.count(operateur) < \ 1 or operateur == "+" and loperateurs.count(operateur) < \ 2 else: test = ('-*/+').find(operateur) >= 0 and loperateurs.count(operateur) < \ 1 if test: #On n'accepte pas plus de 1 produit, différence, quotient et de 2 sommes ou parenthèses par calcul. if i == 0 or loperateurs[-1] != '(' or ('*/').find(operateur) < \ 0: #pas de * ou / dans une parenthèse. i = i + 1 loperateurs.append(operateur) elif operateur == '(' and (')+').find(loperateurs[-1]) < 0: #Il ne peut y avoir de ( après une ) ou après un + p = p + 1 loperateurs.append(operateur) elif operateur == ')': p = p - 1 loperateurs.append(operateur) while p > 0: loperateurs.append(')') p = p - 1 if entier: loperandes = [random.randrange(12) + 2 for i in range(nb)] else: loperandes = [((random.randrange(88) + 12) * 1.0) / 10 for i in range(nb)] exercice = [loperandes[0]] i = 1 j = 0 while i < len(loperandes) or j < len(loperateurs): if j < len(loperateurs): exercice.append(loperateurs[j]) j = j + 1 while j < len(loperateurs) and (loperateurs[j] == '(' or loperateurs[j - 1] == ')'): exercice.append(loperateurs[j]) j = j + 1 if i < len(loperandes): exercice.append(loperandes[i]) i = i + 1 return exercice #for i in xrange(1): # l=valeurs_priorites_fractions(3, 1) # cor,res, programme=OperateurPrioritaire(l,6,pre="", post="",solution=[]) # while programme<5: # l=valeurs_priorites_fractions(3, 1) # cor,res,programme=OperateurPrioritaire(l,6,pre="", post="",solution=[]) # print "$" + Affichage(l)+"$\\par" # for i in cor: # print "$" + i +"$\\par" pyromaths/src/outils/._Polynomes.py0000644000175000017500000000031511702101415020143 0ustar didrocksdidrocksMac OS X  2ATTRGޥ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._System.py0000644000175000017500000000031511702101415017442 0ustar didrocksdidrocksMac OS X  2ATTRGީ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/Geometrie.py0000644000175000017500000003360411702101415017670 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from random import randrange def choix_points(n): """ choisit n points parmi A, B, C, ..., Z @param n: nombre de points \xc3\xa0 choisir @type n: integer """ points = [chr(i + 65) for i in range(26)] liste = [] for i in range(n): liste.append(points.pop(randrange(len(points)))) return liste couples_pythagore = ( (12, 16, 20), (15, 20, 25), (10, 24, 26), (20, 21, 29), (18, 24, 30), (16, 30, 34), (21, 28, 35), (12, 35, 37), (15, 36, 39), (24, 32, 40), (27, 36, 45), (14, 48, 50), (30, 40, 50), (24, 45, 51), (20, 48, 52), (28, 45, 53), (33, 44, 55), (40, 42, 58), (36, 48, 60), (11, 60, 61), (16, 63, 65), (25, 60, 65), (33, 56, 65), (39, 52, 65), (32, 60, 68), (42, 56, 70), (48, 55, 73), (24, 70, 74), (21, 72, 75), (45, 60, 75), (30, 72, 78), (48, 64, 80), (18, 80, 82), (13, 84, 85), (36, 77, 85), (40, 75, 85), (51, 68, 85), (60, 63, 87), (39, 80, 89), (54, 72, 90), (35, 84, 91), (57, 76, 95), (65, 72, 97), (28, 96, 100), (60, 80, 100), (20, 99, 101), (48, 90, 102), (40, 96, 104), (63, 84, 105), (56, 90, 106), (60, 91, 109), (66, 88, 110), (36, 105, 111), (15, 112, 113), (69, 92, 115), (80, 84, 116), (45, 108, 117), (56, 105, 119), (72, 96, 120), (22, 120, 122), (27, 120, 123), (35, 120, 125), (44, 117, 125), (75, 100, 125), (32, 126, 130), (50, 120, 130), (66, 112, 130), (78, 104, 130), (81, 108, 135), (64, 120, 136), (88, 105, 137), (84, 112, 140), (55, 132, 143), (17, 144, 145), (24, 143, 145), (87, 116, 145), (100, 105, 145), (96, 110, 146), (48, 140, 148), (51, 140, 149), (42, 144, 150), (90, 120, 150), (72, 135, 153), (93, 124, 155), (60, 144, 156), (85, 132, 157), (84, 135, 159), (96, 128, 160), (36, 160, 164), (99, 132, 165), (65, 156, 169), (119, 120, 169), (26, 168, 170), (72, 154, 170), (80, 150, 170), (102, 136, 170), (52, 165, 173), (120, 126, 174), (49, 168, 175), (105, 140, 175), (78, 160, 178), (108, 144, 180), (19, 180, 181), (70, 168, 182), (33, 180, 183), (57, 176, 185), (60, 175, 185), (104, 153, 185), (111, 148, 185), (88, 165, 187), (114, 152, 190), (95, 168, 193), (130, 144, 194), (48, 189, 195), (75, 180, 195), (99, 168, 195), (117, 156, 195), (28, 195, 197), (56, 192, 200), (120, 160, 200), ) def trouve_couples_pythagore(max): ls = [] for i in xrange(26): for j in xrange(i-1): a = i b = j+1 for k in xrange(140): x = (2*k+1)*(a**2-b**2) y = (2*k+1)*(2*a*b) z = (2*k+1)*(a**2+b**2) if z > max: break ls.append(tuple(sorted([x,y,z]))) ls.sort(key = operator.itemgetter(2)) cpt = 1 while cpt < len(ls): if ls[cpt]==ls[cpt-1]: ls.pop(cpt) else: cpt += 1 return tuple(ls) #---------------------------------------------------- # Cotation des longeurs sur une figure psTricks # A, B sont les coordonnées de deux points # cotation_h écrit au dessus du segment #---------------------------------------------------- def cotation(A,B,longueur,couleur="",unite="cm"): (xA,yA)=A (xB,yB)=B if couleur!="": couleur="\\color{%s}"%couleur return u"\\pcline[linestyle=none](%s,%s)(%s,%s) \\bput{:U}{%s\\unit[%s]{%s}}" %(xA,yA,xB,yB,couleur,longueur,unite) def cotation_h(A,B,longueur,couleur="",unite="cm"): (xA,yA)=A (xB,yB)=B if couleur!="": couleur="\\color{%s}"%couleur return u"\\pcline[linestyle=none](%s,%s)(%s,%s) \\aput{:U}{%s\\unit[%s]{%s}}" %(xA,yA,xB,yB,couleur,longueur,unite) #def trouve_couples_pythagore(valeurmax): # (liste, listecouples) = ([], []) # for a in range(valeurmax): # liste.append(a ** 2) # for c in range(valeurmax): # for b in range(int((c + 1) / 2 ** .5)): # if liste.count((c + 1) ** 2 - (b + 1) ** 2): # a = liste.index((c + 1) ** 2 - (b + 1) ** 2) # listeinter = [c + 1, b + 1, a] # listeinter.sort() # if listeinter[0] > 9: # listecouples.append(tuple(listeinter)) # # if listecouples==[] : # listecouples.append(tuple(listeinter)) # else : # ajout=1 # for i in xrange(len(listecouples)) : # if not(listeinter[2]%listecouples[i][2]) and not(listeinter[1]%listecouples[i][1]) and not(listeinter[0]%listecouples[i][0]) : # if listeinter[2]//listecouples[i][2]==listeinter[1]//listecouples[i][1]==listeinter[0]//listecouples[i][0] : ajout=0 # if ajout : # listeinter=[c+1,b+1,a] # listeinter.sort() # listecouples.append(tuple(listeinter)) # # return tuple(listecouples) class Metapost: def __init__(self): self.text = [] self.num = 1 def fin(self): self.text.append("end;") return self def triangle( self, A, B, C, a=0, b=0, c=0, alpha=0, beta=0, gamma=0, rotation=0, angledroit=0, ): """Construit un triangle en metapost quelles que soient les données. La base est le côté [AB] de longueur c. @param A, b, C : nom des trois sommets (obligatoire) @param a, b, c : longueurs des trois côtés opposés au sommet de même nom @param alpha, beta, gamma : mesure des 3 angles de sommets A, B et C @param rotation: mesure en degrés de l'angle de la rotation de centre A appliquée au triangle @param angledroit: doit-on afficher l'angle droit ? """ self.text.append("beginfig(%s);\n" % self.num) self.text.append("u:=1cm;\n") self.text.append("pair %s, %s, %s, m[];\n" % (A, B, C)) self.text.append("picture $;\n") self.text.append(" %s=origin;\n" % A) if angledroit: marques=[0, 0, 0, "%s \degres" % alpha, "%s \degres" % beta, "%s \degres" % gamma] if a: marques[0]="%s cm" % a if b: marques[1]="%s cm" % b if c: marques[2]="%s cm" % c points=[A, B, C] #on donne les trois longueurs des 3 côtés if a and b and c: alpha = degres(math.acos(((b ** 2 + c ** 2) - a ** 2 * 1.) / ((2 * b) * c))) beta = degres(math.acos(((c ** 2 + a ** 2) - b ** 2 * 1.) / ((2 * c) * a))) elif a and b and gamma: # Un angle et les deux côtés adjacents (c, beta, alpha) = self.triangle_angle_cotes_adjacents(a, b, gamma) elif b and c and alpha: (a, gamma, beta) = self.triangle_angle_cotes_adjacents(b, c, alpha) elif c and a and beta: (b, alpha, gamma) = self.triangle_angle_cotes_adjacents(c, a, beta) elif b and c and beta: # Un angle, le côté opposé et un côté adjacent (a, alpha, gamma) = self.triangle_angle_cote_adjacent_cote_oppose(b, c, beta) elif b and a and beta: (c, gamma, alpha) = self.triangle_angle_cote_adjacent_cote_oppose(b, a, beta) elif a and b and alpha: (c, gamma, beta) = self.triangle_angle_cote_adjacent_cote_oppose(a, b, alpha) elif a and c and alpha: (b, beta, gamma) = self.triangle_angle_cote_adjacent_cote_oppose(a, c, alpha) elif c and a and gamma: (b, beta, alpha) = self.triangle_angle_cote_adjacent_cote_oppose(c, a, gamma) elif c and b and gamma: (a, alpha, beta) = self.triangle_angle_cote_adjacent_cote_oppose(c, b, gamma) elif alpha and beta and c: # Deux angles et le côté commun pass # on sait faire elif beta and gamma and a: c = (a * math.sin((gamma * math.pi) / 180)) / math.sin(((beta + gamma) * math.pi) / 180) alpha = (180 - beta) - gamma elif alpha and gamma and b: c = (b * math.sin((gamma * math.pi) / 180)) / math.sin(((alpha + gamma) * math.pi) / 180) beta = (180 - alpha) - gamma elif a and alpha and beta: # Deux angles et un côté non commun c = (a * math.sin(((alpha + beta) * math.pi) / 180)) / math.sin((alpha * math.pi) / 180) elif a and alpha and gamma: c = (a * math.sin((gamma * math.pi) / 180)) / math.sin((alpha * math.pi) / 180) beta = (180 - alpha) - gamma elif b and beta and alpha: c = (b * math.sin(((alpha + beta) * math.pi) / 180)) / math.sin((beta * math.pi) / 180) elif b and beta and gamma: c = (b * math.sin((gamma * math.pi) / 180)) / math.sin((beta * math.pi) / 180) alpha = (180 - beta) - gamma elif c and alpha and gamma: beta = (180 - alpha) - gamma elif c and beta and gamma: alpha = (180 - beta) - gamma alpha = alpha + rotation beta = beta - rotation self.text.append(" %s= (%s*u, 0) rotated %s;\n" % (B, c, rotation)) self.text.append(" %s = %s + whatever*dir(%s);\n" % (C, A, alpha)) self.text.append(" %s = %s + whatever*dir(180-%s);\n" % (C, B, beta)) self.text.append(" draw %s -- %s -- %s -- cycle;\n" % (A, B, C)) # Codage de l'angle droit s'il y en a un. if angledroit: if alpha - rotation == 90: self.text.append(" draw (%s+5*unitvector(%s-%s))--(%s+5*unitvector(%s-%s)+\n" % (A, B, A, A, B, A)) self.text.append(" 5*unitvector(%s-%s))--(%s+5*unitvector(%s-%s));\n" % ( C, A, A, C, A)) elif beta + rotation == 90: self.text.append(" draw (%s+5*unitvector(%s-%s))--(%s+5*unitvector(%s-%s)+\n" % (B, A, B, B, A, B)) self.text.append(" 5*unitvector(%s-%s))--(%s+5*unitvector(%s-%s));\n" % (C, B, B, C, B)) elif gamma == 90: self.text.append(" draw (%s+5*unitvector(%s-%s))--(%s+5*unitvector(%s-%s)+\n" % (C, A, C, C, A, C)) self.text.append(" 5*unitvector(%s-%s))--(%s+5*unitvector(%s-%s));\n" % ( B, C, C, B, C)) for i in range(3): if marques[i]: self.text.append(" m3:=unitvector(%s-%s) rotated 90;\n" % (points[(i+1)%3], points[(i+2)%3])) self.text.append(" $:=image(\n") self.text.append(" label(btex %s etex rotated angle(%s-%s),(%s+%s)/2+2mm*m3);\n" % (marques[i], points[(i+1)%3], points[(i+2)%3], points[(i+1)%3], points[(i+2)%3])) self.text.append(" );\n draw $;\n") self.text.append(" label.llft(btex $%s$ etex, %s);\n" % (A, A)) self.text.append(" label.lrt(btex $%s$ etex, %s);\n" % (B, B)) self.text.append(" label.top(btex $%s$ etex, %s);\n" % (C, C)) self.text.append("""endfig; """) self.num = self.num + 1 return self def triangle_angle_cotes_adjacents(self, a, b, gamma): c = math.sqrt(a ** 2 + b ** 2 - 2 * a * b * math.cos(radians(gamma))) alpha = 90. - gamma / 2 + degres(math.atan((((a - b) * 1.) / (a + b)) / math.tan(radians(gamma / 2)))) beta = 90. - gamma / 2 - degres(math.atan((a - b) * 1. / (a + b) / math.tan(radians(gamma / 2)))) return (c, beta, alpha) def triangle_angle_cote_adjacent_cote_oppose(self, b, c, beta): if b <= c * math.sin((beta * math.pi) / 180): alpha = gamma = a = 0 # Pas possible de résoudre else: gamma = degres(math.asin(((c * math.sin((beta * math.pi) / 180)) / b) * 1.)) alpha = (180 - beta) - gamma a = math.sqrt(b ** 2 - c ** 2 * math.sin((beta * math.pi) / 180) ** 2) + c * math.cos((beta * math.pi) / 180) return (a, alpha, gamma) #fig = Metapost() #fig = Metapost.triangle( #fig, "A", "B", "C", a=3, b=4.2, c=4.2, rotation=10, angledroit=1) #fig = Metapost.triangle( #fig, "D", "E", "F", a=4, b=5.7, c=6.5, rotation=90, angledroit=1) #fig = Metapost.triangle( #fig, "G", "H", "I", a=3.5, b=3.5, c=3.5, rotation=0, angledroit=1) #fig = Metapost.triangle( #fig, "J", "K", "L", a=4, b=4.5, c=4.5, rotation=30, angledroit=1) #fig = Metapost.fin(fig) #print string.join(fig.text, "") pyromaths/src/outils/__init__.pyc0000644000175000017500000000022511702412270017647 0ustar didrocksdidrocks Oc@sdS(N((((s>/Users/administrateur/Desktop/pyromaths/src/outils/__init__.pytspyromaths/src/outils/._TexFiles.py0000644000175000017500000000031511702101415017701 0ustar didrocksdidrocksMac OS X  2ATTRGޭ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/System.pyc0000644000175000017500000002430411702412270017400 0ustar didrocksdidrocks Oc @sddkZddkZddkZddklZddklZddklZddk l Z dZ dZ d Z d d Zd Zd ZdZdZdS(iN(tetree(t _elementpath(tfindalli(t mise_en_formecCs6tii|diotii|dS|S(s_supprime l'éventuelle extension ext du nom de fichier filename. ext est de la forme '.tex'ii(tostpathtsplitexttlower(tfilenametext((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pytsupprime_extension"scCs0tii|di|jo|S||S(s`ajoute si nécessaire l'extension ext au nom de fichier filename. ext est de la forme '.tex'i(RRRR(RR ((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pytajoute_extension)s#cCsddkl}tid}ti|d}dti|d_d|ti|d_d ti|d _d ti|d _d ti|d _dti|d_dti|d_ti|d}dti|d_dti|d_dti|d_ti|d}dti|d_dti|d_dti|d_ti|d td!tS("s/Crée le fichier de configuration au format xmli(tHOMEt pyromathstoptionst exercicest nom_fichiers%stchemin_fichieruFiche de révisionst titre_fichetTruetcorrigetpdftFalsetunpdfs pyromaths.textmodelet informationss10.10tversionuPyromaths est un programme qui permet de générer des fiches d’exercices de mathématiques de collège ainsi que leur corrigé. Il crée des fichiers au format pdf qui peuvent ensuite être imprimés ou lus sur écran.t descriptions pyromaths.icoticonetauteuruJérôme Ortaistnomujerome.ortais@pyromaths.orgtemailshttp://www.pyromaths.orgtsitet pretty_printtencoding( tValuesR RtElementt SubElementttextttostringRtunicode(R troottchildtsubchild((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pytcreate_config_file3s&icCsd|d}t|o|i p|ii o|d|_nxL|D]D}t||d|i p|ii o|d|_qOqOW|i p|ii o ||_qn1|o)|i p|ii o ||_n|S(sIndente correctement les fichiers xml. By Filip Salomonsson; published on February 06, 2007. http://infix.se/2007/02/06/gentlemen-indent-your-xmls s i(tlenR&tstriptindentttail(telemtleveltite((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pyR/Ms # c Csddkl}t}ti|}|i}tit}x|idti D]}t |p|g}|i }x.|d j o |i d||i }qW|} xtdt |D]} | i|| id jo| t |djom| djo/ti|i|| di|| inti||| i| i|| i} n| i|| i} | t |djo | } qqW| d jo%t}|iti| |i_q#| i|ijo*|didjot}|i| _q#qYqYW|o`titii|ddd d d } | itit|d tdt| ind S(scModifie le fichier de configuration si besoin, excepté les options utilisateur déjà configuréesi(t CONFIGDIRttagiiRs pyromaths.xmlR"sutf-8tmodetwR!N(R#R5RRtparsetgetroottXMLR,titerR$R-t getparenttNonetinserttrangetfindR6R%RR&tcodecstopenRRtjointwriteR'R/R(tclose( tfileR5tmodifietoldtreetoldroottnewroottelementtparentsR4toldtagR3t oldparenttf((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pytmodify_config_file`sF     4 / '*(cCsrt|d}t|d}ti|dddd}ti|dddd}|d}tii|dd }|d o3t||d |d pt||d qnx|d D]}ddkl}ddkl} ddk l } ddk l } ddk l } h|d6| d6| d6| d6| d6} | |di |d||qW|d o|d oo|i d|i d|i d|i d|i d|i d|i dt||dq(|i d|i dt||dt||dn|i|i|d olti|dddd}ti|dddd }x|D]}|i |qW|i|int||d!o|d  ot|ntii|}tii|}d"d#k}|id$joNtii|diti}tii|diti}nctiitii|diti}tiitii|diti}|d od"d%kl}ti|td&|d}x1tdD]#}|d'd(d)|gd*|qW|d+d,d-|d.|gd*||d/d0d1|d2|gd*||it|d3|jp |d3o_tid4jotid2|qtid5jotid6|qtid7|n|d!o7|d  o+ti|td&|d}x1tdD]#}|d'd(d)|gd*|q[W|d+d,d-|d.|gd*||d/d0d1|d2|gd*||it|d3|jp |d3o_tid4jotid2|qUtid5jotid6|qUtid7|qjqnti d8|nd#S(9sCréation et compilation des fiches d'exercices. parametres = {'fiche_exo': f0, 'fiche_cor': f1, 'liste_exos': self.lesexos, 'creer_pdf': self.checkBox_create_pdf.checkState(), 'creer_unpdf': self.checkBox_unpdf.isChecked() and self.checkBox_unpdf.isEnabled(), 'titre': unicode(self.lineEdit_titre.text()), 'niveau': unicode(self.comboBox_niveau.currentText()), }t fiche_exot fiche_corR"sutf-8R7R8ttitreis.mpt creer_pdftentetet creer_unpdft liste_exosi(tsixiemes(t cinquiemes(t quatriemes(t troisiemes(tlyceeiiis\label{LastPage} s \newpage u8\currentpdfbookmark{Le corrigé des exercices}{Corrigé}sE\lhead{\textsl{\footnotesize{Page \thepage/ \pageref{LastCorPage}}}} s\setcounter{page}{1} s\setcounter{exo}{0} s\label{LastCorPage} tpiedtatrRiNssd-20841.pyromaths.org(tcalls%s-pyromaths.logtlatexs-interaction=batchmodes%s.textstdouttdvipss-qs%s.dvis-o%s.pstps2pdfs-sPAPERSIZE#a4s%s.pss%s.pdftopenpdftnttdarwins open %s.pdfsxdg-open %s.pdfs%s-corrige.tex(!R(RBRCRRRtcopie_tronq_modeleRYRZR[R\R]tmainRERFRtdirnametsockett gethostnametencodetsystgetfilesystemencodingtbasenamet subprocessRatchdirR@t nettoyagetnamet startfiletplatformtsystemtremove(t parametrestexotcortf0tf1RTtfiche_metaposttexerciceRYRZR[R\R]tfonctiontlinetdir0tdir1Rltf0noexttf1noextRatlogR3((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pytcreations      #                 %)11   !$$    !$$  cCsyixd D]}ti||q Wtiid|djo&tid|tid|nWntj onXd S( s3Supprime les fichiers temporaires créés par LaTeXs.auxs.dvis.outs.pss%s.pdfis%s.logs%s-pyromaths.logN(s.auxs.dvis.outs.ps(RRyRtgetsizetOSError(t basefilenameR ((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pyRtscCsGd|}d|}d}|d}tiitii|dd|o tii|dd|}nftiitii|dd|o tii|dd|}ndtii|ddGH|d}|d }|d o d }nd }tid jo6tiitii|ddtidCopie des morceaux des modèles, suivant le schéma du master.s% fin s% iRtdatadirt templatesu0Le fichier modèle n'a pas été trouvé dans %sRTtniveauRWu;\currentpdfbookmark{Les énoncés des exercices}{Énoncés}tRgtpackagest TEXINPUTSs tabvar.texR"sutf-8R7R`s##{{[A-Z]*}}##iiiN(RRtisfileRDRutnormpathtenvironRBRCRR-RtreplacetevalRERF(tdestRztmastert master_fintntsourceRTRtbookmarkttabvarRRttemptocc((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pyRi sH   ) )        !   (RoRRBtlxmlRRtDONTUSEtreRtTexFilesRR R R,R/RQRRtRi(((s</Users/administrateur/Desktop/pyromaths/src/outils/System.pyts$    ) s pyromaths/src/outils/Arithmetique.py0000644000175000017500000001122611702101415020405 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import math, random def pgcd(a, b): """Calcule le pgcd entre a et b.""" while b: a, b = b, a%b return a def ppcm(a, b): """Calcule le ppcm entre a et b.""" return a*b/pgcd(a, b) def premier(n): """Teste si un nombre est premier.""" return not [x for x in xrange(2,int(math.sqrt(n)) + 1) if n%x == 0] def eratosthene(n): """Etablit la liste des nombres premiers inferieurs a n.""" return [x for x in xrange(2, n) if premier(x)] def factor(n): """Retourne la liste des facteurs premiers du nombre n.""" premiers = [] candidats = xrange(2,n+1) candidat = 2 while not premiers and candidat in candidats: if n%candidat == 0 and premier(candidat): premiers.append(candidat) premiers = premiers + factor(n/candidat) candidat += 1 return premiers def factorise(n): """Retourne la liste des facteurs premiers du nombre n, ainsi que le détail de la factorisation.""" primes = [] temp = n etapes = [] primes_etapes = [] limite=int(math.sqrt(n))+1 candidate = 2 while (candidate < limite): if n % candidate == 0: primes.append(candidate) primes_etapes.append(str(candidate)) n = n / candidate if n == 1: break primes_etapes.append(str(n)) etapes.append(primes_etapes) primes_etapes = primes_etapes[:-1] else: candidate += 1 if (n != 1) or (primes == []): primes.append(n) return (primes, etapes) def factoriseTex(n): """Version LaTeX pour factorise.""" corrige = ["\\begin{align*}", str(n)] etapes = factorise(n)[1] primes = factorise(n)[0] if len(primes) > 1: for i in range(len(etapes)): text = ' & = ' for j in range(len(etapes[i])): if j != len(etapes[i]) - 1: text += etapes[i][j] + ' \\times ' else: text += etapes[i][j] corrige.append(text + '\\\\') corrige.append("\\end{align*}") else: corrige = [str(n) + " est un nombre premier.\\par "] return (primes, corrige) def carrerise(n): """Trouve le plus petit facteur par lequel multiplier pour obtenir un carré.""" if round(math.sqrt(n), 0)==math.sqrt(n): return 1 elif n<=0: return n else: primes = factorise(n)[0] q = {} for element in primes: if (primes.count(element) % 2 == 1): q[element]=1 ncar=1 for element in q.iterkeys(): ncar *= element return ncar def combinaison(n, k): """renvoie le nombre de combinaisons de n objets pris k à k""" if k > n//2: k = n-k x = 1 y = 1 i = n-k+1 while i <= n: x = (x*i)//y y += 1 i += 1 return x def signe(a): """renvoie 1 si a est>0, -1 si a<0""" if a < 0: return -1 else: return 1 def valeur_alea(a, b): """choisit une valeur comprise entre a et b non nulle""" while True: alea = random.randrange(a, b + 1) if alea != 0: return alea #--------------------------------------------------------------------- # A supprimer dès que quatriemes/developpements.py aura été corrigé #--------------------------------------------------------------------- def ecrit_tex(file, formule, cadre=None, thenocalcul='\\thenocalcul = ', tabs=1): """Écrit la ligne dans le fichier""" if formule != '': if cadre == None or not cadre: file.write((u' \\[ %s%s \\] \n') % (thenocalcul, formule)) else: file.write((u' \\[ \\boxed{%s%s} \\] \n') % (thenocalcul, formule)) pyromaths/src/outils/Priorites3.py0000644000175000017500000005611111702101415020011 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #---------------------------------------------------------------------- # Pyromaths : GESTION DES PRIORITES #---------------------------------------------------------------------- from ..classes.PolynomesCollege import Polynome from ..outils.Affichage import decimaux def cherche_polynome(calcul, index): """Recherche le premier polynôme dans la chaîne calcul à une position supérieure ou égale à index, sans expression régulière @calcul: str @index: int""" index = calcul.find("Polynome(", index) if index < 0: return None par, i = 1, index+9 # nombre de parenthèses ouvertes, début de recherche while par: if calcul.find("(", i)>0: i = min(calcul.find("(", i), calcul.find(")", i)) else: i = calcul.find(")", i) if calcul[i] == ")": par += -1 else: par += 1 return calcul[index:i+1] def cherche_decimal(calcul, index): """130 fois plus rapide qu'avec une expression régulière ! Un nombre décimal peut être entouré de parenthèses s'il a un signe, ou avoir un signe s'il est en début de chaîne @calcul: str @index: int""" end = len(calcul) while index<=end: try: int(calcul[index]) except: index+=1 else: break if index>end: return None while end>index: try: float(calcul[index:end]) except ValueError: end -= 1 else: break if index>1 and (calcul[index-2:index] == "(+" or calcul[index-2:index] == "(-") : if end < len(calcul) and calcul[end]==")": index -= 2 end += 1 else: index -= 1 return calcul[index:end] def split_calcul(calcul): """Partitionne la chaîne de caractères pour obtenir une liste d'opérateurs, de parenthèses, de polynômes et de nombres @calcul: str""" l = [] findings = (cherche_polynome, cherche_decimal) for finding in findings: nb = finding(calcul, 0) while nb: l.extend(calcul.partition(nb)) if l[-3] and l[-2]: l0 = split_calcul(l[-3]) if l0: l0.extend(l[-2:]) l = l[:-3] l.extend(l0) elif not l[-3]: l.pop(-3) calcul = l[-1] nb = finding(calcul, 0) l = l[:-1] if calcul: l.append(calcul) while l and not l[0]: l.pop(0) return l def EstNombre(value): """Test si Value est un nombre ou pas @value: str""" if value in "**/+-()": return False else: return isinstance(eval(value), (float, int, Polynome)) def splitting(calcul): """Partitionne la chaîne de caractères pour obtenir une liste d'opérateurs, de parenthèses, de polynômes et de nombres puis arrange la liste des opérandes et opérateurs @calcul: str""" if calcul == "": return [] l = split_calcul(calcul) if l[0] == "+" and len(l) > 1: l[0] += l.pop(1) elif l[0] == "-" and len(l) > 1 and l[1][0] in "0123456789": l[0] += l.pop(1) j = 0 while j < len(l): op, i, t = l[j], 0, [] if op == "**": j+= 1 else: while i < len(op) and op[i] in '+-*/()': t.append(op[i]) i += 1 if i == len(op): l[j:j+1] = t j += len(t) else: j += 1 return l def recherche_parentheses(calcul): """Recherche les parenthèses intérieures dans une liste @calcul: list""" if calcul.count("("): debut = calcul.index("(") if calcul[debut+1:].count(")"): fin = calcul[debut:].index(")") + debut else: return None for i in range(calcul[debut + 1:fin].count("(")): debut += calcul[debut+1:].index("(") + 1 return (debut, fin+1) else: return None def recherche_puissance(calcul): """Recherche la première occurrence d'une puissance dans une liste de calculs. Elle doit être entourée de deux nombres. @calcul: list""" if calcul.count("**"): i = calcul.index("**") return (i-1, i+2) else: return None def recherche_operation(calcul, op, l_interdit, debut = 0): """Recherche la première occurrence de l'opération op dans la liste de calculs list. L'opérateur doit être entouré de deux nombres, le premier ne doit pas être précédé d'un opérateur inclus dans la liste l_interdit. L'opérateur à trouver doit être avant la position debut (si debut est non nul). @calcul: list @op: str @l_interdit: list @debut: int""" ind, fin = 0, len(calcul) for c in range(calcul.count(op)): ind = calcul.index(op, ind) if ind == 1 and ind < fin-1 and EstNombre(calcul[ind-1]) and\ EstNombre(calcul[ind+1]): if debut: debut = min(debut, ind) else: debut = ind break elif ind > 1 and ind < fin -1 and EstNombre(calcul[ind-1]) and\ EstNombre(calcul[ind+1]) and calcul[ind-2] not in l_interdit: if debut: debut = min(debut, ind) else: debut = ind break else: ind += 1 if debut: return debut else: return None def recherche_fin_operation(calcul, op, l_interdit, debut): """Recherche la fin de la suite d'opération @op situé à la position @debut de la liste de calculs @calcul, en vérifiant que cet enchaînement n'est pas suivi par un opérateur compris dans @l_interdit. @calcul: list @op: str @l_interdit: list @debut: int""" index, fin, unique = debut + 2, len(calcul), False while index < fin-1 and calcul[index] == op and EstNombre(calcul[index+1]): index +=2 if index < fin and calcul[index] in l_interdit: index -=2 if index == debut: return None return index def recherche_produit(calcul): """Recherche la première occurrence d'une multiplication ou divisions dans une liste de calculs. Elle doit être précédée d'un nombre qui ne doit pas être précédé d'une puissance ou d'une division, NI SUIVIE D'UN EXPOSANT ! @calcul: list""" debut = recherche_operation(calcul, "*", ("**", "/")) debut = recherche_operation(calcul, "/", ("**", "/"), debut) if debut is not None: fin = recherche_fin_operation(calcul, calcul[debut], ("**"), debut) if fin is not None: return (debut - 1, fin) return None def recherche_somme(calcul): """Recherche la première occurrence d'une addition ou soustraction dans une liste de calculs. Elle doit être précédée d'un nombre qui ne doit pas être précédé d'une puissance, d'une multiplication, d'une division ou d'une soustraction, NI SUIVIE D'UN EXPOSANT, D'UNE MULTIPLICATION OU D'UNE DIVISION ! @calcul: list""" debut = recherche_operation(calcul, "+", ("**", "*", "/", "-")) debut = recherche_operation(calcul, "-", ("**", "*", "/", "-"), debut) if debut is not None: fin = recherche_fin_operation(calcul, calcul[debut], ("**", "*", "/"), debut) if fin is not None: return (debut - 1, fin) return None def recherche_neg(calcul): """Recherche la première occurence d'un opposé ## -(-5) ou -Polynome ## ou d'une écriture du style +(-5) dans une liste de calculs ET NE DOIT PAS ĘTRE SUIVI D'UN EXPOSANT ! @calcul: list""" ind, debut, fin = 0, None, len(calcul) for c in range(calcul.count("-")): ind = calcul.index("-", ind) if ind < fin-1 and EstNombre(calcul[ind+1]): n = eval(calcul[ind+1]) if calcul[ind+1][0] == "(" or isinstance(n, Polynome): # or (isinstance(n, Polynome) and (len(n)>1 or n.monomes[0][0]<0)): debut = ind break else: ind += 1 for c in range(calcul[ind+1:].count("+")): ind = calcul.index("+", ind) if ind < fin-1 and EstNombre(calcul[ind+1]) and calcul[ind+1][0] == "(": if debut is not None: debut = min(debut, ind) else: debut = ind break else: ind += 1 if debut is not None and (debut+2 == fin or (debut+21: sol.insert(0, "(") sol.append(")") elif sol and isinstance(eval(sol[0]), (int, float)) and post and post[0] == "*" and \ 'Polynome(' in post[1] and len(eval(post[1])) == 1 and \ eval(post[1])[0][0] == 1: # Sans doute une factorisation de sommes de polynômes sol = [repr(eval(sol[0])*eval(post [1]))] post = post[2:] #Suppression des parenthèses autour de ((9.0-80.0)*Polynome("x")) devenu (Polynome("-71.0x")) if post and result and post[0] == ")" and result[-1] == "(" : result, post = result[:-1], post[1:] else: # Transforme les réels en polynômes afin de permettre les opérations bpoly = False for k in range(len(calc)): if not bpoly and calc[k][:9] == "Polynome(": bpoly = True elif bpoly and calc[k] not in "**/-+()" and calc[k-1] != "**" and isinstance(eval(calc[k]), (float, int)): calc[k] = "Polynome([[%s, 0]])" % eval(calc[k]) sol = eval("".join(calc)) if isinstance(sol, basestring): sol = splitting(sol) elif isinstance(sol, (int, float)): sol = [str(sol)] elif isinstance(sol, Polynome): sol = [repr(sol)] else : raise valueError(u"Le résultat a un format inattendu") if recherche == recherche_neg: # Ajoute le "+" ou sépare le "-": # "1-(-9)" => "1 + 9" et "1+(-9)" => "1 - 9" if sol[0][0] == "-": sol = ["-", sol[0][1:]] else: sol = ["+", sol[0]] if recherche == recherche_produit and len(sol) > 1: # Ajoute les parenthèses si produit précédé d'un "-" ou "*" # ou suivi d'un "*" if (result and result[-1] in "*-") or (post and post[0] == "*"): sol.insert(0, "(") sol.append(")") # Si @sol est négatif et @result se termine par un "+", on l'enlève if result and result[-1] == "+" and sol and sol[0][0] == "-": result[-1] = "-" sol[0] = sol[0].lstrip("-") result.extend(sol) calcul = post if calcul: test = recherche(calcul) else: test = None if post and recherche == recherche_neg: break_somme=True result.extend(post) if not result: result = calcul tmp = "".join(result) # if cherche_polynome(tmp, 0): # index = tmp.find("+-") # while index >=0 : # nb = cherche_decimal(tmp, index+2) # tmp = tmp[:index+1] + "(-" + nb + ")" + tmp[index+2+len(nb):] # index = tmp.find("+-") # result = splitting(tmp) return result def priorites(calcul): """Effectue un enchaînement d'opérations contenues dans calcul en respectant les priorités et en détaillant les étapes. @calcul: str""" # if cherche_polynome(calcul, 0)>=0: litteral = True # else: litteral = False calcul = splitting(calcul) solution = [] while len(calcul)>1: s= effectue_calcul(calcul) if s: s = post_polynomes(s) solution.append(s) calcul = [k for k in s] # dissocie calcul et s if len(calcul) == 1 and post_polynomes(calcul) != s: # Finit la réduction du polynôme résultat solution.append(calcul) return solution def texify(liste_calculs): """Convertit une liste de chaînes de caractères 'liste_calculs' contenant des polynômes en liste de chaînes de caractères au format TeX""" ls = [] for calcul in liste_calculs: if isinstance(calcul, basestring): calcul = splitting(calcul) s = "" puiss = 0 for i in range(len(calcul)): el = calcul[i] if el[:9] == "Polynome(": # Doit-on entourer ce polynôme de parenthèses ? p = eval(el) if i+1 < len(calcul): q = calcul[i+1] else: q= "" if (s and s[-1] in "*-" and (len(p)>1 or p.monomes[0][0]<0)) \ or (q and q == "*" and len(p)>1) \ or ((len(p)>1 or p.monomes[0][0]!=1) and q and q == "**"): s += "(" + str(p) +")" elif s and s[-1] == "+" and p.monomes[0][0]<0: s = s[:-1] s += str(p) else: s += str(p) elif EstNombre(el): if el[0]=="(": s += "(" + decimaux(el[1:-1]) + ")" else: s += decimaux(el) elif el == "**": s += "**{" puiss += 1 elif el == "(": if puiss: puiss += 1 s += "(" elif el == ")": if puiss: puiss -= 1 s += ")" else : # "+", "-", "*", "/" s += el if puiss == 1 and s[-1] != "{": puiss = 0 s += "}" s = s.replace("**{", "^{") s = s.replace("(", "\\left( ") s = s.replace(")", "\\right) ") s = s.replace("*", "\\times ") s = s.replace("/", "\\div ") if not ls or s != ls[-1]: ls.append(s) return ls #---------------------------------------------------------------------- # Pyromaths : FICHIERS DE TESTS #---------------------------------------------------------------------- def valeurs(n, polynomes=0, entier=1): """Renvoie une chaîne de caractères contenant un calcul aléatoire de n nombres, qui sont soit des entiers, soit des décimaux, soit des polynômes.""" import random def deci(entier): if entier: return random.randrange(-11, 11) else: return random.randrange(-110, 110)/10. def poly(entier): long = random.randrange(3) degre=[0, 1, 2] p = [[deci(entier), degre.pop(random.randrange(len(degre)))] for i in range(long+1)] p = Polynome(p, "x") while p == Polynome([[0, 0]], "x"): degre=[0, 1, 2] p = [[deci(entier), degre.pop(random.randrange(len(degre)))] for i in range(long+1)] p = Polynome(p, "x") if len(p) == 1 and Polynome.degre(p) == 0: p = p[0][0] if p < 0: p = "(" + str(p) +")" else: p = str(p) else: p = repr(p) return p if polynomes: nb=poly else: nb=deci nbp = [] lo = ['+','*','-'] for i in range(n): if not i: s = "%s" % nb(entier) else: if nbp and nbp[-1] > 2 and not random.randrange(2): s += ')' nbp.pop(-1) s += lo[random.randrange(3)] if nbp: for cpt in range(len(nbp)): nbp[cpt] += 1 a = random.randrange(3) if s[-1] in '*-/' and i<=n-2 and not a: s += '(' nbp.append(1) nombre = nb(entier) if nombre < 0: s += "(" + str(nombre) + ")" else: s += str(nombre) if not polynomes: #TODO: tester les puissances avec les polynômes a = random.randrange(10) if (not nbp or nbp[-1]>1) and not a: s += "**2" while nbp: s += ')' nbp.pop(-1) return s def test_entiers(nbval, polynomes, entiers): for c in range(10000): a = valeurs(nbval, polynomes, entiers) try: r = priorites(a) texify(r) except: print(a) break else: if not polynomes: print u"%s ème calcul" % (c+1), a, " = ", eval(a), u" en %s étapes"%(len(r)) if eval(a) != eval("".join(r[-1])): print a, " = ", eval(a) print r break if polynomes: from sympy import Symbol, expand x = Symbol('x') print u" : %s ème calcul en %s étapes" % (c+1, len(r)) if not len(r): print a break else: t0=sympyfy([a])[0] t1=sympyfy(r[-1]) if isinstance(eval(t1[0]), (int, float)) : t1[0] = "%s+x-x" % (t1[0]) if isinstance(eval(t0), (int, float)) : t0 = "%s+x-x" % (t0) if eval(t0).expand()!=eval(t1[0]).expand(): print a, "=", t1 print "\n".join(sympyfy(r)) print u"Devrait être : ", eval(t0).expand() break def sympyfy(liste_calculs): """Convertit une liste de chaînes de caractères 'liste_calculs' contenant des polynômes en liste de chaînes de caractères au format Sympy""" ls = [] for calcul in liste_calculs: if isinstance(calcul, basestring): calcul = splitting(calcul) s = "" puiss = 0 for i in range(len(calcul)): el = calcul[i] if el[:9] == "Polynome(": # Doit-on entourer ce polynôme de parenthèses ? p = eval(el) if i+1 < len(calcul): q = calcul[i+1] else: q= "" if (s and s[-1] in "*-" and (len(p)>1 or p.monomes[0][0]<0)) \ or (q and q == "*" and len(p)>1) \ or ((len(p)>1 or p.monomes[0][0]!=1) and q and q == "**"): s += "(" + str(p) +")" elif s and s[-1] == "+" and p.monomes[0][0]<0: s = s[:-1] s += str(p) else: s += str(p) elif EstNombre(el): if el[0]=="(": s += "(" + decimaux(el[1:-1]) + ")" else: s += decimaux(el) elif el == "**": s += "**{" puiss += 1 elif el == "(": if puiss: puiss += 1 s += "(" elif el == ")": if puiss: puiss -= 1 s += ")" else : # "+", "-", "*", "/" s += el if puiss == 1: puiss = 0 s += "}" s = s.replace("\\,x", "*x") s = s.replace("\\,", "") s = s.replace("**{", "**") s = s.replace("^{", "**") s = s.replace("}", "") # s = s.replace("(", "\\left( ") # s = s.replace(")", "\\right) ") # s = s.replace("**{", "^{") # s = s.replace("*", "\\times ") # s = s.replace("/", "\\div ") if not ls or s != ls[-1]: ls.append(s) return ls def main(): from sympy import Symbol, expand x = Symbol('x') test_entiers(nbval=13, polynomes=1, entiers=1) # a = valeurs(2, 1, 1) # a = 'Polynome([[8, 2]], "x")*Polynome([[3, 1]], "x")-Polynome([[-3, 0], [4, 2], [10, 1]], "x")*Polynome([[-4, 2], [5, 0], [-11, 1]], "x")-Polynome([[3, 2], [-5, 1]], "x")-(Polynome([[3, 2], [-1, 0]], "x")*Polynome([[3, 2], [1, 0]], "x")*Polynome([[-6, 2], [10, 1], [2, 0]], "x"))*Polynome([[-9, 0], [-7, 2], [8, 1]], "x")-Polynome([[-8, 1]], "x")+Polynome([[-8, 2], [4, 0]], "x")+Polynome([[10, 1]], "x")+Polynome([[-9, 2], [6, 1], [7, 0]], "x")' # print(a) ## s= sympyfy([a]) # print sympyfy(priorites(a)) # r = texify(priorites(a)) # print "\\item $A=", texify([a])[0] , "$\\par" # for i in r: # print "$A=", # print "".join(i), # print "$\\par" pyromaths/src/outils/._Arithmetique.py0000644000175000017500000000031511702101415020617 0ustar didrocksdidrocksMac OS X  2ATTRGޠ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._decimaux.py0000644000175000017500000000031511702101415017755 0ustar didrocksdidrocksMac OS X  2ATTRGޢ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._TeXMiseEnForme.py0000644000175000017500000000031511702101415020750 0ustar didrocksdidrocksMac OS X  2ATTRGޯ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._System.pyc0000644000175000017500000000031511702412270017611 0ustar didrocksdidrocksMac OS X  2ATTRGު55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._Fractions.py0000644000175000017500000000031511702101415020106 0ustar didrocksdidrocksMac OS X  2ATTRGޣ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._Priorites2.py0000644000175000017500000000031511702101415020220 0ustar didrocksdidrocksMac OS X  2ATTRGާ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._TestEnv.pyc0000644000175000017500000000031511702412270017715 0ustar didrocksdidrocksMac OS X  2ATTRGެ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._Priorites3.py0000644000175000017500000000031511702101415020221 0ustar didrocksdidrocksMac OS X  2ATTRGި55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._TexFiles.pyc0000644000175000017500000000031511702412270020050 0ustar didrocksdidrocksMac OS X  2ATTRGޮ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/System.py0000644000175000017500000003233511702101415017234 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import sys, os, codecs from lxml import etree from lxml import _elementpath as DONTUSE # Astuce pour inclure lxml dans Py2exe from re import findall from .TexFiles import mise_en_forme #============================================================== # Gestion des extensions de fichiers #============================================================== def supprime_extension(filename, ext): """supprime l'éventuelle extension ext du nom de fichier filename. ext est de la forme '.tex'""" if os.path.splitext(filename)[1].lower(): return os.path.splitext(filename)[0] return filename def ajoute_extension(filename, ext): """ajoute si nécessaire l'extension ext au nom de fichier filename. ext est de la forme '.tex'""" if os.path.splitext(filename)[1].lower() == ext: return filename return filename + ext #============================================================== # Gestion du fichier de configuration de Pyromaths #============================================================== def create_config_file(): """Crée le fichier de configuration au format xml""" from ..Values import HOME root = etree.Element("pyromaths") child = etree.SubElement(root, "options") etree.SubElement(child, "nom_fichier").text="exercices" etree.SubElement(child, "chemin_fichier").text="%s" % HOME etree.SubElement(child, "titre_fiche").text=u"Fiche de révisions" etree.SubElement(child, "corrige").text="True" etree.SubElement(child, "pdf").text="True" etree.SubElement(child, "unpdf").text="False" etree.SubElement(child, "modele").text="pyromaths.tex" child = etree.SubElement(root, "informations") etree.SubElement(child, "version").text="10.10" etree.SubElement(child, "description").text=u"Pyromaths est un programme qui permet de générer des fiches d’exercices de mathématiques de collège ainsi que leur corrigé. Il crée des fichiers au format pdf qui peuvent ensuite être imprimés ou lus sur écran." etree.SubElement(child, "icone").text="pyromaths.ico" subchild= etree.SubElement(child, "auteur") etree.SubElement(subchild, "nom").text=u"Jérôme Ortais" etree.SubElement(subchild, "email").text=u"jerome.ortais@pyromaths.org" etree.SubElement(subchild, "site").text="http://www.pyromaths.org" return etree.tostring(root, pretty_print=True, encoding=unicode) def indent(elem, level=0): """Indente correctement les fichiers xml. By Filip Salomonsson; published on February 06, 2007. http://infix.se/2007/02/06/gentlemen-indent-your-xml""" i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " for e in elem: indent(e, level+1) if not e.tail or not e.tail.strip(): e.tail = i + " " if not e.tail or not e.tail.strip(): e.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i return elem def modify_config_file(file): """Modifie le fichier de configuration si besoin, excepté les options utilisateur déjà configurées""" from ..Values import CONFIGDIR modifie = False oldtree = etree.parse(file) oldroot = oldtree.getroot() newroot = etree.XML(create_config_file()) for element in newroot.iter(tag=etree.Element): if not len(element): parents = [element] e = element.getparent() while e is not None: parents.insert(0,e) e = e.getparent() oldtag = oldroot for i in range(1, len(parents)): if oldtag.find(parents[i].tag) is None and i < len(parents) - 1 : if i > 1: etree.SubElement(oldroot.find(parents[i-1].tag), parents[i].tag) else: etree.SubElement(oldroot, parents[i].tag) oldtag = oldtag.find(parents[i].tag) else: oldtag = oldtag.find(parents[i].tag) if i == len(parents)-2: oldparent = oldtag if oldtag is None: # Ajoute un nouvel item dans le fichier xml modifie = True etree.SubElement(oldparent, element.tag).text = element.text elif oldtag.text != element.text and parents[1].tag != "options": # Modifie un item existant s'il ne s'agit pas des options modifie = True oldtag.text = element.text if modifie: f = codecs.open(os.path.join(CONFIGDIR, "pyromaths.xml"), encoding='utf-8', mode = 'w') f.write(etree.tostring(indent(oldroot), pretty_print=True, encoding=unicode)) f.close() #============================================================== # Créer et lance la compilation des fichiers TeX #============================================================== def creation(parametres): """Création et compilation des fiches d'exercices. parametres = {'fiche_exo': f0, 'fiche_cor': f1, 'liste_exos': self.lesexos, 'creer_pdf': self.checkBox_create_pdf.checkState(), 'creer_unpdf': self.checkBox_unpdf.isChecked() and self.checkBox_unpdf.isEnabled(), 'titre': unicode(self.lineEdit_titre.text()), 'niveau': unicode(self.comboBox_niveau.currentText()), }""" exo = unicode(parametres['fiche_exo']) cor = unicode(parametres['fiche_cor']) f0 = codecs.open(exo, encoding='utf-8', mode='w') f1 = codecs.open(cor, encoding='utf-8', mode='w') titre = parametres['titre'] fiche_metapost = os.path.splitext(exo)[0] + '.mp' if parametres['creer_pdf']: copie_tronq_modele(f0, parametres, 'entete') if not parametres['creer_unpdf']: copie_tronq_modele(f1, parametres, 'entete') for exercice in parametres['liste_exos']: from ..sixiemes import sixiemes from ..cinquiemes import cinquiemes from ..quatriemes import quatriemes from ..troisiemes import troisiemes from ..lycee import lycee fonction = {0: sixiemes, 1: cinquiemes, 2: quatriemes, 3: troisiemes, 4: lycee} fonction[exercice[0]].main(exercice[1], f0, f1) if parametres['creer_pdf']: if parametres['creer_unpdf']: f0.write("\\label{LastPage}\n") f0.write("\\newpage\n") f0.write(u"\\currentpdfbookmark{Le corrigé des exercices}{Corrigé}") f0.write("\\lhead{\\textsl{\\footnotesize{Page \\thepage/ \\pageref{LastCorPage}}}}\n") f0.write("\\setcounter{page}{1} ") f0.write("\\setcounter{exo}{0}\n") f1.write("\\label{LastCorPage}\n") copie_tronq_modele(f1, parametres, 'pied') else: f0.write("\\label{LastPage}\n") f1.write("\\label{LastPage}\n") copie_tronq_modele(f0, parametres, 'pied') copie_tronq_modele(f1, parametres, 'pied') f0.close() f1.close() if parametres['creer_unpdf']: f0 = codecs.open(exo, encoding='utf-8', mode='a') f1 = codecs.open(cor, encoding='utf-8', mode='r') for line in f1: f0.write(line) f0.close() f1.close() # indentation des fichiers teX créés mise_en_forme(exo) if parametres['corrige'] and not parametres['creer_unpdf']: mise_en_forme(cor) # Dossiers et fichiers d'enregistrement, définitions qui doivent rester avant le if suivant. dir0=os.path.dirname(exo) dir1=os.path.dirname(cor) import socket if socket.gethostname() == "sd-20841.pyromaths.org": # Chemin complet pour Pyromaths en ligne car pas d'accents f0noext=os.path.splitext(exo)[0].encode(sys.getfilesystemencoding()) f1noext=os.path.splitext(cor)[0].encode(sys.getfilesystemencoding()) else: # Pas le chemin pour les autres, au cas où il y aurait un accent dans # le chemin (latex ne gère pas le 8 bits) f0noext=os.path.splitext(os.path.basename(exo))[0].encode(sys.getfilesystemencoding()) f1noext=os.path.splitext(os.path.basename(cor))[0].encode(sys.getfilesystemencoding()) if parametres['creer_pdf']: from subprocess import call os.chdir(dir0) log = open('%s-pyromaths.log' % f0noext, 'w') for i in range(2): call(["latex", "-interaction=batchmode", "%s.tex" % f0noext], stdout=log) call(["dvips", "-q", "%s.dvi" % f0noext, "-o%s.ps" % f0noext], stdout=log) call(["ps2pdf", "-sPAPERSIZE#a4", "%s.ps" % f0noext, "%s.pdf" % f0noext], stdout=log) log.close() nettoyage(f0noext) if not "openpdf" in parametres or parametres["openpdf"]: if os.name == "nt": #Cas de Windows. os.startfile('%s.pdf' % f0noext) elif sys.platform == "darwin": #Cas de Mac OS X. os.system('open %s.pdf' % f0noext) else: os.system('xdg-open %s.pdf' % f0noext) if parametres['corrige'] and not parametres['creer_unpdf']: os.chdir(dir1) log = open('%s-pyromaths.log' % f1noext, 'w') for i in range(2): call(["latex", "-interaction=batchmode", "%s.tex" % f1noext], stdout=log) call(["dvips", "-q", "%s.dvi" % f1noext, "-o%s.ps" % f1noext], stdout=log) call(["ps2pdf", "-sPAPERSIZE#a4", "%s.ps" % f1noext, "%s.pdf" % f1noext], stdout=log) log.close() nettoyage(f1noext) if not "openpdf" in parametres or parametres["openpdf"]: if os.name == "nt": #Cas de Windows. os.startfile('%s.pdf' % f1noext) elif sys.platform == "darwin": #Cas de Mac OS X. os.system('open %s.pdf' % f1noext) else: os.system('xdg-open %s.pdf' % f1noext) else: os.remove('%s-corrige.tex' % f0noext) def nettoyage(basefilename): """Supprime les fichiers temporaires créés par LaTeX""" try: for ext in ('.aux', '.dvi', '.out', '.ps'): os.remove(basefilename+ext) if os.path.getsize('%s.pdf' % basefilename) > 1000 : os.remove('%s.log' % basefilename) os.remove('%s-pyromaths.log' % basefilename) except OSError: pass #le fichier à supprimer n'existe pas et on s'en moque. def copie_tronq_modele(dest, parametres, master): """Copie des morceaux des modèles, suivant le schéma du master.""" master_fin = '% fin ' + master master = '% ' + master n = 0 ## Le fichier source doit être un modèle, donc il se trouve dans le dossier 'modeles' de pyromaths. source = parametres['modele'] if os.path.isfile(os.path.join(parametres['datadir'], 'templates',source)): source = os.path.join(parametres['datadir'], 'templates', source) elif os.path.isfile(os.path.join(parametres['datadir'], 'templates', source)): source = os.path.join(parametres['datadir'], 'templates', source) else: #TODO: Message d'erreur, le modèle demandé n'existe pas print(u"Le fichier modèle n'a pas été trouvé dans %s" % os.path.join(parametres['datadir'], 'templates')) ## Les variables à remplacer : titre = parametres['titre'] niveau = parametres['niveau'] if parametres['creer_unpdf']: bookmark=u"\\currentpdfbookmark{Les énoncés des exercices}{Énoncés}" else: bookmark="" if os.name == 'nt': os.environ['TEXINPUTS']= os.path.normpath(os.path.join(parametres['datadir'], 'packages')) tabvar = 'tabvar.tex' else: tabvar = os.path.normpath(os.path.join(parametres['datadir'], 'packages', 'tabvar.tex')) #rawstring pour \tabvar -> tab + abvarsous windows modele = codecs.open(source, encoding='utf-8', mode='r') for line in modele: if master_fin in line: break if n > 0: temp = findall('##{{[A-Z]*}}##',line) if temp: occ = temp[0][4:len(temp)-5].lower() #line = sub('##{{[A-Z]*}}##',eval(occ),line) line = line.replace(temp[0], eval(occ)) dest.write(line) if master in line: n = 1 modele.close() return pyromaths/src/outils/Conversions.py0000644000175000017500000000215211702101415020252 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import math def radians(alpha): # convertit un angle en degré en radians return alpha*math.pi/180 def degres(alpha): return alpha*180/math.pi pyromaths/src/outils/Fractions.py0000644000175000017500000000506111702101415017674 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- from ..classes.Fractions import Fractions from . import Arithmetique, Affichage import random import math #=============================================================================== # Gère le calcul fractionnaire #=============================================================================== def EffectueSommeFractions(fr1, fr2, s, pre, post): if s == "+": fr = fr1 + fr2 else: fr = fr1 - fr2 cor = [] if fr1.n and fr2.n: ppcm = Arithmetique.ppcm(fr2.d, fr1.d) if abs(fr1.d) - abs(fr2.d): cor.append("%s%s%s%s%s" % (pre, Fractions.TeX(fr1, True, coef=ppcm // abs(fr1.d)), s, Fractions.TeX(fr2, True, coef=ppcm // abs(fr2.d)), post)) if pre.rstrip().endswith('(') and post.lstrip().startswith(')'): pre = pre.rstrip()[:len(pre.rstrip()) - 1] post = post.lstrip()[1:] cor.append("%s%s%s" % (pre, Fractions.TeX(fr, True), post)) if fr.n: frs = Fractions.simplifie(fr) if abs(frs.n) != abs(fr.n): cor.append("%s%s%s" % (pre, Fractions.TeX(frs, True, coef=fr.d // frs.d), post)) cor.append("%s%s%s" % (pre, Fractions.TeX(frs, True), post)) else: cor.append("%s%s%s" % (pre, Fractions.TeX(fr, True), post)) return cor def EffectueProduitFractions(fr1, fr2, pre, post): fr1s = Fractions.simplifie(fr1) fr2s = Fractions.simplifie(fr2) cor = [] if fr1.n and fr2.n: if abs(fr1s.d) < abs(fr1.d) or abs(fr2s.d) < abs(fr2.d): cor.append("%s%s \\times %s%s" % (pre, Fractions.TeXSimplifie(fr1), Fractions.TeXSimplifie(fr2), post)) cor.append("%s%s \\times %s%s" % (pre, Fractions.TeX(fr1s, True), Fractions.TeX(fr2s, True), post)) fr = fr1s * fr2s frs = Fractions.simplifie(fr) if abs(frs.d - fr.d): cor.append("%s%s%s" % (pre, Fractions.TeXProduit(fr1s, fr2s), post)) cor.append("%s%s%s" % (pre, Fractions.TeX(frs, True), post)) else: cor.append("%s%s%s" % (pre, Fractions.TeX(Fractions(0), True), post)) return cor def EffectueQuotientFractions(fr1, fr2, pre, post): fr2 = Fractions(1, 1) / fr2 cor = ["%s%s \\times %s%s" % (pre, Fractions.TeX(fr1, True), Fractions.TeX(fr2, True), post)] cor.extend(EffectueProduitFractions(fr1, fr2, pre, post)) return cor pyromaths/src/outils/Priorites2.py0000644000175000017500000001701111702101415020004 0ustar didrocksdidrocks# -*- coding: utf-8 -*- import re ## TODO Gestion des signes qui se suivent ( 3+-5 ou 3*-5 ) def priorites(calcul, pre = "", post = "", solution = []): if not solution: solution = [calcul] recherche_parentheses = r""" ^(.*) #des calculs dans le groupe 0 ( #début du groupe 1 \( #commence par une parenthèse ouvrante (?: #regroupement 0 (non groupe) [\+\-]? #un éventuel signe (?: #regroupement 1 (non groupe) \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant \) #une parenthèse fermante | #ou \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 1 [\+\-\*/]+ #un opérateur )+ #fin du regroupement 0 (présent au moins #un fois) [\+\-]? #un éventuel signe (?: #regroupement 0 (non groupe) \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant \) #une parenthèse fermante | #ou \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une éventuelle #partie décimale et un éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 0 présent une seule fois \) #fini par une parenthèse fermante ) #fin du groupe 1 (.*)$ #des calculs pour finir """ test = re.search(recherche_parentheses, calcul, re.VERBOSE) while test: sous_calcul = test.groups() (calcul, solution) = priorites_operations(sous_calcul[1], sous_calcul[0], sous_calcul[2], solution) calcul = solution[-1] test = re.search(recherche_parentheses, calcul, re.VERBOSE) calcul, solution = priorites_operations(calcul, pre, post, solution) return(solution) def traite_operation(operateur, calcul, pre, post, solution): pattern = r""" ( #groupe 0 ^\(* #le calcul est au début (aux parenthèses près) #les signes +/- font parti du groupe 2 | #ou ^.*?[\+\-]? #il y a des calculs avant, le 1e signe +/- #est un opérateur ) #fin du groupe 0 ( #groupe 1 (?: #regroupement 1 (non groupe) [\+\-]? #un éventuel signe \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant \) #une parenthèse fermante | #ou [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 1 {0} #opération (?: #regroupement 2 (non groupe) [\+\-]? #un éventuel signe \( #une parenthèse ouvrante [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant \) #une parenthèse fermante | #ou [\+\-]? #un éventuel signe \d+\.?\d*(?:e[\+\-]\d+)? #on cherche un nombre avec une #éventuelle partie décimale et un #éventuel exposant | #ou \w+ #un littéral ) #fin du regroupement 2 ) #fin du groupe 1 (.*?)$ #tout le reste """.format(operateur) test = re.search(pattern, calcul, re.VERBOSE) while test: sous_calcul = test.groups() sous_resultat = eval(sous_calcul[1]) if (sous_calcul[0] and sous_calcul[0][-1] == '(') and \ (sous_calcul[2][0] and sous_calcul[2][0] == ')') and \ (post[:2] != '**' or sous_resultat > 0): #permet de supprimer les parenthèses solution.extend([pre + sous_calcul[0][:-1] + str(sous_resultat) + sous_calcul[2][1:] + post]) else: solution.extend([pre + sous_calcul[0] + str(sous_resultat) + sous_calcul[2] + post]) calcul = sous_calcul[0] + str(sous_resultat) + sous_calcul[2] test = re.search(pattern, calcul, re.VERBOSE) return (calcul, pre, post, solution) def priorites_operations(calcul, pre = "", post = "", solution = []): calcul, pre, post, solution = traite_operation("\*\*", calcul, pre, post, solution) calcul, pre, post, solution = traite_operation("[\*/]", calcul, pre, post, solution) calcul, pre, post, solution = traite_operation("[\+\-]", calcul, pre, post, solution) return (calcul, solution) for element in priorites("(2-5)**2+(5-2)**3+((3*4+5)*2+3*(32-5*7)**2)*5+17*(12-3*5)"): print element #print priorites("((-(-1)+-2)++3)") #print priorites("4-((-1+-2)+3)") #print priorites('8-(-5*(2-4))') #print priorites("1+2+3+4") #print priorites("-3**+2") #print priorites("9+8*7") #print priorites("8+1.3e+2") pyromaths/src/outils/._TestEnv.py0000644000175000017500000000031511702101415017546 0ustar didrocksdidrocksMac OS X  2ATTRGޫ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/Affichage.py0000644000175000017500000001107111702101415017577 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import re from .decimaux import decimaux from ..classes import Racine, Fractions def tex_coef(coef, var, bplus=0, bpn=0, bpc=0): """ coef est le coefficient à écrire devant la variable var bplus est un booleen : s'il est vrai, il faut ecrire le signe + bpn est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'écriture si coef est negatif. bpc est un booleen : s'il est vrai, il faut mettre des parentheses autour de l'écriture si coef =! 0 ou 1 et var est non vide """ if coef != 0 and abs(coef) != 1: if var == '': a = TeX(coef) else: a = '%s\\,%s' % (TeX(coef), var) if bplus and coef > 0: a = '+' + a elif coef == 1: if var == '': a = '1' else: a = '%s' % var if bplus: a = '+' + a elif coef == 0: a = '' elif coef == -1: if var == '': a = '-1' else: a = '-%s' % var if bpn and coef < 0 or bpc and coef != 0 and coef != 1 and var != '': a = '\\left( ' + a + '\\right)' return a def TeXz(nombre): '''n'affiche pas b si b=0''' if nombre==0: return "" else: return TeX(nombre) def tTeX(nombre): '''raccourci pour TeX(nombre,terme=True)''' return TeX(nombre,terme=True) def pTeX(nombre): '''raccourci pour TeX(nombre,parenthese=True)''' return TeX(nombre,parenthese=True) def fTeX(nombre): '''raccourci pour TeX(nombre,fractex="\\frac")''' return TeX(nombre,fractex="\\frac") def TeX(nombre,parenthese=False,terme=False,fractex="\\dfrac"): '''renvoie une chaine de caractere pour TeX''' strTeX=finTeX="" #Affichage simplifié des racines ou fractions if isinstance(nombre,Racine.RacineDegre2) and nombre.radicande==0: #Affiche la RacineDegre2 comme une Fractions nombre=Fractions.Fractions(nombre.numerateur,nombre.denominateur) if isinstance(nombre,Fractions.Fractions) and nombre.denominateur==1: #Affiche la Fractions comme un entier nombre=nombre.numerateur #parentheses des fractions if parenthese and ( isinstance(nombre,Racine.RacineDegre2) and nombre.denominateur==1 and (nombre.numerateur or nombre.coeff<0 ) #RacineDegre2 avec radicande nécessairement grâce au tri or isinstance(nombre,Fractions.Fractions) and nombre.numerateur<0 or isinstance(nombre,int) and nombre<0 or isinstance(nombre,float) and nombre<0): strTeX="\\left(" finTeX="\\right)" elif terme and (isinstance(nombre,Racine.RacineDegre2) and (nombre.denominateur!=1 or (nombre.numerateur >0 or nombre.numerateur==0 and nombre.coeff>=0)) or nombre>=0) : strTeX="+" finTeX="" ##Affichage if nombre==float("inf"): return "+\\infty " elif nombre==float("-inf"): return "-\\infty " elif isinstance(nombre,int) or isinstance(nombre,float): return strTeX+decimaux(nombre)+finTeX elif isinstance(nombre,Fractions.Fractions): if nombre.numerateur < 0: strTeX += "-"+fractex+"{"+decimaux(-nombre.numerateur)+"}{"+decimaux(nombre.denominateur)+"} " else: strTeX += fractex+"{"+decimaux(nombre.numerateur)+"}{"+decimaux(nombre.denominateur)+"} " strTeX+=finTeX return strTeX elif isinstance(nombre,Racine.RacineDegre2): return strTeX+str(nombre)+finTeX else: return strTeX+str(nombre)+finTeX def radicalTeX(n): return "\\sqrt{%s}"%(decimaux(n)) pyromaths/src/outils/._Priorites.py0000644000175000017500000000031511702101415020136 0ustar didrocksdidrocksMac OS X  2ATTRGަ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._Geometrie.py0000644000175000017500000000031511702101415020076 0ustar didrocksdidrocksMac OS X  2ATTRGޤ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/outils/._Affichage.py0000644000175000017500000000031511702101415020013 0ustar didrocksdidrocksMac OS X  2ATTRGޟ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/0000755000175000017500000000000011734627250015716 5ustar didrocksdidrockspyromaths/src/sixiemes/decimaux.py0000644000175000017500000006232611702101415020061 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random from ..outils import Affichage, Arithmetique #=============================================================================== # Écrire un nombre en lettres ou en chiffres #=============================================================================== def NombreEnLettres(n, France=True): unite = { 1: "un", 2: 'deux', 3: 'trois', 4: 'quatre', 5: 'cinq', 6: 'six', 7: 'sept', 8: 'huit', 9: 'neuf', 10: 'dix', 11: 'onze', 12: 'douze', 13: 'treize', 14: 'quatorze', 15: 'quinze', 16: 'seize', 17: 'dix-sept', 18: 'dix-huit', 19: 'dix-neuf', } dizaineF = {2: 'vingt', 3: 'trente', 4: 'quarante', 5: 'cinquante', 6: 'soixante', 7: "", 8: 'quatre-vingt', 9: ""} dizaineB = {2: 'vingt', 3: 'trente', 4: 'quarante', 5: 'cinquante', 6: 'soixante', 7: 'septante', 8: 'octante', 9: 'nonante'} coefs = {0: 'cent', 1: 'mille', 2: 'million', 3: 'milliard'} result = "" # Cas particulier de zéro if n == 0: result = u'zéro' else: coef = 0 while n > 0: # Récupération de l'unité du bloc de trois chiffres en cours u = n % 10 n = n // 10 # Récupération de la dizaine du bloc de trois chiffres en cours d = n % 10 n = n // 10 # Traitement des dizaines temp = "" # Passage sur la dizaine inférieure pour 10 à 19 # et pour 70-79 90-99 dans le cas de la France if d == 1 or (d == 7 or d == 9) and France: d = d - 1 u = u + 10 if d > 1: if France: if n: temp = '-' + dizaineF[d] else: temp = dizaineF[d] # Ajout du cas particulier de 'et' entre la dizaine et 1 if d < 8 and (u == 1 or u == 11): temp = temp + '-et' else: if n: temp = '-' + dizaineB[d] else: temp = dizaineB[d] # Ajout du cas particulier de 'et' entre la dizaine et 1 if u == 1: temp = temp + '-et' # ajout du texte de l'unité if u > 0 and (d or n): temp = temp + '-' + unite[u] elif u > 0: temp = unite[u] # ajout du 's' à Quatre-vingt si rien ne suit #if (result == '') and (d == 8) and (u == 0) and France : result = 's' if d == 8 and u == 0 and France: temp = temp + 's' result = temp + result # Récupération de la centaine du bloc de trois chiffres en cours c = n % 10 n = n // 10 if c > 0: temp = "" if c > 1 and n: temp = '-' + unite[c] elif c > 1: temp = unite[c] if c == 1 and not n: temp = coefs[0] else: temp = temp + '-' + coefs[0] # Traitement du cas particulier du 's' à cent si rien ne suit if result == "" and c > 1: result = 's' result = temp + result # Traitement du prochain groupe de 3 chiffres if n > 0: coef = coef + 1 i = n % 1000 if i > 1 and coef > 1: result = 's' + result # Traitement du cas particulier 'mille' ( non pas 'un mille' ) if i == 1 and coef == 1: n = n - 1 result = coefs[coef] + result elif i > 0: result = '-' + coefs[coef] + result return result def nombreATrouver(): """a contient la liste des nombres à créer où il peut ne pas y avoir de centaines, de centaines de milliers, d'unités ou de milliers""" a = [random.randrange(100) + random.randrange(1000) * 10 ** 3, random.randrange(1000) + random.randrange(100) * 10 ** 3, random.randrange(1000) * 10 ** 3, random.randrange(1000)] (lnb, list) = ([], []) for i in range(4): lnb.append(random.randrange(1, 1000) * 10 ** 6 + a[i]) for i in range(4): n = a[i] if n % 1000: # il y a des unités dans le nombre e = random.randrange(1, 4) lnb.append(n * 10 ** (-e)) else: e = random.randrange(4, 7) lnb.append(n * 10 ** (-e)) for i in range(8): list.append(lnb.pop(random.randrange(len(lnb)))) return list def EcritNombreDecimal(n): txt = "" if n != int(n): #n n'est pas un nombre entier (e, d) = str(n).split('.') (e, d) = (int(e), int(d)) else: (e, d) = (int(n), 0) if not d: txt = NombreEnLettres(e) elif e: txt = NombreEnLettres(e) if d: partieDec = [u" dixième", u" centième", u" millième"] if txt.rfind("un") == len(txt) - 2: # le texte se finit par un. On l'accorde en genre avec unité txt = txt + "e" if e == 1: txt = txt + u' unité et ' if e > 1: txt = txt + u' unités et ' txt = txt + NombreEnLettres(d) + partieDec[len(str(n).split('.')[1]) - 1] if d > 1: txt = txt + 's' return txt def EcritEnChiffre(exo, cor): lnb = nombreATrouver() for i in range(len(lnb)): exo.append("\\item " + EcritNombreDecimal(lnb[i]) + " : \\dotfill") cor.append("\\item " + EcritNombreDecimal(lnb[i]) + " : ") cor.append(Affichage.decimaux(lnb[i], 0) + '') def EcritEnLettre(exo, cor): lnb = nombreATrouver() for i in range(8): exo.append("\\item " + Affichage.decimaux(lnb[i], 0) + " : \\dotfill") cor.append("\\item " + Affichage.decimaux(lnb[i], 0) + " : ") cor.append(EcritNombreDecimal(lnb[i]) + '') def EcrireNombreLettre(): exo = ["\\exercice", "\\begin{enumerate}", u'\\item Écrire en chiffres les nombres suivants.', '\\begin{enumerate}'] cor = ["\\exercice*", "\\begin{enumerate}", u'\\item Écrire en chiffres les nombres suivants.', '\\begin{enumerate}'] EcritEnChiffre(exo, cor) exo.append('\\end{enumerate}') exo.append(u'\\item Écrire en lettres les nombres suivants (sans utiliser le mot ``virgule").') exo.append('\\begin{enumerate}') cor.append('\\end{enumerate}') cor.append(u'\\item Écrire en lettres les nombres suivants (sans utiliser le mot ``virgule").') cor.append('\\begin{enumerate}') EcritEnLettre(exo, cor) exo.append('\\end{enumerate}') exo.append('\\end{enumerate}') cor.append('\\end{enumerate}') cor.append('\\end{enumerate}') return (exo, cor) #=============================================================================== # Conversions #=============================================================================== units = ["L", "m", "g"] division = ["k", "h", "da", "", "d", "c", "m"] #paramétrage des flèches : mofifie le paramétrage par défaut de PSTricks s'il n'est pas limité par un environnement ou {groupe} ## nodesepA = -1.5mm : décale le départ de la flèche ## linewidth = 0.6pt : épaisseur de la flèches ## linestyle = dotted : style pointillé ## vref = -0.8mm : décale la flèche vers le bas, sous les chiffres PSSET_FLECHE = '\\psset{nodesepA = -1.5mm, linewidth = 0.6pt, linestyle = dotted, vref = -0.8mm}' def Conversions(n): if n == 1:#Conversions de L, m ou g #le module sixiemes.sixiemes va appeler Conversions(1)() return tex_units #exo_conversion(exo, cor, 1) #le choix des valeurs prises, l'absence de grammes et litres ne rendent pas cette rédaction pertinente else: #conversions de m² ou m³ return exo_conversion(n) def valeurs_units(): """ renvoie les valeurs pour les conversions d'unités """ a = Arithmetique.valeur_alea(101, 999) p = random.randrange(-2, 0) unit = random.randrange(3) if unit: #mètres ou grammes, on peut utiliser les k imax = 7 else: #Litres, donc pas de kL imax = 6 div0 = random.randrange(imax + p) while 1: div1 = random.randrange(imax) if div0 != div1: break if not unit: #Litres, donc pas de kL donc on décale d'un rang div0, div1 = div0 + 1, div1 + 1 return (a, p, unit, div0, div1) #101< a <999 ex a = 245 #p = {-2,-1} donne 2,45 ou 24,5 #unit = {0, 1, 2} => {L, m, g} #div0 unité 0 #div1 unité converti def tex_units(): """ Écrit l'exercice sur les conversions d'unités et le corrigé au format LaTeX @param exo: fichier exercices @param cor: fichier corrige """ exo = ["\\exercice", 'Effectuer les conversions suivantes :', '\\begin{multicols}{3}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", #paramétrage des flèches, ce paramétrage est limité à l'exercice # et ne modifie pas le paramétrage PSTricks du document car sa portée est limité par le groupe ouvert par "{" "{", PSSET_FLECHE, 'Effectuer les conversions suivantes :', '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] #Construit les 6 questions de l'exercice for i in range(6): (a, p, unit, div0, div1) = valeurs_units() if unit: u = tuple([units[unit] for i in range(7)]) else: u = tuple([units[unit] for i in range(6)]) nb0 = Affichage.decimaux(a * 10 ** p, 0) nb1 = Affichage.decimaux(a * 10 ** ((p + div1) - div0), 0) exo.append("\\item %s~%s%s=\dotfill~%s%s" % (nb0, division[div0], units[unit], division[div1], units[unit])) cor.append("\\item %s~%s%s=%s~%s%s\\par" % (nb0, division[div0], units[unit], nb1, division[div1], units[unit])) nblist = [nb0[i] for i in range(len(nb0))] if nblist.count(','): chf_unite = nblist.index(',') - 1 nblist.pop(chf_unite + 1) else: chf_unite = len(nblist) - 1 tex_tableau(cor, div0, div1, u, nblist, chf_unite) cor.append("\\end{tabular}") cor.append("\\ncline{->}{virg0}{virg1}") exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') #ferme le groupe limitant la portée de PSSET_FLECHE cor.append('{') return (exo, cor) def tex_tableau(cor, div0, div1, u, nblist, chf_unite): """tableau de conversion pour les unités simples : L, g ou m""" #Si len(u) == 6, on a des Litres, on ne doit pas avoir la colonne kL if len(u) == 6: cor.append("\\begin{tabular}{c|c|c|c|c|c}") cor.append("h%s & da%s & %s & d%s & c%s & m%s \\\\ \\hline" %u ) #décale d'une colonne pour supprimer kL delta = 1 div0 = div0 - 1 div1 = div1 - 1 else: cor.append("\\begin{tabular}{c|c|c|c|c|c|c}") cor.append("k%s & h%s & da%s & %s & d%s & c%s & m%s \\\\ \\hline" % u) #ne supprime pas le kg, km delta = 0 for i in range(-div0 + chf_unite): tmp = nblist.pop(0) nblist[0] = tmp + nblist[0] for i in range(div0 - chf_unite): nblist.insert(0, '0') for i in range(-len(u) + len(nblist)): tmp = nblist.pop(7) nblist[6] = nblist[6] + tmp #les zéros à droites des chiffres significatifs for i in range(len(u) - len(nblist)): nblist.append('0') #place les \nodes et la virgule dans le tableau nblist[div0] = "%s\\Rnode{virg0}{\\ }"%(nblist[div0]) nblist[div1] = "{%s\\Rnode{virg1}{\\textcolor{red}{ \\LARGE ,}}}"%(nblist[div1]) #ajoute au tabular la ligne avec 6 ou 7 colonnes cor.append(("%s "+("& %s"*(6-delta))) % tuple(nblist)) def exo_conversion(exposant): """construit l'exercice de conversion d'unité d'aire ou de volume exposant 2 pour m² exposant 3 pour m³""" exo = ["\\exercice", 'Effectuer les conversions suivantes :', '\\begin{multicols}{3}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", #la portée de \psset est par le group ouvert par "{" "{", PSSET_FLECHE, '\\def\\virgule{\\textcolor{red}{ \\LARGE ,}}', 'Effectuer les conversions suivantes :', '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] #ajoute le ² ou ³ si nécessaire str_exposant=(u"^%s"%(exposant))*(exposant > 1) u = tuple([division[i]+"m%s"%str_exposant for i in range(7)]) entete_tableau = ((" \\multicolumn{%s}{c|}"%exposant +"{$\\rm %s$} &")*6 +"\\multicolumn{%s}{c}"%exposant+"{$\\rm %s$}" )%u ligne_tab = [] for i in range(6): #imprime la correction et sauvegarde la ligne et la flèche pour le tableau imprimé ensuite ligne_tab += tex_conversion(exo, cor,exposant, u) + ["\\ncline{->}{virg0}{virg1} \\\\"] #ferme la correction et l'énoncé cor.append('\\end{enumerate}') cor.append('\\end{multicols}') exo.append('\\end{enumerate}') exo.append('\\end{multicols}') #impression du tableau et des lignes sauvegardées précédemment cor.append("\\begin{tabular}{*{%s}{p{3.5mm}|}p{3.5mm}}"%(exposant*7-1)) cor.append(entete_tableau + "\\\\ \\hline") #ajoute les lignes affichant les conversions cor += ligne_tab cor.append("\\end{tabular}") #ferme le groupe dans lequel PSSET_FLECHE portait cor.append("}") #C'est fini return (lambda: (exo, cor)) def tex_conversion(exo, cor, exposant, u): """Écrit une question sur les conversions d'unités d'aires ou de volume et le corrigé au format LaTeX @param exo: fichier exercices @param cor: fichier corrige exposant = 2 ou 3 pour les aires ou les volumes """ a = random.randint(101,999) p = random.randint(-2,-1) while True: (div0,div1)=(random.randrange(6),random.randrange(7),) #Pas de mm³ par ce que ça sort du tableau if (div0-div1) in [-2,-1,1,2]: #pas trop loin car ça fait de très longs nombres break nb0 = a * 10 ** p nb1 = nb0 * 10 ** ( exposant * ( div1- div0)) exo.append("\\item $\\unit[%s]{%s}=\\unit[\\dotfill]{%s}$"% (Affichage.decimaux(nb0), u[div0], u[div1])) cor.append("\\item $\\unit[%s]{%s}=\\unit[%s]{%s}$\\vspace{1ex}\\par" % (Affichage.decimaux(nb0), u[div0], Affichage.decimaux(nb1), u[div1])) return tex_tableau_conversion(div0, div1, nb0, u, exposant) def tex_tableau_conversion(div0, div1, nb0, u, exposant): nb_dict = nbre_to_dict(nb0,div0,div1,exposant) nblist = [str(nb_dict.get(i,"")) for i in range(7*exposant)] nblist[exposant*(div0 + 1)-1] = "%s\\Rnode{virg0}{\\ }"% nb_dict.get(exposant*(div0+1)-1,"0") nblist[exposant*(div1 + 1)-1] = "{%s\\Rnode{virg1}{\\virgule}}"% nb_dict.get(exposant*(div1+1)-1,"0") return [("%s " + "& %s"*(7*exposant-1)) % tuple(nblist)] def nbre_to_dict(nbre ,div0,div1,exposant): #exposant peut être 2 ou 3 pour les m² ou les m³ nbre = int(round(nbre*100)) nb_dict = {} for i in range(min(exposant*(div0+1),exposant*(div1+1))-1,max(exposant*(div0+1),exposant*(div1+1))): nb_dict[i] = "\\textcolor{red}{0}" curseur = 1+exposant*(div0+1) while nbre % 10 == 0: nbre = nbre / 10 curseur -= 1 while nbre > 0: chiffre = nbre % 10 nbre = (nbre-chiffre)/10 nb_dict[curseur] = "\\textcolor{blue}{%s}"%chiffre curseur -= 1 return nb_dict #=============================================================================== # Placer une virgule #=============================================================================== valeurs = ["milliers", "centaines", "dizaines", u"unités", u"dixièmes", u"centièmes", u"millièmes"] def valeurs_decimaux(): """ Choisit les valeurs """ nb = 0 chiffres = [1, 2, 3, 4, 5, 6, 7, 8, 9] for i in range(6): nb = nb + chiffres.pop(random.randrange(len(chiffres))) * 10 ** \ i return nb def tex_place_virgule(exo, cor): """ Écrit un exercices demandant de placer une virgule dans un nombre. @param exo: fichier exerices @param cor:fichier corrigé """ valeurs_index = [0, 1, 2, 3, 4, 5, 6] nb = valeurs_decimaux() exo.append(u"Placer une virgule (en ajoutant éventuellement des zéros) dans\ le nombre %s de telle sorte que :" % nb) exo.append('\\begin{enumerate}') cor.append(u"Placer une virgule (en ajoutant éventuellement des zéros) dans\ le nombre %s de telle sorte que :" % nb) cor.append('\\begin{enumerate}') for i in range(6): dec = [str(nb)[i] for i in range(len(str(nb)))] index_dec = random.randrange(6) index_valeurs = valeurs_index.pop(random.randrange(len(valeurs_index))) exo.append(u"\\item le chiffre %s soit le chiffre des %s : " \ % (dec[index_dec], valeurs[index_valeurs])) cor.append(u"\\item le chiffre %s soit le chiffre des %s : " \ % (dec[index_dec], valeurs[index_valeurs])) resultat = ecrit_nombre_decimal(dec, (index_dec + 4) - index_valeurs) exo.append('\\dotfill') cor.append(Affichage.decimaux(resultat, 0) + '') exo.append('\\end{enumerate}') cor.append('\\end{enumerate}') def ecrit_nombre_decimal(dec, index): """ Renvoie une chaine de caractère représentant le nombre dec avec la virgule à la place index. Ajoute les zéros nécessaires. @param dec: décomposition d'un nombre entier @param index: place de la virgule dans la liste dec """ if index < 1: dec.insert(0, '0') dec.insert(1, '.') for i in range(-index): dec.insert(2, '0') elif index < len(dec): dec.insert(index, '.') else: for i in range(index - len(dec)): dec.append('0') strnb = "" for i in range(len(dec)): strnb = strnb + dec[i] return strnb def PlaceVirgule(): exo = ["\\exercice"] cor = ["\\exercice*"] tex_place_virgule(exo, cor) return (exo, cor) #=============================================================================== # Écriture fractionnaire #=============================================================================== def valeurs_frac(): n1 = random.randrange(11, 10000) p1 = random.randrange(1, 4) return (n1, p1) def choix_trou_frac(exo, cor, n1, p1): i = random.randrange(3) p2 = random.randrange(2) #sert à compliquer un peu l'exercice if i > 1: exo.append('\\item $\\cfrac{%s}{%s}=\\ldots$' % (Affichage.decimaux(n1 * 10 ** p2), Affichage.decimaux(10 ** (p1 + p2)))) cor.append('\\item $\\cfrac{%s}{%s}=\\mathbf{%s}$' % (Affichage.decimaux(n1 * 10 ** p2), Affichage.decimaux(10 ** (p1 + p2)), Affichage.decimaux(n1 * 10 ** (-p1), 1))) elif i > 0: exo.append('\\item $\\cfrac{%s}{\ldots}=%s$' % (Affichage.decimaux(n1 * 10 ** p2), Affichage.decimaux(n1 * 10 ** (-p1), 1))) cor.append('\\item $\\cfrac{%s}{\\mathbf{%s}}=%s$' % (Affichage.decimaux(n1 * 10 ** p2), Affichage.decimaux(10 ** (p1 + p2)),\ Affichage.decimaux(n1 * 10 ** (-p1), 1))) else: exo.append('\\item $\\cfrac{\ldots}{%s}=%s$' % (Affichage.decimaux(10 ** (p1 + p2)), Affichage.decimaux(n1 * 10 ** (-p1), 1))) cor.append('\\item $\\cfrac{\\mathbf{%s}}{%s}=%s$' % (Affichage.decimaux(n1 * 10 ** p2), Affichage.decimaux(10 ** (p1 + p2)), Affichage.decimaux(n1 * 10 ** (-p1), 1))) def tex_frac(exo, cor): for i in range(6): (nombre, puissance) = valeurs_frac() choix_trou_frac(exo, cor, nombre, puissance) def EcritureFractionnaire(): exo = ["\\exercice", u"Compléter :", '\\begin{multicols}{3}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", u"Compléter :", '\\begin{multicols}{3}\\noindent', '\\begin{enumerate}'] tex_frac(exo, cor) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) #=============================================================================== # Décomposition des nombres décimaux #=============================================================================== def valeurs_dec(): lpuissances = [3, 2, 1, 0, -1, -2, -3] p = [] v = [] for i in range(3): p.append(lpuissances.pop(random.randrange(len(lpuissances)))) v.append(random.randrange(1, 10)) return (v, p) def tex_decomposition(v, p): exo, cor = [], [] for i in range(3): if p[i] < 0: exo.append('%s\\times \\cfrac{1}{%s}' % (v[i], Affichage.decimaux(10 ** (-p[i]), 1))) cor.append('%s\\times \\cfrac{1}{%s}' % (v[i], Affichage.decimaux(10 ** (-p[i]), 1))) else: exo.append('%s\\times %s' % (v[i], Affichage.decimaux(10 ** p[i], 1))) cor.append('%s\\times %s' % (v[i], Affichage.decimaux(10 ** p[i], 1))) if i < 2: exo.append('+') cor.append('+') else: exo.append('=') cor.append('=') exo.append('\\dotfill$') cor.append('%s$' % Affichage.decimaux(v[0] * 10 ** p[0] + v[1] * 10 ** p[1] + v[2] * 10 ** p[2], 1)) return " ".join(exo), " ".join(cor) def tex_dec(exo, cor): for i in range(6): txt = '\\item $' (chiffres, puissances) = valeurs_dec() txt_exo, txt_cor = tex_decomposition(chiffres, puissances) exo.append(txt + txt_exo) cor.append(txt + txt_cor) def Decomposition(): exo = ["\\exercice", u"Compléter avec un nombre décimal :", '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", u"Compléter avec un nombre décimal :", '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] tex_dec(exo, cor) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) #=============================================================================== # Classer des nombres dans l'ordre #=============================================================================== def choix_nombres(): nb = [] unite = random.randrange(10) for i in range(3): n = unite for j in range(i + 1): n = n + random.randrange(1, 10) * 10 ** (-(j + 1)) nb.append(n) n = random.randrange(10) + random.randrange(10) / 10.0 while n == nb[0]: n = random.randrange(10) + random.randrange(10) / 10.0 nb.append(n) return nb def classer(exo, cor): lnb = choix_nombres() random.shuffle(lnb) if random.randrange(2): ordre = "croissant" else: ordre = u"décroissant" exo.append("\\item Classer les nombres suivants dans l'ordre %s.\\par " % ordre) cor.append("\\item Classer les nombres suivants dans l'ordre %s.\\par " % ordre) str="" for i in range(len(lnb)): if i: str += " \\kern1cm ; \\kern1cm " str += Affichage.decimaux(lnb[i], 0) exo.append(str) cor.append(str + "\\par") lnb.sort() if ordre == "croissant": ordre = "\\textless" else: ordre = "\\textgreater" lnb.reverse() str="" for i in range(len(lnb)): if i: str +=" \\kern1cm %s \\kern1cm " % ordre str += Affichage.decimaux(lnb[i], 0) cor.append(str) def ClasserNombres(): exo = ["\\exercice", '\\begin{enumerate}'] cor = ["\\exercice*", '\\begin{enumerate}'] classer(exo, cor) classer(exo, cor) exo.append('\\end{enumerate}') cor.append('\\end{enumerate}') return (exo, cor) pyromaths/src/sixiemes/angles.py0000644000175000017500000002146011702101415017525 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import math from random import randrange from ..outils import Arithmetique from ..outils import Geometrie def eq_droites(A, B): (xA, yA) = A (xB, yB) = B a = ((yB - yA) * 1.0) / (xB - xA) b = ((xB * yA - xA * yB) * 1.0) / (xB - xA) return (a, b) def inter_droites(A, B, C, D): """ Calcule les coordonn\xc3\xa9es du point d'intersection des droites (AB) et (CD) """ (a1, b1) = eq_droites(A, B) (a2, b2) = eq_droites(C, D) if a1 == a2: #droites parallèles xI = A[0] yI = A[1] else: xI = ((b2 - b1) * 1.0) / (a1 - a2) yI = ((a1 * b2 - a2 * b1) * 1.0) / (a1 - a2) return (xI, yI) def dist_pt_droite(A, B, C): """ calcule la distance du point C \xc3\xa0 la droite (AB) """ (a, b) = eq_droites(A, B) (xC, yC) = C d = (abs(a * xC - yC + b) * 1.0) / math.sqrt(a ** 2 + 1) return d def dist_points(A, B): """ Calcul la distance entre deux points""" (xA, yA) = A (xB, yB) = B d = math.sqrt((xB - xA) ** 2 + (yB - yA) ** 2) return d def coord_projete(A, B, C): """ Calcule les coordonn\xc3\xa9es du projet\xc3\xa9 orthogonal de C sur la droite (AB) """ (xA, yA) = A (xB, yB) = B (xC, yC) = C n = dist_points(A, B) p = (xB - xA) / n q = (yB - yA) / n s = p * (xC - xA) + q * (yC - yA) return (xA + s * p, yA + s * q) def verifie_distance_mini(A, B, C, D): """ V\xc3\xa9rifie que la distance minimale entre [AB] et [AC] est sup\xc3\xa9rieure \xc3\xa0 dmin """ dmin = 1.2 (xA, yA) = A (xB, yB) = B if xA > xB: (xA, yA, xB, yB) = (xB, yB, xA, yA) (xC, yC) = C (xD, yD) = D if xC > xD: (xC, yC, xD, yD) = (xD, yD, xC, yC) (xI, yI) = inter_droites(A, B, C, D) if xA <= xI <= xB and xC <= xI <= xD or xA <= coord_projete(A, B, C)[0] <= \ xB and dist_pt_droite(A, B, C) < dmin or xA <= coord_projete(A, B, D)[0] <= xB and dist_pt_droite(A, B, D) < dmin or xC <= \ coord_projete(C, D, A)[0] <= xD and dist_pt_droite(C, D, A) < \ dmin or xC <= coord_projete(C, D, B)[0] <= xD and dist_pt_droite(C, D, B) < dmin or dist_points(A, C) < dmin or dist_points(A, D) < \ dmin or dist_points(B, C) < dmin or dist_points(B, D) < dmin: isValid = False else: isValid = True return isValid def verifie_angle(lpoints, A, B, C): """ V\xc3\xa9rifie que l'angle BAC ne coupe pas les autres angles d\xc3\xa9j\xc3\xa0 trac\xc3\xa9s """ if len(lpoints) == 0: #Premier angle créé isValid = True else: for i in range(len(lpoints)): (A1, B1, C1) = (lpoints[i])[:3] isValid = verifie_distance_mini(A, B, A1, B1) and \ verifie_distance_mini(A, B, A1, C1) and \ verifie_distance_mini(A, C, A1, B1) and \ verifie_distance_mini(A, C, A1, C1) if not isValid: break return isValid def cree_angles(nb_angles, xmax, ymax): ''' cr\xc3\xa9e une s\xc3\xa9rie d\'angles "non s\xc3\xa9quents" ''' (xmax, ymax) = (xmax - .5, ymax - .5) #taille de l'image en cm lg_seg = 6 #longueur des côtés des angles lpoints = [] cpt = 0 #evite une boucle infinie while len(lpoints) < nb_angles and cpt < 1000: (xA, yA) = (randrange(5, xmax * 10) / 10.0, randrange(5, ymax * 10) / 10.0) alpha = randrange(360) #angle entre un côté et l'horizontal if len(lpoints) < nb_angles / 2: beta = randrange(90, 180) #crée un angle droit ou obtus else: beta = randrange(0, 75) + 15 #crée un angle aigu (entre 15° et 89°) xB = xA + lg_seg * math.cos((alpha * math.pi) / 180) yB = yA + lg_seg * math.sin((alpha * math.pi) / 180) xC = xA + lg_seg * math.cos(((alpha + beta) * math.pi) / 180) yC = yA + lg_seg * math.sin(((alpha + beta) * math.pi) / 180) (A, B, C) = ((xA, yA), (xB, yB), (xC, yC)) if xA != xB and xA != xC and .5 < xB < xmax and .5 < yB < ymax and \ .5 < xC < xmax and .5 < yC < ymax and verifie_angle(lpoints, A, B, C): lpoints.append((A, B, C, alpha, beta)) else: cpt = cpt + 1 #print len(lpoints) return lpoints def PosAngle(alpha, beta): """retourne les angles pour placer les points sur la figure""" A = (alpha + beta / 2.0 + 180) % 360 B = (alpha - 90) % 360 C = (alpha + beta + 90) % 360 return (A, B, C) def PointName(l3noms, indice): list = [] for i in range(3): list.append(l3noms[i]) return tuple(list) def figure(exo, cor, lpoints, lnoms, xmax, ymax): exo.append("\\begin{pspicture}(%s,%s)" % (xmax, ymax)) exo.append("\\psframe(0,0)(%s,%s)" % (xmax, ymax)) exo.append("\\psset{PointSymbol=none,MarkAngleRadius=0.6}") cor.append("\\begin{pspicture}(%s,%s)" % (xmax, ymax)) cor.append("\\psset{PointSymbol=none,MarkAngleRadius=0.6}") cor.append("\\psframe(0,0)(%s,%s)" % (xmax, ymax)) for i in range(len(lnoms)): points_exo = '' points_cor = '' points_exo += "\\pstGeonode[PointName={%s,%s,%s}," % lnoms[i] points_cor += "\\pstGeonode[PointName={%s,%s,%s}," % lnoms[i] points_exo += "PosAngle={%s,%s,%s}]" % PosAngle(lpoints[i][3], lpoints[i][4]) points_cor += "PosAngle={%s,%s,%s}]" % PosAngle(lpoints[i][3], lpoints[i][4]) for j in range(3): points_exo += "(%.2f,%.2f)" % lpoints[i][j] points_exo += "{a%s%s}" % (j, i) points_cor += "(%.2f,%.2f)" % lpoints[i][j] points_cor += "{a%s%s}" % (j, i) exo.append(points_exo) cor.append(points_cor) exo.append("\\pstMarkAngle{a%s%s}{a%s%s}{a%s%s}{}"%(1,i,0,i,2,i)) cor.append("\\pstMarkAngle{a%s%s}{a%s%s}{a%s%s}{}"%(1,i,0,i,2,i)) exo.append("\\pstLineAB[nodesepB=-.5]{a0%s}{a1%s}\\pstLineAB[arrows=-|,linestyle=none]{a0%s}{a1%s}" % (i, i, i, i)) cor.append("\\pstLineAB[nodesepB=-.5]{a0%s}{a1%s}\\pstLineAB[arrows=-|,linestyle=none]{a0%s}{a1%s}" % (i, i, i, i)) exo.append("\\pstLineAB[nodesepB=-.5]{a0%s}{a2%s}\\pstLineAB[arrows=-|,linestyle=none]{a0%s}{a2%s}" % (i, i, i, i)) cor.append("\\pstLineAB[nodesepB=-.5]{a0%s}{a2%s}\\pstLineAB[arrows=-|,linestyle=none]{a0%s}{a2%s}" % (i, i, i, i)) exo.append("\\end{pspicture}\\par") cor.append("\\end{pspicture}\\par") return (exo, cor) def reponses(exo, cor, lpoints, lnoms): cor.append("\\begin{multicols}{4}") for i in range(len(lnoms)): cor.append("$\\widehat{%s%s%s}=%s\degres$\\par" % (lnoms[i][1], lnoms[i][0], lnoms[i][2], lpoints[i][4])) if lpoints[i][4] < 90: cor.append("angle aigu\\par") elif lpoints[i][4] > 90: cor.append("angle obtus\\par") else: cor.append("angle droit\\par") cor.append("\\end{multicols}") exo.append("\\begin{tabularx}{\\textwidth}{|*{4}{X|}}") exo.append("\\hline angle 1 : & angle 2 : & angle 3 : & angle 4 : \\\\") exo.append("\\hline &&& \\\\ &&& \\\\ &&& \\\\ \\hline") exo.append("\\end{tabularx}") def MesureAngles(): nb_angles = 4 (xmax, ymax) = (18, 8) #taille de l'image en cm lnoms = [] lpoints = [] cpt = 0 while len(lpoints) < nb_angles: if cpt > 1000: lpoints = [] cpt = 0 lpoints = cree_angles(nb_angles, xmax, ymax) cpt = cpt + 1 tmpl = Geometrie.choix_points(3 * nb_angles) for i in range(nb_angles): lnoms.append(tuple(tmpl[3 * i:3 * i + 3])) exo = ["\\exercice", "Nommer, mesurer et donner la nature de chacun des angles suivants :\\par "] cor = ["\\exercice*", "Nommer, mesurer et donner la nature de chacun des angles suivants :\\par "] figure(exo, cor, lpoints, lnoms, xmax, ymax) reponses(exo, cor, lpoints, lnoms) return (exo, cor) pyromaths/src/sixiemes/aires.py0000644000175000017500000002534411702101415017364 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #import sys, os #sys.path.append(os.path.join(os.path.dirname(__file__), "..")) import random from ..outils import Affichage def boxes(): """Crée les boites pour insérer les figures dans un environnement 36x16""" b0x, b0y = random.randrange(5, 2*36/3-1), random.randrange(5, 2*16/3+1) b1x, b1y = random.randrange(5, 2*(36-b0x)/3-1), random.randrange(5, 2*16/3+1) b2x, b2y = 36-b0x-b1x-2, random.randrange(5, 2*16/3+1) b3x, b3y = b0x, 16-b0y-1 b4x, b4y = b1x, 16-b1y-1 b5x, b5y = b2x, 16-b2y-1 return (b0x, b0y), (b1x, b1y), (b2x, b2y), (b3x, b3y), (b4x, b4y), (b5x, b5y) def carre(dim, n_fig): """Dessine en psTricks un carre de dimensions inf(dim) et numérote la figure avec n_fig""" if dim[0]0: s0, s1, s2, s3 = (tab, 0), (dim[0], 0), (dim[0]-tab, dim[1]), (0, dim[1]) frame0, frame1 = s0, dim else: s0, s1, s2, s3 = (0, 0), (dim[0]+tab, 0), (dim[0], dim[1]), (-tab, dim[1]) frame0, frame1 = s0, (dim[0]+tab, dim[1]) else: tab = random.randrange(1, min(dim[1]/2, dim[1]-3))*(-1)**random.randrange(2) if tab>0: s0, s1, s2, s3 = (0, tab), (dim[0], 0), (dim[0], dim[1]-tab), (0, dim[1]) frame0, frame1 = s0, dim else: s0, s1, s2, s3 = (0, 0), (dim[0], -tab), (dim[0], dim[1]), (0, dim[1]+tab) frame0, frame1 = s0, (dim[0], dim[1]+tab) f = "\\pspolygon[fillstyle=hlines]%s%s%s%s\n" % (s0, s1, s2, s3) f += "\\rput(%.2f,%.2f)" % isobarycentre((0, 0), dim) f += "{\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{figure %s}} " % n_fig fc = "\\pspolygon%s%s%s%s\n" % (s0, s1, s2, s3) fc += "\\psframe[linestyle=dashed, fillstyle=hlines]%s%s\n" % (frame0, frame1) fc += "\\rput(%.2f,%.2f)" % isobarycentre((0, 0), dim) fc += "{\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{figure %s}} " % n_fig s = "Aire de la figure %s : " % n_fig s += u"c'est l'aire du rectangle en pointillés.\\par\n" s += u"$%s = %s$~unités d'aire" %(aire_rectangle(frame0, frame1)[0], aire_rectangle(frame0, frame1)[1]) return (f, fc, s) def triangle_rectangle(dim, n_fig): """Dessine en psTricks un triangle rectangle dans une boite de dimensions dim et numérote la figure avec n_fig""" sommets = [(0, 0), (dim[0], 0), dim, (0, dim[1])] s0 = random.randrange(4) s1, s2 = (s0+1)%4, (s0+2)%4 s0, s1, s2 = sommets[s0], sommets[s1], sommets[s2] f = "\\pspolygon[fillstyle=hlines]%s%s%s\n" % (s0, s1, s2) f += "\\rput(%.2f,%.2f)" % isobarycentre(s0, s1, s2) f += "{\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{figure %s}} " % n_fig fc = "\\psframe[linestyle=dashed]%s%s\n" % (s0, s2) fc += f s = "Aire de la figure %s : " % n_fig s += u"c'est la moitié de l'aire du rectangle en pointillés.\\par\n" s += u"$(%s) \\div 2= %s$~unités d'aire" %(aire_rectangle(dim)[0], Affichage.decimaux(aire_rectangle(dim)[1]/2., 1)) return f, fc, s def triangle_base(dim, n_fig): """Dessine en psTricks un triangle avec une base horizontale ou verticale dans une boite de dimensions dim et numérote la figure avec n_fig""" sommets = [(0, 0), (dim[0], 0), dim, (0, dim[1])] s0 = random.randrange(4) s1 = (s0+1)%4 x0, x1 = sommets[(s0+2)%4][0], sommets[(s0+3)%4][0] y0, y1 = sommets[(s0+2)%4][1], sommets[(s0+3)%4][1] if x0>x1: x0, x1 = x1, x0 if y0>y1: y0, y1 = y1, y0 if x0 != x1: x0 = random.randrange(x0+1, x1) if y0 != y1: y0 = random.randrange(y0+1, y1) s2 = (x0, y0) s0, s1 = sommets[s0], sommets[s1] f = "\\pspolygon[fillstyle=hlines]%s%s%s\n" % (s0, s1, s2) f += "\\rput(%.2f,%.2f)" % isobarycentre(s0, s1, s2) f += "{\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{figure %s}} " % n_fig fc = "\\psframe[linestyle=dashed]%s%s\n" % (s0, s2) fc += "\\psframe[linestyle=dashed]%s%s\n" % (s2, s1) fc += f s = "Aire de la figure %s : " % n_fig s += u"c'est la moitié de l'aire du rectangle en pointillés.\\par\n" s += u"$(%s) \\div 2= %s$~unités d'aire" %(aire_rectangle(dim)[0], Affichage.decimaux(aire_rectangle(dim)[1]/2., 1)) return f, fc, s def triangle_qcq(dim, n_fig): """Dessine en psTricks un triangle quelconque dans une boite de dimensions dim et numérote la figure avec n_fig""" sommets = [(0, 0), (dim[0], 0), dim, (0, dim[1])] s0 = random.randrange(4) angle0, angle1, angle2 = sommets[(s0+1)%4], sommets[(s0+2)%4], sommets[(s0+3)%4] x0, x1 = sommets[(s0+1)%4][0], sommets[(s0+2)%4][0] y0, y1 = sommets[(s0+1)%4][1], sommets[(s0+2)%4][1] if x0>x1: x0, x1 = x1, x0 if y0>y1: y0, y1 = y1, y0 if x0 != x1: x0 = random.randrange(x0+1, x1) if y0 != y1: y0 = random.randrange(y0+1, y1) s1 = (x0, y0) x0, x1 = sommets[(s0+2)%4][0], sommets[(s0+3)%4][0] y0, y1 = sommets[(s0+2)%4][1], sommets[(s0+3)%4][1] if x0>x1: x0, x1 = x1, x0 if y0>y1: y0, y1 = y1, y0 if x0 != x1: x0 = random.randrange(x0+1, x1) if y0 != y1: y0 = random.randrange(y0+1, y1) s2 = (x0, y0) s0 = sommets[s0] f = "\\pspolygon[fillstyle=hlines]%s%s%s\n" % (s0, s1, s2) f += "\\rput(%.2f,%.2f)" % isobarycentre(s0, s1, s2) f += "{\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{figure %s}}" % n_fig fc = "\\psframe[linestyle=dashed](0,0)(%s,%s) " % dim fc += "\\rput(%.2f,%.2f){\\pscirclebox{1}} " % isobarycentre(s0, s1, angle0) fc += "\\rput(%.2f,%.2f){\\pscirclebox{2}} " % isobarycentre(s1, s2, angle1) fc += "\\rput(%.2f,%.2f){\\pscirclebox{3}}\n" % isobarycentre(s2, s0, angle2) fc += f s = "Aire de la figure %s : " % n_fig s += u"on calcule l'aire du rectangle en pointillés et on soustrait " s += "les aires des triangles rectangles \\pscirclebox{1}, " s += "\\pscirclebox{2} et \\pscirclebox{3}.\\par\n" s += "$(%s) - (%s) \\div 2 - (%s) \\div 2 - (%s) \\div 2 " %\ (aire_rectangle(dim)[0], aire_rectangle(s0, s1)[0], aire_rectangle(s1, s2)[0], aire_rectangle(s2, s0)[0]) s += u"= %s$~unités d'aire" % Affichage.decimaux(aire_rectangle(dim)[1] - aire_rectangle(s0, s1)[1]/2. - aire_rectangle(s0, s2)[1]/2. - aire_rectangle(s1, s2)[1]/2., 1) return f, fc, s def aire_rectangle(pos1, pos2=(0, 0)): """Affiche le calcul et le résultat de l'aire d'un rectangle, les coordonnées de deux sommets opposés étant pos1 et pos2""" dx = abs(pos1[0] - pos2[0]) dy = abs(pos1[1] - pos2[1]) return ("%s \\times %s" % (dx, dy), dx*dy) def isobarycentre(*args): nbarg = len(args)*1. isobar = [0, 0] for i in args: isobar = [isobar[0]+i[0]/nbarg, isobar[1]+i[1]/nbarg] return tuple(isobar) def figure(): """Dessine en psTricks la figure de l'exercice sur les aires (quadrillage et figures géométriques)""" exo, cor, sol = [], [], ["\\begin{enumerate}"] t = "\\begin{pspicture}(0,0)(18,9)\n" t += "\\psgrid[subgriddiv=2, gridlabels=0pt]\n" t += "\\psframe[fillstyle=vlines, hatchsep=1pt](0,0)(.5,.5)\n" t += u"\\rput[l](0.6,0.25){\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{unité d'aire}}\n" t += "\\psset{unit=5mm}\n" exo.append(t) cor.append(t) dim0, dim1, dim2, dim3, dim4, dim5 = boxes() xtab0 = 0 ytab3 = ytab4 = ytab5 = 2 xtab1 = dim0[0] + 1 xtab2 = dim0[0] + dim1[0] + 2 ytab0 = dim3[1]+3 ytab1 = dim4[1]+3 ytab2 = dim5[1]+3 fig = [carre, rectangle, triangle_rectangle, triangle_base, triangle_qcq, parallelogramme] for i in range(len(fig)): r = fig.pop(random.randrange(len(fig)))(eval('dim'+str(i)), i+1) exo.append("\\rput(%s,%s){\n" % (eval('xtab' + str(i%3)), eval('ytab' + str(i)))+ r[0] + '\n}') cor.append("\\rput(%s,%s){\n" % (eval('xtab' + str(i%3)), eval('ytab' + str(i)))+ r[1] + '\n}') sol.append("\\item %s" % r[2]) exo.append("\\end{pspicture}") cor.append("\\end{pspicture}") cor.extend(sol) cor.append("\\end{enumerate}") return("\n".join(exo), "\n".join(cor)) def main(): exo, cor, sol = [], [], [] exo = ["\\exercice", u"Calculer l'aire de chacune des figures suivantes dans l'unité d'aire donnée :\\par"] cor = ["\\exercice*", u"Calculer l'aire de chacune des figures suivantes dans l'unité d'aire donnée :\\par"] exercice = figure() exo.append(exercice[0]) cor.append(exercice[1]) return(exo, cor) pyromaths/src/sixiemes/arrondi.py0000644000175000017500000000726611702101415017722 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from random import randint, shuffle from ..outils.Affichage import decimaux def valide_hasard(): """renvoie un nombre float non multiple de 10000""" nbre, unite = randint(1000,100000), randint(1,9) return float(nbre)*10+unite def ArrondirNombreDecimal(): """Crée et corrige un exercice d'arrondis avec les encadrements.""" hasard = [valide_hasard() for i in range(4)] precision = [u'au millième', u'au centième', u'au dixième', u'à l\'unité', u'à la dizaine', u'à la centaine', 'au millier', u'à la dizaine de milliers'] choix = [(i,j) for i in range(7) for j in range(3)] shuffle(choix) choix_precision = [choix[i][0] for i in range(4)] choix_supinf = [choix[i][1] for i in range(4)] ## choix_precision = [randint(0, 7), randint(0, 7), randint(0, 7), ## randint(0, 7)] ## choix_supinf = [randint(0, 2), randint(0, 2), randint(0, 2), randint(0, 2)] supinf = ['', u' par défaut', u' par excès'] #FIXME #Arrondir n'est pas synonyme de valeur approchée #Valeur approchée par excès  #Valeur approchée par défaut  #Arrondi = la « meilleure » valeur approchée #et ne paraît employé ici correctement nombres = [(hasard[0])/(10**(-choix_precision[0]+4)), (hasard[1])/(10**(-choix_precision[1]+4)), (hasard[2])/(10**(-choix_precision[2]+4)), (hasard[3])/(10**(-choix_precision[3]+4))] exo = ["\\exercice", '\\begin{enumerate}'] cor = ["\\exercice*", '\\begin{enumerate}'] for k in range(4): exo.append( "\\item Arrondir " + decimaux(nombres[k]) + " " + precision[choix_precision[k]] + supinf[choix_supinf[k]] + '.' ) arrondi = round(nombres[k], -choix_precision[k]+3) if (arrondi > nombres[k]): defaut = arrondi - 10**(choix_precision[k]-3) exc = arrondi if (arrondi <= nombres[k]): defaut = arrondi exc = arrondi + 10**(choix_precision[k]-3) if (choix_supinf[k] == 0): solution = arrondi elif (choix_supinf[k] == 1): solution = defaut elif (choix_supinf[k] == 2): solution = exc cor.append( '\\item L\'encadrement de ' + decimaux(nombres[k]) + ' ' + precision[choix_precision[k]] + ' est :\\par' ) cor.append( decimaux(defaut) + ' < ' + decimaux(nombres[k]) + ' < ' + decimaux(exc) + '\\par' ) cor.append( u'On en déduit que son arrondi ' + precision[choix_precision[k]] + ' ' + supinf[choix_supinf[k]] + ' est : ' + decimaux(solution) + '.') exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return (exo, cor) pyromaths/src/sixiemes/._operations.py0000644000175000017500000000031511702101415020650 0ustar didrocksdidrocksMac OS X  2ATTRGޑ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/._aires.py0000644000175000017500000000031511702101415017570 0ustar didrocksdidrocksMac OS X  2ATTRGފ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/.___init__.py0000644000175000017500000000031511702101415020224 0ustar didrocksdidrocksMac OS X  2ATTRGމ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/fractions.py0000644000175000017500000003505111702101415020245 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random import math #=============================================================================== # Fractions partage #=============================================================================== def dimensions_rectangle(): taille_max = 8 while True: (l, h) = (random.randrange(4, taille_max), random.randrange(4, taille_max)) div_t = diviseurs(l * h) if len(div_t) > 3: break if l < h: (l, h) = (h, l) return (l, h) def numerateur_denominateur(l, h, cas): """ @param l: largeur @param h: longueur @param cas: - nid: numerateur < denominateur - un: numerateur = denominateur - nsd: numerateur > denominateur @type cas: string """ ldiv = diviseurs(l * h) if cas == "un": d = random.randrange(3, l * h) else: while True: d = ldiv[random.randrange(len(ldiv) - 1)] if d > 2: break if cas == "un": n = d elif cas == "nid": n = random.randrange(1, d) else: n = random.randrange(d + 1, d * 2) return (n, d) def trace_rectangle(exo, cor, l, h, cas): exo.append("\\psgrid[gridcolor=Olive,subgriddiv=0,gridlabels=0pt]") cor.append("\\psgrid[gridcolor=Olive,subgriddiv=0,gridlabels=0pt]") exo.append("\\psframe[linewidth=1.5\\pslinewidth,linecolor=Maroon](0,0)(%s,%s)"% (l, h)) cor.append("\\psframe[linewidth=1.5\\pslinewidth,linecolor=Maroon](0,0)(%s,%s)"% (l, h)) if cas == "nsd": cor.append("\\psframe[linewidth=1.5\\pslinewidth,linecolor=Maroon](%s,0)(%s,%s)" % (l + 1, 2 * l + 1, h)) def fractions_partage_corrige(l, h, n, d): div_l = diviseurs(l) div_h = diviseurs(h) div_d = diviseurs(d) (lc, hc) = (l, h) if n == d: (lc, hc) = (l, h) elif div_l.count(d): lc = l // d elif div_h.count(d): hc = h // d else: for i in range(len(div_d) - 1): if div_l.count(div_d[i + 1]) and div_h.count(d // div_d[i + 1]): (lc, hc) = (l // div_d[i + 1], (h * div_d[i + 1]) // d) break return (lc, hc) def trace_partage(cor, l, h, lc, hc, cas): if lc < l: cor.append("\\multips(%s,0)(%s,0){%s}{\\psline[linecolor=Maroon](0,0)(0,%s)}" % (lc, lc, l // lc - 1, h)) if cas == "nsd": cor.append("\\rput(%s,0){\\multips(%s,0)(%s,0){%s}{\\psline[linecolor=Maroon](0,0)(0,%s)}}" % (l + 1, lc, lc, l // lc - 1, h)) if hc < h: cor.append("\\multips(0,%s)(0,%s){%s}{\\psline[linecolor=Maroon](0,0)(%s,0)}" % (hc, hc, h // hc - 1, l)) if cas == "nsd": cor.append("\\rput(%s,0){\\multips(0,%s)(0,%s){%s}{\\psline[linecolor=Maroon](0,0)(%s,0)}}" % (l + 1, hc, hc, h // hc - 1, l)) def coloriage(cor, n, d, l, h, lc, hc): if n == d: cor.append("\\psframe[fillstyle=solid](0,0)(%s,%s)" % (l, h)) else: (x, y, nfig) = (0, 0, 0) for i in range(n): if nfig: cor.append("\\rput(%s,0){\\psframe[fillstyle=solid](%s,%s)(%s,%s)}" % (nfig, x, y, x + lc, y + hc)) else: cor.append("\\psframe[fillstyle=solid](%s,%s)(%s,%s)" % (x, y, x + lc, y + hc)) if x + lc < l: x = x + lc elif y + hc < h: (x, y) = (0, y + hc) else: (x, y, nfig) = (0, 0, l + 1) def diviseurs(n): l = [] for i in range(1, int(math.sqrt(n)) + 1): if not n % i: l.append(i) if i != n // i: l.append(n // i) l.sort() return l def FractionPartage(): exo = ["\\exercice", '\\begin{multicols}{2}', '\\begin{enumerate}'] cor = ["\\exercice*", '\\begin{multicols}{2}', '\\begin{enumerate}'] lcas = ["nid", "un", "nsd", "nid", "nsd"] for i in range(4): cas = lcas.pop(random.randrange(len(lcas))) if cas == "nsd": while True: (l, h) = dimensions_rectangle() if l < 8: break else: (l, h) = dimensions_rectangle() (n, d) = numerateur_denominateur(l, h, cas) (lc, hc) = fractions_partage_corrige(l, h, n, d) exo.append("\\item Colorer $\\frac{%s}{%s}$ de ce rectangle.\\par" % (n, d)) cor.append("\\item Colorer $\\frac{%s}{%s}$ de ce rectangle.\\par" % (n, d)) exo.append("\\psset{unit=4mm}") cor.append("\\psset{unit=4mm}") exo.append("\\begin{pspicture}(16,%s)" % h) cor.append("\\begin{pspicture}(16,%s)" % h) (lc, hc) = fractions_partage_corrige(l, h, n, d) coloriage(cor, n, d, l, h, lc, hc) trace_rectangle(exo, cor, l, h, cas) trace_partage(cor, l, h, lc, hc, cas) exo.append("\\end{pspicture}") cor.append("\\end{pspicture}") if i == 1: exo.append("\\columnbreak") cor.append("\\columnbreak") exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) #=============================================================================== # Fractions et abscisses #=============================================================================== def valeurs_abscisses(): origine = random.randrange(3, 11) nb_divisions = ( 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, ) div = nb_divisions[random.randrange(len(nb_divisions))] nb_subd = diviseurs(div) subd = nb_subd[random.randrange(len(nb_subd) - 2) + 1] while subd < 3: subd = nb_subd[random.randrange(len(nb_subd) - 2) + 1] nb_grad = 58 #nb de graduations sur la demi-droite graduée lpts = [0 for i in range(7)] #liste des places des points à trouver/placer sur la 1/2 droite graduée lpts[4] = random.randrange(1, nb_grad // div + 1) * div for i in range(2): a = random.randrange(1, nb_grad) while lpts.count(a): a = random.randrange(1, nb_grad) lpts[i] = a for i in range(2): a = random.randrange(1, (nb_grad * subd) // div) while lpts.count((a * div) // subd): a = random.randrange(1, (nb_grad * subd) // div) lpts[i + 2] = (a * div) // subd for i in range(2): a = random.randrange(1, (nb_grad * subd) // div) while lpts.count((a * div) // subd): a = random.randrange(1, (nb_grad * subd) // div) lpts[i + 5] = (a * div) // subd #npts=noms_pts(7) npts = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] lnum = list(range(7)) #liste des numérateurs lnum[0] = origine * div + lpts[0] lnum[1] = origine * div + lpts[1] lnum[2] = origine * subd + (lpts[2] * subd) // div lnum[3] = origine * subd + (lpts[3] * subd) // div lnum[4] = random.randrange(3, div) while diviseurs(div).count(lnum[4]): lnum[4] = random.randrange(3, div) lnum[5] = origine * div + lpts[5] lnum[6] = origine * div + lpts[6] return (origine, div, subd, lpts, npts, lnum) def noms_pts(nb): # renvoie nb noms de points (listenb, listepts) = ([], []) for i in range(26): listenb.append(i + 65) for i in range(nb): listepts.append(chr(listenb.pop(random.randrange(26 - i)))) listepts.sort() return listepts def unites_fractions(exo, cor, origine, div, subd): postf = u'ièmes' lch = [ 'cinqu', 'six', 'sept', 'huit', 'neuv', 'dix', 'onz', 'douz', 'treiz', 'quatorz', 'quinz', 'seiz', 'dix-sept', 'dix-huit', 'dix-neuv', 'vingt', ] lfr = dict([(i + 5, lch[i] + postf) for i in range(len(lch))]) lfr[2] = 'demis' lfr[3] = 'tiers' lfr[4] = 'quarts' exo.append(u'\\item 1 unité = \\ldots %s' % lfr[div]) exo.append(u'\\item 1 unité = \\ldots~%s' % lfr[subd]) exo.append(u'\\item %s unités = \\ldots~%s' % (origine, lfr[div])) exo.append(u'\\item %s unités = \\ldots~%s' % (origine, lfr[subd])) cor.append(u'\\item 1 unité = %s %s' % (div, lfr[div])) cor.append(u'\\item 1 unité = %s %s' % (subd, lfr[subd])) cor.append(u'\\item %s unités = %s %s' % (origine, origine * div, lfr[div])) cor.append(u'\\item %s unités = %s %s' % (origine, origine * subd, lfr[subd])) def trace_demi_droite(exo, cor, origine, div, subd, lpts, npts, lnum): exo.append("\\psline[arrowscale=2,linecolor=Maroon]{->}(0,0)(18,0)") exo.append("\\rput(2mm,0){%") exo.append("\\multips(0,0)(3 mm,0){58}{\\psline[linecolor=Maroon](0,-.1)(0,.1)}") exo.append("\\multips(0,0)(%s mm,0){%s}{\\psline[linecolor=Maroon](0,-.2)(0,.2)}" % (div * 3, 58 // div + 1)) cor.append("\\psline[arrowscale=2,linecolor=Maroon]{->}(0,0)(18,0)") cor.append("\\rput(2mm,0){%") cor.append("\\multips(0,0)(3 mm,0){58}{\\psline[linecolor=Maroon](0,-.1)(0,.1)}") cor.append("\\multips(0,0)(%s mm,0){%s}{\\psline[linecolor=Maroon](0,-.2)(0,.2)}" % (div * 3, 58 // div + 1)) for i in range(58 // div + 1): exo.append("\\rput[t](%s mm,-3mm){\\centering %s}" % ((i * div) * 3, origine + i)) cor.append("\\rput[t](%s mm,-3mm){\\centering %s}" % ((i * div) * 3, origine + i)) for i in range(2): exo.append("\\rput[t](%s mm,4mm){\\centering $%s$}" % (lpts[i + 5] * 3 + .1, npts[i + 5])) for i in range(7): cor.append("\\rput[t](%s mm,4mm){\\centering $%s$}" % (lpts[i] * 3 + .1, npts[i])) exo.append("}") cor.append("}") def ecrit_abscisses(exo, cor, origine, div, subd, lpts, lnum): exo.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[0], div)) exo.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[1], div)) exo.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[2], subd)) exo.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[3], subd)) exo.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (origine * lnum[4] + (lpts[4] // div) * lnum[4], lnum[4])) cor.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[0], div)) cor.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[1], div)) cor.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[2], subd)) cor.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[3], subd)) cor.append("\\item $\\left(\\cfrac{%s}{%s}\\right)$" % (origine * lnum[4] + (lpts[4] // div) * lnum[4], lnum[4])) def trouve_abscisses(exo, cor, div, subd, lnum): exo.append("\\item $F~\\left(\\cfrac{\\ldots}{%s}\\right)$" % div) exo.append("\\item $F~\\left(\\cfrac{\\ldots}{%s}\\right)$" % subd) exo.append("\\item $G~\\left(\\cfrac{\\ldots}{%s}\\right)$" % div) exo.append("\\item $G~\\left(\\cfrac{\\ldots}{%s}\\right)$" % subd) cor.append("\\item $F~\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[5], div)) cor.append("\\item $F~\\left(\\cfrac{%s}{%s}\\right)$" % ((lnum[5] * subd) // div, subd)) cor.append("\\item $G~\\left(\\cfrac{%s}{%s}\\right)$" % (lnum[6], div)) cor.append("\\item $G~\\left(\\cfrac{%s}{%s}\\right)$" % ((lnum[6] * subd) // div, subd)) def QuestionsAbscisses(): exo = ["\\exercice"] cor = ["\\exercice*"] (origine, div, subd, lpts, npts, lnum) = valeurs_abscisses() exo.append("\\begin{enumerate}") exo.append(u"\\item Compléter :") exo.append("\\begin{multicols}{2}") exo.append("\\begin{enumerate}") cor.append("\\begin{enumerate}") cor.append(u"\\item Compléter :") cor.append("\\begin{multicols}{2}") cor.append("\\begin{enumerate}") unites_fractions(exo, cor, origine, div, subd) exo.append("\\end{enumerate}") exo.append("\\end{multicols}") exo.append(u"\\item Sur la demi-droite ci-dessous, placer les points d'abscisse donnée :") exo.append("\\begin{multicols}{5}") exo.append("\\begin{enumerate}") exo.append("\\renewcommand{\\theenumii}{\\Alph{enumii}}") exo.append("\\renewcommand{\\labelenumii}{$\\theenumii$}") cor.append("\\end{enumerate}") cor.append("\\end{multicols}") cor.append(u"\\item Sur la demi-droite ci-dessous, placer les points d'abscisse donnée :") cor.append("\\begin{multicols}{5}") cor.append("\\begin{enumerate}") cor.append("\\renewcommand{\\theenumii}{\\Alph{enumii}}") cor.append("\\renewcommand{\\labelenumii}{$\\theenumii$}") ecrit_abscisses(exo, cor, origine, div, subd, lpts, lnum) exo.append("\\end{enumerate}") exo.append("\\end{multicols}") exo.append(u"\\item Compléter les abscisses des points suivants :") exo.append("\\begin{multicols}{4}") exo.append("\\begin{enumerate}") cor.append("\\end{enumerate}") cor.append("\\end{multicols}") cor.append(u"\\item Compléter les abscisses des points suivants :") cor.append("\\begin{multicols}{4}") cor.append("\\begin{enumerate}") trouve_abscisses(exo, cor, div, subd, lnum) exo.append("\\end{enumerate}") exo.append("\\end{multicols}") exo.append("\\end{enumerate}") exo.append("\\begin{pspicture}(0,-.5)(18,.5)") cor.append("\\end{enumerate}") cor.append("\\end{multicols}") cor.append("\\end{enumerate}") cor.append("\\begin{pspicture}(0,-.5)(18,.5)") trace_demi_droite(exo, cor, origine, div, subd, lpts, npts, lnum) exo.append("\\end{pspicture}") cor.append("\\end{pspicture}") return (exo, cor) pyromaths/src/sixiemes/__init__.py0000644000175000017500000000171511702101415020014 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/sixiemes/._sixiemes.py0000644000175000017500000000031511702101415020313 0ustar didrocksdidrocksMac OS X  2ATTRGޓ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/._angles.py0000644000175000017500000000031511702101415017736 0ustar didrocksdidrocksMac OS X  2ATTRGދ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/._quotients.py0000644000175000017500000000031511702101415020520 0ustar didrocksdidrocksMac OS X  2ATTRGޒ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/operations.py0000644000175000017500000004323611702101415020444 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import math import random import string from ..outils import Arithmetique, Affichage #=============================================================================== # Poser des opérations #=============================================================================== def valeurs(): nba = Arithmetique.valeur_alea(111, 99999) while 1: nbb = Arithmetique.valeur_alea(111, 99999) if nbb - (nbb // 10) * 10: break puisb = Arithmetique.valeur_alea(-2, 0) nbb = nbb * 10 ** puisb deca = [str(nba)[i] for i in range(len(str(nba)))] decb = [str(nbb)[i] for i in range(len(str(nbb)))] if random.randrange(2): (nba, deca, nbb, decb) = (nbb, decb, nba, deca) if deca.count('.'): posa = deca.index('.') else: posa = len(deca) if decb.count('.'): posb = decb.index('.') else: posb = len(decb) lavtvirg = max(posa, posb) laprvirg = max(len(deca) - posa, len(decb) - posb) return (nba, nbb, deca, decb, lavtvirg, laprvirg) def valeurs_prod(): while 1: nba = Arithmetique.valeur_alea(101, 9999) if nba - (nba // 10) * 10: break puisa = Arithmetique.valeur_alea(-3, -1) while 1: nbb = Arithmetique.valeur_alea(101, 999) if nbb - (nbb // 10) * 10: break puisb = Arithmetique.valeur_alea(-3, -1) return (nba, nbb, puisa, puisb) def lignes(ligne, deca, lavtvirg, laprvirg): if deca.count('.'): posa = deca.index('.') else: posa = len(deca) if posa < lavtvirg: for i in range(lavtvirg - posa): ligne.append('') for i in range(len(deca)): if deca[i] == '.': ligne.append(',') else: ligne.append(str(deca[i])) for i in range(laprvirg - (len(deca) - posa)): if ligne.count(','): ligne.append('0') else: ligne.append(',') return ligne def mon_int(t): # retourne un entier texte sous la forme d'un nombre, zéro sinon if t == '': t = 0 elif ('1234567890').count(t): t = int(t) else: t = 0 return t def retenues_somme(ligne1, ligne2): lg = len(ligne1) ligne0 = ['' for i in range(lg)] for i in range(lg - 1): #on déplace la retenue pour qu'elle ne soit pas au-dessus de la virgule if ligne1[(lg - i) - 1] == ',' and ligne0[(lg - i) - 1] == '1': ligne0[(lg - i) - 2] = '1' elif mon_int(ligne1[(lg - i) - 1]) + mon_int(ligne2[(lg - i) - 1]) + \ mon_int(ligne0[(lg - i) - 1]) > 9: ligne0[(lg - i) - 2] = '1' return ligne0 def retenues_diff(ligne1, ligne2): lg = len(ligne1) ret = 0 for i in range(lg - 1): if not (ligne1[(lg - i) - 1] == ',' and ret): if mon_int(ligne1[(lg - i) - 1]) < mon_int(ligne2[(lg - i) - 1]) + ret: ligne1[(lg - i) - 1] = '$_1$%s' % ligne1[(lg - i) - 1] tmpret = 1 else: tmpret = 0 if ret: ligne2[(lg - i) - 1] = '%s$_1$' % ligne2[(lg - i) - 1] ret = tmpret return (ligne1, ligne2) def tex_somme(exo, cor): (ligne1, ligne2) = ([''], ['+']) (nba, nbb, deca, decb, lavtvirg, laprvirg) = valeurs() total = nba + nbb dectotal = [str(total)[i] for i in range(len(str(total)))] if dectotal.index('.') <= lavtvirg: ligne3 = [''] else: ligne3 = [] ligne1 = lignes(ligne1, deca, lavtvirg, laprvirg) ligne2 = lignes(ligne2, decb, lavtvirg, laprvirg) ligne3 = lignes(ligne3, dectotal, lavtvirg, laprvirg) ligne0 = retenues_somme(ligne1, ligne2) if ligne0[0] == '1': ligne0[0] = '\\tiny 1' exo.append('\\item La somme des termes %s et %s.\\par' % (Affichage.decimaux(nba), Affichage.decimaux(nbb))) cor.append('\\item La somme des termes %s et %s.\\par' % (Affichage.decimaux(nba), Affichage.decimaux(nbb))) cor.append('\\begin{tabular}[t]{*{%s}{c}}' % (lavtvirg + laprvirg + 1)) cor.append('%s \\\\' % ' & \\tiny '.join(ligne0)) cor.append('%s \\\\' % ' & '.join(ligne1)) cor.append('%s \\\\\n\\hline' % ' & '.join(ligne2)) cor.append('%s \\\\' % ' & '.join(ligne3)) cor.append('\\end{tabular}\\par') formule = '%s+%s = %s' % (Affichage.decimaux(nba, 1), Affichage.decimaux(nbb, 1), Affichage.decimaux(nba + nbb, 1)) cor.append((u'\\[ \\boxed{%s} \\] ').expandtabs(2 * 3) % (formule)) def tex_difference(exo, cor): (ligne1, ligne2) = ([''], ['-']) (nba, nbb, deca, decb, lavtvirg, laprvirg) = valeurs() if nba < nbb: (nba, nbb, deca, decb) = (nbb, nba, decb, deca) total = nba - nbb dectotal = [str(total)[i] for i in range(len(str(total)))] if dectotal.index('.') <= lavtvirg: ligne3 = [''] else: ligne3 = [] ligne1 = lignes(ligne1, deca, lavtvirg, laprvirg) ligne2 = lignes(ligne2, decb, lavtvirg, laprvirg) ligne3 = lignes(ligne3, dectotal, lavtvirg, laprvirg) (ligne1, ligne2) = retenues_diff(ligne1, ligne2) exo.append(u"\\item La différence des termes %s et %s.\\par" % (Affichage.decimaux(nba), Affichage.decimaux(nbb))) cor.append(u"\\item La différence des termes %s et %s.\\par" % (Affichage.decimaux(nba), Affichage.decimaux(nbb))) cor.append('\\begin{tabular}[t]{*{%s}{c}}' % (lavtvirg + laprvirg + 1)) cor.append('%s \\\\' % ' & '.join(ligne1)) cor.append('%s \\\\\n\\hline' % ' & '.join(ligne2)) cor.append('%s \\\\' % ' & '.join(ligne3)) cor.append('\\end{tabular}\\par') formule = '%s-%s = %s' % (Affichage.decimaux(nba, 1), Affichage.decimaux(nbb, 1), Affichage.decimaux(nba - nbb, 1)) cor.append((u'\\[ \\boxed{%s} \\] ').expandtabs(2 * 3) % (formule)) def pose_mult(nba, nbb): (ligne, total) = ([], 0) for i in range(int(math.log10(nbb)) + 1): sstotal = ((nbb - (nbb // 10) * 10) * nba) * 10 ** i total = total + sstotal ligne.append(sstotal) nbb = nbb // 10 return (ligne, total) def ligneprod(ligne, dec, lg): ligne.extend(['' for i in range((lg - len(dec)) - len(ligne))]) ligne.extend(dec) return ligne def tex_produit(exo, cor): (nba, nbb, puisa, puisb) = valeurs_prod() deca = [','.join(str(nba * 10 ** puisa).rsplit('.'))[i] \ for i in range(len(str(nba * 10 ** puisa)))] decb = [','.join(str(nbb * 10 ** puisb).rsplit('.'))[i] \ for i in range(len(str(nbb * 10 ** puisb)))] (dec3, total) = pose_mult(nba, nbb) (dec3bis, total) = pose_mult(nbb, nba) total = ((nba * 10 ** puisa) * nbb) * 10 ** puisb dec4 = [str(total)[i] for i in range(len(str(total)))] if dec4.count('.'): i = dec4.index('.') if (len(dec4) - i) - 1 < -(puisa + puisb): for j in range(-(puisa + puisb) - len(dec4) + i + 1): dec4.append('0') #ajoute les 0 inutiles au produit dec4.pop(i) # supprime le point décimal dec4[i - 1] = '%s\\Huge ,' % dec4[i - 1] # et ajoute une Huge virgule au chiffre des unités lg = max(len(dec4), max(len(deca), len(decb))) # nombre de colonnes dans le tableau exo.append('\\item Le produit des facteurs %s et %s.\\par' % (Affichage.decimaux(nba * 10 ** puisa), Affichage.decimaux(nbb * 10 ** puisb))) cor.append('\\item Le produit des facteurs %s et %s.\\par' % (Affichage.decimaux(nba * 10 ** puisa), Affichage.decimaux(nbb * 10 ** puisb))) cor.append('\\begin{enumerate}') cor.append(u'\\item Première méthode :\\par') cor.append('\\begin{tabular}[t]{*{%s}{c}}' % lg) cor.append('%s \\\\' % ' & '.join(ligneprod([], deca,lg))) cor.append('%s \\\\\n\\hline' % ' & '.join(ligneprod(['$\\times$'], decb, lg))) for i in range(len(dec3)): dec = [str(dec3[i])[j] for j in range(len(str(dec3[i])))] cor.append('%s \\\\' % ' & '.join(ligneprod([], dec, lg))) cor.append('\\hline \\\\') cor.append('%s \\\\' % ' & '.join(ligneprod([], dec4, lg))) cor.append('\\end{tabular}') cor.append(u'\\item Seconde méthode :\\par') cor.append('\\begin{tabular}[t]{*{%s}{c}}' % len(dec4)) cor.append('%s \\\\' % ' & '.join(ligneprod([], decb, lg))) cor.append('%s \\\\\n\\hline' % ' & '.join(ligneprod(['$\\times$'], deca, lg))) for i in range(len(dec3bis)): dec = [str(dec3bis[i])[j] for j in range(len(str(dec3bis[i])))] cor.append('%s \\\\' % ' & '.join(ligneprod([], dec, lg))) cor.append('\\hline \\\\') cor.append('%s \\\\' % ' & '.join(ligneprod([], dec4, lg))) cor.append('\\end{tabular}') cor.append('\\end{enumerate}') #outils.Arithmetique.ecrit_tex(f1, '%s\\times%s = %s' % (Affichage.decimaux(nba * #10 ** puisa, 1), Affichage.decimaux(nbb * 10 ** #puisb, 1), Affichage.decimaux((nba * nbb) * 10 ** (puisa + #puisb), 1)), cadre=1, thenocalcul='', tabs=3) #### Remplacement de la fonction Arithmetique.ecrit_tex : formule = '%s\\times%s = %s' % (Affichage.decimaux(nba * 10 ** puisa, 1), Affichage.decimaux(nbb * 10 ** puisb, 1), Affichage.decimaux((nba * nbb) * 10 ** (puisa + puisb), 1)) cor.append((u'\\[ \\boxed{%s} \\] ').expandtabs(2 * 3) % (formule)) def Operations(): nb_exos = 3 tex_exos = (tex_somme, tex_difference, tex_produit) ordre_exos = [i for i in range(nb_exos)] exo = ["\\exercice", u'Poser et effectuer les opérations suivantes.', '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", u'Poser et effectuer les opérations suivantes.', '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] for i in range(nb_exos): a = random.randrange(nb_exos - i) j = ordre_exos.pop(a) tex_exos[j](exo, cor) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) #=============================================================================== # Calcul mental #=============================================================================== def tex_calcul_mental(exo, cor): modules = (plus, moins, plus, div) calculs = [i for i in range(20)] for i in range(20): j = random.randrange(0, len(calculs)) (a, b) = modules[calculs[j] // 5](10) if calculs[j] // 5 == 0: choix_trou(a, b, a + b, '+', exo, cor) if calculs[j] // 5 == 1: choix_trou(a, b, a - b, '-', exo, cor) if calculs[j] // 5 == 2: choix_trou(a, b, a * b, '\\times', exo, cor) if calculs[j] // 5 == 3: choix_trou(a, b, a // b, '\\div', exo, cor) calculs.pop(j) def choix_trou(nb1, nb2, tot, operateur, exo, cor): nbaleatoire = random.randrange(4) if nbaleatoire > 1: exo.append('\\item $%s %s %s = \\ldots\\ldots$' % (nb1, operateur, nb2)) cor.append('\\item $%s %s %s = \\mathbf{%s}$' % (nb1, operateur, nb2, tot)) elif nbaleatoire > 0: exo.append('\\item $%s %s \\ldots\\ldots = %s$' % (nb1, operateur, tot)) cor.append('\\item $%s %s \\mathbf{%s} = %s$' % (nb1, operateur, nb2, tot)) else: exo.append('\\item $\\ldots\\ldots %s %s = %s$' % (operateur, nb2, tot)) cor.append('\\item $\\mathbf{%s} %s %s = %s$' % (nb1, operateur, nb2, tot)) def plus(valeurmax): (a, b) = (Arithmetique.valeur_alea(1, valeurmax), Arithmetique.valeur_alea(1, valeurmax)) return (a, b) def moins(valeurmax): (a, b) = (Arithmetique.valeur_alea(1, valeurmax), Arithmetique.valeur_alea(1, valeurmax)) return (a + b, a) def div(valeurmax): (a, b) = (Arithmetique.valeur_alea(1, valeurmax), Arithmetique.valeur_alea(1, valeurmax)) return (a * b, a) def CalculMental(): exo = ["\\exercice", 'Effectuer sans calculatrice :', '\\begin{multicols}{4}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", 'Effectuer sans calculatrice :', '\\begin{multicols}{4}\\noindent', '\\begin{enumerate}'] tex_calcul_mental(exo, cor) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) #=============================================================================== # PRODUITS ET QUOTIENTS PAR 10, 100, 1000 #=============================================================================== def tex_dix(exo, cor): nb = 4 # nb de calculs de chaque type l = valeurs10(nb) for i in range(len(l)): j = random.randrange(0, len(l)) tex_formule_dix(l.pop(j), exo, cor) def tex_formule_dix(l, exo, cor): if l[2] == '*': alea = random.randrange(0, 5) if alea > 1: exo.append('\\item $%s \\quad\\times\\quad %s \\quad = \\quad \\dotfill$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1))) cor.append('\\item $%s \\times %s = \\mathbf{%s}$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] * l[1], 1))) elif alea > 0: exo.append('\\item $%s \\quad\\times\\quad \\dotfill \\quad = \\quad %s$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[0] * l[1], 1))) cor.append('\\item $%s \\times \\mathbf{%s} = %s$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] * l[1], 1))) else: exo.append('\\item $\\dotfill \\quad\\times\\quad %s \\quad = \\quad %s$' % (Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] * l[1], 1))) cor.append('\\item $\\mathbf{%s} \\times %s = %s$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] * l[1], 1))) else: alea = random.randrange(0, 5) if alea > 1: exo.append('\\item $%s \\quad\\div\\quad %s \\quad = \\quad \\dotfill$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1))) cor.append('\\item $%s \\div %s = \\mathbf{%s}$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] / l[1], 1))) elif alea > 0: exo.append('\\item $%s \\quad\\div\\quad \\dotfill \\quad = \\quad %s$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[0] / l[1], 1))) cor.append('\\item $%s \\div \\mathbf{%s} = %s$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] / l[1], 1))) else: exo.append('\\item $\\dotfill \\quad\\div\\quad %s \\quad = \\quad %s$' % (Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] / l[1], 1))) cor.append('\\item $\\mathbf{%s} \\div %s = %s$' % (Affichage.decimaux(l[0], 1), Affichage.decimaux(l[1], 1), Affichage.decimaux(l[0] / l[1], 1))) def valeurs10(nb): # renvoie nb valeur de chaque type : *10, /10, *0.1 l = [] for i in range(nb): if random.randrange(0, 1): l.append((Arithmetique.valeur_alea(111, 999) * 10 ** random.randrange(-3, 0), 10 ** (i + 1), '*')) else: l.append((10 ** (i + 1), Arithmetique.valeur_alea(111, 999) * 10 ** random.randrange(-3, 0), '*')) for i in range(nb): l.append((Arithmetique.valeur_alea(111, 999) * 10 ** random.randrange(-3, 0), 10 ** (i + 1), '/')) for i in range(nb): if random.randrange(0, 1): l.append((Arithmetique.valeur_alea(111, 999) * 10 ** random.randrange(-3, 0), 10 ** (-i - 1), '*')) else: l.append((10 ** (-i - 1), Arithmetique.valeur_alea(111, 999) * 10 ** random.randrange(-3, 0), '*')) return l def ProduitPuissanceDix(): exo = ["\\exercice", u'Compléter sans calculatrice :', '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] cor = ["\\exercice*", u'Compléter sans calculatrice :', '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}'] tex_dix(exo, cor) exo.append('\\end{enumerate}') exo.append('\\end{multicols}') cor.append('\\end{enumerate}') cor.append('\\end{multicols}') return (exo, cor) pyromaths/src/sixiemes/symetrie.py0000644000175000017500000001036711702101415020121 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random from math import atan, cos, pi, sin, floor, ceil #=============================================================================== # Symétrique d'une figure par rapport à une droite avec quadrillage #=============================================================================== def valeurs_quad2(nb_pts): vals = [] for i in range(nb_pts): angle = random.randrange((i * 360) / nb_pts, ((i + 1) * 360) / nb_pts) vals.append(((random.randrange(1, 7) * .5) * cos((angle * pi) / 180), (random.randrange(1, 7) * .5) * sin((angle * pi) / 180))) return vals def valeurs_quad(nb_pts): vals = [] for i in range(nb_pts): (alpha, beta) = ((i * 360) / nb_pts, ((i + 1) * 360) / nb_pts) (x, y) = (0, 0) while x == 0 or angle < alpha or angle > beta: (x, y) = (random.randrange(-6, 7) * .5, random.randrange(-6, 7) * .5) if x > 0: angle = int((atan((y * 1.0) / x) * 180) / pi + 360) % \ 360 if x < 0: angle = int((atan((y * 1.0) / x) * 180) / pi + 180) vals.append((x, y)) return vals def place_pts(vals, angle): txt = [" \\pstGeonode[PointSymbol=x,PointName=none]"] for i in range(len(vals)): txt.append("(%s,%s)" % vals[i]) txt.append("{%s}" % chr(i + 97)) txt.append("\n\\pstGeonode[PointSymbol=none,PointName=none](-4.5;%s){A}(4.5;%s){B}" % (angle, angle)) txt.append("\n\\psline[linecolor=Black, linewidth=1pt, nodesep=-4.5](A)(B)") txt.append("\n\\pspolygon[linecolor=Maroon, linewidth=1pt]") for i in range(len(vals)): txt.append("(%s)" % chr(i + 97)) return ("").join(txt) def SymetrieQuadrillage(): exo = ["\\exercice", u"Construire la symétrique de chacune des figures par rapport à la droite en", "utilisant le quadrillage :\\par", "\\psset{unit=.9cm}"] cor = ["\\exercice*", u"Construire la symétrique de chacune des figures par rapport à la droite en", "utilisant le quadrillage :\\par", "\\psset{unit=.9cm}"] nbpts = 5 langles = [0, 90, 45, 135] for j in range(3): angle = langles.pop(random.randrange(len(langles))) vals = valeurs_quad(nbpts) txt = place_pts(vals, angle) exo.append("\\begin{pspicture*}(-3,-3)(3,3)") exo.append("\\psgrid[subgriddiv=2,gridlabels=0pt]") exo.append(txt) cor.append("\\begin{pspicture*}(-3,-3)(3,3)") cor.append("\\psgrid[subgriddiv=2,gridlabels=0pt]") cor.append(txt) txt_cor = "\\pstOrtSym[PointSymbol=x,PointName=none]{A}{B}{" for i in range(len(vals)): if i > 0: txt_cor += "," txt_cor += "%s" % chr(i + 97) txt_cor += "}[" for i in range(len(vals)): if i > 0: txt_cor += "," txt_cor += "%s1" % chr(i + 97) txt_cor += "]\n \pspolygon[linecolor=Black, linestyle=dashed, linewidth=1pt]" for i in range(len(vals)): txt_cor += "(%s1)" % chr(i + 97) cor.append(txt_cor) exo.append("\\end{pspicture*}") cor.append("\\end{pspicture*}") if j < 2: exo.append("\\hfill") cor.append("\\hfill") return (exo, cor) pyromaths/src/sixiemes/._decimaux.py0000644000175000017500000000031511702101415020264 0ustar didrocksdidrocksMac OS X  2ATTRGލ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/quotients.py0000644000175000017500000000456611702101415020317 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random def valeurs_diviseurs(): diviseurs = [2, 3, 5, 9, 10] liste = [] for i in range(5): liste.append(diviseurs.pop(random.randrange(len(diviseurs))) * random.randrange(11, 100)) return liste def liste_diviseurs(l): diviseurs = (2, 3, 5, 9, 10) reponse = [] for i in range(len(l)): reponse.extend([[l[i]]]) for j in range(len(diviseurs)): if l[i] % diviseurs[j]: # n'est pas divisible reponse[i].append("$\\Square$") else: reponse[i].append("$\\CheckedBox$") return reponse def Divisible(): l = valeurs_diviseurs() reponse = liste_diviseurs(l) exo = ["\\exercice", u'Cocher les bonnes réponses :\\par'] cor = ["\\exercice*", u'Cocher les bonnes réponses :\\par'] exo.append("\\begin{tabular}{c@{ est divisible : \kern1cm}r@{ par 2\\kern1cm}r@{ par 3\\kern1cm}r@{ par 5\\kern1cm}r@{ par 9\\kern1cm}r@{ par 10}}") cor.append("\\begin{tabular}{c@{ est divisible : \kern1cm}r@{ par 2\\kern1cm}r@{ par 3\\kern1cm}r@{ par 5\\kern1cm}r@{ par 9\\kern1cm}r@{ par 10}}") for i in range(len(l)): exo.append("%s & $\\square$ & $\\square$ & $\\square$ & $\\square$ & $\\square$ \\\\" % l[i]) cor.append("%s & %s & %s & %s & %s & %s \\\\" % tuple(reponse[i])) exo.append("\\end{tabular}") cor.append("\\end{tabular}") return (exo, cor) pyromaths/src/sixiemes/._arrondi.py0000644000175000017500000000031511702101415020123 0ustar didrocksdidrocksMac OS X  2ATTRGތ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/._fractions.py0000644000175000017500000000031511702101415020455 0ustar didrocksdidrocksMac OS X  2ATTRGސ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/espace.py0000644000175000017500000002566111702101415017523 0ustar didrocksdidrocks # Pyromaths # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if notPopen, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import random #from ..outils.Affichage import decimaux def noms_sommets(nb): """Renvoie nb noms de sommets""" (listenb, listepts) = ([], []) for i in range(26): listenb.append(i + 65) for i in range(nb): listepts.append(str(chr(listenb.pop(random.randrange(26 - i))))) listepts.sort() return listepts def connect(pt,F1,F2): """renvoie les sommets connectes à pt""" if pt in F1: result=[F1[F1.index(pt)-1],F1[(F1.index(pt)+1)%len(F1)],F2[F1.index(pt)]] else: result=[F2[F2.index(pt)-1],F2[(F2.index(pt)+1)%len(F2)],F1[F2.index(pt)]] return result def reponse1(pt,F1,F2): """renvoie la réponse à la première question""" conn=connect(pt,F1,F2) ptc1=conn[random.randrange(0,len(conn))] conn.remove(ptc1) ptc2=conn[random.randrange(0,len(conn))] conn.remove(ptc2) ptc3=conn[0] F3=[F2[0],F1[0],F1[3],F2[3]] F4=[F2[0],F2[1],F1[1],F1[0]] F5=[F1[1],F2[1],F2[2],F1[2]] F6=[F1[2],F2[2],F2[3],F1[3]] F2b=F2[:] F2b.reverse() if (pt in F1) and (ptc1 in F1) and (ptc2 in F1): i=F1.index(pt) j=F2.index(ptc3) res=[pt,F1[(i+1)%4],F1[(i+2)%4],F1[(i+3)%4],ptc3,F2[(j+1)%4],F2[(j+2)%4],F2[(j+3)%4]] elif (pt in F2) and (ptc1 in F2) and (ptc2 in F2): i=F2b.index(pt) j=F1.index(ptc3) res=[pt,F2b[(i+1)%4],F2b[(i+2)%4],F2b[(i+3)%4],ptc3,F1[(j-1)%4],F1[(j-2)%4],F1[(j-3)%4]] elif (pt in F3) and (ptc1 in F3) and (ptc2 in F3): i=F3.index(pt) j=F5.index(ptc3) res=[pt,F3[(i+1)%4],F3[(i+2)%4],F3[(i+3)%4],ptc3,F5[(j-1)%4],F5[(j-2)%4],F5[(j-3)%4]] elif (pt in F4) and (ptc1 in F4) and (ptc2 in F4): i=F4.index(pt) j=F6.index(ptc3) res=[pt,F4[(i+1)%4],F4[(i+2)%4],F4[(i+3)%4],ptc3,F6[(j-1)%4],F6[(j-2)%4],F6[(j-3)%4]] elif (pt in F5) and (ptc1 in F5) and (ptc2 in F5): i=F5.index(pt) j=F3.index(ptc3) res=[pt,F5[(i+1)%4],F5[(i+2)%4],F5[(i+3)%4],ptc3,F3[(j-1)%4],F3[(j-2)%4],F3[(j-3)%4]] elif (pt in F6) and (ptc1 in F6) and (ptc2 in F6): i=F6.index(pt) j=F4.index(ptc3) res=[pt,F6[(i+1)%4],F6[(i+2)%4],F6[(i+3)%4],ptc3,F5[(j-1)%4],F5[(j-2)%4],F5[(j-3)%4]] return res def reponse2(pt1,ptc1,F1,F2): """renvoie la réponse à la deuxième question et le segment[p1ptc1]""" rep=[] connects=connect(pt1,F1,F2) for pt in connects: if pt<>ptc1: rep.append('['+pt1+pt+']') connects2=connect(ptc1,F1,F2) for pt in connects2: if pt<>pt1: rep.append('['+ptc1+pt+']') rep.append('['+pt1+ptc1+']') return tuple(rep) def reponse3(pt2,ptc2,F1,F2): """renvoie la réponse à la troisièmequestion et le segment[pt2ptc2]""" if (pt2 in F1) and (ptc2 in F1): copy=F1[:] i=F1.index(pt2) j=F1.index(ptc2) copy.remove(pt2) copy.remove(ptc2) k=F1.index(copy[0]) l=F1.index(copy[1]) rep=('['+F2[i]+F2[j]+']','['+F1[k]+F1[l]+']','['+F2[k]+F2[l]+']','['+pt2+ptc2+']') elif (pt2 in F2) and (ptc2 in F2): copy=F2[:] i=F2.index(pt2) j=F2.index(ptc2) copy.remove(pt2) copy.remove(ptc2) k=F2.index(copy[0]) l=F2.index(copy[1]) rep=('['+F1[i]+F1[j]+']','['+F1[k]+F1[l]+']','['+F2[k]+F2[l]+']','['+pt2+ptc2+']') else: if pt2 in F1: i=F1.index(pt2) else: i=F2.index(pt2) rep=('['+F1[(i+1)%len(F1)]+F2[(i+1)%len(F1)]+']','['+F1[(i+2)%len(F1)]+F2[(i+2)%len(F1)]+']','['+F1[(i+3)%len(F1)]+F2[(i+3)%len(F1)]+']','['+pt2+ptc2+']') return tuple(rep) def main(): """Face 1, Face 2""" noms_pts=(noms_sommets(8)) F1=noms_pts[0:4] F2=noms_pts[4:8] pt=noms_pts[random.randrange(0,len(noms_pts))] rp1=reponse1(pt,F1,F2) pt1=noms_pts[random.randrange(0,len(noms_pts))] conn1=connect(pt1,F1,F2) pt2= noms_pts[random.randrange(0,len(noms_pts))] conn2=connect(pt2,F1,F2) ptc1= conn1[random.randrange(0,len(conn1))] ptc2= conn2[random.randrange(0,len(conn2))] rp2=u"%s, %s, %s et %s sont les arêtes perpendiculaires à %s."%reponse2(pt1,ptc1,F1,F2) rp3=u"%s, %s et %s sont les arêtes parallèles à %s."%reponse3(pt2,ptc2,F1,F2) exo=["\\exercice", u"Les figures 1 et 2 représentent le même cube %s%s%s%s%s%s%s%s.\\\ "%tuple(noms_pts), "\\psset{xunit=1.0cm,yunit=1.0cm,dotstyle=*,dotsize=3pt 0,linewidth=0.8pt,arrowsize=3pt 2,arrowinset=0.25}", "\\begin{pspicture*}(-2,-0.38)(15,4.5)", "\\psframe[fillstyle=solid,fillcolor=darkgray,framearc=0.2](-1,3.5)(-0.5,4)", "\\rput[bl](-0.85,3.65){\\white{\\textbf{$1$}}}", "\\psline[linestyle=dashed,linecolor=Maroon,dash=4pt 4pt](3.5,1)(1.5,1)", "\\psline[linestyle=dashed,linecolor=Maroon,dash=4pt 4pt](1.5,1)(1.5,3)", "\\psline[linestyle=dashed,linecolor=Maroon,dash=4pt 4pt](1.5,1)(0.5,0)", "\\psframe[linecolor=Maroon](0.5,0)(2.5,2)", "\\psline[linecolor=Maroon](1.5,3)(3.5,3)", "\\psline[linecolor=Maroon](3.5,3)(3.5,1)", "\\psline[linecolor=Maroon](0.5,2)(1.5,3)", "\\psline[linecolor=Maroon](2.5,2)(3.5,3)", "\\psline[linecolor=Maroon](2.5,0)(3.5,1)", "\\rput[bl](0.22,2.08){%s}"%F1[0], "\\rput[bl](2.28,2.16){%s}"%F1[1], "\\rput[bl](2.6,-0.22){%s}"%F1[2], "\\rput[bl](0.15,-0.22){%s}"%F1[3], "\\rput[bl](1.4,3.08){%s}"%F2[0], "\\rput[bl](3.58,3.04){%s}"%F2[1], "\\rput[bl](3.58,1.04){%s}"%F2[2], "\\rput[bl](1.58,1.04){%s}"%F2[3], "\\psline[linecolor=Maroon](5.2,-04)(5.2,4)", "\\psframe[fillstyle=solid,fillcolor=darkgray,framearc=0.2](5.7,3.5)(6.2,4)", "\\rput[bl](5.85,3.65){\\white{\\textbf{$2$}}}", "\\psline[linecolor=Maroon](8.48,2.71)(7.18,2.42)", "\\psline[linecolor=Maroon](7.18,2.42)(7.18,0.46)", "\\psline[linestyle=dashed, linecolor=Maroon, dash=4pt 4pt](7.18,0.46)(8.48,0.75)", "\\psline[linestyle=dashed, linecolor=Maroon, dash=4pt 4pt](8.48,0.75)(8.48,2.71)", "\psline[linecolor=Maroon](10,2.46)(8.7,2.17)", "\\psline[linecolor=Maroon](8.7,2.17)(8.7,0.21)", "\\psline[linecolor=Maroon](8.7,0.21)(10,0.5)", "\\psline[linecolor=Maroon](10,0.5)(10,2.46)", "\\psline[linecolor=Maroon](10,2.46)(8.48,2.71)", "\\psline[linecolor=Maroon](7.18,2.42)(8.7,2.17)", "\\psline[linecolor=Maroon](8.7,0.21)(7.18,0.46)", "\\psline[linestyle=dashed,dash=4pt 4pt, linecolor=Maroon](10,0.5)(8.48,0.75)", "\\rput[bl](8.68,2.27){%s}"%rp1[0], "\\rput[bl](10.06,2.5){%s}"%rp1[1], "\\rput[bl](8.71,-0.1){%s}"%rp1[3], "\\end{pspicture*}", "\\begin{enumerate}", u"\\item Compléter les sommets manquants de la figure 2.", u"\\item Donner toutes les arêtes perpendiculaires à [%s%s]."%(pt1,ptc1), u"\\item Donner toutes les arêtes parallèles à [%s%s]."%(pt2,ptc2), "\\end{enumerate}"] cor=["\\exercice*", u"Les figures 1 et 2 représentent le même cube %s%s%s%s%s%s%s%s.\\\ "%tuple(noms_pts), "\\psset{xunit=1.0cm,yunit=1.0cm,dotstyle=*,dotsize=3pt 0,linewidth=0.8pt,arrowsize=3pt 2,arrowinset=0.25}", "\\begin{pspicture*}(-2,-0.38)(15,4.5)", "\\psframe[fillstyle=solid,fillcolor=darkgray,framearc=0.2](-1,3.5)(-0.5,4)", "\\rput[bl](-0.85,3.65){\\white{\\textbf{$1$}}}", "\\psline[linestyle=dashed,linecolor=Maroon,dash=4pt 4pt](3.5,1)(1.5,1)", "\\psline[linestyle=dashed,linecolor=Maroon,dash=4pt 4pt](1.5,1)(1.5,3)", "\\psline[linestyle=dashed,linecolor=Maroon,dash=4pt 4pt](1.5,1)(0.5,0)", "\\psframe[linecolor=Maroon](0.5,0)(2.5,2)", "\\psline[linecolor=Maroon](1.5,3)(3.5,3)", "\\psline[linecolor=Maroon](3.5,3)(3.5,1)", "\\psline[linecolor=Maroon](0.5,2)(1.5,3)", "\\psline[linecolor=Maroon](2.5,2)(3.5,3)", "\\psline[linecolor=Maroon](2.5,0)(3.5,1)", "\\rput[bl](0.22,2.08){%s}"%F1[0], "\\rput[bl](2.28,2.16){%s}"%F1[1], "\\rput[bl](2.6,-0.22){%s}"%F1[2], "\\rput[bl](0.15,-0.22){%s}"%F1[3], "\\rput[bl](1.4,3.08){%s}"%F2[0], "\\rput[bl](3.58,3.04){%s}"%F2[1], "\\rput[bl](3.58,1.04){%s}"%F2[2], "\\rput[bl](1.58,1.04){%s}"%F2[3], "\\psline[linecolor=Maroon](5.2,-04)(5.2,4)", "\\psframe[fillstyle=solid,fillcolor=darkgray,framearc=0.2](5.7,3.5)(6.2,4)", "\\rput[bl](5.85,3.65){\\white{\\textbf{$2$}}}", "\\psline[linecolor=Maroon](8.48,2.71)(7.18,2.42)", "\\psline[linecolor=Maroon](7.18,2.42)(7.18,0.46)", "\\psline[linestyle=dashed,dash=4pt 4pt, linecolor=Maroon](7.18,0.46)(8.48,0.75)", "\\psline[linestyle=dashed,dash=4pt 4pt, linecolor=Maroon](8.48,0.75)(8.48,2.71)", "\psline[linecolor=Maroon](10,2.46)(8.7,2.17)", "\\psline[linecolor=Maroon](8.7,2.17)(8.7,0.21)", "\\psline[linecolor=Maroon](8.7,0.21)(10,0.5)", "\\psline[linecolor=Maroon](10,0.5)(10,2.46)", "\\psline[linecolor=Maroon](10,2.46)(8.48,2.71)", "\\psline[linecolor=Maroon](7.18,2.42)(8.7,2.17)", "\\psline[linecolor=Maroon](8.7,0.21)(7.18,0.46)", "\\psline[linestyle=dashed,dash=4pt 4pt, linecolor=Maroon](10,0.5)(8.48,0.75)", "\\rput[bl](10.05,0.2){%s}"%rp1[2], "\\rput[bl](8.71,-0.1){%s}"%rp1[3], "\\rput[bl](8.1,0.79){%s}"%rp1[6], "\\rput[bl](6.8,0.2){%s}"%rp1[7], "\\rput[bl](10.06,2.5){%s}"%rp1[1], "\\rput[bl](8.68,2.27){%s}"%rp1[0], "\\rput[bl](7.08,2.54){%s}"%rp1[4], "\\rput[bl](8.5,2.83){%s}"%rp1[5], "\\end{pspicture*}", "\\begin{enumerate}", u"\\item Compléter les sommets manquants de la figure 2.", u"\\item Donner toutes les arêtes perpendiculaires à [%s%s].\\par "%(pt1,ptc1), rp2, u"\\item Donner toutes les arêtes parallèles à [%s%s]. \\par "%(pt2,ptc2), rp3, "\\end{enumerate}"] return (exo,cor) pyromaths/src/sixiemes/._droites.py0000644000175000017500000000031511702101415020136 0ustar didrocksdidrocksMac OS X  2ATTRGގ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/sixiemes.py0000644000175000017500000000400511702101415020076 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from . import angles, decimaux, droites, fractions, operations, quotients from . import symetrie, arrondi, aires, espace import random def write(f0, f1, exos): f0.write("\n") f1.write("\n") f0.writelines(x + "\n" for x in exos[0]) f1.writelines(x + "\n" for x in exos[1]) def main(exo, f0, f1): modules = ( operations.CalculMental, decimaux.EcrireNombreLettre, decimaux.PlaceVirgule, decimaux.EcritureFractionnaire, decimaux.Decomposition, decimaux.Conversions(1), decimaux.Conversions(2), decimaux.Conversions(3), operations.Operations, operations.ProduitPuissanceDix, decimaux.ClasserNombres, droites.Droites, droites.Perpendiculaires, droites.Proprietes, quotients.Divisible, fractions.FractionPartage, fractions.QuestionsAbscisses, aires.main, symetrie.SymetrieQuadrillage, angles.MesureAngles, espace.main, arrondi.ArrondirNombreDecimal ) write(f0, f1, modules[exo]()) pyromaths/src/sixiemes/droites.py0000644000175000017500000006234011702101415017727 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random import math def nodesep(ligne): """ Défini les valeurs nodesep : 0 pour une extrémité, -0.5 pour une continuité @param ligne: droite, demi-droite, segment @type ligne: string """ if ligne == 'une droite': retour = ['-6', '-6'] elif ligne == 'une demi-droite': retour = ['0', '-6'] else: retour = ['0', '0'] return retour def choix_points(n): """ choisit n points parmi A, B, C, ..., Z @param n: nombre de points à choisir @type n: integer """ points = [chr(i + 65) for i in range(26)] liste = [] for i in range(n): liste.append(points.pop(random.randrange(len(points)))) return liste def choix_ligne(n): """ Retourne n propositions parmi droite, segment et demi-droite @param n: nombre de propositions @type n: interger """ lignes = ['une droite', 'une demi-droite', 'un segment'] (liste_lignes, retour) = ([], []) for i in range((n - 1) // len(lignes) + 1): liste_lignes.extend(lignes) for i in range(n): retour.append(liste_lignes.pop(random.randrange(len(liste_lignes)))) return retour def symboles(ligne): """ Retourne les couples (), [] ou [) correspondant au type de ligne @param ligne: droite, demi-droite ou segment @type ligne: string """ if ligne == 'une droite': retour = ['(', ')'] elif ligne == 'une demi-droite': retour = ['[', ')'] else: retour = ['[', ']'] return retour def prepare_tuple(lpoints, ligne): """ Prepare deux tuples pour permettre l'affichage de la question et de la solution @param lpoints: les points de la figure @type lpoints: liste de lettres @param ligne: droite, demi-droite ou segment @type ligne: string """ (retour_exo, retour_sol) = ([], []) #choix des deux points permettant de tracer la ligne : templist = [i for i in range(len(lpoints))] deuxpoints = [] for i in range(2): deuxpoints.append(lpoints[templist.pop(random.randrange(len(templist)))]) #choix des symbole correspondant à la ligne : lsymboles = symboles(ligne) retour_sol.append(lsymboles[0]) retour_sol.extend(deuxpoints) retour_sol.append(lsymboles[1]) retour_sol.append(ligne) #choix des trous pour l'exercice : alea = random.randrange(3) if alea > 1: retour_exo = ['\\ldots', '\\ldots', '\\ldots', '\\ldots', '\\dotfill'] elif alea > 0: retour_exo = ['\\ldots'] retour_exo.extend(retour_sol[1:3]) retour_exo.extend(['\\ldots', retour_sol[4]]) else: retour_exo = retour_sol[:4] retour_exo.append('\\dotfill') return (tuple(retour_exo), tuple(retour_sol)) def tex_figure(liste, lpoints, points_coord, nodesep=0): """ Écrit dans un fichier tex la construction de 3 points et éventuellement une droite, une demi-droite ou un segment. @param liste: liste d'exos ou corrigés @type liste: liste @param lpoints: liste de 3 points @type lpoints: liste de 3 strings @param nodesep: liste des dépassements pour pstricks @type nodesep: liste de 2 strings """ liste.append('\\begin{pspicture*}(-0.5,0.2)(4.5,2.2)') liste.append('\\psset{PointSymbol=x}') liste.append('\\pstGeonode[PosAngle=90](0.5,%s){%s}(2,%s){%s}(3.5,%s){%s}' % points_coord) if nodesep: liste.append('\\pstLineAB[nodesepA=%s, nodesepB=%s]{%s}{%s}' % tuple(nodesep)) liste.append('\\end{pspicture*}\\tabularnewline') def coord_points(lpoints): """Définit les ordonnées de trois points nommés dont les noms sont dans lpoints""" ordonnees = [random.randrange(5, 16)/10.for i in range(3)] while abs(2*ordonnees[1]-ordonnees[0]-ordonnees[2])<.5: ordonnees = [random.randrange(5, 16)/10.for i in range(3)] random.shuffle(ordonnees) for i in range(3): ordonnees.insert(2*i+1, lpoints[i]) return tuple(ordonnees) def tex_ligne_tableau(exo, cor, ligne): """ Écrit une ligne de tableau dans un fichier tex @param exo: fichier d'exercices @type exo: file @param cor: fichier de corrections @type cor: file @param ligne: droite, demi-droite ou segment @type ligne: string """ lpoints = choix_points(3) (exer, solution) = prepare_tuple(lpoints, ligne) exo.append('$%s %s%s %s$ est %s &' % exer) cor.append('$%s %s%s %s$ est %s &' % solution) lnodesep = nodesep(ligne) lnodesep.extend(solution[1:3]) points_coord=coord_points(lpoints) if exer != ('\\ldots', '\\ldots', '\\ldots', '\\ldots', '\\dotfill'): tex_figure(exo, lpoints, points_coord) else: tex_figure(exo, lpoints, points_coord, lnodesep) tex_figure(cor, lpoints, points_coord, lnodesep) exo.append('\\hline') cor.append('\\hline') def Droites(): """ Écrit les 5 lignes du tableau @param exo: fichier d'exercices @type exo: file @param cor: fichier de corrections @type cor: file """ exo = ["\\exercice", u"Compléter les pointillés et les figures :\\par", '\\renewcommand{\\tabularxcolumn}[1]{m{#1}}', '\\begin{tabularx}{\\linewidth}{|X|>{\\centering}m{5cm}|}', '\\hline', u'\\textbf{phrase} & \\textbf{Figure} \\tabularnewline \\hline'] cor = ["\\exercice*", u"Compléter les pointillés et les figures :\\par", '\\renewcommand{\\tabularxcolumn}[1]{m{#1}}', '\\begin{tabularx}{\\linewidth}{|X|>{\\centering}m{5cm}|}', '\\hline', u'\\textbf{Phrase} & \\textbf{Figure} \\tabularnewline \\hline'] line = choix_ligne(5) for i in range(5): tex_ligne_tableau(exo, cor, line[i]) exo.append('\\end{tabularx}') cor.append('\\end{tabularx}') return (exo, cor) #------------------------------------------------------------------------------ # Parallèles et perpendiculaires #------------------------------------------------------------------------------ #perp à (ac) passant par b => val2=('a', 'c', 'a', 'c', 'b', 'b', 'b', 'a' #para à (ab) passant apr d => val2=('a', 'b', 'a', 'b', 'd', 'd') def fig_perp(points, coor, solution=0, per=[], par=[]): val_enonce = ( points[0], points[1], coor[0], coor[1], coor[2], coor[3], points[2], points[3], coor[4], coor[5], coor[6], coor[7],) pts = ('a', 'b', 'c', 'd') text = \ """ \\begin{pspicture*}(-4,-4)(4,4) \psset{PointSymbol=x} \pstGeonode[PointName={%s,%s}](%s;%s){a}(%s;%s){b} \pstGeonode[PointName={%s,%s}](%s; %s){c}(%s; %s){d}""" % \ val_enonce if solution: val_soluce = ( pts[per[0]], pts[per[1]], pts[per[0]], pts[per[1]], pts[per[2]], pts[per[2]], pts[per[2]], pts[per[0]], pts[par[0]], pts[par[1]], pts[par[0]], pts[par[1]], pts[par[2]], pts[par[2]]) text = text + \ """ \pstLineAB[nodesep=-4, linecolor=DarkBlue]{%s}{%s} \pstProjection[PointName=none]{%s}{%s}{%s}[e]\pstLineAB[nodesep=-7, linecolor=DarkBlue]{%s}{e} \pstRightAngle[, linecolor=DarkBlue]{%s}{e}{%s} \pstLineAB[nodesep=-4, linecolor=DarkRed]{%s}{%s} \pstTranslation[PointName=none,PointSymbol=none]{%s}{%s}{%s}[f] \pstLineAB[nodesep=-7, linecolor=DarkRed]{%s}{f} \end{pspicture*}""" % \ val_soluce return text def noms_sommets(nb): # renvoie nb noms de sommets (listenb, listepts) = ([], []) for i in range(26): listenb.append(i + 65) for i in range(nb): listepts.append(chr(listenb.pop(random.randrange(26 - i)))) listepts.sort() return tuple(listepts) def cree_coordonnees(long=3): from math import floor alpha = random.randrange(180) k0 = random.randrange(50, 100) / 100.0 a0 = alpha + random.randrange(30, 120) k1 = random.randrange(50, 100) / 100.0 a1 = alpha + random.randrange(210, 300) return (long, alpha, long, alpha + 180, floor((k0 * 10) * long) / 10.0, a0, floor((k1 * 10) * long) / 10.0, a1) def enonce_perp(exo, cor): coor = cree_coordonnees(3) noms = noms_sommets(4) par, per = [], [] lval = [0, 1, 2, 3] for i in range(3): par.append(lval.pop(random.randrange(len(lval)))) while per==[] or (par[0], par[1]) == (per[0], per[1]) or \ (par[0], par[1]) == (per[1], per[0]) : lval = [0, 1, 2, 3] per = [] for i in range(3): per.append(lval.pop(random.randrange(len(lval)))) exo.append(fig_perp(noms, coor)) cor.append(fig_perp(noms, coor, 1, per, par)) exo.append('\end{pspicture*}\\par\n\\begin{enumerate}') cor.append('\\par\n\\begin{enumerate}') s_per = u"\\item Tracer la droite perpendiculaire à la droite $(%s%s)$ passant par $%s$" s_par = u"\\item Tracer la droite parallèle à la droite $(%s%s)$ passant par $%s$" s_per = s_per % (noms[per[0]], noms[per[1]], noms[per[2]]) s_par = s_par % (noms[par[0]], noms[par[1]], noms[par[2]]) if random.randrange(2): exo.append(s_par) cor.append(s_par) exo.append(s_per) cor.append(s_per) else: exo.append(s_per) cor.append(s_per) exo.append(s_par) cor.append(s_par) exo.append('\\end{enumerate}') cor.append('\\end{enumerate}') def Perpendiculaires(): exo = ["\\exercice", u"Réaliser les figures suivantes :\\par", '\\begin{multicols}{2}'] cor = ["\\exercice*", u"Réaliser les figures suivantes :\\par", '\\begin{multicols}{2}'] enonce_perp(exo, cor) exo.append('\\columnbreak') cor.append('\\columnbreak') enonce_perp(exo, cor) exo.append('\\end{multicols}') cor.append('\\end{multicols}') return (exo, cor) #------------------------------------------------------------------------------ # Propriétés #------------------------------------------------------------------------------ def fonction(angle, xa, ya, dist=0, droite='par'): """ Retourne une fonction à utiliser avec psplot @param angle: compris entre 1 et 89° ou 91 et 179°. Angle entre la droite et l'axe des abscisses @type angle: @param xa: abscisse d'un point de la droite @type xa: @param ya: ordonnée d'un point de la droite @type ya: @param dist: distance entre l'origine et la droite @type dist: @param droite: 'par' pour une parallèle et 'per' pour une perpendiculaire """ angle_rad = (angle * math.pi) / 180 if droite == 'par': coef = math.floor(math.tan(angle_rad) * 1000) / 1000.0 ord_or = math.floor(((ya - xa * math.tan(angle_rad)) - dist / math.cos(angle_rad)) * 1000) / 1000.0 return '{x %s mul %s add}' % (coef, ord_or) else: coef = math.floor(-1000 / math.tan(angle_rad)) / 1000.0 return '{x %s mul}' % coef def PointInter(angle, xa, ya, dist=0): angle_rad = (angle * math.pi) / 180 coef1 = math.floor(math.tan(angle_rad) * 1000) / 1000.0 ord_or1 = math.floor(((ya - xa * math.tan(angle_rad)) - dist / math.cos(angle_rad)) * 1000) / 1000.0 coef2 = math.floor(-1000 / math.tan(angle_rad)) / 1000.0 x = ord_or1 / (coef2 - coef1) y = x * coef2 return ',PosAngle=%s](%s,%s)' % (45 + angle, math.floor(x * 1000) / 1000.0, math.floor(y * 1000) / 1000.0) def Points(angle, xa, ya, dist=0): angle_rad = (angle * math.pi) / 180 coef = math.floor(math.tan(angle_rad) * 1000) / 1000.0 ord_or = math.floor(((ya - xa * math.tan(angle_rad)) - dist / math.cos(angle_rad)) * 1000) / 1000.0 lpos = [] if -1.5 < -2 * coef + ord_or < 1.5: x = -1.5 y = math.floor((x * coef + ord_or) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) if -1.5 < 2 * coef + ord_or < 1.5: x = 1.5 y = math.floor((x * coef + ord_or) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) if -2.1 < (1.5 - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / \ math.tan(angle_rad) < 2.1: y = 1.1 x = math.floor(((y - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / math.tan(angle_rad)) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) if -2.1 < (-1.5 - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / \ math.tan(angle_rad) < 2.1: y = -1.1 x = math.floor(((y - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / math.tan(angle_rad)) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) return lpos def figure(angle, xa, ya, dist, lpoints, noms, par_per, dist2=0): """ @param angle: @param xa: @param ya: @param dist: @param lpoints: @param noms: 1: nomme la droite (AB) 2: nomme la droite (d1) @param par_per: 1: parallèles + perpendiculaires 2: 3 parallèles 3: 2 perpendiculaires """ ltxt = [] ltxt.append('\\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6)') ltxt.append('\\footnotesize') if par_per < 3: ltxt.append('\\psplot[linewidth=1.5\\pslinewidth]{-2.1}{2.1}%s' % fonction(angle, xa, ya)) ltxt.append('\\psplot[linewidth=1.5\\pslinewidth]{-2.1}{2.1}%s' % fonction(angle, xa, ya, dist)) else: ltxt.append('\\psplot{-2.1}{2.1}%s' % fonction(angle, xa, ya)) ltxt.append('\\psplot{-2.1}{2.1}%s' % fonction(angle, xa, ya, dist)) if par_per == 2: ltxt.append('\\psplot[linewidth=1.5\\pslinewidth]{-2.1}{2.1}%s' % fonction(angle, xa, ya, dist2)) else: ltxt.append('\\psplot{-2.1}{2.1}%s' % fonction(angle, xa, ya, droite='per')) if noms: #nomme les droites par deux points if par_per != 2: #2 points d'intersection ltxt.append('\\pstGeonode[PointSymbol={none,x},PointName={%s,%s} %s{i1}%s{a1}' % (lpoints[0], lpoints[1], PointInter(angle, xa, ya), Points(angle, xa, ya)[0])) ltxt.append('\\pstGeonode[PointSymbol={none,x},PointName={%s,%s} %s{i2}%s{b1}' % (lpoints[2], lpoints[3], PointInter(angle, xa, ya, dist), Points(angle, xa, ya, dist)[0])) ltxt.append('\\pstGeonode[PointSymbol=none,PointName=none]%s{c1}%s{c2}' % (Points(angle + 90, 0, 0)[0], Points(angle + 90, 0, 0)[1])) else: #pas de point d'intersection pts = Points(angle, xa, ya) ltxt.append('\\pstGeonode[PointSymbol=x,PosAngle=%s,PointName={%s,%s}]%s{a1}%s{a2}' % (angle + 45, lpoints[0], lpoints[1], pts[0], pts[1])) pts = Points(angle, xa, ya, dist) ltxt.append('\\pstGeonode[PointSymbol=x,PosAngle=%s,PointName={%s,%s}]%s{b1}%s{b2}' % (angle - (45.0 * dist) / abs(dist), lpoints[2], lpoints[3], pts[0], pts[1])) pts = Points(angle, xa, ya, dist2) ltxt.append('\\pstGeonode[PointSymbol=x,PosAngle=%s,PointName={%s,%s}]%s{c1}%s{c2}' % (angle - (45.0 * dist2) / abs(dist2), lpoints[4], lpoints[5], pts[0], pts[1])) else: #nomme les droites (d_1), ... if par_per != 2: #2 points d'intersection ltxt.append('\\pstGeonode[PointSymbol=none,PointName={none,%s} %s{i1}%s{a1}' % (lpoints[0], PointInter(angle, xa, ya), Points(angle, xa, ya)[0])) ltxt.append('\\pstGeonode[PointSymbol=none,PointName={none,%s} %s{i2}%s{b1}' % (lpoints[1], PointInter(angle, xa, ya, dist), Points(angle, xa, ya, dist)[0])) ltxt.append('\\pstGeonode[PointSymbol=none,PointName={none,%s}]%s{c1}%s{c2}' % (lpoints[2], Points(angle + 90, 0, 0)[0], Points(angle + 90, 0, 0)[1])) else: pts = Points(angle, xa, ya) ltxt.append('\\pstGeonode[PointSymbol=none,PosAngle=%s,PointName={%s,none}]%s{a1}%s{a2}' % (angle + 45, lpoints[0], pts[0], pts[1])) pts = Points(angle, xa, ya, dist) ltxt.append('\\pstGeonode[PointSymbol=none,PosAngle=%s,PointName={%s,none}]%s{b1}%s{b2}' % (angle - (45.0 * dist) / abs(dist), lpoints[1], pts[0], pts[1])) #FIXME list index out of range pts = Points(angle, xa, ya, dist2) ltxt.append('\\pstGeonode[PointSymbol=none,PosAngle=%s,PointName={%s,none}]%s{c1}%s{c2}' % (angle - (45.0 * dist2) / abs(dist2), lpoints[2], pts[0], pts[1])) if par_per != 2: if angle < 90: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c1}{i1}{a1}') else: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c2}{i1}{a1}') if par_per == 3: if angle < 90: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c1}{i2}{b1}') else: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c2}{i2}{b1}') ltxt.append('\\end{pspicture*}') return ltxt def valeurs_figures(par_per): noms = random.randrange(2) if noms: lpoints = noms_sommets(6) else: lindices = [1, 2, 3] lpoints = [] for i in range(3): lpoints.append('(d_%s)' % lindices.pop(random.randrange(len(lindices)))) angle = random.randrange(1, 90) + 90 * random.randrange(2) xa = random.randrange(-5, 5) / 10.0 ya = random.randrange(-3, 3) / 10.0 if random.randrange(2): dist = random.randrange(4, 9) / 10.0 else: dist = -random.randrange(4, 9) / 10.0 if par_per == 2: if dist > 0: dist2 = -random.randrange(4, 9) / 10.0 else: dist2 = random.randrange(4, 9) / 10.0 return (angle, xa, ya, dist, lpoints, noms, dist2) else: return (angle, xa, ya, dist, lpoints, noms) def enonce_prop(exo, cor): exo.append('\\renewcommand{\\tabularxcolumn}[1]{m{#1}}') exo.append('\\begin{tabularx}{\\textwidth}[t]{|m{3cm}|m{4cm}|X|m{3cm}|}') exo.append('\\hline') exo.append(u'\\multicolumn{1}{|c|}{\\bf Données} & \\multicolumn{1}{|c|}{\\bf Figure codée}') exo.append(u'& \\multicolumn{1}{|c|}{\\bf Propriété} & \\multicolumn{1}{|c|}{\\bf Conclusion}\\\\') cor.append('\\renewcommand{\\tabularxcolumn}[1]{m{#1}}') cor.append('\\begin{tabularx}{\\textwidth}[t]{|m{3cm}|m{4cm}|X|m{3cm}|}') cor.append('\\hline') cor.append(u'\\multicolumn{1}{|c|}{\\bf Données} & \\multicolumn{1}{|c|}{\\bf Figure codée}') cor.append(u'& \\multicolumn{1}{|c|}{\\bf Propriété} & \\multicolumn{1}{|c|}{\\bf Conclusion}\\\\') ltypes = [1, 2, 3] lexos = [] for i in range(3): lexos.append(ltypes.pop(random.randrange(len(ltypes)))) for i in range(3): exo.append('\\hline') cor.append('\\hline') v = valeurs_figures(lexos[i]) if lexos[i] == 2: if v[5]: #noms de la forme (AB), on ajoute des parenthèses exo.append('''$(%s%s)//(%s%s)$\\par et\\par $(%s%s)//(%s%s)$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''' % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][4], v[4][5])) cor.append('$(%s%s)//(%s%s)$\\par et\\par $(%s%s)//(%s%s)$ & ' % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][4], v[4][5])) else: exo.append('''$%s//%s$\\par et\\par $%s//%s$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''' % (v[4][0], v[4][1], v[4][0], v[4][2])) cor.append('$%s//%s$\\par et\\par $%s//%s$ & ' % (v[4][0], v[4][1], v[4][0], v[4][2])) cor.append('%s & ' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i], v[6])))#eror out of range in figure cor.append(u'Si deux droites sont parallèles, alors toute parallèle à l\'une est parallèle à l\'autre. &') if v[5]: cor.append('$(%s%s)//(%s%s)$ \\\\\n \\hline' % (v[4][2], v[4][3], v[4][4], v[4][5])) else: cor.append('$%s//%s$ \\\\\n \\hline' % (v[4][1], v[4][2])) else: fig = random.randrange(2) if lexos[i] == 1: if v[5]: if not fig: exo.append('''$(%s%s)//(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''' % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][0], v[4][2])) cor.append('$(%s%s)//(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ &' % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][0], v[4][2])) else: if not fig: exo.append('''$%s//%s$\\par et\\par $%s\perp%s$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''' % (v[4][0], v[4][1], v[4][0], v[4][2])) cor.append('$%s//%s$\\par et\\par $%s\perp%s$ &' % (v[4][0], v[4][1], v[4][0], v[4][2])) if fig: exo.append('& %s & & \\\\' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append('%s & ' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append(u'Si deux droites sont parallèles, alors toute perpendiculaire à l\'une est perpendiculaire à l\'autre. &') if v[5]: cor.append('$(%s%s)\\perp(%s%s)$ \\\\\n \\hline' % (v[4][2], v[4][3], v[4][0], v[4][2])) else: cor.append('$%s\perp%s$ \\\\\n \\hline' % (v[4][1], v[4][2])) else: if v[5]: if not fig: exo.append('''$(%s%s)\\perp(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''' % (v[4][0], v[4][1], v[4][0], v[4][2], v[4][2], v[4][3], v[4][0], v[4][2])) cor.append('$(%s%s)\\perp(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ &' % (v[4][0], v[4][1], v[4][0], v[4][2], v[4][2], v[4][3], v[4][0], v[4][2])) else: if not fig: exo.append('''$%s\\perp%s$\\par et\\par $%s\perp%s$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''' % (v[4][0], v[4][2], v[4][1], v[4][2])) cor.append('$%s\\perp%s$\\par et\\par $%s\perp%s$ &' % (v[4][0], v[4][2], v[4][1], v[4][2])) if fig: exo.append('& %s & & \\\\' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append('%s &' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append(u'Si deux droites sont perpendiculaires à une même troisième alors elles sont parallèles entre elles. &') if v[5]: cor.append('$(%s%s)//(%s%s)$ \\\\\n \\hline' % (v[4][0], v[4][1], v[4][2], v[4][3])) else: cor.append('$%s//%s$ \\\\\n \\hline' % (v[4][0], v[4][1])) exo.append('''\\hline \\end{tabularx} ''') cor.append('\\end{tabularx}') def Proprietes(): exo = ["\\exercice", u"Compléter le tableau suivant :\\par Les droites en gras sont parallèles.\\par """] cor = ["\\exercice*", u"Compléter le tableau suivant :\\par Les droites en gras sont parallèles.\\par """] enonce_prop(exo, cor) return (exo, cor) pyromaths/src/sixiemes/._espace.py0000644000175000017500000000031511702101415017725 0ustar didrocksdidrocksMac OS X  2ATTRGޏ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/sixiemes/._symetrie.py0000644000175000017500000000031511702101415020326 0ustar didrocksdidrocksMac OS X  2ATTRGޔ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/Values.py0000644000175000017500000001116011702412057015670 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # from time import strftime from os.path import normpath, dirname, exists, abspath, join from os import environ, name from sys import executable, getfilesystemencoding import sys #import troisiemes.troisiemes, quatriemes.quatriemes, cinquiemes.cinquiemes #import sixiemes.sixiemes, lycee.lycee def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located.""" return hasattr(sys, "frozen") def data_dir(): """Renvoie le dossier data, selon qu'on utilise pyromaths à partir des sources, de l'exécutable win32 ou du paquet deb""" if we_are_frozen(): return join(normpath(dirname(unicode(executable, getfilesystemencoding()))), 'data') elif exists(join(abspath(dirname(__file__)),'../data/')): return normpath(join(abspath(dirname(__file__)),'../data/')) else: return '/usr/share/pyromaths/' def icon_dir(): """Renvoie le dossier où se trouve l'icône, selon qu'on utilise pyromaths à partir des sources, de l'exécutable win32 ou du paquet deb""" if we_are_frozen() or exists(join(abspath(dirname(__file__)),'../data/')): return join(DATADIR, 'images', 'pyromaths.png') else: return join('/usr/share/pixmaps', 'pyromaths.png') if name == 'nt': def home(): return unicode(environ['USERPROFILE'], getfilesystemencoding()) def configdir(): return join(unicode(environ['APPDATA'], getfilesystemencoding()), "pyromaths") elif sys.platform == "darwin": #Cas de Mac OS X. def home(): return unicode(environ['HOME'], getfilesystemencoding()) def configdir(): return join(home(), "Library", "Application Support", "Pyromaths") else: def home(): try: return unicode(environ['HOME'], getfilesystemencoding()) except KeyError: # Pyromaths en ligne, l'user apache n'a pas de $HOME return "" def configdir(): return join(home(), ".config", "pyromaths") VERSION = '11.05.1b2' COPYRIGHT_YEAR = strftime('%Y') COPYRIGHTS = u'© 2006 – %s Jérôme Ortais
\n' \ u'Pyromaths est distribué sous ' \ u'licence GPL.' % (COPYRIGHT_YEAR) WEBSITE = 'http://www.pyromaths.org/' DATADIR = data_dir() ICONDIR = icon_dir() HOME = home() CONFIGDIR = configdir() LESFICHES = [[u'Sixième', '', [ u'Calcul mental', u'Écrire un nombre décimal', u'Placer une virgule', u'Écriture fractionnaire ou décimale', u'Décomposition de décimaux', u'Conversions unités', u"Conversions unités d'aires", u"Conversions unités de volumes", u'Poser des opérations (sauf divisions)', u'Produits, quotients par 10, 100, 1000', u'Classer des nombres décimaux', u'Droites, demi-droites, segments', u'Droites perpendiculaires et parallèles', u'Propriétés sur les droites', u'Multiples de 2, 3, 5, 9, 10', u'Fractions partage', u'Fractions et abscisses', u'Aires et quadrillage', u'Symétrie et quadrillages', u'Mesurer des angles', u'Représentation dans l\'espace', u'Arrondir des nombres décimaux' ]], [u'Cinquième', '', [ u'Priorités opératoires', u'Symétrie centrale', u'Fractions égales', u'Sommes de fractions', u'Produits de fractions', u'Repérage', u'Addition de relatifs', u'Construction de triangles', u'Construction de parallélogrammes', u'Échelles', u'Aire de disques', u'Représentation de données', ]], [u'Quatrième', '', [ u'Calcul mental', u'Sommes de fractions', u'Produits et quotients de fractions', u'Fractions et priorités', u'Bases du calcul littéral', u'Réduire des expressions littérales', u'Propriétés sur les puissances', u'Propriétés sur les puissances de 10', u'Écritures scientifiques', u'Puissances de 10', u'Distributivité', u'Double distributivité', u'Théorème de Pythagore', u'Réciproque du théorème de Pythagore', u'Cercle et théorème de Pythagore', u'Théorème de Thalès', u'Trigonométrie', ]], [u'Troisième', '', [ u'Fractions', u'Puissances', u'PGCD', u'Développements', u'Factorisations', u'Dévt, factorisat°, calcul et éq° produit', u'Équation', u'Racines carrées', u'Système d\'équations', u'Fonctions affines', u'Probabilités', u'Théorème de Thalès', u'Réciproque du théorème de Thalès', u'Trigonométrie', u'Arithmétique' ]], [u'Lycée', '', [ u'Équations 2° degré', u'Factorisations 2° degré', u'Factorisations degré 3', u'Étude de signe', u"Sens de variations", u"Étude de fonctions", u"Vecteurs", ], [ u'Niveau 1èreS', u'Niveau 1èreS', u'Niveau 1èreS', u'Niveau 1èreS', u"Niveau 1èreS, Term STG", u"Niveau Term S", u"Niveau Seconde", ]], ] pyromaths/src/._lycee0000755000175000017500000000031511702101415015314 0ustar didrocksdidrocksMac OS X  2ATTRGr55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._quatriemes0000755000175000017500000000031511702101415016372 0ustar didrocksdidrocksMac OS X  2ATTRGv55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._interface.pyc0000644000175000017500000000031511702412270016746 0ustar didrocksdidrocksMac OS X  2ATTRGq55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/__init__.pyc0000644000175000017500000000021611702412270016330 0ustar didrocksdidrocks Oc@sdS(N((((s7/Users/administrateur/Desktop/pyromaths/src/__init__.pytspyromaths/src/interface.pyc0000644000175000017500000006262611702412270016546 0ustar didrocksdidrocks / Oc @sddklZlZddkZddkZddkZddkZddklZddk l Z l Z l Z l Z lZlZlZdefdYZdeifdYZd ZdS( i(tQtGuitQtCoreN(tSystem(tHOMEt CONFIGDIRtDATADIRt LESFICHESt COPYRIGHTStVERSIONtICONDIRt Ui_MainWindowcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZRS(cBs_eiied|_g|_eidjo'|id|i e i e n|i d|idddde i}|id |i|e ie iie ii}e i||_e i|i|_e i|_|iid |id |_e i|i|_|ii|i|ii d eidjo|iid ne i|i|_!|ii|i!|i!i deidjo|i!id ne i|i|_"|ii|i"|i"i deidjo|i"id ne i#dde ii$e ii%}|ii&||ii'|idddde i(|i|_)|i)i*e+eidjo|i)idnxe,dD]}dd|dUdd|d|fdUe-e.|d}xe,|D]r}|i/d||xUe,dD]G}dd||fdUdd|d|||dd|fdUqLWq%Wdd|dUqW|i)i0|i)i1|i2d|i)i0|i)i1|i3d|i)i0|i)i1|i4d|i)i0|i)i1|i5d|i)i0|i)i1|i6d e i|_7|i)i8|i7d!|i)i0|i)i1|i7d"e i|i7|_9e i:|_;e i|_<e i=|i7|_>|i>i d#|i<i|i>e i=|i7|_?|i?i d$|i<i|i?e i=|i7|_@|i@i d%|i<i|i@|i;i'|i<e i|_Ae iB|i7|_C|iCi |id&|iAi|iCe i:|_De iB|i7|_E|iEi |id'|iDi|iEe i|i7|_F|iFi d(|iDi|iF|iAi'|iDe iB|i7|_G|iGi |id)|iAi|iG|i;i'|iA|i9i'|i;dddde iH|i7|_I|iIiJe iHiK|iIiLe iHiM|i9i|iIdddde i:|_Ne i|_Oe iP|i7|_Q|iQi d*|iQiRd+|iQiSeT|id,|iOi|iQe iP|i7|_U|iUi d-|iUiRd.|iUiSeT|id/|iOi|iUe iP|i7|_V|iVi d0|iViRd1|iViSeT|id2|iOi|iV|iNi'|iOe i#dde ii%e ii$} |iNi&| e i|_We i:|_Xe i|_Ye i=|i7|_Z|iZi d3|iYi|iZe i=|i7|_[|i[i d4|iYi|i[|iXi'|iYe i|_\e i]|i7|_^|i^i_e+|i^i&d5|i^i&d6|i^i&d7|i^i&d8|i^i&d9|i\i|i^e i]|i7|_`eiaeiiebd:} eiaeiied:} d} x| D]}} eiic| dd;joZ|i`i&ed| e-| d< | |id=jo|i`ie| n| d7} q q Wx| D]} eiic| dd;jos|i`i&efig|i`ih| ed| e-| d< | |id=jo|i`ie| n| d7} q q W|i\i|i`|iXi'|i\|iWi'|iX|iNi'|iW|i9i'|iNdddde i|i7|_i|iii d>eidjo|iiid n|i9i|iid<ddde i#dd?e ii$e ii%}|i9i&|d@ddde i#dde ii%e ii$}|i9i&|d<ddd|ii|i)dddd|ij|ie ik||_l|iliefimdddAdBeidjo|ilidn|in|ile io|il|_p|ipiqdCe io|il|_r|iriqdDe is||_t|iu|it|itivdEeidjo|itidne iw||_x|ixi dFe iw||_y|iyi de iw||_z|izi dGe iw||_{|i{i dH|ipi||ix|ipi}|ipi||iy|iri||iz|iri}|iri||i{|ili||ipi~|ili||iri~e idI|}efii|efidJe iefidKefii|ixefidJ|iefii|iyefidJe iefidKefii|izefidJ|iefii|i{efidJ|iefii|i!efidLe iefidKefii|i"efidL|iefii|iefidL|iefii|iiefidL|iefii|iFefidL|iefii|iQefidM|ixOe,dD]A}x8e,e-e.|dD]}dNd||fdUqCWq"Wxe,dD]}e-e.|d}xe,|D]}dOd||e.|d|fdUdPd||eiiebdQdRfdUdSd||eiiebdQdTdUd||ffdUdVd||fdUqWqtWefii|dS(WNs pyromaths.xmltdarwins%background-color: rgb(251, 245, 225);t Pyromathsii,iii i toptionsuCréersbackground-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));tQuitteruRéinitialiserii(is%background-color: rgb(251, 231, 178);isself.tab_%se = QtGui.QWidget()is5self.gridLayout_%se = QtGui.QGridLayout(self.tab_%se)iscspacerItem_%s_%s = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)s;self.gridLayout_%se.addItem(spacerItem_%s_%s, %s, %s, 1, 1)s'self.tabWidget.addTab(self.tab_%se, "")t6et5et4et3euLycéettOptionsuNom par défaut du fichier : u3Chemin par défaut pour enregistrer les fichiers : s Titre de la fiche d'exercices : t nom_fichiertchemin_fichiert Parcourirt titre_ficheuCréer le corrigéu<Pyromaths doit-il créer la fiche de correction détaillée?tcorrigeu Créer le pdfu3Pyromaths doit-il créer les fiches au format pdf ?tpdfuCréer un seul pdfuGLe corrigé et les exercices doivent-ils être dans le même document ?tunpdfsNiveau :uModèle de mise en page :sClasse de 6\iemesClasse de 5\iemesClasse de 4\iemesClasse de 3\iemesClasse de 2\up{nde}t templatess.texitmodeleu"Enregistrer dans les préférencesiiiitFichiertAideufPour avoir un aperçu d'un exercice, positionner le curseur de la souris sur le point d'interrogation.sTous les exercicesuAccéder au siteu À propossCtrl+Qs activated()squit()s clicked()sstateChanged(int)s^QtCore.QObject.connect(self.spinBox_%s_%s, QtCore.SIGNAL("valueChanged(int)"), self.setNbExos)sself.label_%s_%s.setText(u"%s")s0self.imglabel_%s_%s.setText(r'')timagess whatsthis.pngs3self.imglabel_%s_%s.setToolTip(r'')t vignettess %se-%02d.pnguXself.spinBox_%s_%s.setToolTip(u"Choisissez le nombre d'exercices de ce type à créer.")(tostpathtjoinRt configfiletliste_creationtsystplatformt setStyleSheett setWindowIconRtQIconR tsetWindowTitlet setGeometrytQFontt setPointSizetsetFontt QSizePolicyt PreferredtQWidgett centralwidgett QGridLayoutt gridLayoutt QVBoxLayouttverticalLayoutt setMargint lire_configtconfigt QPushButtont pushButton_okt addWidgettsetTexttpushButton_quittpushButton_eraset QSpacerItemtMinimumt ExpandingtaddItemt addLayoutt QTabWidgett tabWidgettsetAutoFillBackgroundtTruetrangetlenRtinsert_spinboxt setTabTexttindexOfttab_6ettab_5ettab_4ettab_3ettab_2et tab_optionstaddTabt gridLayout_2t QHBoxLayoutthorizontalLayout_options1tverticalLayout_16tQLabeltopt_nom_fichiertopt_chemin_fichiertopt_titre_fichetverticalLayout_17t QLineEditRthorizontalLayout_chemin_fichierRtpushButton_parcourirRtQFrametlinet setFrameShapetHLinetsetFrameShadowtSunkenthorizontalLayout_3tverticalLayout_21t QCheckBoxtcheckBox_corriget setToolTipt setCheckedtintt checkBox_pdftcheckBox_unpdftverticalLayout_20thorizontalLayout_2tverticalLayout_18t opt_niveaut label_modeletverticalLayout_19t QComboBoxtcomboBox_niveaut setEditabletcomboBox_modeletlistdirRtsplitexttstrtsetCurrentIndexRtQStringt setItemTexttpushButton_enr_opttsetCentralWidgettQMenuBartmenubartQRectt setMenuBartQMenut menuFichiertsetTitlet menu_propost QStatusBart statusbart setStatusBart showMessagetQActiontactionTous_les_exercicest actionQuittertactionAcceder_au_sitetaction_a_propost addActiont addSeparatort menuActiont QShortcuttQObjecttconnecttSIGNALtqApptSLOTtcreer_tous_les_exercicestsitetaboutteffacer_choix_exercicestcreer_les_exercicestenregistrer_configtoption_parcourirtoption_corriget QMetaObjecttconnectSlotsByName(tselft MainWindowtfontt sizePolicyt spacerItemtleveltnb_exostitcolt spacerItem13tmodelest modeles_hometcounttelementt spacerItem14t spacerItem15tkeyQuittbox((s8/Users/administrateur/Desktop/pyromaths/src/interface.pytsetupUis      $   3""""""$$'$$"  %!%%!%%%%%    cCs4tii|d|}|otidndS(s*Dialogue si pyromaths.xml est défectueux.sErreur critiqueiN(Rt QMessageBoxtcriticalR'texit(Rtmessagetreply((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyterreur_critiquescCsqd}tidjotiitdd}ntiitdd}tiidd||t t fdS(s.Crée la boîte de dialogue "À propos de..." u



Version %s

Pyromaths est un programme qui permet de créer des fiches d'exercices types de mathématiques niveau collège avec leur corrigé.

Les fiches sont produites au format LaTeX. Pyromaths lance ensuite les commandes nécessaires à la production de fichiers pdf (latex - dvips - ps2pdf) et les ouvre.

Remerciements à :

  • David Robert pour l'idée de départ ;
  • Yves Gesnel pour le portage de Pyromaths sur Mac OS X ;
  • Arnaud Kientz pour ses graphismes, son implication dans le code de Pyromaths et son amitié ;
  • Guillaume Barthélémy pour ses exercices ;
  • Nicolas Bissonnier pour son arrivée dans l'équipe de développement ;
  • Nicolas Pourcelot pour ses conseils et son implication prochaine dans le code de Pyromaths ;
  • Didier Roche pour l'intégration de Pyromaths dans les dépôts Ubuntu ;
  • Jacqueline Gouguenheim-Desloy a porté Pyromaths sur Mac OS X à ses débuts. Son soutien et son amitié nous ont été précieux. Sa disparition est une perte douloureuse pour la communauté du logiciel libre.

%s

R R s pyromaths.pngspyromaths-banniere.pnguÀ propos de PyromathsN( R'R(R"R#R$RRRRtNoneRR(Rttexttbanniere((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRs 9c Csk|i|igjo#tiidddtiin+h |iid6|i io |i i d6t |i i d6|iid6t |iid6t |ii d6t |ii d 6t |iid d 6td 6td 6}g}xftt|iD]O}|i|d}|i|d}|idd|t|d|fqWti|_xdtt|D]P}ti||}|itii tii!Btii"B|ii#|qWt$}x9tt|D]%}|d||jo t%}qqW|ot&|it|n t'|it|}|i(dS(svVérifie si la liste d'exercices n'est pas vide puis sélectionne les noms des fichiers exercices et corrigéss Attention !u'Veuillez sélectionner des exercices...t creer_pdft creer_unpdfttitreRtniveauRRs.texRtdatadirt configdiriis%se: %siiN()tvalide_optionsR&RRtwarningRtOkRpt isCheckedRqt isEnabledtunicodeRRRlRyt currentTextRRR{RRRKRLtappendRt QListWidgettListtQListWidgetItemtsetFlagsRtQtt ItemIsEnabledtItemIsSelectabletItemIsDragEnabledRERJtFalsetvalidetChoixOrdreExostexec_( Rt parametrestlistRRtexotitemtbmonotform((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRsN   +cCs|id}ttiidd|idtii}d}|oxtdD]}g}x5tt t |dD]}|i ||fqW|djot i i|dd |}t i i|d d |}h t d 6|d 6|d 6|d6dd6dd6dd |d6t|iidd6td6td6td6td6}nt i i|d}t i i|d}h t d 6|d 6|d 6|d6dd6dd6dd6t|iidd6td6td6td6td6}ti|q[WndS(s Créer des fiches exemples pour tous les niveaux avec tous les exercices dans le dossier /home/jerome/workspace/Pyromaths/src/exemples RuDossier où créer les fichesRiiiis%se.texis%se-corrige.text les_fichest fiche_exot fiche_cort liste_exost1RsExemple de ficheRs%s\iemeRs.texRRRRRs Lycee.texsLycee-corrige.texuLycéeN(RRRt QFileDialogtgetExistingDirectoryRR;t ShowDirsOnlyRKRLRRR"R#R$R~R{RRJRRRtcreation(Rtd0RRtlisteRtcorR((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRsX    cBs_g|_xOedD]A}x8eee|dD]}dd||fdUq7WqWdS(sMRemet toutes les SpinBox à zéro et vide la liste d'exercices sélectionnésiisself.spinBox_%s_%s.setValue(0)iN(R&RKRLR(RRR((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyR*s   c Cs~tii|i}|i}|id}t|ii|id_t|i i|id_t|i i|id_t |i i |id_t |ii |id_t |ii |id_t|iid|id _ti|id d d d }|itii|dtd ddtid d|idS(sFonction qui se charge d'enregistrer les options de l'interface dans le fichier de configuration après avoir complété le dictionnaire.R RRRRRRs.texRtencodingsutf-8tmodetwt pretty_printsUTF-8txml_declarationtstrictN(tlxmltetreetparseR%tgetroottfindRRRRRR~RlRRpRqR{RtcodecstopentwritettostringRJtdecodetclose(RttreetrootR tf((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyR1s !!!!!!%!cBs,d||f}d|dUd||fdUeieiieii}|id|idd|dUd|dUd ||fdUd ||fdUd ||fdUd ||fdUd ||fdUd|dUd||fdUd||fdUd|||d|dfdUdS(sGPlace autant de SpinBox que d'exercices pour chaque niveau et les nommes%s_%ss.self.horizontalLayout_%s = QtGui.QHBoxLayout()Ns.self.spinBox_%s = QtGui.QSpinBox(self.tab_%se)i(isNsizePolicy.setHeightForWidth(self.spinBox_%s.sizePolicy().hasHeightForWidth())s)self.spinBox_%s.setSizePolicy(sizePolicy)s3self.horizontalLayout_%s.addWidget(self.spinBox_%s)s-self.imglabel_%s = QtGui.QLabel(self.tab_%se)s4self.horizontalLayout_%s.addWidget(self.imglabel_%s)s*self.label_%s = QtGui.QLabel(self.tab_%se)s1self.horizontalLayout_%s.addWidget(self.label_%s)saspacerItem_%s = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)s/self.horizontalLayout_%s.addItem(spacerItem_%s)sEself.gridLayout_%se.addLayout(self.horizontalLayout_%s, %s, %s, 1, 1)i(RR1tFixedtsetHorizontalStretchtsetVerticalStretch(RRRttreatedR((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRMDs"      cCsh}tii|i}|i}|i|}xX|D]P}|idjo d}n$|idjo d}n |i}|||it setLayoutRRRtacceptR(RRt LesFichesRtparentRtlayoutt buttonBox((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRs&       "cCs$t|it|i|idS(sÉcrit une liste contenant la liste des exercices dans l'ordre choisit par l'utilisateur et demande à celui-ci les noms de fichiers pour les exercices et les corrigésN(RRRRR(R((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyR#sN(RRt__doc__RRR#(((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRs  cCsB|d}g}g}x<t|iD](}|it|i|iq)WxP|D]H}dt|d}||di|d} |i|| fq\Wd\} } ti } t i |dd} t| i dd tii|d d | d } | djo&t i| d|oi|d  o]t| i dd tiitii| dtiitii| dd } nBtiitii| dtiitii| d} | djoT|ot i| dn| |d<| |d<||d<||dndS(sk Permet de choisir les noms et emplacements des fichiers tex, les écrits et lance la compilation LaTexRiiiiRRs.texsEnregistrer sous...Ru%s.texsDocuments Tex (*.tex)Ru%s-corrige.texRRRRN(RR(RKRRRRRRotindexRRRtsupprime_extensiontgetSaveFileNameRR"R#R$tajoute_extensiontdirnameR}tbasenameR(RR$RRtltlesexosRRRtpostf0tf1tsaveastfilename((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyRsF &     &&     (tPyQt4RRR"RRR'toutilsRtValuesRRRRRRR tobjectR RRR(((s8/Users/administrateur/Desktop/pyromaths/src/interface.pyts04|.pyromaths/src/classes/0000755000175000017500000000000011734627250015525 5ustar didrocksdidrockspyromaths/src/classes/PolynomesCollege.py0000644000175000017500000004174511702101415021353 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import re if __name__=="__main__": import sys sys.path.append('..') from ..outils.Affichage import decimaux _POLYNOME_FORMAT = re.compile(r""" \s* # éventuellement des espaces pour commencer ( # chaque monôme [-+]?\d+\.?\d*(?:e[-+]\d+)?[a-df-hkmnp-zA-NP-Z]?(?:\^\d+)? # au moins un nombre décimal | # OU [-+]?\d*\.?\d*(?:e[-+]\d+)?[a-df-hkmnp-zA-NP-Z](?:\^\d+)? # au moins une variable ) \s* # éventuellement des espaces pour finir """, re.VERBOSE) _MONOME_FORMAT = re.compile(r""" \s* # éventuellement des espaces pour commencer (?P[-+]?) # un éventuel signe (?P\d*\.?\d*(?:e[-+]\d+)?) # un éventuel coefficient (?:(?P[a-df-hkmnp-zA-NP-Z])(?:\^(?P\d+))?)? # une éventuelle variable avec son éventuel degré \s* # éventuellement des espaces pour finir """, re.VERBOSE) class Polynome(): """Cette classe crée la notion de polynômes. Polynome([[2,2],[3,1],[4,0]], 'z') est équivalent à 2z^2+3z+4. Un polynôme peut aussi être produit à l'aide d'une chaîne de la forme Polynome("2y^2+3y+4") Les variables ne peuvent être : e, i, j, l, o, O. """ def __init__(self, monomes, var=None): """Crée un polynôme. Accepte une chaîne de caractères comme '2x^2-4x+6' ou une liste de monômes [coefficient, degré] finit par une string contenant la variable. Par exemple, Polynome([[5,2], [-4,1], [6,0]], 't') équivaut à Polynome("+5t^2-4t+6") """ monomes = monomes or '0' # monômes du polynôme, par défaut un polynôme nul if isinstance(monomes, basestring): # Gère la construction des polynôme à partir d'une chaîne de caractères listmonomes = [] for monome in _POLYNOME_FORMAT.finditer(monomes): m = _MONOME_FORMAT.search(monome.group(0)) if m is None: raise ValueError(u'chaîne invalide pour un objet Polynôme : %s' % input) m_sign = m.group('sign') or '+' m_coef = float(m.group('coef') or 1) m_deg = int(m.group('deg') or (m.group('var') and '1') or '0') m_var = m.group('var') or var if m_var and not var: var = m_var # attribue une variable à var if m_var != var: raise ValueError(u'Le nom de la variable (%s) est incorrect pour le Polynôme %s' % (var, monomes)) if m_sign == '-': m_coef = -m_coef if m_coef: # supprime les monômes de coefficient 0 listmonomes.append([m_coef, m_deg]) if listmonomes: self.monomes = listmonomes else: self.monomes = [[0, 0]] self.var = var or 'x' else: #Supprime les monomes nuls : for k in range(len(monomes)-1, -1, -1): if not monomes[k][0]: monomes.pop(k) if not monomes: monomes=[[0, 0]] self.monomes = monomes self.var = var or 'x' # Variable par défaut def __repr__(self): """repr(self) Renvoie une chaîne de caractère pouvant être utilisée pour créer un polynôme. S'appelle ainsi : repr(p) où p est un polynôme""" return "Polynome(%s, \"%s\")" % (self.monomes, self.var) def __str__(self): """str(self) Renvoie une version LaTeX du polynôme""" var = self.var s = "" for m in self.monomes: if isinstance(m, list): if m[1] > 1: # Monôme de degré au moins 2 if m[0] == 1: s = s + "+" + var + "^{" + str(m[1]) + "}" elif m[0] == -1: s = s + "-" + var + "^{" + str(m[1]) + "}" elif m[0] > 0: s = s + "+" +decimaux(m[0], 1) + r"\," + var + "^{" + str(m[1]) + "}" else: s = s + decimaux(m[0], 1) + r"\," + var + "^{" + str(m[1]) + "}" elif m[1] == 1: # Monôme de degré 1 if m[0] == 1: s = s + "+" + var elif m[0] == -1: s = s + "-" + var elif m[0] > 0: s = s + "+" + decimaux(m[0], 1) + r"\," + var else: s = s + decimaux(m[0], 1) + r"\," + var else: # Monôme de degré 0 if m[0] < 0: s = s + decimaux(m[0], 1) else: s = s + "+" + decimaux(m[0], 1) # supprime le + en début de séquence s = s.lstrip("+") if not s: s="0" return s def __getitem__(self, i): """Renvoie le i ème monôme""" return self.monomes[i] def __iadd__(self, other): """Définit @self += @other""" if isinstance(other, (float, int)): other = Polynome([[other, 0]], self.var) m1, m2 = [m for m in self.monomes], [m for m in other.monomes] if Polynome.degre(self) <= 0: self.var = other.var elif Polynome.degre(other)<=0: other.var = self.var if self.var != other.var: raise ValueError(u'Pyromaths ne sait additionner que deux polynômes de même variable') else : m=[] m1.extend(m2) for monomes in m1: if monomes[0]: m.append(monomes) return Polynome(m, self.var) def __eq__(self, other): """Renvoie True si @self est égal à @other, False sinon. Ne tient pas compte de l'ordre des monômes""" if not isinstance(other, Polynome): other = Polynome(other, self.var) return not (self.var != other.var or \ sorted(self.monomes, key = lambda x: (-x[1], x[0])) != \ sorted(other.monomes, key = lambda x: (-x[1], x[0]))) def __ne__(self, other): """ @self différent de @other ?""" return not (self==other) def __add__(self, other): """Calcule la somme des polynômes @self et @other""" if isinstance(other, basestring): other = eval(other) self += other return self def __radd__(self, other): if isinstance(other, basestring): other = eval(other) if isinstance(other, (float, int)): other = Polynome([[other, 0]], self.var) return other + self def __sub__(self, other): """Jamais utilisé !""" if not isinstance(other, Polynome): self.monomes.append([-other, 0]) return self elif len(other) == 1 and other.monomes[0][0]>0: #Cas où on soustrait un polynôme de longueur 1 et de coef positif return self + (-other) return "%r+%r" %(self, -other) def __rsub__(self, other): """Jamais utilisé !""" if not isinstance(other, str): other=str(other) return other + -self def __neg__(self): """Renvoie l'opposé d'un polynôme""" m = [m1 for m1 in self.monomes] for i in range(len(m)): m[i][0] = -m[i][0] return Polynome(m, self.var) def __pos__(self): """+a""" return self def __mul__(self, other): #TODO: Cas d'un produit par 0 ou 1 if not isinstance(other, Polynome): other=Polynome(repr(other), self.var) m1, m2 = [m for m in self.monomes], [m for m in other.monomes] if Polynome.degre(self) == 0: self.var = other.var elif Polynome.degre(other)==0: other.var = self.var if self.var != other.var: raise ValueError(u'Pyromaths ne sait multiplier que deux polynômes de même variable') p0, p1 = Polynome.reduit(self), Polynome.reduit(other) if len(p0) == len(p1) == 2 and (p0[0]==p1[0] or p0[1] == p1[1]) and\ ((p0[0][0] == -p1[0][0] and p0[0][1] == p1[0][1]) or \ (p0[1][0] == -p1[1][0] and p0[1][1] == p1[1][1])): # 3ème identité remarquable if p0[0]==p1[0]: return "%r**2-%r**2" % (Polynome([p0[0]], self.var), \ Polynome([[abs(p0[1][0]), p0[1][1]]],\ self.var)) else: return "%r**2-%r**2" % (Polynome([p0[1]], self.var), \ Polynome([[abs(p0[0][0]), p0[0][1]]], \ self.var)) elif len(m1)>1 or len(m2)>1: p0, p1 = Polynome.reduit(self), Polynome.reduit(other) if p0!=self or p1 != other: if isinstance(p0, Polynome): p0 = repr(p0) else: p0 = "(" + p0 + ")" if isinstance(p1, Polynome): p1 = repr(p1) else: p1 = "(" + p1 + ")" return p0 + "*" + p1 m = "" for f1 in m1: for f2 in m2: m += repr(Polynome([f1], self.var)) + "*" m += repr(Polynome([f2], self.var)) + "+" m = m[:-1] # suppression du dernier + return m elif not m1[0][0] or not m1[0][0]: return 0 else: if m2[0][0] == 1 or (m2[0][1] == 0 and m1[0][1] == 0): # 3*x ou 3*4 -> 3x ou 12 return Polynome([[m1[0][0]*m2[0][0], m1[0][1]+m2[0][1]]],self.var) else: # 3x*4 ou x*3x ou 3x*4x => 3*4*x ou 3*x*x ou 3*4*x*x m = [] if m1[0][0] != 1: m.append(str(m1[0][0])) if m2[0][0]<0: m.append("(" + str(m2[0][0]) + ")") else: m.append(str(m2[0][0])) if m1[0][1]>0: m.append("Polynome(\"%s^%s\")" % (self.var, m1[0][1])) if m2[0][1]>0: m.append("Polynome(\"%s^%s\")" % (self.var, m2[0][1])) return "*".join(m) def __rmul__(self, other): """Multiplication de @other (qui n'est pas un polynôme) par @self (qui en est un) - Si @other est une suite de produits de monômes, et @self un polynôme de rang 1, on effectue toutes les multiplications en une fois - Sinon, on calcule d'abord @other""" if isinstance(other, (int, float)): other = Polynome(repr(other), self.var) return other*self if isinstance(other, str): from ..outils.Priorites3 import splitting ls = splitting(other) if ls.count("+") or ls.count("-"): # Réduire @other avant de faire le produit et vérifier s'il faut # des parenthèses autour de l'expression @other par, besoin = 0, False for k in range(len(ls)): if ls[k] == "(": par +=1 elif ls[k] == ")": par -= 1 elif not par and ls[k] in "+-": besoin = True break if besoin: return "(" + other + ")*" + repr(self) else: return other + "*" + repr(self) elif len(self) > 1: return other + "*" + repr(self) else: index = 0 for i in range(len(ls)): if "Polynome(" in ls[i]: if len(eval(ls[i]))>1: return other + "*" + repr(self) elif Polynome.degre(eval(ls[i]))>0: index = index or i index = index or len(ls) if self.monomes[0][0] != 1: ls.insert(index, "*") if self.monomes[0][0] < 0: ls.insert(index, "(" + str(self.monomes[0][0]) + ")") else: ls.insert(index, str(self.monomes[0][0])) if self.monomes[0][1] > 0: ls.append("*") ls.append("Polynome([%s], \"%s\")" %([1, self.monomes[0][1]], self.var)) return "".join(ls) else: raise ValueError(u"Type non prévu. Bogue en perspective !") def __len__(self): "retourne le nombre de monômes d'un polynôme" m = [m1 for m1 in self.monomes] m =Polynome.ordonne(Polynome(m, self.var)) return len(self.monomes) def degre(self): "retourne le degré d'un polynôme, -1 pour le polynôme nul" if self == Polynome(""): return -1 else: m = [m1 for m1 in self.monomes] m =Polynome.ordonne(Polynome(m, self.var)) return m.monomes[0][1] def __pow__(self, other): if len(self) == 2 and other ==2: a0 = self.monomes[0][0] b0 = self.monomes[1][0] p = a0*b0 a = Polynome([[abs(a0), self.monomes[0][1]]], self.var) b = Polynome([[abs(b0), self.monomes[1][1]]], self.var) if p < 0: return "%r**2-2*%r*%r+%r**2"%(a, a, b, b) else: return "%r**2+2*%r*%r+%r**2"%(a, a, b, b) elif len(self)==1: return Polynome([[self[0][0]**other, self[0][1]*other]], self.var) else: result=self for i in range(other-1): result = eval(result*self) return result def reduit(self): """Renvoie une version réduite du polynôme self""" polynome = [] for monome in Polynome.ordonne(self).monomes: if polynome and monome[1] == polynome[-1][1]: polynome[-1][0] += monome[0] else: polynome.append([monome[0], monome[1]]) #ATTENTION : polynome.append(monome) modifie self !!! for k in range(len(polynome)-1, -1, -1): if polynome[k][0] == 0: polynome.pop(k) return Polynome(polynome, self.var) def reduction_detaillee(self): """Ordonne puis effectue les factorisations qui permettent de réduire un polynôme""" po = Polynome.ordonne(self) if not Polynome.reductible(self) or repr(po) != repr(self): return po else: reductible = False var = self.var m = [m for m in po.monomes] s, p = "", "Polynome(\"" tmp = "" for i in range(len(m)): if tmp == "": tmp = "(%s" % str(m[i][0]) elif m[i][1] == m[i-1][1]: if m[i][0]>0: tmp += "+" tmp += str(m[i][0]) reductible = True else: if reductible: tmp += ")" s += "+%s*%r" % (tmp, Polynome('1%s^%s' % (var, m[i-1][1]))) else: s += "+Polynome(\"%s%s^%s\")" % (str(m[i-1][0]), var, m[i-1][1]) tmp = "(%s" % str(m[i][0]) reductible = False if reductible: tmp += ")" if m[-1][1]==0: tmp = eval(tmp) s += "+Polynome(\"%s\")" % tmp else: s += "+%s*%r" % (tmp, Polynome('1%s^%s' % (var, m[-1][1]))) else: s += "+Polynome(\"%s%s^%s\")" % (str(m[-1][0]), var, m[-1][1]) s = s.lstrip("+") # suppression du + initial return s def reductible(self): """Renvoie 1 si le polynôme est réductible, 0 sinon.""" if self != Polynome.reduit(self): return 1 else: return 0 def ordonne(self): """Ordonne les monômes du polynôme @self en écrivant en premier ceux de degré supérieur""" m1 = self.monomes m1 = sorted(m1, key = lambda x: (-x[1])) return Polynome(m1, self.var) pyromaths/src/classes/._PolynomesCollege.py0000644000175000017500000000031511702101415021554 0ustar didrocksdidrocksMac OS X  2ATTRG޹55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/.___init__.py0000644000175000017500000000031511702101415020033 0ustar didrocksdidrocksMac OS X  2ATTRG޶55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/._Racine.py0000644000175000017500000000031511702101415017475 0ustar didrocksdidrocksMac OS X  2ATTRG޺55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/__init__.py0000644000175000017500000000171511702101415017623 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/classes/Vecteurs.py0000644000175000017500000000640411702101415017664 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import math import random from ..classes.Racine import simplifie_racine class Vecteur: def __init__(self, x=0, y=0): self.x=x self.y=y def __eq__(self, vec): '''Teste l'égalité entre deux vecteurs''' return (self.x==vec.x) and (self.y==vec.y) def __add__(self, vec): '''Addition''' return Vecteur(self.x+vec.x,self.y+vec.y) def __sub__(self, vec): '''Soustraction''' return Vecteur(self.x-vec.x,self.y-vec.y) def __mul__(self, c): '''Multiplication par un nombre''' ## Besoin du produit scalaire ou du produit vectoriel ? if isinstance(c, float) or isinstance(c, int): return Vecteur(c*self.x,c*self.y) def __rmul__(self, c): '''Multiplication Reverse''' ## Besoin du produit scalaire ou du produit vectoriel ? if isinstance(c, float) or isinstance(c, int): return self * c def __neg__(self): '''Négatif d'un vecteur''' return -1 * self def __div__(self, c): if isinstance(c, float) or isinstance(c, int): return Vecteur(self.x/float(c), self.y/float(c)) def __abs__(self): '''Retourne la norme du vecteur sous la forme coeff,radicande où sqrt(n)=coeff*sqrt(radicande)''' return simplifie_racine(self.x**2 + self.y**2) def __str__(self): '''Affichage sous forme de coordonnées''' return '(' + str(self.x) + ',' + str(self.y) + ')' def normeTex(self): '''Affichage TeX de la racine simplifiée de la racine, sans les dollars.''' norme = abs(self) if norme[0] == 1: return "\sqrt{" + str(norme[1]) + "}" elif norme[1] == 1: return str(norme[0]) else: return str(norme[0]) + "\sqrt{" + str(norme[1]) + "}" def randvect(a, b): '''Retourne un vecteur aléatoire et s'occupe de placer l'abscisse au-dessus de a et l'ordonnée dans [0,b]. Il faut que b>=10.''' x = random.randint(-5,5) y = random.randint(-5,5) posx = a + max(1-x, 1) ## 1 colonne minimum d'écart if y>=0: posy = random.randint(0, math.fabs(y - 2)) + 1 ## Ajouter 1 pour éviter de coller au bas de la grille else: posy = random.randint(math.fabs(y), b) ## Comme y < 0, cela ne colle pas au bas de la grille return [Vecteur(x,y), posx, posy] pyromaths/src/classes/SecondDegre.py0000644000175000017500000000342511702101415020246 0ustar didrocksdidrocks# -*- coding: utf-8 -*- import random from ..outils.Arithmetique import factorise, carrerise from math import sqrt from ..outils.Affichage import suppr0, suppr0list class Poly2: """Classe pour les polynômes du second degré.""" def __init__(self, a, b, c): if a == 0: print "Erreur de définition ! a doit être différent de 0." self.a = a self.b = b self.c = c self.delta = suppr0(b**2 - 4*a*c) if self.delta > 0: self.signedelta = "strictement positif" self.nbrac = 2 elif self.delta < 0: self.signedelta = "strictement négatif" self.nbrac = 0 else: self.signedelta = "nul" self.nbrac = 1 def __add__(self, other): return Poly2(self.a + other.a, self.b + other.b, self.c + other.c) def __radd__(self, other): return Poly2(self.a + other.a, self.b + other.b, self.c + other.c) def __sub__(self, other): return Poly2(self.a - other.a, self.b - other.b, self.c - other.c) def __rsub__(self, other): return Poly2(self.a - other.a, self.b - other.b, self.c - other.c) def __str__(self): if self.b<=0: sep1 = '' else: sep1 = '+' if self.c<=0: sep2 = '' else: sep2 = '+' if self.a == 1: a1 = '' else: a1 = str(suppr0(self.a)) if self.b == 1: b1 = '' else: b1 = str(suppr0(self.b)) if self.b == 0: deg1 = '' b1 = '' else: deg1 = 'x' return a1 + 'x^2' + sep1 + b1 + deg1 + sep2 + str(suppr0(self.c)) def print_signe(self, signe): return str(self) + " " + signe + " 0" pyromaths/src/classes/._Polynome.py0000644000175000017500000000031511702101415020076 0ustar didrocksdidrocksMac OS X  2ATTRG޸55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/._Terme.py0000644000175000017500000000031511702101415017350 0ustar didrocksdidrocksMac OS X  2ATTRG޼55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/._Fractions.py0000644000175000017500000000031511702101415020224 0ustar didrocksdidrocksMac OS X  2ATTRG޷55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/Racine.py0000644000175000017500000002707011702101415017267 0ustar didrocksdidrocks# -*- coding: utf-8 -*- from ..outils.decimaux import decimaux from ..outils.Arithmetique import carrerise, pgcd, ppcm from math import sqrt from Fractions import Fractions def produitfacteurs(facteurs): """Affiche sous forme de produit les éléments d'une liste.""" prodfacteurs = '' for element in facteurs: prodfacteurs += str(element) + ' \\times ' return prodfacteurs[:-7] class Racine: def __init__(self, radicande, coeff = 1, indice = 2): if (radicande < 0) or not (isinstance(indice, int)): print "Erreur de définition ! Le radicande doit être positif et l'indice un nombre entier !" self.radicande = radicande self.indice = indice # Nombre entier self.coeff = coeff # Coeff devant la racine def __add__(self, other): if not (isinstance(other, Racine)): return str(self) + " + " + str(other) if (self.radicande == other.radicande) and (self.indice == other.indice): return [str(self.simplifie()[0]) + "+" + str(other.simplifie()[0]), Racine(self.radicande, self.coeff + other.coeff, self.indice)] else: return str(self) + " + " + str(other) def __radd__(self, other): return self + other def __sub__(self, other): if not (isinstance(other, Racine)): return str(self) + " + " + str(other) if (self.radicande == other.radicande) and (self.indice == other.indice): return Racine(self.radicande, self.coeff - other.coeff, self.indice) else: return (str(self) + " - " + str(other), "tset") def __rsub__(self, other): return -(self - other) def __mul__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Racine(self.radicande, self.coeff * other, self.indice) elif self.indice == other.indice: return Racine(self.radicande * other.radicande, self.coeff * other.coeff, self.indice) else: return str(self) + ' x ' + str(other) def __rmul__(self, other): return self * other def __div__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Racine(self.radicande, self.coeff / other, self.indice) elif self.indice == other.indice: return Racine(self.radicande / float(other.radicande), self.coeff / float(other.coeff), self.indice) else: return str(self) + ' / ' + str(other) def __rdiv__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Racine(self.radicande, other / float(self.coeff * self.radicande), self.indice) elif self.indice == other.indice: return Racine(other.radicande / float(self.radicande), other.coeff / float(self.coeff), self.indice) else: return str(other) + ' / ' + str(self) def __str__(self): if self.coeff == 0: return "0" else: if self.coeff == 1: coeff = "" else: coeff = decimaux(self.coeff, 1) + " \\, " if self.radicande == 0: coeff = "" racine = "" radicande = "0" elif self.indice == 2: racine = "\\sqrt{" radicande = decimaux(self.radicande, 1) + "}" else: racine = "\\sqrt[{0}]{{".format(self.indice) radicande = decimaux(self.radicande, 1) + "}" return coeff + racine + radicande def simplifie(self): facteurs = factor(self.radicande) prodfacteurs = produitfacteurs(facteurs) if self.indice == 2: racine = "\\sqrt{" else: racine = "\\sqrt[{0}]{{".format(self.indice) coeff = self.coeff radicande = self.radicande detail = [str(self), ' = ', str(coeff) + racine + prodfacteurs + '}'] for element in facteurs: if facteurs.count(element) % self.indice == 0: coeff *= element for n in range(self.indice): facteurs.remove(element) radicande = radicande // (element**(self.indice)) prodfacteurs = produitfacteurs(facteurs) detail.append(' = ') detail.append(str(coeff) + ' \\times ' + racine + prodfacteurs + '}') if radicande == 1: return (coeff, detail) else: return (Racine(radicande, coeff, self.indice), detail) def simplifie_racine(n): '''renvoie coeff,radicande où sqrt(n)=coeff*sqrt(radicande)''' if n==0: return 0,0 else: ncar=carrerise(n) return int(sqrt(n//ncar)),ncar def pTeX(n): """renvoie (n) si n<0""" if n<0: return "("+decimaux(n)+")" else: return decimaux(n) def tTeX(n): if n==1: return "" elif n==-1: return "-" elif n>=0: return "+"+decimaux(n) else: return decimaux(n) class RacineDegre2: def __init__(self,numerateur=0,denominateur=1,coeff=1,radicande=0): self.numerateur=numerateur self.denominateur=denominateur self.coeff=coeff self.radicande=radicande def __str__(self): if isinstance(self.numerateur,str): #utilisé dans le détail de la simplification numerateur=self.numerateur else: numerateur=decimaux(self.numerateur)*(self.numerateur!=0) #renvoie "" si self.numerateur=0 if self.radicande!=0: if isinstance(self.coeff,str):#utilisé dans le détail de la simplification if self.coeff[0]!="-" and self.coeff[0]!="+": numerateur+="+" numerateur+=self.coeff+"\\sqrt{"+decimaux(self.radicande)+"}" elif self.coeff==1: numerateur+="+\\sqrt{"+decimaux(self.radicande)+"}" elif self.coeff==-1: numerateur+="-\\sqrt{"+decimaux(self.radicande)+"}" else: numerateur+=tTeX(self.coeff)+"\\sqrt{"+decimaux(self.radicande)+"}" if numerateur=='': numerateur = '0' if self.denominateur==1: result=numerateur else: result="\\dfrac{%s}{%s}"%(numerateur,self.denominateur) if result[0]=='+': return result[1:] else: return result def simplifie(self,detail=False): liste_detail=[] coeff,radicande=simplifie_racine(self.radicande) numerateur=self.numerateur if self.radicande!=0: if self.coeff==1: det_coeff="+ " elif self.coeff==-1: det_coeff="- " else: det_coeff="%s\\times "%(self.coeff) if coeff!=1 or radicande==1: det_coeff+=str(coeff) else: det_coeff="0" if radicande==1: #det_coeff="%s\\times%s"%(tTeX(self.coeff),coeff) liste_detail.append("\\dfrac{%s %s}{%s}"%\ (self.numerateur,det_coeff ,self.denominateur)) radicande=0 numerateur=self.numerateur+(self.coeff)*int(coeff) coeff=0 if coeff!=1: liste_detail.append(str(RacineDegre2(numerateur, self.denominateur, det_coeff, radicande))) coeff=(self.coeff)*int(coeff) simplifie=pgcd(pgcd(coeff,numerateur),self.denominateur) numerateur=numerateur//simplifie coeff=coeff//simplifie denominateur=self.denominateur//simplifie if simplifie!=1: if radicande!=0 or denominateur!=1: det_numerateur="%s_{\\times %s}"%(numerateur,pTeX(simplifie)) det_denominateur="%s_{\\times %s}"%(denominateur,pTeX(simplifie)) det_coeff="%s_{\\times %s}"%(coeff,pTeX(simplifie)) liste_detail.append(str(RacineDegre2(det_numerateur,det_denominateur,det_coeff,radicande))) liste_detail.append(str(RacineDegre2(numerateur,denominateur,coeff,radicande))) if detail: return RacineDegre2(numerateur,denominateur,coeff,radicande),liste_detail return RacineDegre2(numerateur,denominateur,coeff,radicande) def __add__(self,other): if isinstance(other,RacineDegre2): if self.radicande==other.radicande or self.radicande==0 or other.radicande==0: radicande=max(self.radicande,other.radicande) premier,second=self,other else: premier=self.simplifie() second=other.simplifie() if self.radicande==other.radicande or self.radicande==0 or other.radicande==0: radicande=max(self.radicande,other.radicande) else: return NotImplemented denominateur=ppcm(premier.denominateur,second.denominateur) facteur1=denominateur/premier.denominateur facteur2=denominateur/second.denominateur #if self.radicande==other.radicande: coeff=premier.coeff*facteur1*(premier.radicande!=0)+second.coeff*facteur2*(second.radicande!=0) if coeff==0: radicande=0 return RacineDegre2(premier.numerateur*facteur1+second.numerateur*facteur2, denominateur, coeff, radicande) elif isinstance(other,int): return self + RacineDegre2(other) elif isinstance(other,Fractions): return self + RacineDegre2(other.numerateur,other.denominateur) def __radd__(self,other): return self+other def __neg__(self): return RacineDegre2(-self.numerateur,self.denominateur,-self.coeff,self.radicande) def __sub__(self,other): return self+(-other) def __rsub__(self,other): return -self + other def __mul__(self,other): if isinstance(other,Fractions): return self*RacineDegre2(other.numerateur,other.denominateur,0,self.radicande) elif isinstance(other,int): return self*RacineDegre2(other,1,0,self.radicande) else: radicande=max(self.radicande,other.radicande)#cela autorise d'avoir un radicande=0 mais n'efface pas l'autre coeff=self.numerateur*(other.coeff*(other.radicande!=0))+(self.coeff*(self.radicande!=0))*other.numerateur if coeff==0: radicande=0 numerateur=self.numerateur*other.numerateur+(self.coeff*other.coeff)*(not(self.radicande==0 or other.radicande==0))*self.radicande return RacineDegre2(numerateur, self.denominateur*other.denominateur, coeff, radicande) def __invert__(self): return self.denominateur*RacineDegre2(self.numerateur,self.numerateur**2-self.coeff**2*self.radicande,-self.coeff,self.radicande) def __div__(self,othrer): return self*~other def __rdiv__(self,other): return ~self*other def __rmul__(self,other): return self*other def __pow__(self,n): result=1 for i in range(n): result=result*self return result def __float__(self): return (self.numerateur+self.coeff*sqrt(self.radicande))/self.denominateur def __cmp__(self,other): comp=float(self)-float(other) if comp>0: return 1 elif comp<0: return -1 else: return 0 pyromaths/src/classes/Polynome.py0000644000175000017500000002514211702101415017666 0ustar didrocksdidrocks# -*- coding: utf-8 -*- if __name__=="__main__": import sys,os sys.path.append(os.path.join('..')) from .Racine import simplifie_racine, RacineDegre2, sqrt from .Fractions import Fractions import re from ..outils.Affichage import pTeX, TeX, radicalTeX, fTeX, Fractions, tTeX class Polynome: '''Classe de polynôme pour le lycee''' def __init__(self, liste_coeff, var = "x"): self.var = var # Lettre pour la var liste_reduite={} if isinstance(liste_coeff,str): liste_coeff=str_Polynome(liste_coeff,var) elif isinstance(liste_coeff,list): liste_coeff=dict((i,liste_coeff[i])for i in range(len(liste_coeff))) elif isinstance(liste_coeff,int) or isinstance(liste_coeff,Fractions.Fractions) or isinstance(liste_coeff,float): liste_coeff={0:liste_coeff} for i in liste_coeff.iterkeys(): if liste_coeff[i] != 0: liste_reduite[i]=liste_coeff[i]+Fractions.Fractions(0, 1) if liste_reduite=={} or liste_coeff==[]: liste_reduite={0:0} self.dictio = liste_reduite self.puiss = liste_reduite.keys() self.puiss.sort(reverse=True) self.deg=self.degre() self.degre_max=max(0,self.deg) def __len__(self): return max(0,self.deg)+1 def degre(self): degre=float("-inf") for i in self.dictio.iterkeys(): if i > degre and self.dictio[i] !=0: degre=i return degre def __getitem__(self,i): '''P[i] renvoie le coefficient de rang i''' return self.dictio.get(i,0) def __str__(self): '''renvoie une str pour un affichage python''' return self.TeX(var=self.var) def TeX(self,var='',display=True,parenthese=False): '''renvoie une chaine de caractere imprimant les fractions dans TeX''' if var=='': var=self.var exposants = []+self.puiss premier = 1 string='' if display: fractex="\\dfrac" else: fractex="\\frac" for exposant in exposants : if premier: if self[exposant]==1 and exposant!=0: string='' elif self[exposant]==-1 and exposant!=0: string='-' else: string=TeX(self[exposant]) premier=0 elif self[exposant] != 1: if self.dictio[exposant] == -1: string += '-' else: string+=tTeX(self[exposant]) else: string+="+" if exposant == 1: terme = var elif (exposant == 0) and ((self[exposant] == 1) or (self[exposant] == -1)): terme = '1' elif exposant == 0: terme = '' else: terme = var + u'^' + str(exposant) string+=terme if parenthese and (len(self.puiss)>1 or self[self.degre_max]<0): return "\\left("+string+"\\right)" else: return string def __add__(self, other): if isinstance(other,int) or isinstance(other,float) or isinstance(other,Fractions.Fractions) or isinstance(other,RacineDegre2): return self+Polynome({0:other},var=self.var) result={0:0} liste1=self.puiss liste2=other.puiss for i in liste1 : s=self.dictio.get(i)+other.dictio.get(i,0) if s!=0: result[i]=s for i in liste2: if i not in liste1: result[i]=other.dictio[i] return Polynome(result,var=self.var) def __mul__(self, other): if isinstance(other,Polynome): result=Polynome({0:0},var=self.var) for i in self.dictio.iterkeys(): for j in other.dictio.iterkeys(): exposant=i+j coefficient=self.dictio[i]*other.dictio[j] result = result + Polynome({exposant:coefficient},var=self.var) return result else: return self*Polynome(other) def __ne__(self,other): return not(self == other) def __eq__(self,other): if (isinstance(other,int) or isinstance(other,Fractions.Fractions) or isinstance(other,float)): if self.degre_max==0 and self[0]==other: return True else: return False elif self.var==other.var and self.dictio==other.dictio: return True else: return False def __pow__(self, other): if isinstance(other,int) and other>=0: result=Polynome({0:1},self.var) for i in xrange(other): result*=self return result def __radd__(self, other): if isinstance(other,int) or isinstance(other,float) or isinstance(other,Fractions.Fractions): return self+Polynome({0:other},var=self.var) return self + other def __sub__(self, other): return self + (-other) def __rsub__(self, other): return -(self - other) def __neg__(self): return self * Polynome({0:-1},var=self.var) def __rmul__(self,nombre): return self*Polynome({0:nombre}) def __div__(self,other): if isinstance(other,int): return Fractions.Fractions(1,other)*self elif isinstance(other,Fractions.Fractions) or isinstance(other,float)or isinstance(other,RacineDegre2): return (1/other)*self else: quotient=Polynome({},var=self.var) reste=self diviseur_degre=other.deg while diviseur_degre <= reste.deg: ajout_quotient_deg=reste.deg-diviseur_degre facteur= reste.dictio[reste.deg]/other.dictio[other.deg] ajout_quotient=Polynome({ajout_quotient_deg:facteur},var=self.var) quotient=quotient+ajout_quotient soustrait_reste=ajout_quotient*other reste=reste-soustrait_reste return quotient,reste def simplifie(self): result={} for i in self.puiss: if isinstance(self[i],(Fractions.Fractions,RacineDegre2)): result[i]=self[i].simplifie() else: result[i]=self[i] return Polynome(result) def __call__(self,x,): '''renvoie la Fraction ou l'int P(x)''' if x==float("inf") or x==float("-inf"): if self.degre_max==0: return self[0] elif self.deg%2==0: return self[self.deg]*float("inf") else: return self[self.deg]*x elif isinstance(x,str): return self.TeX(var=x) else: result=0 for i in self.dictio.iterkeys(): result= result+self[i]*x**i if isinstance(result,Fractions.Fractions): result=result.simplifie() if result.denominateur==1: return result.numerateur else: return result def racine_evidente(self,liste=[-2,-1,0,1,2]): listerac=[] for i in liste: if self(i)==0: listerac=listerac+[i] return listerac def factorise(self,TeX=False,racines=[0,-1,1,2,-2]): facteurs=[Polynome({0:self.dictio[self.deg]},var=self.var)] developpe,reste=self/facteurs[0] for r in racines: while developpe(r)==0: rac=-r developpe,reste = developpe/Polynome({1:1,0:rac},var=self.var) facteurs=facteurs+[Polynome({1:1,0:rac})] if TeX: stringTeX="" if not(facteurs[0]==Polynome({0:1},var=self.var)): stringTeX+=facteurs[0].TeX() for i in facteurs[1:]: if i[0]!=0: stringTeX+="\\left("+i.TeX()+"\\right) \\times " else: stringTeX+=i.TeX()+" \\times " if developpe==Polynome({0:1},var=self.var): return stringTeX[:-7] else: return stringTeX+"\\left("+developpe.TeX()+"\\right)" else: return facteurs + [developpe] def derive(self): result={} for i in self.dictio.iterkeys(): if i == 0: result[0]=0 else: result[i-1]=int(i)*self[i] return Polynome(result,self.var) def primitive(self): result={} for i in self.dictio.iterkeys(): result[i+1]=Fractions.Fractions(1,int(i+1))*self.dictio[i] return Polynome(result,self.var) def str_Polynome(string,var='x'): '''str -> dict''' #TODO reconnaitre les coefficients fractionnaires resultat = [] termes = {} separeplus = (string).split("+") for element in separeplus: temp = [] temp = element.split("-") for bis in temp: resultat.append(bis) if temp.index(bis) != len(temp)-1: resultat.append(-1) if separeplus.index(element) != len(separeplus)-1: resultat.append(1) if '' in resultat: resultat.remove('') for element in resultat: index = resultat.index(element) if index > 0: coeff = resultat[index-1] else: coeff = 1 if (element not in [-1, 1]): if element==var: termes[1]=(coeff) else: a = re.findall('\d+(?:\.\d*)?', element) if (len(a) == 1) and (not re.findall('\^', element)) and (re.findall(var, element)): termes[1]=coeff * Fractions.Fractions(eval(a[0])) elif (len(a) == 1) and (re.findall(var, element)): termes[int(a[0])]=coeff * 1 elif (len(a) == 1): termes[0]=coeff * Fractions.Fractions(eval(a[0])) else: termes[int(a[1])]=coeff * Fractions.Fractions(eval(a[0])) return termes if __name__=="__main__": from TEST.imprimetest import * X=Polynome("x") P=Polynome({2:4,1:8,0:1,3:0}) ## Q=Polynome({2:-4,0:-1,1:8}) ## R=Polynome({3:1,2:1,1:-2}) ## D=Polynome({1:1,0:2}) ## F=Polynome("x-4") ## FF=Polynome("x^2-3") ## Divi=FF*F+7 ## FR=Polynome({3:Fractions(2,3),2:Fractions(2,3),1:Fractions(-4,3)}) ## print "P=", P ## print "Q=", Q ## print "R=", R ## print "FR=",FR ## R_facteur=R.factorise() ## print "R=",R.factorise(TeX=True) ## #TeX_division(R,D) ## print Divi*Polynome("x^3")-28*X ## #imprime_TeX(TeX_division(Divi*Polynome("x^3")-28*X,F*X)) pyromaths/src/classes/._SecondDegre.py0000644000175000017500000000031511702101415020456 0ustar didrocksdidrocksMac OS X  2ATTRG޻55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/Fractions.py0000644000175000017500000001614611702101415020020 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import string import math import os from ..outils import Arithmetique class Fractions: """Classe permettant d'opérer sur les fractions. Une fraction est stockée ainsi : (numérateur, dénominateur)""" def __init__(self, n, d=1): self.numerateur = self.n = n self.denominateur = self.d = d def simplifie(self): # retourne la fraction rendue irréductible pgcd = Arithmetique.pgcd(self.n, self.d) return Fractions(self.n // pgcd, self.d // pgcd) def __str__(self): return self.TeX(signe=0,coef=None) def TeX(self, signe=0, coef=None): """Permet d'écrire une fraction au format TeX. @param signe: Si vrai, écrit la fraction avec un dénominateur positif @param coef: Multiplie le numérateur et le dénominateur par un même nombre """ if signe: (self.n, self.d) = ((self.n * abs(self.d)) // self.d, abs(self.d)) if self.n: if coef and coef != 1: text = "\\dfrac{%s_{\\times %s}}{%s_{\\times %s}}" % (self.n, coef, self.d, coef) elif self.d != 1: text = "\\dfrac{%s}{%s}" % (self.n, self.d) else: text = "%s" % self.n else: text = "0" return text def TeXProduit(self, fraction): if self.d < 0: (self.n, self.d) = (-self.n, -self.d) if fraction.d < 0: (fraction.n, fraction.d) = (-fraction.n, -fraction.d) c1 = abs(Arithmetique.pgcd(self.n, fraction.d)) c2 = abs(Arithmetique.pgcd(self.d, fraction.n)) simplifiable = 0 # permet de savoir si on a simplifiée le produit if c1 > 1: n1 = "%s \\times \\cancel{%s}" % (self.n // c1, c1) d2 = "%s \\times \\cancel{%s}" % (fraction.d // c1, c1) else: n1 = self.n d2 = fraction.d if c2 > 1: d1 = "%s \\times \\bcancel{%s}" % (self.d // c2, c2) n2 = "%s \\times \\bcancel{%s}" % (fraction.n // c2, c2) else: d1 = self.d n2 = fraction.n return "%s \\times %s" % (Fractions.TeX(Fractions(n1, d1), signe= None), Fractions.TeX(Fractions(n2, d2), signe=None)) def TeXSimplifie(self): frs = Fractions.simplifie(self) coef = abs(self.n // frs.n) if coef > 1: texte = \ "\\dfrac{%s_{\\times \\cancel %s}}{%s_{\\times \\cancel %s}}" % \ (self.n // coef, coef, self.d // coef, coef) else: texte = Fractions.TeX(self, signe=None) return texte def __add__(self, fraction): if (isinstance(fraction,int) or isinstance(fraction,float)): fraction=Fractions(fraction) if isinstance(fraction,Fractions): ppcm = Arithmetique.ppcm(self.d, fraction.d) return Fractions((self.n * ppcm) // self.d + (fraction.n * ppcm) // fraction.d, ppcm) else: return fraction+self def __radd__(self,other): return self+other def __sub__(self, fraction): return self + (-fraction) def __rsub__(self,other): return (-self) + other def __mul__(self, fraction): if (isinstance(fraction,int) or isinstance(fraction,float)): fraction=Fractions(fraction) if isinstance(fraction,Fractions): return Fractions(self.n * fraction.n, self.d * fraction.d) else: return fraction*self def __rmul__(self,other): return self*other #def __truediv__(self, fraction): # pour Python 3 def __div__(self, fraction): if (isinstance(fraction,int) or isinstance(fraction,float)): fraction=Fractions(fraction) if isinstance(fraction,Fractions): return Fractions(self.n * fraction.d, self.d * fraction.n) else: return self*~fraction def __rdiv__(self,other): return other*~self def __invert__(self): return Fractions(self.d,self.n) def __neg__(self): return Fractions(-self.n,self.d) def __pow__(self,n): result=1 for i in range(n): result=result*self return result def __trunc__(self): return self.n//self.d def __lt__(self, other): if isinstance(other,int) or isinstance(other,float): other=Fractions(other) if other.d*self.d > 0: return self.n*other.d < self.d * other.n else : return not(self.n*other.d < self.d * other.n) def __le__(self, other): if isinstance(other,int) or isinstance(other,float): other=Fractions(other) if other.d*self.d > 0: return self.n*other.d <= self.d * other.n else : return not(self.n*other.d <= self.d * other.n) def __eq__(self, other): if isinstance(other,int) or isinstance(other,float): other=Fractions(other) if isinstance(other,Fractions): return self.n*other.d == self.d * other.n def __ne__(self, other): if isinstance(other,int) or isinstance(other,float): other=Fractions(other) return self.n*other.d != self.d * other.n def __gt__(self, other): if isinstance(other,int) or isinstance(other,float): other=Fractions(other) if other.d*self.d > 0: return self.n*other.d > self.d * other.n else : return not(self.n*other.d > self.d * other.n) def __ge__(self, other): if isinstance(other,int) or isinstance(other,float): other=Fractions(other) if other.d*self.d > 0: return self.n*other.d >= self.d * other.n else : return not(self.n*other.d >= self.d * other.n) def __float__(self): return 1.0*self.n/self.d def __int__(self): try: assert (self.n / self.d == int(self.n / self.d)), 'La fraction n\'est pas un nombre entier !' return int(self.n) except AssertionError, args: print '%s: %s' % (args.__class__.__name__, args) pyromaths/src/classes/._Vecteurs.py0000644000175000017500000000031511702101415020074 0ustar didrocksdidrocksMac OS X  2ATTRG޽55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/classes/Terme.py0000644000175000017500000000525411702101415017142 0ustar didrocksdidrocks# -*- coding: utf-8 -*- class Terme: def __init__(self, coeff, puiss = 1, var = 'x'): if (not (isinstance(puiss, int))) or (not (isinstance(var, str))): print "Erreur de définition ! La puissance doit être un nombre relatif !" self.puiss = puiss # Nombre entier self.coeff = coeff # Coeff devant le terme self.var = var # Lettre pour la var def __add__(self, other): if not (isinstance(other, Terme)): return str(self) + " + " + str(other) if (self.puiss == other.puiss) and (self.var == other.var): return Terme(self.coeff + other.coeff, self.puiss, self.var) else: return str(self) + " + " + str(other) def __radd__(self, other): return self + other def __sub__(self, other): if not (isinstance(other, Terme)): return str(self) + " + " + str(other) if (self.puiss == other.puiss) and (self.var == other.var): return Terme(self.coeff - other.coeff, self.puiss, self.var) else: return str(self) + " - " + str(other) def __rsub__(self, other): return -(self - other) def __mul__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Terme(self.coeff * other, self.puiss, self.var) elif self.var == other.var: return Terme(self.coeff * other.coeff, self.puiss + other.puiss, self.var) else: return Terme(self.coeff * other.coeff, self.puiss + other.puiss, self.var + other.var) def __rmul__(self, other): return self * other def __div__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Terme(self.coeff / other, self.puiss, self.var) elif self.var == other.var: return Terme(self.coeff / other.coeff, self.puiss - other.puiss, self.var) else: return str(self.coeff / other.coeff) + str(Terme(1, self.puiss, self.var)) + " / " + str(Terme(1, other.puiss, other.var)) def __rdiv__(self, other): return self.inv() * other def inv(self): return Terme(1.0 / self.coeff, - self.puiss, self.var) def __str__(self): if self.coeff == 1: coeff = '' elif self.coeff == -1: coeff = '-' else: coeff = str(self.coeff) + ' ' if self.puiss == 1: terme = self.var elif (self.puiss == 0) and ((self.coeff == 1) or (self.coeff == -1)): terme = '1' elif self.puiss == 0: terme = '' else: terme = self.var + u'^' + str(self.puiss) return coeff + terme pyromaths/src/pyromaths.py0000755000175000017500000000543511702101415016463 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from sys import argv, exit import sys from os import access, R_OK, makedirs, chdir from os.path import join, isdir, dirname, realpath, split from codecs import open def main(): #=============================================================================== # Imports spécifiques à Pyromaths #=============================================================================== from outils.System import create_config_file, modify_config_file from outils.TestEnv import test from Values import CONFIGDIR import interface from PyQt4 import QtGui, QtCore class StartQT4(QtGui.QMainWindow, interface.Ui_MainWindow): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.ui = interface.Ui_MainWindow() self.ui.setupUi(self) #=========================================================================== # Création du fichier de configuration si inexistant #=========================================================================== if not access(join(CONFIGDIR, "pyromaths.xml"), R_OK): if not isdir(CONFIGDIR): makedirs(CONFIGDIR) f = open(join(CONFIGDIR, "pyromaths.xml"), encoding='utf-8', mode='w') f.write(u"" + create_config_file()) f.close() modify_config_file(join(CONFIGDIR, "pyromaths.xml")) templatesdir = join(CONFIGDIR, "templates") if not isdir(templatesdir): makedirs(templatesdir) packagesdir = join(CONFIGDIR, "packages") if not isdir(packagesdir): makedirs(packagesdir) app = QtGui.QApplication(argv) pyromaths = StartQT4() pyromaths.show() test(pyromaths) exit(app.exec_()) if __name__ == "__main__": basedir = dirname(realpath(__file__)) _path, _dir = split(basedir) sys.path[0] = realpath(_path) exec("from %s import pyromaths" % _dir) pyromaths.main() pyromaths/src/lycee/0000755000175000017500000000000011734627250015171 5ustar didrocksdidrockspyromaths/src/lycee/ExoPolynome.py0000644000175000017500000011476511702101415020020 0ustar didrocksdidrocks# -*- coding: utf-8 -*- from random import randrange from ..classes.Polynome import Fractions,Polynome, pTeX, TeX,simplifie_racine, RacineDegre2, radicalTeX, sqrt, fTeX from ..outils.Polynomes import poly_racines_entieres, poly_racines_fractionnaires, poly_racines_quelconques, poly_id_remarquables,poly_degre3_racines_entieres, TeX_division, poly_degre3_racines_fractionnaires, randint from ..outils.decimaux import decimaux from ..outils.Arithmetique import pgcd Fractions=Fractions.Fractions def exo_racines_degre2(): '''exercice recherche de racines second degré''' exo=["\\exercice"] cor=["\\exercice*"] #intervalle pour les racines entières ou fractionnaire rac_min=-10 rac_max=10 #denominateur maximmum pour les racines fractionnaires denom_max=denom1=12 #Valeurs absolues maximales des coefficients d'un polynôme quelconque abs_a=1 abs_b=10 abs_c=10 #X est le polynome P=x pour faciliter la construction des polynômes, inconnues=['x','y','z','t'] nom_poly=['P','Q','R','S'] exo.append(u"Résoudre les équations suivantes :") cor.append(u"Résoudre les équations suivantes :") exo.append("\\begin{enumerate}") cor.append("\\begin{enumerate}") #Racines entières nomP='P' var=inconnues[randrange(4)] X=Polynome({1:1},var) P=poly_racines_entieres(rac_min,rac_max,X) exo.append("\\item $%s=0$\\par"%(P(var))) cor.append("\\item $%s=0$\\par"%(P(var))) cor=redaction_racines(P,nomP,var,cor) #Racines fractionnaires nomP='P' var=inconnues[randrange(4)] X=Polynome({1:1},var) P=poly_racines_fractionnaires(rac_min,rac_max,denom_max,X) exo.append("\\item $%s=0$\\par"%(P(var))) cor.append("\\item $%s=0$\\par"%(P(var))) cor=redaction_racines(P,nomP,var,cor) #Racines quelconques nomP='P' var=inconnues[randrange(4)] X=Polynome({1:1},var) P=poly_racines_quelconques(abs_a,abs_b,abs_c,X) exo.append("\\item $%s=0$\\par"%(P(var))) cor.append("\\item $%s=0$\\par"%(P(var))) redaction_racines(P,nomP,var,cor) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def exo_factorisation_degre2(): '''exercice recherche de racines second degré''' exo=["\\exercice"] cor=["\\exercice*"] #intervalle pour les racines entières ou fractionnaire rac_min=-10 rac_max=10 #X est le polynome P(x)=x pour faciliter la construction des polynômes, inconnues=['x','y','z','t'] nom_poly=['P','Q','R','S'] exo.append(u"Factoriser les polynômes suivants :") #cor=[]u"Factoriser les polynômes suivants :"] exo.append("\\begin{enumerate}") cor.append("\\begin{enumerate}") ####identites remarquables nomP=nom_poly[randrange(4)] var=inconnues[randrange(4)] X=Polynome({1:1},var) P,sgns=poly_id_remarquables(rac_min,rac_max,X)#sgns=-2,0 ou 2 exo.append(u"\\item Factoriser $%s(%s)=%s$ à l'aide d'une identité remarquable."% (nomP,var,P(var))) cor.append("\\item Factoriser $%s(%s)=%s$"% (nomP,var,P(var))) factorisation,racines=factorise_identites_remarquables(P,sgns,var,racines=True) factorise="$$%s"% P for i in range(len(factorisation)): factorise+="="+factorisation[i] cor.append(factorise+"$$") ####Racines entières nomP=nom_poly[randrange(4)] var=inconnues[randrange(4)] X=Polynome({1:1},var) P=poly_racines_entieres(rac_min,rac_max,X) exo.append("\\item $%s(%s)=%s$"%(nomP,var,P(var))) cor.append("\\item Factoriser $%s(%s)=%s$\\par"%(nomP,var,P(var))) exo,cor=redaction_factorisation(P,nomP,exo,cor) ####Racines fractionnaires nomP=nom_poly[randrange(4)] var=inconnues[randrange(4)] X=Polynome({1:1},var) #denominateur maximmum pour les racines fractionnaires denom_max=12 P=poly_racines_fractionnaires(rac_min,rac_max,denom_max,X) exo.append("\\item $%s(%s)=%s$"%(nomP,var,P(var))) cor.append("\\item Factoriser $%s(%s)=%s$\\par"%(nomP,var,P(var))) exo,cor=redaction_factorisation(P,nomP,exo,cor) ####Racines quelconques nomP=nom_poly[randrange(4)] var=inconnues[randrange(4)] X=Polynome({1:1},var) #Valeurs absolues maximales des coefficients d'un polynôme quelconque abs_a=1 abs_b=10 abs_c=10 P=poly_racines_quelconques(abs_a,abs_b,abs_c,X) exo.append("\\item $%s(%s)=%s$"%(nomP,var,P(var))) cor.append("\\item Factoriser $%s(%s)=%s$\\par"%(nomP,var,P(var))) exo,cor=redaction_factorisation(P,nomP,exo,cor) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def exo_factorisation_degre3(): '''exercice de factorisation degre3''' #intervalle pour les racines entières ou fractionnaire rac_min=-10 rac_max=10 #denominateur maximmum pour les racines fractionnaires denom_max=denom1=12 #Valeurs absolues maximales des coefficients d'un polynôme quelconque abs_a=1 abs_b=10 abs_c=10 #X est le polynome P=x pour faciliter la construction des polynômes, TODO : changer l'inconnue inconnues=['x','y','z','t'] nom_poly=['P','Q','R','S'] exo=["\\exercice", "\\begin{enumerate}"] cor=["\\exercice*", "\\begin{enumerate}"] X=Polynome({1:1},var="x") racines_quelconques=[i for i in range(-10,11)] E=poly_degre3_racines_entieres(rac_min,rac_max,X,racines=racines_quelconques) exo,cor=factorisation_degre3(E,"E",exo,cor,racines=racines_quelconques) F=poly_degre3_racines_fractionnaires(rac_min,rac_max,denom1,X) exo,cor=factorisation_degre3(F,"F",exo,cor) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def exo_tableau_de_signe(): #intervalle pour les racines entières ou fractionnaire rac_min=-10 rac_max=10 #denominateur maximmum pour les racines fractionnaires denom_max=denom1=12 #Valeurs absolues maximales des coefficients d'un polynôme quelconque abs_a=1 abs_b=10 abs_c=10 #X est le polynome P=x pour faciliter la construction des polynômes, TODO : changer l'inconnue inconnues=['x','y','z','t'] nom_poly=['P','Q','R','S'] borneinf=-5#float("-inf") bornesup=5#float("inf") var="x" X=Polynome({1:1},var=var) Poly=[poly_racines_entieres(rac_min,rac_max,X), poly_racines_fractionnaires(rac_min,rac_max,denom1,X), poly_racines_quelconques(abs_a,abs_b,abs_c,X)] intervalles=[[0,5],[-5,5],[float("-inf"),float("inf")]] exo=["\\exercice", "\\begin{enumerate}"] cor=["\\exercice*", "\\begin{enumerate}"] nomP="P" for i in range(len(Poly)): P=Poly[i] borneinf,bornesup=intervalles[i] if borneinf==float("-inf") and bornesup==float("inf"): TeXintervalle="\\mathbb R" else: if borneinf!=float("-inf"): TeXintervalle="[" else: TeXintervalle="]" TeXintervalle+="%s~;~%s"%(TeX(borneinf),TeX(bornesup)) if bornesup==float("inf"): TeXintervalle+="[" else: TeXintervalle+="]" exo.append(u"\\item Étudier le signe du polynôme $%s=%s$ sur $I=%s$." % (nomP,P,TeXintervalle)) cor.append(u"\\item Étudier le signe du polynôme $%s=%s$ sur $I=%s$.\\par" % (nomP,P,TeXintervalle)) delta,simplrac,racines,str_racines,factorisation=factorisation_degre2(P,factorisation=False) redaction_racines(P,nomP,var,cor) tableau_de_signe(P,nomP,delta,racines,cor,borneinf,bornesup,detail=False) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def exo_variation(): exo=["\\exercice", "\\begin{enumerate}"] cor=["\\exercice*", "\\begin{enumerate}"] quest1,cor1=quest_fonctions_rationnelles() quest2,cor2=quest_variation_degre3(borneinf=-10,bornesup=10) exo+=quest1+quest2 cor+=cor1 + cor2 exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def exo_variation_lim(): """Étude de fonctions avec calculs de limites""" exo=["\\exercice", "\\begin{enumerate}"] cor=["\\exercice*", "\\begin{enumerate}"] quest3,cor3=quest_variation_degre3(borneinf=float("-inf"),bornesup=float("+inf")) quest4,cor4=quest_fonctions_rationnelles_sur_R() exo+=quest3+quest4 cor+= cor3 +cor4 exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def quest_fonctions_rationnelles(): nomf=['f','g','h','k'][randrange(4)] var=['t','x'][randrange(2)] X=Polynome({1:1},var) #intervalle pour les racines entières ou fractionnaire rac_min=-9 rac_max=9 b1=b2=a1=a2=0 while b1==0 or b2==0 or a1==0 or a2==0: b1=randint(rac_min,rac_max) b2=randint(rac_min,rac_max) a1=randint(-5,5) a2=randint(-5,5) P=a1*X+b1 Q=a2*X+b2 borneinf=-10 bornesup=10 #Je veux que f soit définie et dérivable sur I=Intervalle if (-Q[0]/Q[1])>=borneinf and (-Q[0]/Q[1])<=bornesup: if ((-Q[0]/Q[1])-borneinf)<(bornesup-(-Q[0]/Q[1])): Intervalle=[int(round(-Q[0]/Q[1]))+1,bornesup] else: Intervalle=[borneinf,int(round(-Q[0]/Q[1]))-1] #dérivée numerateur="%s\\times%s-%s\\times%s"%(P.derive().TeX(parenthese=True),Q.TeX(parenthese=True), P.TeX(parenthese=True),Q.derive().TeX(parenthese=True)) numerateur_simplifie=(P.derive()*Q-P*Q.derive()).simplifie() denominateur=u"%s^2"%(Q.TeX(parenthese=True)) f_derivee="\\dfrac{%s}{%s}"%(numerateur,denominateur) f_derivee_simplifiee="\\dfrac{%s}{%s}"%(numerateur_simplifie,denominateur) VI=(-Q[0]*Fractions(1)/Q[1]).simplifie() exo=[u"\\item On considère la fonction $%s$ définie sur $I=[%s~;~%s]$ par $%s(%s)=\dfrac{%s}{%s}$."%(nomf,Intervalle[0],Intervalle[1],nomf,var,P,Q), "\\begin{enumerate}"] cor=[u"\\item On considère la fonction $%s$ définie sur $I=[%s~;~%s]$ par $%s(%s)=\dfrac{%s}{%s}$."%(nomf,Intervalle[0],Intervalle[1],nomf,var,P,Q), "\\begin{enumerate}"] exo.append(u"\\item Justifier que $%s$ est définie et dérivable sur $I$."%(nomf)) cor.append(u"\\item Justifier que $%s$ est définie et dérivable sur $I$."%(nomf)) cor.append(u" Pour déterminer la valeur interdite, on doit résoudre $%s=0$."%(Q(var))) cor.append("\\begin{align*}") cor.append("%s&=0\\\\"% Q) cor.append("%s&=%s"%((Q-Q[0]),TeX(-Q[0]))) cor.append("\\\\") if Q[1]!=1: x0=-Q[0]*Fractions(1)/Q[1] x1=x0.simplifie() cor.append("%s&=%s"%(var,TeX(-Q[0]*Fractions(1)/Q[1]))) cor.append("\\\\") if x0.denominateur!=x1.denominateur: cor.append("%s&=%s"%(var,TeX(x1))) cor.append("\\\\") cor.pop(-1) cor.append("\\end{align*}") cor.append(u"Or $%s$ n'est pas dans l'intervalle $[%s~;~%s]$ et comme $%s$ est un quotient de polynômes, alors $%s$ est définie et dérivable sur $I$."%\ (TeX(VI),Intervalle[0],Intervalle[1],nomf,nomf)) exo.append(u"\\item Déterminer $%s'(%s)$ pour tout $%s\in[%s~;~%s]$."%\ (nomf,var,var,Intervalle[0],Intervalle[1])) cor.append(u"\\item Déterminer $%s'(%s)$ pour tout $%s\in[%s~;~%s]$."%\ (nomf,var,var,Intervalle[0],Intervalle[1])) cor.append(u"$$%s'(%s)=%s=%s$$"%(nomf,var,f_derivee,f_derivee_simplifiee)) exo.append(u"\\item En déduire le sens de variations de $%s$ sur $I$."%(nomf)) cor.append(u"\\item En déduire le sens de variations de $%s$ sur $I$.\\par"%(nomf)) if numerateur_simplifie.degre_max==0: cor.append(u" Comme $%s$ est un carré, il est toujours positif.\\\\"%(denominateur)) f_xmin=TeX((Fractions(1)*P(Intervalle[0])/Q(Intervalle[0])).simplifie()) f_xmax=TeX((Fractions(1)*P(Intervalle[1])/Q(Intervalle[1])).simplifie()) if numerateur_simplifie[0]<0: cor.append(u" De plus, $%s<0$ donc pour tout $%s$ de $I$, $%s'(%s)<0$. Ainsi, on obtient "%\ (numerateur_simplifie[0],var,nomf,var)) cor.append("$$\\tabvar{") cor.append("\\tx{%s}&\\tx{%s}&&\\tx{%s}\\cr"%(var,TeX(Intervalle[0]),TeX(Intervalle[1]))) cor.append("\\tx{%s'(%s)}&&\\tx{-}&&\\cr"%(nomf,var)) cor.append("\\tx{%s}&\\txh{%s}&\\fd&\\txb{%s}\\cr"%(nomf,f_xmin,f_xmax)) cor.append("}$$") else: cor.append(u" De plus, $%s>0$ donc pour tout $%s$ de $I$, $%s'(%s)>0$."%\ (numerateur_simplifie[0],var,nomf,var)) cor.append("$$\\tabvar{") cor.append("\\tx{%s}&\\tx{%s}&&\\tx{%s}\\cr"%(var,TeX(Intervalle[0]),TeX(Intervalle[1]))) cor.append("\\tx{%s'(%s)}&&\\tx{+}&&\\cr"%(nomf,var)) cor.append("\\tx{%s}&\\txb{%s}&\\fm&\\txh{%s}\\cr"%(nomf,f_xmin,f_xmax)) cor.append("}$$") else: cor.append(u" Je ne sais pas faire avec un tel numérateur $%s$."%(numerateur_simplifie)) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def quest_fonctions_rationnelles_sur_R(): nomf=['f','g','h','k'][randrange(4)] var=['t','x'][randrange(2)] X=Polynome({1:1},var) #intervalle pour les racines entières ou fractionnaire rac_min=-9 rac_max=9 b1=b2=a1=a2=0 while b1==0 or b2==0 or a1==0 or a2==0 or a1*(-float(b2)/a1)+b1==0 or (a1*b2/a2 - b1)==0: #(a1*b2/a2 - b1)==0 on teste que la racine de Q n'annule pas P donc on ne peut pas simplifier b1=randint(rac_min,rac_max) b2=randint(rac_min,rac_max) a1=randint(-5,5) a2=randint(-5,5) P=a1*X+b1 Q=a2*X+b2 borneinf=float("-inf") bornesup=float("+inf") Intervalle=[borneinf,bornesup] TeXintervalle="\\mathbb R" #dérivée numerateur="%s\\times%s-%s\\times%s"%(P.derive().TeX(parenthese=True),Q.TeX(parenthese=True), P.TeX(parenthese=True),Q.derive().TeX(parenthese=True)) numerateur_simplifie=(P.derive()*Q-P*Q.derive()).simplifie() VI=(-Q[0]*Fractions(1)/Q[1]).simplifie() denominateur=u"%s^2"%(Q.TeX(parenthese=True)) f_derivee="\\dfrac{%s}{%s}"%(numerateur,denominateur) f_derivee_simplifiee="\\dfrac{%s}{%s}"%(numerateur_simplifie,denominateur) exo=[u"\\item On considère la fonction $%s$ définie par $%s(%s)=\\dfrac{%s}{%s}$."%(nomf,nomf,var,P,Q), "\\begin{enumerate}"] cor=[u"\\item On considère la fonction $%s$ définie par $%s(%s)=\\dfrac{%s}{%s}$."%(nomf,nomf,var,P,Q), "\\begin{enumerate}"] exo.append(u"\\item Déterminer l'ensemble de définition $\\mathcal{D}_{%s}$ de $%s$."%(nomf,nomf)) cor.append(u"\\item Déterminer l'ensemble de définition $\\mathcal{D}_{%s}$ de $%s$.\par"%(nomf,nomf)) cor.append(u" La fonction rationnelle $%s$ est définie et dérivable en $%s$ si $%s\\neq0$."%(nomf,var,Q(var))) cor.append("\\begin{align*}\n\ %s&=0\\\\\n\ %s&=%s\\\\\n\ %s&=%s\\\\\n\ %s&=%s\n\ \\end{align*}"%(Q,(Q-Q[0]),TeX(-Q[0]),var,TeX(-Q[0]*Fractions(1)/Q[1]),var,TeX(VI))) cor.append(u"On en déduit que $\\mathcal{D}_{%s}=\\mathcal{D'}_{%s}=]-\\infty~;~%s[\cup]%s~;~+\\infty[$."%\ (nomf,nomf,TeX(VI),TeX(VI))) exo.append(u"\\item Déterminer $%s'(%s)$ pour tout $%s\in\\mathcal{D'}_{%s}$."%\ (nomf,var,var,nomf)) cor.append(u"\\item Déterminer $%s'(%s)$ pour tout $%s\in\\mathcal{D'}_{%s}$."%\ (nomf,var,var,nomf)) cor.append(u"$$%s'(%s)=%s=%s$$"%(nomf,var,f_derivee,f_derivee_simplifiee)) exo.append(u"\\item Déterminer les limites de $%s$ aux bornes de $\\mathcal{D}_{%s}$."%(nomf,nomf)) cor.append(u"\\item Déterminer les limites de $%s$ aux bornes de $\\mathcal{D}_{%s}$."%(nomf,nomf)) limite = P[1]/Q[1] limite_simple = limite.simplifie() cor.append("$$\\lim_{%s\\to -\\infty}\\dfrac{%s}{%s}= "%(var,P,Q)) cor.append("\\lim_{%s\\to -\\infty}\\dfrac{%s%s}{%s%s} = %s" %(var,coeffTeX(P[1]),var,coeffTeX(Q[1]),var,limite)) if limite.n == limite_simple.n: cor.append("$$") else: cor.append("= %s $$"%(TeX(limite_simple))) cor.append("$$\\lim_{%s\\to +\\infty}\\dfrac{%s}{%s}= "%(var,P,Q)) cor.append("\\lim_{%s\\to +\\infty}\\dfrac{%s%s}{%s%s} = %s" %(var,coeffTeX(P[1]),var,coeffTeX(Q[1]),var,limite)) if limite.n == limite_simple.n: cor.append("$$") else: cor.append("= %s $$"%(TeX(limite_simple))) cor.append("Pour $%s=%s$, on a $%s=%s"%(var,TeX(VI),P,TeX(P(VI)))) if P(VI)<0: limites=["-\\infty","+\\infty"] cor.append("<0$.\\\\") elif P(VI)>0: limites=["+\\infty","-\\infty"] cor.append(">0$.\\\\") else:cor.append("$.\\\\") #Impossible car on test (a1*b2/a2 - b1)!=0 VIplus="\\substack{%s\\to %s\\\\%s>%s}"%(var,fTeX(VI),var,fTeX(VI)) VImoins="\\substack{%s\\to %s\\\\%s<%s}"%(var,fTeX(VI),var,fTeX(VI)) if Q[1]<0: cor.append("De plus, $%s>0$ si $%s<%s$"%(Q,var,TeX(VI))) cor.append("et $%s<0$ si $%s>%s$.\\\\"%(Q,var,TeX(VI))) cor.append(u"$$\\lim_{%s}\\dfrac{%s}{%s}=%s $$"%(VImoins,P,Q,limites[0])) cor.append(u"$$\\lim_{%s}\\dfrac{%s}{%s}=%s $$"%(VIplus,P,Q,limites[1])) else: cor.append("De plus, $%s<0$ si $%s<%s$"%(Q,var,TeX(VI))) cor.append("et $%s>0$ si $%s>%s$.\\\\"%(Q,var,TeX(VI))) cor.append(u"$$\\lim_{%s}\\dfrac{%s}{%s}=%s $$"%(VImoins,P,Q,limites[0])) cor.append(u"$$\\lim_{%s}\\dfrac{%s}{%s}=%s $$"%(VIplus,P,Q,limites[1])) exo.append(u"\\item Dresser le tableau de variations de $%s$ sur $\\mathcal{D}_{%s}$."%(nomf,nomf)) cor.append(u"\\item Dresser le tableau de variations de $%s$ sur $\\mathcal{D}_{%s}$.\\par"%(nomf,nomf)) if numerateur_simplifie.degre_max==0: cor.append(u" Comme $%s$ est un carré, il est toujours positif.\\\\"%(denominateur)) f_xmin = TeX((P[1]/Q[1]).simplifie()) f_xmax = f_xmin if numerateur_simplifie[0]<0: cor.append(u" De plus, $%s<0$ donc pour tout $%s$ de $I$, $%s'(%s)<0$. Ainsi, on obtient "%\ (numerateur_simplifie[0],var,nomf,var)) cor.append("$$\\tabvar{") cor.append("\\tx{%s}&\\tx{%s}&&&\\tx{%s}&&&\\tx{%s}\\cr"%(var,TeX(Intervalle[0]),TeX(VI),TeX(Intervalle[1]))) cor.append("\\tx{%s'(%s)}&&\\tx{-}&&\\dbt &&\\tx{-}&\\cr"%(nomf,var)) cor.append("\\tx{%s}&\\txh{%s}&\\fd&\\txb{-\\infty}&\\dbt&\\txh{+\\infty}&\\fd&\\txb{%s}\\cr"%(nomf,f_xmin,f_xmax)) cor.append("}$$") else: cor.append(u" De plus, $%s>0$ donc pour tout $%s$ de $I$, $%s'(%s)>0$."%\ (numerateur_simplifie[0],var,nomf,var)) cor.append("$$\\tabvar{") cor.append("\\tx{%s}&\\tx{%s}&&&\\tx{%s}&&&\\tx{%s}\\cr"%(var,TeX(Intervalle[0]),TeX(VI),TeX(Intervalle[1]))) cor.append("\\tx{%s'(%s)}&&\\tx{+}&&\\dbt&&\\tx{+}&\\cr"%(nomf,var)) cor.append("\\tx{%s}&\\txb{%s}&\\fm&\\txh{+\\infty}&\\dbt&\\txb{-\\infty}&\\fm&\\txh{%s}\\cr"%(nomf,f_xmin,f_xmax)) cor.append("}$$") else: cor.append(u" Je ne sais pas faire avec un tel numérateur $%s$."%(numerateur_simplifie)) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def coeffTeX(a): if a==1:return "" if a==-1:return "-" return a def quest_variation_degre3(borneinf=float("-inf"),bornesup=float("+inf")): '''Question qui propose l'étude du sens de variation d'un polynôme de degré 3''' Intervalle=[borneinf,bornesup] if borneinf==float("-inf") and bornesup==float("+inf"): TeX_intervalle="\\mathbb R" else: TeX_intervalle="\\left[%s~;~%s\\right]"%(TeX(borneinf),TeX(bornesup)) #intervalle pour les racines entières ou fractionnaire a=3*randint(1,3) rac_min=-9 rac_max=9 #denominateur maximmum pour les racines fractionnaires denom_max=denom1=12 #Valeurs absolues maximales des coefficients d'un polynôme quelconque abs_a=6 abs_b=10 abs_c=10 #X est le polynome P=x pour faciliter la construction des polynômes, inconnues=['x','y','z','t'] nom_poly=['P','Q','R','S'] var="x" X=Polynome({1:1},var=var) nomP=["f","g","h","k","p","q"][randrange(6)] Pprime=poly_racines_entieres(rac_min,rac_max,X,a1=a) P=Pprime.primitive()+randint(-abs_c,abs_c) P=P.simplifie() exo=[u"\\item Étudier le sens de variations de $%s$ définie par $%s(x)=%s$ sur $%s$." % (nomP,nomP,P(var),TeX_intervalle)] cor=[u"\\item Étudier le sens de variations de $%s$ définie par $%s(x)=%s$ sur $%s$." % (nomP,nomP,P(var),TeX_intervalle)] cor.append("\\par $%s'(x)=%s$\\\\" % (nomP,Pprime(var))) cor.append(u"Je dois étudier le signe de $%s'(%s)$ qui est un polynôme du second degré.\\par"%(nomP,var)) delta,simplrac,racines,str_racines,factorisation=factorisation_degre2(Pprime,factorisation=False) #cor=redaction_factorisation(Pprime,nomP+"'",exo=[],cor=cor)[1] #cor.pop(-5) redaction_racines(Pprime,nomP+"'",var,cor) str_signe,str_valeurs,signes,ligne_valeurs=tableau_de_signe(Pprime,nomP+"'",delta,racines,cor,borneinf,bornesup,detail=True) #cor.append(tab_signe) if (delta<=0 and P[3]<0): cor+=u"Donc la fonction polynômiale $%s$ est décroissante sur $%s$." %(nomP,TeX_intervalle) elif (delta<=0 and P[3]>0): cor.append(u"Donc la fonction polynômiale $%s$ est croissante sur $%s$."%(nomP,TeX_intervalle)) else: cor.append("On obtient ainsi le tableau de variation de $%s$."%nomP) [x1,x2]=racines #macro=[["txb","txh"],["fm","fd"]] var_de_P="\\tx{%s}& \\%s{\\rnode{neu0}{%s}}&&"%(nomP,["txb","txh"]["-"==signes[0]],TeX(P(ligne_valeurs[0]))) compteur=0 for i in range(0,len(signes)-1): if signes[i]=='+': if 0 and signes[i+1]=="+": var_de_P+="&&" else: compteur+=1 var_de_P+="\\txh{\\rnode{neu%s}{%s}}&&"%(compteur,TeX(P(ligne_valeurs[i+1]))) else: if 0 and signes[i+1]=="-": var_de_P+="&&" else: compteur+=1 var_de_P+="\\txb{\\rnode{neu%s}{%s}}&&"%(compteur,TeX(P(ligne_valeurs[i+1]))) compteur+=1 if signes[-1]=="+": var_de_P+="\\txh{\\rnode{neu%s}{%s}}\\cr"%(compteur,TeX(P(ligne_valeurs[-1]))) else: var_de_P+="\\txb{\\rnode{neu%s}{%s}}\\cr"%(compteur,TeX(P(ligne_valeurs[-1]))) cor.append("$$ \\tabvar{\n %s\n %s\n %s}$$"%\ (str_valeurs,str_signe,var_de_P)) for i in range(1,compteur+1): cor.append("\\ncline[nodesep=0.15,linewidth=0.5pt]{->}{neu%s}{neu%s}"%(i-1,i)) if borneinf==float("-inf"): cor.append(u"$$\\lim_{%s\\to %s} %s= \\lim_{%s\\to %s} %s%s^3=%s $$ "%(var,"-\\infty",P,var,"-\\infty",P[3],var,TeX(P(float("-inf"))))) if bornesup==float("+inf"): cor.append(u"$$\\lim_{%s\\to %s} %s= \\lim_{%s\\to %s} %s%s^3=%s $$ "%(var,"+\\infty",P,var,"+\\infty",P[3],var,TeX(P(float("inf"))))) return exo,cor ############################################### # # # Fonctions étudiant les polynômes # # # ############################################### def tableau_de_signe(P,nomP,delta,racines,cor,borneinf=float("-inf"),bornesup=float("+inf"),detail=False): '''Étudie le signe d'un polynôme de degré2''' ''' ne fonctionne pas si on a pas borneinf < x1< x2 0] #Ca donne bien ce qu'on veut... signes=[] if delta<0: cor.append("Comme $\\Delta <0$, $%s(%s)$ ne s'annule pas et est toujours du signe de $a$"%(nomP,var)) cor.append("Ainsi ") str_valeurs="\\tx{%s}&\\tx{%s}&& \\tx{%s}\\cr" %(var,TeX(borneinf),TeX(bornesup)) str_signe="\\tx{%s(%s)}&&\\tx{%s}&\\cr" %(nomP,var,signe_a) signes=[signe_a] ligne_valeurs=[borneinf,bornesup] elif delta == 0: cor.append("Comme $\\Delta =0$, $%s(%s)$ s'annule une seule fois pour $%s_0=%s$ et est toujours du signe de $a$.\par"%(nomP,var,var,racines[0])) if racines[0]bornesup: if borneinf!=float("-inf"): intervalle="[" else: intervalle="]" intervalle+="%s~;~%s"%(TeX(borneinf),TeX(bornesup)) if bornesup==float("inf"): intervalle+="[" else: intervalle+="]" cor.append("Or $%s$ n'est pas dans l'intervalle $%s$ donc "%(TeX(racines[0]),intervalle)) ligne_valeurs=[borneinf,bornesup] str_valeurs="\\tx{%s}&\\tx{%s}&& \\tx{%s}\\cr" %(var,TeX(borneinf),TeX(bornesup)) str_signe="\\tx{%s(%s)}&&\\tx{%s}&\\cr" %(nomP,var,signe_a) signes=[signe_a] else: ligne_valeurs=[borneinf,racines[0],bornesup] str_valeurs="\\tx{%s}&\\tx{%s}&& \\tx{%s}&& \\tx{%s}\\cr" %(var,TeX(borneinf),TeX(racines[0]),TeX(bornesup)) str_signe="\\tx{%s(%s)}&&\\tx{%s}&\\tx{0}&\\tx{%s}&\\cr" %(nomP,var,signe_a,signe_a) signes=[signe_a,signe_a] elif delta >0: [x1,x2]=racines cor.append("Comme $\\Delta >0$, $%s(%s)$ est du signe de $-a$ entre les racines."%(nomP,var)) compare=[(x1<=borneinf)+(x2<=borneinf),(x2>=bornesup)+(x1>=bornesup)] #x_x1=x_x2=sign_x1=sign_x2="" if compare!=[0,0]: if borneinf!=float("-inf"): intervalle="[" else: intervalle="]" intervalle+="%s~;~%s"%(TeX(borneinf),TeX(bornesup)) if bornesup==float("inf"): intervalle+="[" else: intervalle+="]" ligne_valeurs=[borneinf] if compare[0]>=1 or compare[1]==2: x_x1=sign_x1="" else: x_x1="&\\tx{%s}&"%(TeX(x1)) ligne_valeurs+=[x1] sign_x1="&\\tx{%s}&\\tx{0}"%(signe_a) signes+=[signe_a] if 2 in compare: entreracines="&\\tx{%s}"%(signe_a) signes+=[signe_a] else: entreracines="&\\tx{%s}"%(signe_moinsa) signes+=[signe_moinsa] if compare[1]>=1 or compare[0]==2: x_x2=sign_x2="" else: x_x2="&\\tx{%s}&"%(TeX(x2)) ligne_valeurs+=[x2] sign_x2="&\\tx{0}&\\tx{%s}"%(signe_a) signes+=[signe_a] ligne_valeurs+=[bornesup] #Ne rien dire si une racine est égale à une borne compare=[compare[0]-(x1==borneinf)-(x2==borneinf),compare[1]-(x1==bornesup)-(x2==bornesup)] if sum(compare)==2 : #les deux racines sont à supprimer cor.append("\\par Or $%s$ et $%s$ ne sont pas dans $%s$."%(TeX(x1),TeX(x2),intervalle)) elif compare[0]==1: cor.append("\\par Or $%s$ n'est pas dans $%s$."%(TeX(x1),intervalle)) elif compare[1]==1: cor.append("\\par Or $%s$ n'est pas dans $%s$."%(TeX(x2),intervalle)) cor.append("Ainsi") str_valeurs="\\tx{%s}& \\tx{%s}& %s %s & \\tx{%s}\\cr"%(var,TeX(borneinf),x_x1,x_x2,TeX(bornesup)) str_signe="\\tx{%s(%s)}&%s %s %s&\\cr" %(nomP,var,sign_x1,entreracines,sign_x2) cor.append("$$\\tabvar{") cor.append(str_valeurs) cor.append("%s}$$"%(str_signe)) if detail: return str_signe,str_valeurs,signes,ligne_valeurs def factorise_identites_remarquables(pol1,sgns,var='',racines=True): '''Factorise un polynomes grâce aux identités remarquables''' if var=='': var=pol1.var X=Polynome({1:1},var) a1=pgcd(int(pol1[0]),pgcd(int(pol1[1]),int(pol1[2])))#du signe de a=pol1[2] if a1!=1 or a1!=-1: pol2=pol1/a1 else: pol2=pol1 #coeff=coeff/int(math.sqrt(a1)) #pol2=(cx)^2 ±2× cx × b + b^2 #pol2[2]=c^2 #pol2[1]=2× cx × b #pol2[0] = b^2 c=int(sqrt(pol2[2]))#problème d'arrondi ? factorisation=[] if a1!=1: pol_temp = (pol1/a1).simplifie() pol_temp.var = var factorisation.append("%s \\times\\big[ %s \\big]"%(TeX(a1),pol_temp)) facteur2 ="%s\\times \\big["%(TeX(a1)) else: facteur2 ="" if c!=1: facteur2 +=u"(%s %s)^2"%(TeX(c),var) else: facteur2 +=u"%s^2"% var if sgns: if sgns==-2: #-2 => (a-b)² facteur2 +="-2 \\times " else: #+2 => (a+b)² facteur2 +="+2 \\times " if c==1: facteur2 +=var else: facteur2 +=TeX(c)+var b=int(sqrt(pol2[0])) facteur2 +=" \\times %s +"%(TeX(b)) else: #a²-b² facteur2 +="-" b=int(sqrt(-(pol2[0]))) facteur2 +=u"%s^2"%(TeX(b)) if a1!=1: facteur2 +="\\big]" factorisation.append(facteur2) facteur3="" if a1!=1: facteur3 +=TeX(a1) sgns=sgns/2 if sgns:#(cx-b)² ou (cx+b)² liste_racines=[Fractions(-(sgns))*b/c] facteur3 +="{(%s)}^2"%(c*X+sgns*b) else:#(cx-b)(cx+b) liste_racines=[Fractions(-1)*b/c,Fractions(1)*b/c] facteur3 +="(%s)(%s)"%(c*X+b,c*X-b) factorisation.append(facteur3) if racines: return factorisation,liste_racines return factorisation def racines_degre2(P): """renvoie les racines d'un polynôme de degré 2""" delta=int(P[1]**2-4*P[2]*P[0]) if delta==0: x0=Fractions(-1,2)*P[1]/P[2] liste_racines=[x0.simplifie()] liste_str_racines=["\\dfrac{-%s}{2\\times %s}"%(pTeX(P[1]),pTeX(P[2]))] simplrac=[False] elif delta>0: simplrac,strx1,x1,strx2,x2=listeracines(P[2],P[1],delta,parentheses=False) liste_racines=[x1,x2] liste_str_racines=[strx1,strx2] else: simplrac=[False] liste_racines=liste_str_racines=[] return delta,simplrac,liste_racines,liste_str_racines #delta #simplrac[0] est True si racine de Delta se simplifie, alors simplrac[1] est la racine de delta simplifiée #liste_racines donne la liste des racines sous la forme simplifiée, sous forme numérique si possible #liste_str_racine est la liste des racines au format TeX, non simplifié. def listeracines(a,b,delta,parentheses=False): '''renvoie racsimple,simplifie,formule_x1,x_1,formule_x2,x2''' '''avec x_10 simplrac est True si racine de delta se simplifie''' a=int(a) b=int(b) parenthesex1=parenthesex2=True #par défaut #simplrac=True strx1="\\dfrac{-%s-\\sqrt{%s}}{2\\times %s}"%(pTeX(b),TeX(delta),pTeX(a)) strx2="\\dfrac{-%s+\\sqrt{%s}}{2\\times %s}"%(pTeX(b),TeX(delta),pTeX(a)) ##on a strx10) parenthesex2=(coeff*a<0) if a<0: strx1,strx2,x1,x2,parenthesex1,parenthesex2=strx2,strx1,x2,x1,parenthesex2,parenthesex1 if parentheses: return simplrac,strx1,x1,strx2,x2,parenthesex1,parenthesex2 else: return simplrac,strx1,x1,strx2,x2 #simplrac[0] est True si racine de Delta se simplifie, alors simplrac[1] est la racine de delta simplifiée def factorisation_degre2(P,factorisation=True): #x1=x2=0 var=P.var X=Polynome({1:1},var) delta=int(P[1]**2-4*P[2]*P[0]) if delta<0: factorisation=[] str_racines=[] racines=[] simplrac=[False] elif delta==0: x0=Fractions(-1,2)*P[1]/P[2] simplrac=[False] racines=[x0.simplifie()] str_racines=["\\dfrac{-%s}{2\\times %s}"%(pTeX(P[1]),pTeX(P[2]))] P0="%s-%s"%(var,pTeX(racines[0])) factorisation=[[P0,P0]]#non simplifiée if 0>racines[0]: P0=X-racines[0] factorisation.append([P0,P0]) else:#delta>0 simplrac,strx1,x1,strx2,x2=listeracines(P[2],P[1],delta) if isinstance(x1,RacineDegre2): x1=x1.simplifie() x2=x2.simplifie() racines=[x1,x2] str_racines=[strx1,strx2] P1="%s-%s"%(var,pTeX(x1)) P2="%s-%s"%(var,pTeX(x2)) factorisation=[[P1,P2]]#non simplifiée #Peut-on simplifier les parenthèses ? if x1.radicande==0 and (x1.numerateur<0 or x2.numerateur<0): P1=(X-x1)(var) P2=(X-x2)(var) factorisation.append([P1,P2]) return delta,simplrac,racines,str_racines,factorisation def factorisation_degre3(E,nomE,exo=[],cor=[],racines=[0,1,-1,2,-2]): '''Factorise un polynôme de degré 3 avec une racine évidente''' var=E.var X=Polynome({1:1},var) exo.append("\\item Soit $%s =%s $"%(nomE,E)) cor.append("\\item Soit $%s=%s $"%(nomE,E)) exo.append("\\begin{enumerate}") cor.append("\\begin{enumerate}") for x0 in racines: if E(x0)==0: break if x0 in [-2,-1,0,1,2]: exo.append(u"\\item Vérifier si $%s $ possède une racine évidente."%(nomE)) else: exo.append(u"\\item Vérifier que $%s$ est une racine de $%s$."%(TeX(x0),nomE)) exo.append("\\item Factoriser $%s $."%(nomE)) cor.append("\\item ") if x0==0: degre_facteur=min(E.puiss) #degre_facteur=1 E2=(E/(X**degre_facteur))[0] if degre_facteur==1: cor.append("On remarque que $%s$ peut se factoriser par $%s$ et $%s=%s\\left(%s\\right)$" %(nomE,var,nomE,var,E2)) elif degre_facteur==2: cor.append(u"On remarque que $%s$ peut se factoriser par $%s^2$ et $%s=%s^2\\left(%s\\right)$"\ %(nomE,E.var,nomE,E.var,E2)) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor else: cor.append("Comme $%s(%s)=0$, on peut diviser $%s$ par $%s$"%(nomE,TeX(x0),nomE,X-x0)) cor.append(TeX_division(E,(X-x0))+"") E2,reste=E/(X-x0) cor.append("\\item On doit maintenant factoriser le polynome $%s_2=%s$\\\\"%(nomE,E2)) delta,simplrac,racines,str_racines,factorisation=factorisation_degre2(E2,factorisation=True) cor=redaction_factorisation(E2,nomP=nomE+"_2",exo=[],cor=cor)[1] cor.append("\\par") cor.append("On en conclue donc que $%s="%(nomE)) final=0 if x0==0: P0=E.var else: P0="\\left(%s\\right)"%(X-x0) if E[3]==-1: cor.append("-") elif E[3]!=1: cor.append(TeX(E[3])) if delta<0: P1=factorisation[-1][0] E_factorise="%s\\times%s$"%(P0,P1) elif delta==0: P1=factorisation[-1][0] E_factorise="%s\\times{\\left(%s\\right)}^2$"%(P0,P1) else: P1=factorisation[-1][0] P2=factorisation[-1][1] E_factorise="%s\\left(%s\\right)\\left(%s\\right)$"%(P0,P1,P2) cor.append(E_factorise) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor #----------------- redaction --------------------------------------------------------- def redaction_factorisation(P,nomP="P",exo=[],cor=[]): var=P.var delta,simpl_delta,racines,str_racines,factorisation=factorisation_degre2(P) redaction_racines(P,nomP,var,cor) #factorisation if delta<0: cor.append(u"On ne peut pas factoriser $%s(%s)$."%(nomP,var)) elif delta==0: cor.append(u"On peut donc écrire ") ligne_factorisation="$$%s(%s)"%(nomP,var) for etape in factorisation: ligne_factorisation+=" = " if P[2]!=1: ligne_factorisation+="%s \\times "%(TeX(P[2])) ligne_factorisation+="{\\left(%s\\right)}^2"%(etape[0]) ligne_factorisation+="$$" cor.append(ligne_factorisation) else: cor.append(u"On peut donc écrire ") ligne_factorisation="$$%s(%s)"%(nomP,var) for etape in factorisation: ligne_factorisation+=" = " if P[2]!=1: ligne_factorisation+="%s \\times "%(TeX(P[2])) if len(etape)==1: ligne_factorisation+=etape[0] else: ligne_factorisation+="\\left(%s\\right)\left(%s\\right)"%(etape[0],etape[1]) ligne_factorisation+="$$" cor.append(ligne_factorisation) return exo,cor def redaction_racines(P,nomP,var,cor=[]): delta,simpl_delta,liste_racines,liste_str_racines=racines_degre2(P) ligne_delta=u"Je calcule $\\Delta=%s^2-4\\times %s\\times %s=%s$"%(pTeX(P[1]),pTeX(P[2]),pTeX(P[0]),TeX(delta)) if simpl_delta[0]: ligne_delta+=" et $%s=%s$.\\par"%(radicalTeX(delta),simpl_delta[1]) else: ligne_delta+=".\\par" cor.append(ligne_delta) if delta<0: cor.append("Comme $\\Delta <0$, $%s(%s)$ n'a pas de racines."%(nomP,var)) elif delta==0: cor.append("Comme $\\Delta=0$, $%s(%s)$ a une seule racine $%s_0=%s=%s$.\\par"%(nomP,var,var,liste_str_racines[0],TeX(liste_racines[0]))) else:#delta>0 [x1,x2]=liste_racines cor.append("Comme $\\Delta>0$, $%s(%s)$ a deux racines :"%(nomP,var)) if isinstance(x1,RacineDegre2): simplification1=simplification2="" x1,detail1=x1.simplifie(True) x2,detail2=x2.simplifie(True) max_len=max(len(detail1),len(detail2)) cor.append("\\begin{align*}") cor.append("%s =&%s &%s =&%s"%\ (liste_str_racines[0],liste_racines[0],liste_str_racines[1],liste_racines[1])) cor.append("\\\\") for i in range(0,max_len): if i liste_points[i][1]: points.append(liste_points[i]) deltaxx=0.3*(points[1][0]-points[0][0]) nderiv=float(points[1][1]-points[0][1])/(points[1][0]-points[0][0]) apres=[(points[0][0]+0.5,points[0][1]+deltaxx*nderiv)] avant=[] if points[0][1]=points[i-1][1] and points[i][1]>=points[i+1][1]): nderiv=0 x_variation.append(points[i][0]) y_variation.append(points[i][1]) variation+='-' else: nderiv=float(points[i-1][1]-points[i+1][1])/(points[i-1][0]-points[i+1][0]) deltax=0.3*(points[i-1][0]-points[i][0]) deltaxx=0.3*(points[i+1][0]-points[i][0]) avant.append((points[i][0]+deltax,points[i][1]+deltax*nderiv)) apres.append((points[i][0]+deltaxx,points[i][1]+deltaxx*nderiv)) avant.append((points[len(points)-1][0]-0.5,points[len(points)-1][1]-0)) string=str(points[0]) for i in range(len(points)-1): string+=str(apres[i])+str(avant[i])+str(points[i+1]) textbezier="\\input{tabvar}\n\ \psset{unit="+str(14.0/largeur)+"cm}\n\ \\begin{pspicture}" textbezier+="("+str(xmin)+","+str(ymin)+")("+str(liste_points[-1][0])+","+str(ymax)+")\n" textbezier+="\psgrid[subgriddiv=0,griddots=10,gridlabels=0pt]\n\ \psaxes[linewidth=1pt,%\n\ ticks=none,%\n\ %labels=none\n\ Dx=2\n\ ]{->}(0,0)" textbezier+="("+str(xmin)+","+str(ymin)+")("+str(liste_points[-1][0])+","+str(ymax)+")\n" impression=textbezier+"\psbezier"+string+"\n"+"\\end{pspicture}\n\\vspace{2cm}\n\n" impression+="$$\n\ \\tabvar{%\n\ \\tx{x}&\\tx{"+str(x_variation[0])+"}" for i in range(1,len(x_variation)): impression+="&& \\tx{"+str(x_variation[i])+"}" impression+="&& \\tx{"+str(points[-1][0])+"}\\cr\n" impression+="\\tx{f(x)}" for i in range(len(variation)): if variation[i]=='+': impression+="&\\txb{"+str(y_variation[i])+"}&\\fm" else: impression+="&\\txh{"+str(y_variation[i])+"}&\\fd" if variation[-1]=='+': impression+="&\\txh{"+str(points[-1][1])+"}" else: impression+="&\\txb{"+str(points[-1][1])+"}" return impression+"\\cr\n}$$\n\n" def tab_var(fonc,Intervalle=["-\\infty","+\\infty"]): if isinstance(fonc,Polynome): return tab_var_poly(fonc,Intervalle[0],Intervalle[1]) else: return "Je ne sais pas étudier les variations de cette fonction" def tab_var_poly(P,borneinf="-\\infty" , bornesup=u"+\\infty"): Intervalle=[borneinf,bornesup] #print"borneinf=",borneinf tab_var="\\input{tabvar}\n" tab_var+="$$\\tabvar{%\n" if P.deg==0: tab_var+=tabvar_x(Intervalle,P.var) Cste=str(P(0)) tab_var+="\\tx{f("+P.var+")}&\\tx{"+Cste+"}&\\fhm&\\tx{"+Cste+"}\\cr\n" return tab_var+"}$$\n" elif P.deg==1: tab_var+=tabvar_x(Intervalle,P.var) if P.dictio[1]>0: tab_var+="\\tx{f("+P.var+")}& &\\fm& \\cr\n" else: tab_var+="\\tx{f("+P.var+")}& &\\fd&\\cr\n" return tab_var+"}$$\n" elif P.deg==2: alpha=-P.dictio[1]/(2*P.dictio[2]) extremum=P(alpha) if (borneinf=="-\\infty" or Intervalle[0]alpha): listex=[Intervalle[0],alpha,Intervalle[1]] if P.dictio[0]>0: tab_var_y ="\\tx{f("+P.var+")}& &\\fd&\\txb{"+nombre_TeX(extremum)+"}&\\fm&\\cr\n" else: tab_var_y ="\\tx{f("+P.var+")}& &\\fm&\\txh{"+nombre_TeX(extremum)+"}&\\fd&\\cr\n" else: listex=Intervalle if P.dictio>0: if not(borneinf=="-\\infty") and Intervalle[0]>alpha: tab_var_y="\\tx{f("+P.var+")}& &\\fm& \\cr\n" else: tab_var_y="\\tx{f("+P.var+")}& &\\fd&\\cr\n" else: if not(borneinf=="-\\infty") and Intervalle[0]>alpha: tab_var_y="\\tx{f("+P.var+")}& &\\fd&\\cr\n" else: tab_var_y="\\tx{f("+P.var+")}& &\\fm& \\cr\n" tab_var+=tabvar_x(listex,P.var) tab_var+=tab_var_y return tab_var+"}$$\n" elif P.deg==3: return u"attends un peu pour le degré 3" ##Les fonctions développées pour les équations du second degré doivent aider else: return u"Degré trop élevé" ##Cas partidulier où P' a une racine évidente, ou polynome bicarré def tabvar_x(listex,var): '''imprime la premiere ligne du tabvar''' var_x="\\tx{"+var+"}&\\tx{"+nombre_TeX(listex[0])+"}" for i in range(1,len(listex)): var_x+="&&\\tx{"+nombre_TeX(listex[i])+"}" return var_x+"\\cr\n" def tabvar_de_f(listef): '''inutile''' return "" def nombre_TeX(nombre):#A remplacer par sepmillier if type(nombre) in [type(int),type(float)]: return str(nombre) elif isinstance(nombre,Fractions): if nombre.denominateur==1: return nombre_TeX(nombre.numerateur) else: return "\\dfrac{"+str(nombre.numerateur)+"}{"+str(nombre.denominateur)+"}" else: return str(nombre) if __name__=="__main__": from TEST.imprimetest import * imprime_TeX(bezier(),"bezier.tex") P=Polynome("x^2+5x-6") imprime_TeX(tab_var(P),"polyvar.tex") pyromaths/src/lycee/lycee.py0000644000175000017500000000276011702101415016632 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import ExoPolynome, Vecteurs def write(f0, f1, exos): f0.write("\n") f1.write("\n") f0.writelines(x + "\n" for x in exos[0]) f1.writelines(x + "\n" for x in exos[1]) def main(exo, f0, f1): modules = ( ExoPolynome.exo_racines_degre2, ExoPolynome.exo_factorisation_degre2, ExoPolynome.exo_factorisation_degre3, ExoPolynome.exo_tableau_de_signe, ExoPolynome.exo_variation, ExoPolynome.exo_variation_lim, Vecteurs.vecteurs_add, ) write(f0, f1, modules[exo]()) pyromaths/src/lycee/._ExoSecondDegre.py0000644000175000017500000000031511702101415020576 0ustar didrocksdidrocksMac OS X  2ATTRG޲55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/lycee/._lycee.py0000644000175000017500000000031511702101415017041 0ustar didrocksdidrocksMac OS X  2ATTRG޴55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/lycee/__init__.py0000644000175000017500000000000011702101415017251 0ustar didrocksdidrockspyromaths/src/lycee/Vecteurs.py0000644000175000017500000003323311702101415017330 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # ##- additions / soustractions de vecteurs ( difficulté : ne pas sortir du cadre ) ##- multiplication d'un vecteur par un réel + add + sous ( difficulté : ne pas sortir du cadre ) ##- lire les coordonnées d'un vecteur ##- placer un point B connaissant A et les coordonnées de vec{AB} : avec coordonnées ou i et j ( difficulté : ne pas sortir du cadre ) ##- calcul de norme ##- simplifier des sommes ##- problèmes de colinéarité from ..classes.Vecteurs import randvect, Vecteur from ..classes.Racine import simplifie_racine import math from random import randint, shuffle def dist_bords(a,b): '''Calcule les distances minimales d'un point de coordonnées (a,b) aux bords du cadre, selon l'axe x et y.''' x = min(a,18-a) # la largeur vaut 18 y = min(b,10-b) # la hauteur vaut 10 return (x,y) def pair(n): '''Retourne le plus petit entier pair strictement plus grand que n''' if (n % 2 == 0): return n+2 else: return n+1 def AffNom(u,crd = 0): '''Renvoie les coordonnées pour l'affichage du nom du vecteur u.''' if u.x == 0 and math.fabs(u.y) > 2: coord = (0,u.y / 2) elif u.x == 0: coord = (-0.5,u.y / 2) elif u.y == 0 and math.fabs(u.x) > 2: coord = (u.x / 2, 0) elif u.y == 0: coord = (u.x / 2, - 0.5) elif math.fabs(u.x)+math.fabs(u.y) < 3: coord = (u.x/ 2.0 + 0.5,u.y / 2.0 + 0.5) else: coord = (u.x /2,u.y / 2) return str(coord[0]) + "," + str(coord[1]) def ChoixVecteur(u,v,w,x,y): listecoeff = [0.5, -0.5, -1, -2, 2, 3, -3] listevect = [(u,"u"),(v,"v"),(w,"w")] shuffle(listecoeff) shuffle(listevect) for vec in listevect: for coeff in listecoeff: if ( 0 <= x + coeff * vec[0].x <= 18 ) and ( 0 <= y + coeff * vec[0].y <= 10 ): return (coeff, coeff * vec[0], vec[1]) def repr_somme(u,v,u1,u2,cor,larg=0): '''Représente la somme des vecteurs u + v.''' a = u + v if (u.x * a.x >= 0 ): largeur = max(math.fabs(u.x),math.fabs(a.x)) if ( a.x > 0 ): departx = 0 elif ( a.x == 0 ): departx = -u.x/2.0+math.fabs(u.x)/2 else: departx = max(math.fabs(u.x),math.fabs(a.x)) else: largeur = math.fabs(u.x)+math.fabs(a.x) if ( u.x >= 0 ): departx = -a.x else: departx = -u.x if (u.y * a.y >= 0 ): hauteur = max(math.fabs(u.y),math.fabs(a.y)) if ( a.y > 0 ): departy = 0 elif ( a.y == 0 ): departy = -u.y/2.0+math.fabs(u.y)/2 else: departy = max(math.fabs(u.y),math.fabs(a.y)) else: hauteur = math.fabs(u.y)+math.fabs(a.y) if ( u.y >= 0 ): departy = -a.y else: departy = -u.y if int(larg) + largeur > 18: cor.append("\\par") # Figure trop large avec la précédente, il faut passer à une nouvelle ligne. depart = "(" + str(departx) + "," + str(departy) + ")" largeur = str(pair(int(largeur))) hauteur = str(pair(int(hauteur))) cor.append(u"\\begin{pspicture*}(0,0)(" + largeur + "," + hauteur + ")") cor.append(u"\\psgrid[subgriddiv=2, gridlabels=0pt]") cor.append(u"\\psset{unit=10mm,arrowscale=2}") cor.append(u"\\rput" + depart + "{") cor.append(u"\\psline[linewidth=1pt, linecolor=DarkGreen]{|->}(0, 0)(" + str(u.x) + ", " + str(u.y) + ")") ## Premier Vecteur cor.append(u"\\rput(" + AffNom(u) + ") \ {\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{\\textcolor{DarkGreen}{$\\overrightarrow{" + u1 + "}$}}}") cor.append(u"\\psline[linewidth=1pt, linecolor=DarkBlue]{|->}(" + str(u.x) + ", " + str(u.y) + ")(" + str(a.x) + ", " + str(a.y) + ")") ## 2e Vecteur k = Vecteur(u.x+a.x,u.y+a.y) cor.append(u"\\rput(" + AffNom(k) + ") \ {\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{\\textcolor{DarkBlue}{$\\overrightarrow{" + u2 + "}$}}}") if len(u2)>1: sgn = "-" else: sgn = "+" cor.append(u"\\psline[linestyle=dashed, linewidth=1pt, linecolor=DarkRed]{|->}(0, 0)(" + str(a.x) + ", " + str(a.y) + ")") ## Résultat de l'opération cor.append(u"\\rput(" + AffNom(a) + ") \ {\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{\\textcolor{DarkRed}{$\\overrightarrow{" + u1 + "}" + sgn + "\\overrightarrow{" + u2[-1] + "}$}}}") cor.append(u"}") cor.append(u"\\end{pspicture*}") return largeur ## récupérer la largeur pour éviter d'aligner des figures trop larges sur la feuille def vecteurs_add(): '''Exercice sur la définition des vecteurs et leurs sommes.''' t = None while not t: # Pour être sûr que l'exercice ait des solutions (u, posux, posuy) = randvect(0, 10) (v, posvx, posvy) = randvect(math.fabs(u.x)+1, 10) (w, poswx, poswy) = randvect(math.fabs(v.x)+math.fabs(u.x)+2, 10) ## Construction du point pour la question 2 if 18 - poswx - max(w.x,0) > 0: restes = (18 - poswx - max(w.x,0),10) pointy = randint(0,10) elif poswy + min(w.y,0) > 10 - poswy - max(w.y,0): restes = (poswx+min(w.x,0),poswy + min(w.y,0)) pointy = randint(0,restes[1]) else: restes = (poswx+min(w.x,0),10 - poswy - max(w.y,0)) pointy = randint(10 - restes[1],10) pointx = randint(18 - restes[0],18) t = ChoixVecteur(u,v,w,pointx,pointy) exo=["\\exercice"] cor=["\\exercice*"] exo.append(u"\\begin{pspicture*}(0,0)(18,10)") exo.append(u"\\psgrid[subgriddiv=2, gridlabels=0pt]") exo.append(u"\\psset{unit=10mm,arrowscale=2}") cor.append(u"\\begin{pspicture*}(0,0)(18,10)") cor.append(u"\\psgrid[subgriddiv=2, gridlabels=0pt]") cor.append(u"\\psset{unit=10mm,arrowscale=2}") exo.append(u"\\psdot(" + str(pointx) + "," + str(pointy) + ")") if pointx < 18 and pointy < 10: nompoint = str(pointx+0.5) + "," + str(pointy+0.5) else: nompoint = str(pointx-0.5) + "," + str(pointy-0.5) exo.append(u"\\rput(" + nompoint + "){\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{$A$}}") cor.append(u"\\psdot(" + str(pointx) + "," + str(pointy) + ")") cor.append(u"\\rput(" + nompoint + "){\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{$A$}}") cor.append(u"\psline[linecolor=DarkBlue]{|->}(" + str(pointx) + "," + str(pointy) + ")(" + str(pointx + t[1].x) + ", " + str(pointy + t[1].y) + ")") bx = pointx + t[1].x by = pointy + t[1].y if bx < 18 and by < 10: nompoint = str(bx+0.5) + "," + str(by+0.5) else: nompoint = str(bx-0.5) + "," + str(by-0.5) cor.append(u"\\psdot(" + str(pointx + t[1].x) + "," + str(pointy + t[1].y) + ")") cor.append(u"\\rput(" + nompoint + "){\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{$B$}}") for vec in [(u, posux, posuy, "u"), (v, posvx, posvy, "v"), (w, poswx, poswy, "w")]: exo.append(u"\\rput(" + str(vec[1]) + "," + str(vec[2]) + "){") exo.append(u"\psline{|->}(0, 0)(" + str(vec[0].x) + ", " + str(vec[0].y) + ")") exo.append(u"\\rput(" + AffNom(vec[0]) + ") \ {\\psframebox[linecolor=white, fillcolor=white, fillstyle=solid]{$\\overrightarrow{" + vec[3] + "}$}}") exo.append(u"}") exo.append(u"\\end{pspicture*}") for vec in [(u, posux, posuy, "u"), (v, posvx, posvy, "v"), (w, poswx, poswy, "w")]: if vec[0].y>0: plus = 1 else: plus = 0 cor.append(u"\\rput(" + str(vec[1]) + "," + str(vec[2]) + "){") cor.append(u"\\psline{|->}(0, 0)(" + str(vec[0].x) + ", " + str(vec[0].y) + ")") cor.append(u"\\psline[linestyle=dashed,linecolor=DarkRed](0, 0)(" + str(vec[0].x) + ", 0)(" + str(vec[0].x) + "," + str(vec[0].y) + ")") cor.append(u"\\rput(" + AffNom(vec[0]) + "){\\psframebox[linecolor=white, fillcolor=white, \ fillstyle=solid]{$\\overrightarrow{" + vec[3] + "}\\ (" + str(vec[0].x) + ";" + str(vec[0].y) + ")$}}") cor.append(u"}") cor.append(u"\\end{pspicture*}") exo.append("\\par") cor.append("\\par") exo.append(u"On se place dans un repère orthonormé et on considère les vecteurs $\\overrightarrow{u}$, $\\overrightarrow{v}$, et $\\overrightarrow{w}$ ci-dessous.") cor.append(u"On se place dans un repère orthonormé et on considère les vecteurs $\\overrightarrow{u}$, $\\overrightarrow{v}$, et $\\overrightarrow{w}$ ci-dessous.") exo.append("\\begin{enumerate}") cor.append("\\begin{enumerate}") exo.append(u"\\item Lire les coordonnées de chacun des vecteurs $\\overrightarrow{u}$, $\\overrightarrow{v}$, et $\\overrightarrow{w}$.") cor.append(u"\\item Lire les coordonnées de chacun des vecteurs $\\overrightarrow{u}$, $\\overrightarrow{v}$, et $\\overrightarrow{w}$.") cor.append("\\par") cor.append(u"Un petit rappel : l'abscisse d'un vecteur est la différence d'abscisse entre le fin et le début du vecteur. \ Concernant le vecteur $\\overrightarrow{u}$, son abscisse est $" + str(u.x) + u"$. \ On lit également son ordonnée : $" + str(u.x) + u"$. \ Donc les coordonnées de $\\overrightarrow{u}$ sont $(" + str(u.x) + ", " + str(u.y) + u" )$. \ Des pointillés ont été ajoutés sur la figure pour faciliter la lecture des coordonnées.") cor.append(u"De même, les coordonnées de $\\overrightarrow{v}$ sont $(" + str(v.x) + ", " + str(v.y) + u" )$ \ et les coordonnées de $\\overrightarrow{w}$ sont $(" + str(w.x) + ", " + str(w.y) + " )$.") exo.append(u"\\item Placer un point B de sorte que le vecteur $\\overrightarrow{AB}$ soit égal à $" + str(t[0]) + " \\times \\overrightarrow{" + t[2] + "}$.") cor.append(u"\\item Placer un point B de sorte que le vecteur $\\overrightarrow{AB}$ soit égal à $" + str(t[0]) + " \\times \\overrightarrow{" + t[2] + "}$.") cor.append(u"\\par") cor.append(u"Le plus simple pour répondre à cette question est de calculer les coordonnées du vecteur $" + str(t[0]) + " \\times \\overrightarrow{" + str(t[2]) + "}$.") cor.append(u"Cela se fait en multipliant les coordonnées de $\\overrightarrow{" + str(t[2]) + "}$ par $" + str(t[0]) + u"$, ce qui donne comme résultat $(" + str(t[1].x) + ";" + str(t[1].y) + ")$.") cor.append(u"En partant du point A et en respectant ces coordonnées, on dessine un vecteur (en bleu sur la figure ci-dessus) qui indique l'emplacement du point B.") exo.append(u"\\item Calculer les normes de chacun des vecteurs $\\overrightarrow{u}$, $\\overrightarrow{v}$, et $\\overrightarrow{w}$.") cor.append(u"\\item Calculer les normes de chacun des vecteurs $\\overrightarrow{u}$, $\\overrightarrow{v}$, et $\\overrightarrow{w}$.") if u.x**2+u.y**2 == simplifie_racine(u.x**2+u.y**2)[1]: # Cas où la simplification est la même, donc inutile d'écrire deux fois la même chose. Norm_u = "$" else: Norm_u = "=" + str(u.normeTex()) + "$" if v.x**2+v.y**2 == simplifie_racine(v.x**2+v.y**2)[1]: Norm_v = "$" else: Norm_v = "=" + str(v.normeTex()) + "$" if w.x**2+w.y**2 == simplifie_racine(w.x**2+w.y**2)[1]: Norm_w = "$" else: Norm_w = "=" + str(w.normeTex()) + "$" cor.append("\\par") cor.append(u"$\|\\overrightarrow{u}\|=\\sqrt{(" + str(u.x) + ")^2+(" + str(u.y) + ")^2}=\\sqrt{" + str(u.x**2) + " + " + str(u.y**2) + "}= \ \\sqrt{" + str(u.x**2 + u.y**2) + "}" + Norm_u + ".\\par") cor.append(u"De la même manière, on obtient :") cor.append(u"$\|\\overrightarrow{v}\|=\\sqrt{(" + str(v.x) + ")^2+(" + str(v.y) + ")^2}=\\sqrt{" + str(v.x**2) + " + " + str(v.y**2) + "}= \ \\sqrt{" + str(v.x**2 + v.y**2) + "}" + Norm_v + " et \\par") cor.append(u"$\|\\overrightarrow{w}\|=\\sqrt{(" + str(w.x) + ")^2+(" + str(w.y) + ")^2}=\\sqrt{" + str(w.x**2) + " + " + str(w.y**2) + "}= \ \\sqrt{" + str(w.x**2 + w.y**2) + "}" + Norm_w + ".\\par") exo.append(u"\\item Dessiner des représentants des vecteurs $\\overrightarrow{u}+\\overrightarrow{v}$, $\\overrightarrow{u}-\\overrightarrow{v}$, $\\overrightarrow{u}-\\overrightarrow{w}$ \ et $\\overrightarrow{v}+\\overrightarrow{w}$.") cor.append(u"\\item Dessiner des représentants des vecteurs $\\overrightarrow{u}+\\overrightarrow{v}$, $\\overrightarrow{u}-\\overrightarrow{v}$, $\\overrightarrow{u}-\\overrightarrow{w}$ \ et $\\overrightarrow{v}+\\overrightarrow{w}$.") cor.append("\\par") cor.append(u"Pour dessiner les sommes ou différences de vecteurs, il faut les mettre \"bouts à bouts\", \ comme sur les figures qui suivent :\\par") i = repr_somme(u,v,'u','v',cor) repr_somme(u,-v,'u','-v',cor,i) cor.append("\\par") i = repr_somme(u,-w,'u','-w',cor) repr_somme(v,w,'v','w',cor,i) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor pyromaths/src/lycee/ExoSecondDegre.py0000644000175000017500000000626611702101415020374 0ustar didrocksdidrocks# -*- coding: utf-8 -*- import sys, os, codecs from ..classes.SecondDegre import Poly2 from ..outils.Affichage import printlist from ..outils.Polynomes import choix_coeffs from ..outils.Arithmetique import * def exo_second_degre(): """Créer une exercice comprenant des équations et inéquations du second degré. PAS FINI.""" exo = "\\exercice\n\ \\begin{multicols}{2}\n\ \\noindent "+ u"Question 1 : Chercher les racines des polynômes suivants :\\par\n" cor = "\\exercice*\n\ \\begin{multicols}{2}\n\ \\noindent "+ u"Question 1 : Chercher les racines des polynômes suivants :\\par\n" ## Equations pol1 = choix_coeffs(False, 2, True) pol2 = choix_coeffs(False, 1, False) pol3 = choix_coeffs(False, 0, True) pol4 = choix_coeffs(False, 2, False) ## Inequations pol5 = choix_coeffs(True, 0, True) pol6 = choix_coeffs(False, 2, True) pol7 = choix_coeffs(False, 1, False) pol8 = choix_coeffs(False, 2, False) ## Somme et produit des racines pol9 = choix_coeffs(True, 2, False) ## Problème du rectangle pol10 = choix_coeffs(True, 2, False) exo+="\\par a)$" + pol1[1].print_signe("=")+"$\n" exo+="\\par b)$" + pol2[1].print_signe("=")+"$\n" exo+="\\par c)$" + pol3[1].print_signe("=")+"$\n" exo+="\\par d)$" + pol4[1].print_signe("=")+"$\n" cor+="\\par a)$" + pol1[1].print_signe("=")+"$\n" cor+="\\par b)$" + pol2[1].print_signe("=")+"$\n" cor+="\\par c)$" + pol3[1].print_signe("=")+"$\n" cor+="\\par d)$" + pol4[1].print_signe("=")+"$\n" cor+="\\par a) On calcule le discriminant : $\\Delta = " + str(pol1[1].delta) + "$.\n" cor+="\\par Comme le discrimimant est $" + pol1[1].signedelta + u"$, on en déduit que ce polynôme possède $" + str(pol1[1].nbrac) + "$ racines." exo+=u"\\par Question 2 : Résoudre les inéquations suivantes : " cor+=u"\\par Question 2 : Résoudre les inéquations suivantes : " exo+="\\par a)$" + pol5[1].print_signe("\\le")+"$\n" exo+="\\par b)$" + pol6[1].print_signe("\\ge")+"$\n" exo+="\\par c)$" + pol7[1].print_signe(">")+"$\n" exo+="\\par d)$" + pol8[1].print_signe("<")+"$\n" cor+="\\par a)$" + pol5[1].print_signe("\\le")+"$\n" cor+="\\par b)$" + pol6[1].print_signe("\\ge")+"$\n" cor+="\\par c)$" + pol7[1].print_signe(">")+"$\n" cor+="\\par d)$" + pol8[1].print_signe("<")+"$\n" exo+="\\par Question 3 : Trouver deux nombres sachant que leur somme est " + str(pol9[1].b) + " et leur produit " + str(pol9[1].c) + ".\n" cor+="\\par Question 3 : Trouver deux nombres sachant que leur somme est " + str(pol9[1].b) + " et leur produit " + str(pol9[1].c) + ".\n" exo+=u"\\par Question 4 : Trouver les dimensions d'un rectangle, sachant que son périmètre est " + str(pol9[1].b) + " et son aire " + str(pol9[1].c) + "." cor+=u"\\par Question 4 : Trouver les dimensions d'un rectangle, sachant que son périmètre est " + str(pol9[1].b) + " et son aire " + str(pol9[1].c) + "." exo+="\\end{multicols}\n" cor+="\\end{multicols}\n" return (exo, cor) if __name__=="__main__": from TEST.imprimetest import * exo,cor=exo_second_degre() imprime_TeX(exo+"\\pagebreak"+cor,"secondegre.tex") pyromaths/src/lycee/._ExoPolynome.py0000644000175000017500000000031511702101415020216 0ustar didrocksdidrocksMac OS X  2ATTRGޱ55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/lycee/._Vecteurs.py0000644000175000017500000000031511702101415017540 0ustar didrocksdidrocksMac OS X  2ATTRG޵55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/interface.py0000644000175000017500000011035511702412057016377 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if notPopen, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from PyQt4 import QtGui, QtCore import os, lxml, codecs, sys from outils import System from Values import HOME, CONFIGDIR, DATADIR, LESFICHES, COPYRIGHTS, VERSION, ICONDIR class Ui_MainWindow(object): def setupUi(self, MainWindow): self.configfile = os.path.join(CONFIGDIR, "pyromaths.xml") self.liste_creation=[] if sys.platform != "darwin": #Cas de Mac OS X. MainWindow.setStyleSheet("background-color: rgb(251, 245, 225);") MainWindow.setWindowIcon(QtGui.QIcon(ICONDIR)) MainWindow.setWindowTitle("Pyromaths") MainWindow.setGeometry(0,44, 500, 200) font = QtGui.QFont() font.setPointSize(10) MainWindow.setFont(font) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) self.centralwidget = QtGui.QWidget(MainWindow) self.gridLayout = QtGui.QGridLayout(self.centralwidget) self.verticalLayout = QtGui.QVBoxLayout() self.verticalLayout.setMargin(9) #============================================================ # lecture du fichier de configuration #============================================================ self.config = self.lire_config('options') #============================================================ # Boutons créer, quitter et annuler #============================================================ self.pushButton_ok = QtGui.QPushButton(self.centralwidget) self.verticalLayout.addWidget(self.pushButton_ok) self.pushButton_ok.setText(u"Créer") if sys.platform != "darwin": #Cas de Mac OS X. self.pushButton_ok.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));") self.pushButton_quit = QtGui.QPushButton(self.centralwidget) self.verticalLayout.addWidget(self.pushButton_quit) self.pushButton_quit.setText("Quitter") if sys.platform != "darwin": #Cas de Mac OS X. self.pushButton_quit.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));") self.pushButton_erase = QtGui.QPushButton(self.centralwidget) self.verticalLayout.addWidget(self.pushButton_erase) self.pushButton_erase.setText(u"Réinitialiser") if sys.platform != "darwin": #Cas de Mac OS X. self.pushButton_erase.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));") spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) #============================================================ # Onglets de la zone centrale #============================================================ self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1) self.tabWidget = QtGui.QTabWidget(self.centralwidget) self.tabWidget.setAutoFillBackground(True) if sys.platform != "darwin": #Cas de Mac OS X. self.tabWidget.setStyleSheet("background-color: rgb(251, 231, 178);") #============================================================ # Remplissage des 4 niveaux #============================================================ for level in range(5): exec("self.tab_%se = QtGui.QWidget()" % (6-level)) exec("self.gridLayout_%se = QtGui.QGridLayout(self.tab_%se)" % (6-level, 6-level)) nb_exos = len(LESFICHES[level][2]) for i in range(nb_exos): self.insert_spinbox(6-level, i) for col in range(2): exec("spacerItem_%s_%s = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)" % (6-level, col)) exec("self.gridLayout_%se.addItem(spacerItem_%s_%s, %s, %s, 1, 1)" % (6-level, 6-level, col, (nb_exos+1)/2, col)) exec("self.tabWidget.addTab(self.tab_%se, \"\")" % (6-level)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_6e), "6e") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_5e), "5e") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4e), "4e") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3e), "3e") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2e), u"Lycée") #============================================================ # Onglet options #============================================================ ############## Onglet options self.tab_options = QtGui.QWidget() self.tabWidget.addTab(self.tab_options, "") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_options), "Options") self.gridLayout_2 = QtGui.QGridLayout(self.tab_options) self.horizontalLayout_options1 = QtGui.QHBoxLayout() ############## Layout pour les noms d'options, en haut à gauche self.verticalLayout_16 = QtGui.QVBoxLayout() ############## Label nom du fichier self.opt_nom_fichier = QtGui.QLabel(self.tab_options) self.opt_nom_fichier.setText(u"Nom par défaut du fichier : ") self.verticalLayout_16.addWidget(self.opt_nom_fichier) ############## Label chemin par défaut pour l'enregistrement des fichiers self.opt_chemin_fichier = QtGui.QLabel(self.tab_options) self.opt_chemin_fichier.setText(u"Chemin par défaut pour enregistrer les fichiers : ") self.verticalLayout_16.addWidget(self.opt_chemin_fichier) ############## Label titre des fiches self.opt_titre_fiche = QtGui.QLabel(self.tab_options) self.opt_titre_fiche.setText("Titre de la fiche d'exercices : ") self.verticalLayout_16.addWidget(self.opt_titre_fiche) self.horizontalLayout_options1.addLayout(self.verticalLayout_16) ############## Layout pour les noms d'options, en haut à droite self.verticalLayout_17 = QtGui.QVBoxLayout() ############## LineEdit nom du fichier self.nom_fichier = QtGui.QLineEdit(self.tab_options) self.nom_fichier.setText(self.config['nom_fichier']) self.verticalLayout_17.addWidget(self.nom_fichier) ############## LineEdit chemin par défaut pour l'enregistrement des fichiers self.horizontalLayout_chemin_fichier = QtGui.QHBoxLayout() self.chemin_fichier = QtGui.QLineEdit(self.tab_options) self.chemin_fichier.setText(self.config['chemin_fichier']) self.horizontalLayout_chemin_fichier.addWidget(self.chemin_fichier) ############## Bouton parcourir self.pushButton_parcourir = QtGui.QPushButton(self.tab_options) self.pushButton_parcourir.setText("Parcourir") self.horizontalLayout_chemin_fichier.addWidget(self.pushButton_parcourir) self.verticalLayout_17.addLayout(self.horizontalLayout_chemin_fichier) ############## LineEdit titre des fiches self.titre_fiche = QtGui.QLineEdit(self.tab_options) self.titre_fiche.setText(self.config['titre_fiche']) self.verticalLayout_17.addWidget(self.titre_fiche) self.horizontalLayout_options1.addLayout(self.verticalLayout_17) self.gridLayout_2.addLayout(self.horizontalLayout_options1, 0, 0, 1, 2) ############## Ligne de séparation self.line = QtGui.QFrame(self.tab_options) self.line.setFrameShape(QtGui.QFrame.HLine) self.line.setFrameShadow(QtGui.QFrame.Sunken) self.gridLayout_2.addWidget(self.line, 1, 0, 1, 2) self.horizontalLayout_3 = QtGui.QHBoxLayout() self.verticalLayout_21 = QtGui.QVBoxLayout() ############## CheckBox "corrigés ou non" self.checkBox_corrige = QtGui.QCheckBox(self.tab_options) self.checkBox_corrige.setText(u"Créer le corrigé") self.checkBox_corrige.setToolTip(u"Pyromaths doit-il créer la fiche de correction détaillée?") self.checkBox_corrige.setChecked(int(self.config['corrige'])) self.verticalLayout_21.addWidget(self.checkBox_corrige) ############## CheckBox "pdf ou non" self.checkBox_pdf = QtGui.QCheckBox(self.tab_options) self.checkBox_pdf.setText(u"Créer le pdf") self.checkBox_pdf.setToolTip(u"Pyromaths doit-il créer les fiches au format pdf ?") self.checkBox_pdf.setChecked(int(self.config['pdf'])) self.verticalLayout_21.addWidget(self.checkBox_pdf) ############## CheckBox "pdf ou non" self.checkBox_unpdf = QtGui.QCheckBox(self.tab_options) self.checkBox_unpdf.setText(u"Créer un seul pdf") self.checkBox_unpdf.setToolTip(u"Le corrigé et les exercices doivent-ils être dans le même document ?") self.checkBox_unpdf.setChecked(int(self.config['unpdf'])) self.verticalLayout_21.addWidget(self.checkBox_unpdf) ############## Espace self.horizontalLayout_3.addLayout(self.verticalLayout_21) spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem13) self.verticalLayout_20 = QtGui.QVBoxLayout() self.horizontalLayout_2 = QtGui.QHBoxLayout() self.verticalLayout_18 = QtGui.QVBoxLayout() ############## Label niveau self.opt_niveau = QtGui.QLabel(self.tab_options) self.opt_niveau.setText("Niveau :") self.verticalLayout_18.addWidget(self.opt_niveau) ############## Label Modèle self.label_modele = QtGui.QLabel(self.tab_options) self.label_modele.setText(u"Modèle de mise en page :") #self.label_modele.setEnabled(False) self.verticalLayout_18.addWidget(self.label_modele) self.horizontalLayout_2.addLayout(self.verticalLayout_18) ############## Layout pour les noms d'options, en bas à droite self.verticalLayout_19 = QtGui.QVBoxLayout() ############## ComboBox niveau self.comboBox_niveau = QtGui.QComboBox(self.tab_options) self.comboBox_niveau.setEditable(True) # l’utilisateur peut entrer son propre texte self.comboBox_niveau.addItem("Classe de 6\\ieme") self.comboBox_niveau.addItem("Classe de 5\\ieme") self.comboBox_niveau.addItem("Classe de 4\\ieme") self.comboBox_niveau.addItem("Classe de 3\\ieme") self.comboBox_niveau.addItem("Classe de 2\\up{nde}") self.verticalLayout_19.addWidget(self.comboBox_niveau) ############## ComboBox modèles self.comboBox_modele = QtGui.QComboBox(self.tab_options) modeles = os.listdir(os.path.join(DATADIR, 'templates')) modeles_home = os.listdir(os.path.join(CONFIGDIR, 'templates')) count = 0 for element in modeles: if os.path.splitext(element)[1] == ".tex": self.comboBox_modele.addItem(str(element[:len(element)-4])) if element == self.config['modele']: self.comboBox_modele.setCurrentIndex(count) count += 1 for element in modeles_home: if os.path.splitext(element)[1] == ".tex": self.comboBox_modele.addItem(QtCore.QString()) self.comboBox_modele.setItemText(count, str(element[:len(element)-4])) if element == self.config['modele']: self.comboBox_modele.setCurrentIndex(count) count += 1 self.verticalLayout_19.addWidget(self.comboBox_modele) self.horizontalLayout_2.addLayout(self.verticalLayout_19) self.verticalLayout_20.addLayout(self.horizontalLayout_2) self.horizontalLayout_3.addLayout(self.verticalLayout_20) self.gridLayout_2.addLayout(self.horizontalLayout_3, 2, 0, 1, 2) ############## Bouton enregistrer self.pushButton_enr_opt = QtGui.QPushButton(self.tab_options) self.pushButton_enr_opt.setText(u"Enregistrer dans les préférences") if sys.platform != "darwin": #Cas de Mac OS X. self.pushButton_enr_opt.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));") self.gridLayout_2.addWidget(self.pushButton_enr_opt, 4, 1, 1, 1) spacerItem14 = QtGui.QSpacerItem(20, 177, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.gridLayout_2.addItem(spacerItem14, 3, 1, 1, 1) spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.gridLayout_2.addItem(spacerItem15, 4, 0, 1, 1) #============================================================ # Barre de menus et de status #============================================================ self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 700, 22)) if sys.platform != "darwin": #Cas de Mac OS X. self.menubar.setStyleSheet("background-color: rgb(251, 231, 178);") MainWindow.setMenuBar(self.menubar) self.menuFichier = QtGui.QMenu(self.menubar) self.menuFichier.setTitle("Fichier") self.menu_propos = QtGui.QMenu(self.menubar) self.menu_propos.setTitle("Aide") self.statusbar = QtGui.QStatusBar(MainWindow) MainWindow.setStatusBar(self.statusbar) self.statusbar.showMessage(u"Pour avoir un aperçu d'un exercice, positionner le curseur de la souris sur le point d'interrogation.") if sys.platform != "darwin": #Cas de Mac OS X. self.statusbar.setStyleSheet("background-color: rgb(251, 231, 178);") #============================================================ # Menus de la barre de menus #============================================================ self.actionTous_les_exercices = QtGui.QAction(MainWindow) self.actionTous_les_exercices.setText("Tous les exercices") self.actionQuitter = QtGui.QAction(MainWindow) self.actionQuitter.setText("Quitter") self.actionAcceder_au_site = QtGui.QAction(MainWindow) self.actionAcceder_au_site.setText(u"Accéder au site") self.action_a_propos = QtGui.QAction(MainWindow) self.action_a_propos.setText(u"À propos") self.menuFichier.addAction(self.actionTous_les_exercices) self.menuFichier.addSeparator() self.menuFichier.addAction(self.actionQuitter) self.menu_propos.addAction(self.actionAcceder_au_site) self.menu_propos.addSeparator() self.menu_propos.addAction(self.action_a_propos) self.menubar.addAction(self.menuFichier.menuAction()) self.menubar.addAction(self.menu_propos.menuAction()) #============================================================ # Raccourcis clavier #============================================================ keyQuit = QtGui.QShortcut("Ctrl+Q", MainWindow) QtCore.QObject.connect(keyQuit, QtCore.SIGNAL("activated()"), QtGui.qApp, QtCore.SLOT("quit()")) #============================================================ # Actions des boutons et menus #============================================================ QtCore.QObject.connect(self.actionTous_les_exercices, QtCore.SIGNAL("activated()"), self.creer_tous_les_exercices) QtCore.QObject.connect(self.actionQuitter, QtCore.SIGNAL("activated()"), QtGui.qApp, QtCore.SLOT("quit()")) QtCore.QObject.connect(self.actionAcceder_au_site, QtCore.SIGNAL("activated()"), self.site) QtCore.QObject.connect(self.action_a_propos, QtCore.SIGNAL("activated()"), self.about) QtCore.QObject.connect(self.pushButton_quit, QtCore.SIGNAL("clicked()"), QtGui.qApp, QtCore.SLOT("quit()")) QtCore.QObject.connect(self.pushButton_erase, QtCore.SIGNAL("clicked()"), self.effacer_choix_exercices) QtCore.QObject.connect(self.pushButton_ok,QtCore.SIGNAL("clicked()"), self.creer_les_exercices) QtCore.QObject.connect(self.pushButton_enr_opt,QtCore.SIGNAL("clicked()"), self.enregistrer_config) QtCore.QObject.connect(self.pushButton_parcourir,QtCore.SIGNAL("clicked()"), self.option_parcourir) QtCore.QObject.connect(self.checkBox_corrige,QtCore.SIGNAL("stateChanged(int)"), self.option_corrige) #============================================================ # Actions des spinBox #============================================================ for level in range(5): for box in range(len(LESFICHES[level][2])): exec("QtCore.QObject.connect(self.spinBox_%s_%s, QtCore.SIGNAL(\"valueChanged(int)\"), self.setNbExos)" % (6-level, box)) for level in range(5): nb_exos = len(LESFICHES[level][2]) for i in range(nb_exos): exec("self.label_%s_%s.setText(u\"%s\")" % (6-level, i, LESFICHES[level][2][i])) exec("self.imglabel_%s_%s.setText(r'')" % (6-level, i, os.path.join(DATADIR, 'images', 'whatsthis.png'))) exec("self.imglabel_%s_%s.setToolTip(r\'\')" % (6-level, i, os.path.join(DATADIR, 'images', 'vignettes', '%se-%02d.png' % (6-level, i)))) exec(u"self.spinBox_%s_%s.setToolTip(u\"Choisissez le nombre d\'exercices de ce type à créer.\")"% (6-level,i)) QtCore.QMetaObject.connectSlotsByName(MainWindow) #============================================================ # Début des fonctions #============================================================ ### Gestion des erreurs def erreur_critique(self, message): """Dialogue si pyromaths.xml est défectueux.""" reply = QtGui.QMessageBox.critical(self, "Erreur critique", message) if reply: sys.exit(1) def about(self): """Crée la boîte de dialogue "À propos de..." """ text = u"""



Version %s

Pyromaths est un programme qui permet de créer des fiches d'exercices types de mathématiques niveau collège avec leur corrigé.

Les fiches sont produites au format LaTeX. Pyromaths lance ensuite les commandes nécessaires à la production de fichiers pdf (latex - dvips - ps2pdf) et les ouvre.

Remerciements à :

  • David Robert pour l'idée de départ ;
  • Yves Gesnel pour le portage de Pyromaths sur Mac OS X ;
  • Arnaud Kientz pour ses graphismes, son implication dans le code de Pyromaths et son amitié ;
  • Guillaume Barthélémy pour ses exercices ;
  • Nicolas Bissonnier pour son arrivée dans l'équipe de développement ;
  • Nicolas Pourcelot pour ses conseils et son implication prochaine dans le code de Pyromaths ;
  • Didier Roche pour l'intégration de Pyromaths dans les dépôts Ubuntu ;
  • Jacqueline Gouguenheim-Desloy a porté Pyromaths sur Mac OS X à ses débuts. Son soutien et son amitié nous ont été précieux. Sa disparition est une perte douloureuse pour la communauté du logiciel libre.

%s

""" if sys.platform == "darwin": #Cas de Mac OS X. banniere = os.path.join(DATADIR, 'images', 'pyromaths.png') else: banniere = os.path.join(DATADIR, 'images', 'pyromaths-banniere.png') QtGui.QMessageBox.about(None, u'À propos de Pyromaths', text % (banniere, VERSION, COPYRIGHTS)) def creer_les_exercices(self): """Vérifie si la liste d'exercices n'est pas vide puis sélectionne les noms des fichiers exercices et corrigés""" self.valide_options() if self.liste_creation == [] : QtGui.QMessageBox.warning(None, 'Attention !', u"Veuillez sélectionner des exercices...", QtGui.QMessageBox.Ok ) else: parametres = { 'creer_pdf': self.checkBox_pdf.isChecked(), 'creer_unpdf': self.checkBox_unpdf.isChecked() and self.checkBox_unpdf.isEnabled(), 'titre': unicode(self.titre_fiche.text()), 'corrige': self.checkBox_corrige.isChecked(), 'niveau': unicode(self.comboBox_niveau.currentText()), 'nom_fichier': unicode(self.nom_fichier.text()), 'chemin_fichier': unicode(self.chemin_fichier.text()), 'modele': unicode(self.comboBox_modele.currentText() + '.tex'), 'datadir': DATADIR, 'configdir': CONFIGDIR } #============================================================ # Choix de l'ordre des exercices #============================================================ list=[] for i in range(len(self.liste_creation)): niveau = self.liste_creation[i][0] exo = self.liste_creation[i][1] list.append("%se: %s" % (6-niveau, LESFICHES[niveau][2][exo])) self.List=QtGui.QListWidget() for i in range(len(list)): item = QtGui.QListWidgetItem(list[i]) item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled) self.List.addItem(item) bmono=True for i in range(len(list)): if list[0] != list[i]: bmono=False if bmono: # S'il ny a qu'un seul type d'exercices, pas la peine de choisir # l'ordre valide(self.List, LESFICHES, parametres) else: form = ChoixOrdreExos(self.List, LESFICHES, parametres) form.exec_() def creer_tous_les_exercices(self): """ Créer des fiches exemples pour tous les niveaux avec tous les exercices dans le dossier /home/jerome/workspace/Pyromaths/src/exemples """ self.valide_options() d0 = "" d0 = unicode(QtGui.QFileDialog().getExistingDirectory (None, u"Dossier où créer les fiches", self.config['chemin_fichier'], QtGui.QFileDialog.ShowDirsOnly)) i = 0 if d0: for niveau in range(5): liste = [] for i in range(len(LESFICHES[niveau][2])): liste.append((niveau, i)) if niveau != 4: exo = os.path.join(d0, "%se.tex" % (6 - niveau)) cor = os.path.join(d0, "%se-corrige.tex" % (6 - niveau)) parametres = { 'les_fiches': LESFICHES, 'fiche_exo': exo, 'fiche_cor': cor, 'liste_exos': liste, 'creer_pdf': '1', 'titre': "Exemple de fiche", 'niveau': "%s\\ieme" % (6-niveau), 'modele': str(self.comboBox_modele.currentText() + '.tex'), 'corrige': True, 'creer_unpdf': True, 'datadir': DATADIR, 'configdir': CONFIGDIR } else: exo = os.path.join(d0, "Lycee.tex" ) cor = os.path.join(d0, "Lycee-corrige.tex" ) parametres = { 'les_fiches': LESFICHES, 'fiche_exo': exo, 'fiche_cor': cor, 'liste_exos': liste, 'creer_pdf': '1', 'titre': "Exemple de fiche", 'niveau': u"Lycée", 'modele': str(self.comboBox_modele.currentText() + '.tex'), 'corrige': True, 'creer_unpdf': True, 'datadir': DATADIR, 'configdir': CONFIGDIR } System.creation(parametres) def effacer_choix_exercices(self): """Remet toutes les SpinBox à zéro et vide la liste d'exercices sélectionnés""" self.liste_creation=[] for level in range(5): for box in range(len(LESFICHES[level][2])): exec("self.spinBox_%s_%s.setValue(0)" % (6-level, box)) def enregistrer_config(self): """Fonction qui se charge d'enregistrer les options de l'interface dans le fichier de configuration après avoir complété le dictionnaire.""" tree = lxml.etree.parse(self.configfile) root = tree.getroot() options = root.find('options') options .find('nom_fichier').text = unicode(self.nom_fichier.text()) options .find('chemin_fichier').text = unicode(self.chemin_fichier.text()) options .find('titre_fiche').text = unicode(self.titre_fiche.text()) options .find('corrige').text = str(self.checkBox_corrige.isChecked()) options .find('pdf').text = str(self.checkBox_pdf.isChecked()) options .find('unpdf').text = str(self.checkBox_unpdf.isChecked()) options .find('modele').text = unicode(self.comboBox_modele.currentText() + '.tex') f = codecs.open(self.configfile, encoding='utf-8', mode='w') f.write(lxml.etree.tostring(root, pretty_print=True, encoding="UTF-8", xml_declaration=True).decode('utf-8', 'strict')) f.close() def insert_spinbox(self, level, box): """Place autant de SpinBox que d'exercices pour chaque niveau et les nomme""" treated="%s_%s" % (level, box) exec("self.horizontalLayout_%s = QtGui.QHBoxLayout()" % (treated)) exec("self.spinBox_%s = QtGui.QSpinBox(self.tab_%se)" % (treated, level)) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(40) sizePolicy.setVerticalStretch(30) exec("sizePolicy.setHeightForWidth(self.spinBox_%s.sizePolicy().hasHeightForWidth())" % (treated)) exec("self.spinBox_%s.setSizePolicy(sizePolicy)" % (treated)) exec("self.horizontalLayout_%s.addWidget(self.spinBox_%s)" % (treated, treated)) exec("self.imglabel_%s = QtGui.QLabel(self.tab_%se)" % (treated, level)) exec("self.horizontalLayout_%s.addWidget(self.imglabel_%s)" % (treated, treated)) exec("self.label_%s = QtGui.QLabel(self.tab_%se)" % (treated, level)) exec("self.horizontalLayout_%s.addWidget(self.label_%s)" % (treated, treated)) exec("spacerItem_%s = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)" % (treated)) exec("self.horizontalLayout_%s.addItem(spacerItem_%s)" % (treated, treated)) exec("self.horizontalLayout_%s.addItem(spacerItem_%s)" % (treated, treated)) exec("self.gridLayout_%se.addLayout(self.horizontalLayout_%s, %s, %s, 1, 1)" % (level, treated, box/2, box%2)) def lire_config(self, section): """Lis le fichier de configuration pyromaths.conf, enregistre les données dans un dictionnaire config""" config = {} tree = lxml.etree.parse(self.configfile) root = tree.getroot() options = root.find(section) for child in options: if child.text == 'True': text = '1' elif child.text == 'False': text = '0' else : text = child.text config[child.tag] = text return config def option_parcourir(self): d0 = QtGui.QFileDialog().getExistingDirectory (None, u"Dossier où créer les fiches", self.config['chemin_fichier'], QtGui.QFileDialog.ShowDirsOnly) if d0: self.chemin_fichier.setText(d0) def option_corrige(self): if not self.checkBox_corrige.isChecked(): self.checkBox_unpdf.setChecked(False) self.checkBox_unpdf.setEnabled(False) else: self.checkBox_unpdf.setEnabled(True) def setNbExos(self): """Modifie le nombre d'exercices dans la variable liste_creation lorsqu'on modifie une spinBox et adapte le niveau affiché dans l'en-tête de la fiche en fonction du plus haut niveau d'exercice""" niveau=0 self.liste_creation = [] for level in range(5): for box in range(len(LESFICHES[level][2])): exec("qte = self.spinBox_%s_%s.value()" % (6 - level, box), locals(), globals()) for i in range(qte): exec("self.liste_creation.append((%s, %s))" % (level, box)) if level > niveau: niveau = level self.comboBox_niveau.setCurrentIndex(niveau) def site(self): """Ouvre le navigatuer internet par défaut sur la page d'accueil du site http://www.pyromaths.org""" import webbrowser webbrowser.open('http://www.pyromaths.org') def valide_options(self): """Synchronise les options éventuellement saisies par l'utilisag QCoreApplication::exec: The event loop is already runningteur avec le dictionnaire de config""" self.config['chemin_fichier'] = self.chemin_fichier.text() self.config['nom_fichier'] = self.nom_fichier.text() self.config['titre_fiche'] = self.titre_fiche.text() self.config['corrige'] = self.checkBox_corrige.isChecked() self.config['pdf'] = self.checkBox_pdf.isChecked() self.config['unpdf'] = self.checkBox_unpdf.isChecked()and self.checkBox_unpdf.isEnabled() #================================================================ # Classe ChoixOrdreExos #================================================================ class ChoixOrdreExos(QtGui.QDialog): """À appeler de la façon suivante : form = ChoixOrdreExos(list, LesFiches, parametres) Permet de choisir l'ordre dans lequel les exercices vont apparaître parametres = {'fiche_exo': 'fiche_cor': 'liste_exos': 'creer_pdf': 'titre': 'corrige': 'niveau': 'nom_fichier': 'chemin_fichier': }""" def __init__(self, list, LesFiches, parametres, parent=None): LESFICHES = LesFiches self.parametres = parametres self.List = list QtGui.QDialog.__init__(self, parent) self.setWindowTitle("Choisissez l'ordre des exercices") layout = QtGui.QHBoxLayout() buttonBox = QtGui.QDialogButtonBox() buttonBox.setOrientation(QtCore.Qt.Vertical) buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) self.List.setAlternatingRowColors(True) self.List.setDragEnabled(True) self.List.setAcceptDrops(True) self.List.setDragDropMode(QtGui.QAbstractItemView.InternalMove) self.List.setDropIndicatorShown(True) layout.addWidget(self.List) layout.addWidget(buttonBox) self.setLayout(layout) QtCore.QObject.connect(buttonBox, QtCore.SIGNAL("accepted()"), self.accept) QtCore.QObject.connect(buttonBox, QtCore.SIGNAL("rejected()"), self.close) def accept(self): """Écrit une liste contenant la liste des exercices dans l'ordre choisit par l'utilisateur et demande à celui-ci les noms de fichiers pour les exercices et les corrigés""" valide(self.List, LESFICHES, self.parametres) self.close() def valide(list, LesFiches, parametres): """ Permet de choisir les noms et emplacements des fichiers tex, les écrits et lance la compilation LaTex""" corrige = parametres['corrige'] l=[] lesexos = [] for i in range(list.count()): l.append(unicode(list.item(i).text())) for text in l: niveau = 6 - int(text[0]) pos = LesFiches[niveau][2].index(text[4:]) lesexos.append((niveau, pos)) #============================================================ # Choix des noms des fichiers exercices et corrigés #============================================================ (f0, f1) = ("", "") saveas = QtGui.QFileDialog() filename = System.supprime_extension(parametres['nom_fichier'], '.tex') f0 = unicode(saveas.getSaveFileName(None, "Enregistrer sous...", os.path.join(parametres['chemin_fichier'], u'%s.tex' % filename), "Documents Tex (*.tex)")) if f0 != None: System.ajoute_extension(f0, '.tex') if corrige and not parametres['creer_unpdf']: f1 = unicode(saveas.getSaveFileName(None, "Enregistrer sous...", os.path.join(os.path.dirname(f0), u"%s-corrige.tex" % os.path.splitext(os.path.basename(f0))[0]), "Documents Tex (*.tex)")) else: f1 = os.path.join(os.path.dirname(f0), u"%s-corrige.tex" % os.path.splitext(os.path.basename(f0))[0]) if f1 != None: if corrige: System.ajoute_extension(f1, '.tex') parametres ['fiche_exo'] = f0 parametres ['fiche_cor'] = f1 parametres ['liste_exos'] = lesexos parametres ['les_fiches'] = LesFiches System.creation(parametres) pyromaths/src/._cinquiemes0000755000175000017500000000031511702101415016355 0ustar didrocksdidrocksMac OS X  2ATTRGn55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/pyromaths.pyc0000644000175000017500000000447011702412270016625 0ustar didrocksdidrocks Oc@sddklZlZddkZddklZlZlZlZddkl Z l Z l Z l Z l Z ddklZdZedjoQe e eZe e\ZZe eeids "( &  pyromaths/src/._Values.pyc0000644000175000017500000000031511702412270016245 0ustar didrocksdidrocksMac OS X  2ATTRGz55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._classes0000755000175000017500000000031511702101415015650 0ustar didrocksdidrocksMac OS X  2ATTRGo55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/Values.pyc0000644000175000017500000001355511702412270016042 0ustar didrocksdidrocks / Oc@seddklZddklZlZlZlZlZddkl Z l Z ddk l Z l Z ddk Z dZdZdZe d jod Zd Zn9e id jod ZdZndZdZdZedZdeZdZeZeZeZeZdddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,ggd-dd.d/d0d1d2d3d4d5d6d7d8d9g gd:ddd1d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIggdJddKdLdMdNdOdPdQdRdSdTdUdHdVdIdWggdXddYdZd[d\d]d^d_gd`d`d`d`dadbdcgggZdS(di(tstrftime(tnormpathtdirnametexiststabspathtjoin(tenvirontname(t executabletgetfilesystemencodingNcCs ttdS(sdReturns whether we are frozen via py2exe. This will affect how we find out where we are located.tfrozen(thasattrtsys(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyt we_are_frozen scCszto&ttttttdSttttt do ttttt dSdSdS(syRenvoie le dossier data, selon qu'on utilise pyromaths à partir des sources, de l'exécutable win32 ou du paquet debtdatas../data/s/usr/share/pyromaths/N( R RRRtunicodeRR RRt__file__(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pytdata_dirs  " cCsNtp"tttttdottddStddSdS(sRenvoie le dossier où se trouve l'icône, selon qu'on utilise pyromaths à partir des sources, de l'exécutable win32 ou du paquet debs../data/timagess pyromaths.pngs/usr/share/pixmapsN(R RRRRRtDATADIR(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyticon_dirs,tntcCsttdtS(Nt USERPROFILE(RRR (((s5/Users/administrateur/Desktop/pyromaths/src/Values.pythome%scCstttdtdS(NtAPPDATAt pyromaths(RRRR (((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyt configdir'stdarwincCsttdtS(NtHOME(RRR (((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyR+scCsttdddS(NtLibrarysApplication Supportt Pyromaths(RR(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyR-scCs3yttdtSWntj odSXdS(NRt(RRR tKeyError(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyR0scCsttddS(Ns.configR(RR(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyR6ss 11.05.1b2s%Yuu© 2006 – %s Jérôme Ortais
Pyromaths est distribué sous licence GPL.shttp://www.pyromaths.org/uSixièmeRu Calcul mentaluÉcrire un nombre décimaluPlacer une virguleu$Écriture fractionnaire ou décimaleuDécomposition de décimauxuConversions unitésuConversions unités d'airesuConversions unités de volumesu&Poser des opérations (sauf divisions)u%Produits, quotients par 10, 100, 1000uClasser des nombres décimauxuDroites, demi-droites, segmentsu'Droites perpendiculaires et parallèlesuPropriétés sur les droitesuMultiples de 2, 3, 5, 9, 10uFractions partageuFractions et abscissesuAires et quadrillageuSymétrie et quadrillagesuMesurer des anglesuReprésentation dans l'espaceuArrondir des nombres décimauxu CinquièmeuPriorités opératoiresuSymétrie centraleuFractions égalesuSommes de fractionsuProduits de fractionsu RepérageuAddition de relatifsuConstruction de trianglesu!Construction de parallélogrammesu ÉchellesuAire de disquesuReprésentation de donnéesu Quatrièmeu"Produits et quotients de fractionsuFractions et prioritésuBases du calcul littéralu$Réduire des expressions littéralesuPropriétés sur les puissancesu%Propriétés sur les puissances de 10uÉcritures scientifiquesuPuissances de 10uDistributivitéuDouble distributivitéuThéorème de Pythagoreu&Réciproque du théorème de Pythagoreu!Cercle et théorème de PythagoreuThéorème de ThalèsuTrigonométrieu Troisièmeu Fractionsu PuissancesuPGCDuDéveloppementsuFactorisationsu,Dévt, factorisat°, calcul et éq° produitu ÉquationuRacines carréesuSystème d'équationsuFonctions affinesu Probabilitésu$Réciproque du théorème de Thalèsu ArithmétiqueuLycéeuÉquations 2° degréuFactorisations 2° degréuFactorisations degré 3uÉtude de signeuSens de variationsuÉtude de fonctionsuVecteursu Niveau 1èreSuNiveau 1èreS, Term STGu Niveau Term SuNiveau Seconde(ttimeRtos.pathRRRRRtosRRR RR R RRRRtplatformtVERSIONtCOPYRIGHT_YEARt COPYRIGHTStWEBSITERtICONDIRRt CONFIGDIRt LESFICHES(((s5/Users/administrateur/Desktop/pyromaths/src/Values.pyts(                   pyromaths/src/._pyromaths.pyc0000644000175000017500000000031511702412270017034 0ustar didrocksdidrocksMac OS X  2ATTRGu55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/._sixiemes0000755000175000017500000000031511702101415016041 0ustar didrocksdidrocksMac OS X  2ATTRGw55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/0000755000175000017500000000000011734627250016232 5ustar didrocksdidrockspyromaths/src/cinquiemes/proportionnalite.py0000644000175000017500000002103411702101415022175 0ustar didrocksdidrocks# -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from random import randint, randrange from ..outils.decimaux import decimaux import math def ncotation(A,B,longueur,couleur=""): """trace une flèche et inscrit horizontalement, dessous, la longueur entre A et B où A et B sont des \node""" linecouleur = "" if couleur!="": linecouleur = ",linecolor = %s"%couleur couleur="\\color{%s}"%couleur return u"\\ncline[linestyle=dashed, offset = -1.5, linewidth = 0.4pt %s]{<->}{%s}{%s} \\Bput{%s %s}" %(linecouleur,A, B,couleur,longueur ) def ncotation_h(A,B,longueur,couleur=""): """idem mais au dessus de la flèche""" linecouleur = "" if couleur!="": linecouleur = ",linecolor = %s"%couleur couleur="\\color{%s}"%couleur return u"\\ncline[linestyle=dashed, offset = 1.5, linewidth = 0.4pt %s]{<->}{%s}{%s} \\Aput{%s %s}" %(linecouleur,A, B,couleur,longueur ) def exo_echelles(): """À partir d'un plan tracé, déterminer l'échelle et des longueurs déterminées.""" #Échelle echelle = [ 100, 250, 400, 500, 750, 1000][randrange(6)] #figure : un plan d'appartement déssiner en psTricks a, d = randint(40,60), randint(36,45) b, c = randint(8, d - 27), randint(9, a - 25 ) xF = a - c xE = xF - 6 yK = b + 9 yF = b - 6 yH = b #Calculs des grandeurs réelles en mm ! reels = [echelle * a, echelle * b, echelle * c, echelle * d] plan = [a, b, c, d] #choix permet de choisir si on donne a, b, c ou d en énoncé choix = randrange(4) reponses = ["a", "b", "c", "d"] enonce = reponses.pop(choix) #sur la deuxième ligne du tableau, on écrit en cm, en gras, les nombres calculés tab_reels = [ "\\bf"*(i!=choix) + decimaux(reels[i]/10.0) for i in range(4)] #Pour placer les quatre lettres sur le plan cotation_couleur = [["a", ""], ["b", ""], ["c", ""], ["d", ""]] #la longueur donnée est tracée en bleu cotation_couleur[choix][1] = "enonce" #figure PSTricks en fonction des paramètres a, d, xE, XF, yF figure = ["\\psset{PointName = none, PointSymbol = none, unit = 1mm, linewidth = .5pt}", "\\definecolor{enonce}{rgb}{0.11,0.56,0.98}", "\\begin{pspicture}(-10mm, -10mm)(50mm ,50mm)", #le rectangle ABCD "\\pstGeonode[CurveType = polygon, linewidth = 1pt](0, 0)A(%s,0)B (%s, %s)C (0, %s)D"%(a, a, d, d), #les points permettant de placer les cloisons "\\pstGeonode(%s, 0){E1}(%s, %s){E2}(%s, 0){F1}(%s, %s){F2}"%(xE, xE, yF, xF, xF, yF), "\\pstGeonode(%s, %s){G1}(%s, %s){G2}(%s, %s){G3}"%(a, b, xF, b, xF, 25), "\\pstGeonode(%s, %s){H1}(%s, %s){H2}(%s, %s){H3}(%s, %s){H4}"%(xE, b, xE, 25, xE, yK, 15, yK), "\\pstGeonode(0, %s){K2}(7, %s){K1}"%(yK, yK), "\\pstGeonode(%s, %s){J1}(%s, %s){J2}(%s, %s){J3}(%s, %s){J4}"%(xE, d - 7, xE, d, xF, d - 7, xF, d), #trace les cloisons, limitées par des tirets "\\ncline{-|}{E1}{E2}\\ncline{-|}{F1}{F2}", "\\ncline{|-}{J1}{J2}\\ncline{|-}{J3}{J4}", "\\ncline{|-}{K1}{K2}", "\\ncline{G1}{G2}\\ncline{|-|}{G3}{G2}", "\\ncline{|-|}{H1}{H2}\\ncline{-|}{H3}{H4}", #place les cotations sr la figure, l'énoncé en bleu ncotation_h("D", "C", cotation_couleur[0][0], cotation_couleur[0][1]), ncotation("B", "G1", cotation_couleur[1][0], cotation_couleur[1][1]), ncotation("F1", "B", cotation_couleur[2][0], cotation_couleur[2][1]), ncotation_h("A", "D", cotation_couleur[3][0], cotation_couleur[3][1]), "\\end{pspicture}"] exo = [u"\\exercice Sur ce plan, la longueur $%s$ mesure en réalité \\unit[%s]{m} :\n"%(enonce, decimaux(reels[choix]/1000.0))] \ + figure +\ ["\\begin{enumerate}", u"\\item Déterminer l'échelle de ce plan.", u"\\item Déterminer les longueurs réelles $%s$, $%s$ et $%s$."%(reponses[0], reponses[1], reponses[2]), "\\end{enumerate}"] cor = [u"\\exercice* Sur ce plan, la longueur $%s$ mesure en réalité \\unit[%s]{m} : \n"%(enonce, decimaux(reels[choix]/1000.0))] \ + figure +\ ["\\begin{enumerate}", u"\\item Déterminer l'échelle de ce plan.\\par", u"Sur le plan, je mesure que $%s=\\unit[%s]{cm}$.\\par"%(enonce, decimaux(plan[choix]/10.0) ), u"Or on sait que en réalité $%s = \\unit[%s]{m} = \\unit[%s]{cm}$"%(enonce, decimaux(reels[choix]/1000.0),decimaux(reels[choix]/10.0)), u" et $%s \\div %s = %s$.\\par"%(decimaux(reels[choix]), decimaux(plan[choix]), decimaux(echelle)), u"L'échelle de ce plan est donc $1/%s^e$."%echelle, u"\\item Déterminer les longueurs réelles $%s$, $%s$ et $%s$.\n"%(reponses[0], reponses[1], reponses[2]), u"Grâce à la question précédente, je peux compléter le tableau :\n", "\\begin{tabular}{|l|c|c|c|c|c}", ("\\multicolumn{1}{c}{}"+"&\\multicolumn{1}{c}{$%s$}"*4+"\\\\")%("a", "b", "c", "d"), "\\cline{1-5}", "Sur le plan (en cm) & %s & %s & %s & %s &\\rnode{plan1}{}\\\\"%tuple(map(lambda n:decimaux(n/10.0),plan)), "\\cline{1-5}", u"En réalité (en cm) & %s & %s & %s & %s &\\rnode{plan2}{}\\\\"%tuple(tab_reels), "\\cline{1-5}", "\\end{tabular}\n", "\\ncbar{->}{plan1}{plan2}\\Aput{$\\times %s$}"%echelle, u"Pour conclure, on convertit ses longueurs en m :\\par", "$$a = \\unit[%s]{m} \\quad ; \\quad b = \\unit[%s]{m} \\quad ; \\quad c = \\unit[%s]{m} \\quad ; \\quad d =\\unit[%s]{m}$$"\ %tuple(map(lambda n:decimaux(n/1000.0),reels)), "\\end{enumerate}"] return exo, cor def exo_fruits(): fruit = ["Cerises", "Tomates", "Pommes", "Poires", "Raisin", "Oranges"][randrange(6)] while 1: a, b, c = randint(10, 50)/10.0, randint(10, 50)/10.0, randint(10, 50)/10.0 if a != b and a != c and b != c: break tarif = randint(20, 50)/10.0 fruits_c = (fruit, a, b, c) fruits_e = (fruit, decimaux(a), decimaux(b), "") prix_c = ("prix", decimaux(fruits_c[1]*tarif), decimaux(fruits_c[2]*tarif), decimaux(fruits_c[3]*tarif)) prix_e = ("prix", decimaux(fruits_c[1]*tarif), "", decimaux(fruits_c[3]*tarif)) fruits_c = (fruit, decimaux(a), decimaux(b), decimaux(c)) tableau_exo = ["\\begin{tabular}{|l|c|c|c|}", "\hline", u"%s (en kg) & %s & %s & %s \\\\"%fruits_e, "\hline", u"%s (en \\euro) & %s & %s & %s \\\\"%prix_e, "\hline", "\\end{tabular}"] tableau_cor = ["\\begin{tabular}{|l|c|c|c|}", "\hline", u"%s (en kg) & %s & %s & \\bf %s \\\\"%fruits_c, "\hline", u"%s (en \\euro) & %s & \\bf %s & %s \\\\"%prix_c, "\hline", "\\end{tabular}"] exo = [u"\\exercice Le prix à payer est proportionnel à la masse de fruits achetés.\\par", u"Détermine la valeur des cases vides"] cor = [u"\\exercice Le prix à payer est proportionnel à la masse de fruits achetés.\\par", u"Détermine la valeur des cases vides"] exo += ["\n"] + tableau_exo cor += ["\n"] + tableau_cor cor.append("$$\\frac{%s \\times %s}{%s} = %s \\quad;\\qquad"%(prix_e[1], fruits_e[2], fruits_e[1],prix_c[2])) cor.append("\\frac{%s \\times %s}{%s} = %s $$"%(fruits_c[1], prix_c[3], prix_e[1],fruits_c[3])) return (exo, cor) pyromaths/src/cinquiemes/._priorites.py0000644000175000017500000000031511702101415021021 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/aires.py0000644000175000017500000001030111702101415017663 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random from ..outils.decimaux import decimaux # # ------------------- Aire de disques ------------------- # def arrondir(nombre): [partie_entiere, partie_decimale] = nombre.split(".") return int(partie_entiere) + (int(partie_decimale[0])>=5) def exo_aire_diques(): exo = ["\\exercice"] cor = ["\\exercice*"] rayon1 = 2*(random.randrange(33) + 1) rayon2 = int(1.5*rayon1) i=random.randrange(2) if i==0: donnees=('rayons', rayon1, rayon2) else: donnees=(u'diamètres', 2*rayon1, 2*rayon2) difference_des_carres = rayon2**2-rayon1**2 aire_arrondie = arrondir(str(3.14 * difference_des_carres)) enonce = \ u"""\\begin{minipage}{4cm} \\begin{pspicture}(-2,-2)(2,2) \\pscircle[fillstyle=solid](0,0){1.5} \\pscircle[fillstyle=solid, fillcolor=white](0,0){1} \\psdots[dotstyle=x](0,0) \\rput(0.3;60){$O$} \\end{pspicture} \\end{minipage}\\hfill \\begin{minipage}{13cm} On considère deux cercles de centre $O$ et de %s respectifs $\\unit[%s]{cm}$ et $\\unit[%s]{cm}$.\\par Calculer l'aire de la couronne circulaire (partie colorée) comprise entre les deux cercles en arrondissant le résultat au $\\unit{cm^2}$ le plus proche.""" % donnees exo.append(enonce) cor.append(enonce) cor.append("\\par\\dotfill{}\\\\\n") if i==0: cor.append(u"On calcule l'aire du disque de rayon $\\unit[%s]{cm}$:" % rayon2) cor.append(u"\\[\\pi \\times %s^2 = \\pi \\times %s \\times %s = \\unit[%s \\pi]{cm^2}\\]" % (rayon2, rayon2, rayon2, decimaux(rayon2**2))) cor.append(u"On calcule l'aire du disque de rayon $\\unit[%s]{cm}$:" % rayon1) cor.append(u"\\[ \\pi \\times %s^2 = \\pi \\times %s \\times %s = \\unit[%s \\pi]{cm^2}\]" % (rayon1, rayon1, rayon1, decimaux(rayon1**2))) else: cor.append(u"Un disque de diamètre $\\unit[%s]{cm}$ a pour rayon $%s \div 2 = \\unit[%s]{cm}$. Calculons son aire:" % (2*rayon2, 2*rayon2, rayon2)) cor.append(u"\\[\\pi \\times %s^2 = \\pi \\times %s \\times %s = \\unit[%s \\pi]{cm^2}\\]" % (rayon2, rayon2, rayon2, decimaux(rayon2**2))) cor.append(u"Un disque de diamètre $\\unit[%s]{cm}$ a pour rayon $%s \div 2 = \\unit[%s]{cm}$. Calculons son aire:" % (2*rayon1, 2*rayon1, rayon1)) cor.append(u"\\[\\pi \\times %s^2 = \\pi \\times %s \\times %s = \\unit[%s \\pi]{cm^2}\\]" % (rayon1, rayon1, rayon1, decimaux(rayon1**2))) cor.append(u"L'aire $\\mathcal{A}$ de la couronne est obtenue en retranchant l'aire du disque de rayon $\\unit[%s]{cm}$ à l'aire du disque de rayon $\\unit[%s]{cm}$:"% (rayon1, rayon2)) cor.append(u"\\[\\mathcal{A} = %s \\pi - %s \\pi= (%s - %s)\\pi =\\unit[%s \\pi]{cm^2}\\]" % (decimaux(rayon2**2), decimaux(rayon1**2), decimaux(rayon2**2), decimaux(rayon1**2), decimaux(difference_des_carres))) cor.append(u"L'aire exacte de la couronne est $\\unit[%s \\pi]{cm^2}$." % (decimaux(difference_des_carres))) cor.append(u"En prenant 3,14 comme valeur approchée du nombre $\\pi$, on obtient :") cor.append(u"\\[\\mathcal{A} \\approx %s \\times 3,14\\]" % decimaux(difference_des_carres)) cor.append(u"\\[\\boxed{\\mathcal{A} \\approx \\unit[%s]{cm^2}}\\]" % decimaux(aire_arrondie)) exo.append("\\end{minipage}\n") cor.append("\\end{minipage}\n") return (exo, cor) pyromaths/src/cinquiemes/._aires.py0000644000175000017500000000031511702101415020104 0ustar didrocksdidrocksMac OS X  2ATTRG޿55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/.___init__.py0000644000175000017500000000031511702101415020540 0ustar didrocksdidrocksMac OS X  2ATTRG޾55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/fractions.py0000644000175000017500000001507411702101415020564 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..classes.Fractions import Fractions #Fractions de pyromaths import random import string from ..outils import Arithmetique def fractions_egales(): exo = ["\\exercice", u"Compléter :", "\\begin{multicols}{4}", " \\begin{enumerate}"] cor = ["\\exercice*", u"Compléter :", "\\begin{multicols}{4}", " \\begin{enumerate}"] for i in range(8): n = d = 1 while n == d: n = random.randrange(1, 11) d = random.randrange(2, 11) c = random.randrange(2, 11) cas = random.randrange(2) if cas: enonce = [n, d, n * c, d * c] solution = [n, d, n * c, d * c] else: enonce = [n * c, d * c, n, d] solution = [n * c, d * c, n, d] trou = random.randrange(4) enonce[trou] = "\\ldots" solution[trou] = "\\mathbf{%s}" % solution[trou] if cas: solution.insert(2, c) solution.insert(1, c) else: solution.insert(4, c) solution.insert(3, c) exo.append("\\item $\\dfrac{%s}{%s}=\\dfrac{%s}{%s}$" % tuple(enonce)) if cas: cor.append("\\item $\\dfrac{%s_{(\\times %s)}}{%s_{(\\times %s)}}=\\dfrac{%s}{%s}$" % tuple(solution)) else: cor.append("\\item $\\dfrac{%s}{%s}=\\dfrac{%s_{(\\times %s)}}{%s_{(\\times %s)}}$" % tuple(solution)) exo.extend([" \\end{enumerate}", "\end{multicols}\n"]) cor.extend([" \\end{enumerate}", "\end{multicols}\n"]) return (exo, cor) def sommes_fractions(): exo = ["\\exercice", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent"] cor = ["\\exercice*", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent"] for i in range(8): if random.randrange(2): s = "+" else: s = "-" n = d = c = n2 = 2 while Arithmetique.pgcd(n, d) > 1: n = random.randrange(1, 11) d = random.randrange(2, 11) while Arithmetique.pgcd(n2, d * c) > 1: c = random.randrange(2, 11) n2 = random.randrange(2, 11) fr1 = Fractions(n, d) fr2 = Fractions(n2, d * c) if s == "-" and (fr1 - fr2).n * (fr1 - fr2).d < 0 or s == "+" and \ random.randrange(2): (fr1, fr2) = (fr2, fr1) exo.append("\\[ \\thenocalcul = %s%s%s \\]" % (Fractions.TeX(fr1), s, Fractions.TeX(fr2))) cor.append("\\[ \\thenocalcul = %s%s%s \\]" % (Fractions.TeX(fr1), s, Fractions.TeX(fr2))) if fr1.d < fr2.d: cor.append("\\[ \\thenocalcul = %s%s%s \\]" % (Fractions.TeX(fr1, coef=c), s, Fractions.TeX(fr2))) else: cor.append("\\[ \\thenocalcul = %s%s%s \\]" % (Fractions.TeX(fr1), s, Fractions.TeX(fr2, coef=c))) if s == "+": fr = fr1 + fr2 else: fr = fr1 - fr2 frs = Fractions.simplifie(fr) if frs.d != fr.d: cor.append("\\[ \\thenocalcul = %s \\]" % Fractions.TeX(frs, coef=fr.d // frs.d)) cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % Fractions.TeX(frs)) else: cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % Fractions.TeX(fr)) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\end{multicols}\n") cor.append("\end{multicols}\n") return (exo, cor) def produits_fractions(): exo = ["\\exercice", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent"] cor = ["\\exercice*", u"Effectuer les calculs suivants et donner le résultat sous la forme d'une fraction simplifiée :", "\\begin{multicols}{4}", " \\noindent"] for i in range(8): n1=d1=n2=d2=a=b=2 while Arithmetique.pgcd(a,b)>1: a=random.randrange(1,11) b=random.randrange(2,11) while Arithmetique.pgcd(n1*a,d1*b)>1: n1=random.randrange(1,11) d1=random.randrange(2,11) while Arithmetique.pgcd(n2*b,d2*a)>1: n2=random.randrange(1,11) d2=random.randrange(2,11) fr1 = Fractions(n1*a, d1*b) fr2 = Fractions(n2*b, d2*a) exo.append("\\[ \\thenocalcul = %s \\times %s \\]" % (Fractions.TeX(fr1), Fractions.TeX(fr2))) cor.append("\\[ \\thenocalcul = %s \\times %s \\]" % (Fractions.TeX(fr1), Fractions.TeX(fr2))) fr1s = Fractions.simplifie(fr1) fr2s = Fractions.simplifie(fr2) if abs(fr1s.d) < abs(fr1.d) or abs(fr2s.d) < abs(fr2.d): cor.append("\\[ \\thenocalcul = %s \\times %s \\]" % (Fractions.TeXSimplifie(fr1), Fractions.TeXSimplifie(fr2))) fr = fr1s * fr2s frs = Fractions.simplifie(fr) if abs(frs.d) < abs(fr.d): cor.append("\\[ \\thenocalcul = %s \\]" % Fractions.TeXProduit(fr1s, fr2s)) cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % Fractions.TeX(frs)) exo.append("\\stepcounter{nocalcul}%") cor.append("\\stepcounter{nocalcul}%") exo.append("\end{multicols}\n") cor.append("\end{multicols}\n") return (exo, cor) pyromaths/src/cinquiemes/__init__.py0000644000175000017500000000171511702101415020330 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # pyromaths/src/cinquiemes/._reperage.py0000644000175000017500000000031511702101415020573 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/._relatifs.py0000644000175000017500000000031511702101415020612 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/symetrie.py0000644000175000017500000001116711702101415020434 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random import string from math import atan, cos, pi, sin, floor, ceil #=============================================================================== # Symétrique d'une figure par rapport à une droite avec quadrillage #=============================================================================== def valeurs_quad2(nb_pts): vals = [] for i in range(nb_pts): angle = random.randrange((i * 360) / nb_pts, ((i + 1) * 360) / nb_pts) vals.append(((random.randrange(1, 7) * .5) * cos((angle * pi) / 180), (random.randrange(1, 7) * .5) * sin((angle * pi) / 180))) return vals def valeurs_quad(nb_pts): vals = [] for i in range(nb_pts): (alpha, beta) = ((i * 360) / nb_pts, ((i + 1) * 360) / nb_pts) (x, y) = (0, 0) while x == 0 or angle < alpha or angle > beta: (x, y) = (random.randrange(-6, 7) * .5, random.randrange(-6, 7) * .5) if x > 0: angle = int((atan((y * 1.0) / x) * 180) / pi + 360) % \ 360 if x < 0: angle = int((atan((y * 1.0) / x) * 180) / pi + 180) vals.append((x, y)) return vals def centre_sym(vals): fin = 0 while not fin: (fin, cpt) = (1, 0) (o1, o2) = (random.randrange(-6, 7) * .5, random.randrange(-6, 7) * .5) while fin and cpt < len(vals): fin = fin and -3 <= 2 * o1 - vals[cpt][0] <= 3 and -3 <= 2 * \ o2 - vals[cpt][1] <= 3 cpt = cpt + 1 return (o1, o2) def place_pts(vals, O): txt = [" \\pstGeonode[PointSymbol=none,PointName=none]"] for i in range(len(vals)): txt.append("(%s,%s)" % vals[i]) txt.append("{%s}" % chr(i + 97)) txt.append("\n \\pstGeonode[PointSymbol=x, linecolor=Black, dotsize=6pt](%s,%s){O}" % O) txt.append("\n \\pspolygon[linewidth=1pt]") for i in range(len(vals)): txt.append("(%s)" % chr(i + 97)) return ("").join(txt) def place_pts_sym(vals): txt = [" \\pstSymO[PointSymbol=x,PointName=none]{O}{"] for i in range(len(vals)): if i > 0: txt.append(",") txt.append("%s" % chr(i + 97)) txt.append("}[") for i in range(len(vals)): if i > 0: txt.append(",") txt.append("%s1" % chr(i + 97)) txt.append("]\n\pspolygon[linecolor=Black,linestyle=dashed, linewidth=1pt]") for i in range(len(vals)): txt.append("(%s1)" % chr(i + 97)) return ("").join(txt) def exo_quadrillage(f0, f1): pass def main(): exo = ["\\exercice", u"Construire la symétrique de chacune des figures par rapport au point O en", "utilisant le quadrillage :\\par", "\\psset{unit=.9cm}"] cor = ["\\exercice*", u"Construire la symétrique de chacune des figures par rapport au point O en", "utilisant le quadrillage :\\par", "\\psset{unit=.9cm}"] nbpts = 5 langles = [0, 90, 45, 135] for i in range(3): angle = langles.pop(random.randrange(len(langles))) vals = valeurs_quad(nbpts) O = centre_sym(vals) txt = place_pts(vals, O) exo.append("\\begin{pspicture*}(-3,-3)(3,3)") exo.append("\\psgrid[subgriddiv=2,gridlabels=0pt]") exo.append(txt) cor.append("\\begin{pspicture*}(-3,-3)(3,3)") cor.append("\\psgrid[subgriddiv=2,gridlabels=0pt]") cor.append(txt) cor.append(place_pts_sym(vals)) exo.append("\end{pspicture*}") cor.append("\end{pspicture*}") if i < 2: exo.append("\\hfill") cor.append("\\hfill") return (exo, cor) pyromaths/src/cinquiemes/._proportionnalite.py0000644000175000017500000000031511702101415022411 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/construction.py0000644000175000017500000014737511702101415021340 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from ..outils import Geometrie as geo import random,math from ..outils.Affichage import decimaux from ..outils.Geometrie import cotation, cotation_h #trigo en degré tan =lambda z:math.tan(math.radians(z)) cos =lambda z:math.cos(math.radians(z)) sin =lambda z:math.sin(math.radians(z)) def shuffle_nom(polygone): """renvoie un nom aléatoire du polygone""" n=len(polygone) polygone=polygone+polygone+polygone debut=n+random.randrange(n) sens=[-1,1][random.randrange(2)] nom="" for i in range(debut,debut+n*sens,sens): nom+=polygone[i] return nom def exo_triangle(test=False): questions=[quest_equilateral, quest_LAL, quest_ALA, quest_AAL, quest_isocele_angbase, quest_isocele_angprincipal, quest_rectangle_hypo_cote, quest_rectangle_hypo_angle, ] exo=["\\exercice", "\\begin{enumerate}"] cor=["\\exercice*", "\\begin{enumerate}"] cor.append("\\definecolor{enonce}{rgb}{0.11,0.56,0.98}") cor.append("\\definecolor{calcul}{rgb}{0.13,0.54,0.13}") cor.append(u"\\psset{MarkAngleRadius=0.6,PointSymbol=none}") if test:#toutes les constructions en test for quest in questions: quest(exo,cor) else:#Construction choisies au hasard random.shuffle(questions) for i in range(4): questions[i](exo,cor) exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor def quest_equilateral(exo,cor): A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) c=0.1*random.randint(40,70)#longueur AB angBAC=angABC=60 exo.append(u"\\item Trace un triangle $%s$ équilatéral de côté $\\unit[%s]{cm}$.\\par"%(nom,decimaux(c))) cor.append(u"\\item Trace un triangle $%s$ équilatéral de côté $\\unit[%s]{cm}$.\\par"%(nom,decimaux(c))) x_C=(c*tan(angABC))/(tan(angABC)+tan(angBAC)) y_C=x_C*tan(angBAC) cor.append(u"\\begin{pspicture}(-1,-1)(%s,%s)"%(c+1,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,A)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,B)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(A,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(A,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_3]"%(B,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_4]"%(B,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_4}{C_3}"%(B)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(u"\\end{pspicture}") def quest_LAL(exo,cor): """on donne un angle et les longueurs de ses deux côtés""" """ angBAC et AB=c et AC=b""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) c=0.1*random.randint(40,70)#longueur AB b=0.1*random.randint(20,100)#longueur BC angBAC=3*random.randint(7,50)#BAC mesure entre 21° et 150° exo.append(u"\\item Trace un triangle $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$" %(nom,A,B,decimaux(c),A,C,decimaux(b),B,A,C,angBAC)) cor.append(u"\\item Trace un triangle $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(c),A,C,decimaux(b),B,A,C,angBAC)) cor.append(u"\\begin{pspicture}(%s,%s)(%s,%s)"%(min(0,b*cos(angBAC))-0.4,-1,max(b,b*cos(angBAC))+0.4,b*sin(angBAC)+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s;%s){%s}(%s,0){%s}"%(A,b,angBAC,C,c,B)) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,C)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(A,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(A,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(A)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) if angBAC<111: x_C,y_C=b*cos(angBAC),b*sin(angBAC) cor.append(cotation_h((0,0),(x_C,y_C),decimaux(b),couleur="enonce")) else: x_C,y_C=b*cos(angBAC),b*sin(angBAC) cor.append(cotation((x_C,y_C),(0,0),decimaux(b),couleur="enonce")) cor.append(u"\\end{pspicture}") def quest_ALA(exo,cor): """on donne deux angles et la longueur du côté commun""" """ angBAC et angABC et AB=c""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) c=0.1*random.randint(40,70)#longueur AB angBAC=5*random.randint(4,12) angABC=5*random.randint(4,12) exo.append(u"\\item Trace un triangle $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$ et $\\widehat{%s%s%s}=%s\\degres$" %(nom,A,B,decimaux(c),B,A,C,angBAC,A,B,C,angABC)) cor.append(u"\\item Trace un triangle $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$ et $\\widehat{%s%s%s}=%s\\degres$\\par" %(nom,A,B,decimaux(c),B,A,C,angBAC,A,B,C,angABC)) x_C=(c*tan(angABC))/(tan(angABC)+tan(angBAC)) y_C=x_C*tan(angBAC) cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(c+1,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,C,B,C)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(C,B,A,angABC)) cor.append(u"\\end{pspicture}") def quest_AAL(exo,cor): """on donne deux angles et la longueur d'un côté non commun aux deux angles""" """ angBAC et angACB et AB=c""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) angBAC=3*random.randint(10,24)#entre 30° et 72° angACB=3*random.randint(10,24)#entre 30° et 72° angABC=180-angBAC-angACB ABmax=int(35*(tan(angABC)+tan(angBAC))/(tan(angBAC)*tan(angABC)))#donne une hauteur inférieur à 35*0.2=7 cm c=0.2*random.randint(20,max(20,ABmax))#longueur AB exo.append(u"\\item Trace un triangle $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$ et $\\widehat{%s%s%s}=%s\\degres$" %(nom,A,B,decimaux(c),B,A,C,angBAC,A,C,B,angACB)) cor.append(u"\\item Trace un triangle $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$ et $\\widehat{%s%s%s}=%s\\degres$\\par" %(nom,A,B,decimaux(c),B,A,C,angBAC,A,C,B,angACB)) cor.append(u"On doit d'abord calculer la mesure de $\\widehat{%s%s%s}$.\\\\" %(A,B,C)) cor.append(u"Or la somme des trois angles d'un triangle est égale à 180\\degres donc $\\widehat{%s%s%s}=180\\degres-%s\\degres-%s\\degres=%s\\degres$.\\par" %(A,B,C,angBAC,angACB,angABC)) x_C=(c*tan(angABC))/(tan(angABC)+tan(angBAC)) y_C=x_C*tan(angBAC) cor.append(u"\\begin{pspicture}(-1,-1)(%s,%s)"%(c+1,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,C,B,C)) cor.append(u"\\pstMarkAngle[linecolor=calcul]{%s}{%s}{%s}{\\color{calcul}%s\\degres}"%(C,B,A,angABC)) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(A,C,B,angACB)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(u"\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\end{pspicture}") def quest_isocele_angbase(exo,cor): """on donne ABC isocele en C, AB=c et angBAC""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) angABC=angBAC=random.randint(20,70) maxc = max(20,int(35 / tan(angBAC)))#longueur c maximale pour que la hauteur soit 7 cm =0.2*35 minc = min(20,int(35 / tan(angBAC))) c=0.2*random.randint(minc,min(maxc,50))#longueur AB #Calcul pour tracer x_C=c/2 y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un triangle $%s$ isocèle en $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$." %(nom,C,A,B,decimaux(c),B,A,C,angBAC)) cor.append(u"\\item Trace un triangle $%s$ isocèle en $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$. \\par" %(nom,C,A,B,decimaux(c),B,A,C,angBAC)) cor.append(u"Comme $%s%s%s$ est un triangle isocèle en $%s$, je sais que les angles adjacents à la base sont de même mesure \ donc $\\widehat{%s%s%s}=\\widehat{%s%s%s}=%s\\degres$.\\par"%(A,B,C,C,A,B,C,B,A,C,angBAC)) cor.append(u"\\begin{pspicture}(-1,-1)(%s,%s)"%(c+1,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,C)) cor.append("\\pstLineAB[linestyle=none]{%s}{%s} \\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(B,C)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul]{%s}{%s}{%s}{%s\\degres}"%(C,B,A,angABC)) cor.append(u"\\end{pspicture}") def quest_isocele_angprincipal(exo,cor): """on donne ABC isocele en C, AB=c et angACB""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) angACB=2*random.randint(20,60)#ACB est pair entre 40° et 120° angBAC=angABC=(180-angACB)/2 maxc = max(20,int(35 / tan(angBAC)))#longueur c maximale pour que la hauteur soit 7 cm =0.2*35 c=0.2*random.randint(20,min(maxc,35))#longueur AB #Calcul pour tracer x_C=c/2 y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un triangle $%s$ isocèle en $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$." %(nom,C,A,B,decimaux(c),A,C,B,angACB)) cor.append(u"\\item Trace un triangle $%s$ isocèle en $%s$ tel que $%s%s=\\unit[%s]{cm}$, $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,C,A,B,decimaux(c),A,C,B,angACB)) cor.append(u"Comme $%s%s%s$ est un triangle isocèle en $%s$, je sais que les angles adjacents à la base sont de même mesure \ donc $\\widehat{%s%s%s}=\\widehat{%s%s%s}$.\\par"%(A,B,C,C,A,B,C,B,A,C)) cor.append(u"De plus, je sais que la somme des mesures des trois angles d'un triangle est égale à 180\\degres \\\\ \ donc $\\widehat{%s%s%s}=\\widehat{%s%s%s}=(180\\degres-%s\\degres)\\div 2=%s\\degres$. \\par" %(B,A,C,A,B,C,angACB,angBAC)) cor.append(u"\\begin{pspicture}(-1,-1)(%s,%s)"%(c+1,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,C)) cor.append("\\pstLineAB[linestyle=none]{%s}{%s} \\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(B,C)) cor.append("\\pstLineAB[linestyle=none]{%s}{%s} \\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce,Mark=MarkHash]{%s}{%s}{%s}{%s\\degres}"%(A,C,B,angACB)) cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\pstMarkAngle[linecolor=calcul]{%s}{%s}{%s}{%s\\degres}"%(C,B,A,angABC)) cor.append(u"\\end{pspicture}") def quest_rectangle_hypo_angle(exo,cor): """on donne un triangle ABC rectangle en C et l'hypotenuse AB et l'angle BAC""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) c=0.2*random.randint(20,35)#longueur AB angBAC=3*random.randint(7,23)#un angle mesurant entre 21° et 69° angABC=90-angBAC #angACB=90 #Calcul pour tracer x_C=(c*tan(angABC))/(tan(angABC)+tan(angBAC)) y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un triangle $%s$ rectangle en $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,C,A,B,decimaux(c),B,A,C,angBAC)) cor.append(u"\\item Trace un triangle $%s$ rectangle en $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,C,A,B,decimaux(c),B,A,C,angBAC)) ## cor.append("\\begin{multicols}{2}") cor.append(u"Je sais que dans un triangle rectangle, les deux angles aigus sont complémentaires \\\\ \ donc $\widehat{%s%s%s}=90\\degres-%s\\degres=%s\\degres$.\\par"%(B,A,C,angBAC,angABC)) cor.append("\\figureadroite{") cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(c+0.4,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(A,C,B)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,C,B,C)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul]{%s}{%s}{%s}{%s\\degres}"%(C,B,A,angABC)) cor.append(u"\\end{pspicture}}{") cor.append("\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,B,decimaux(c))) cor.append(u"\\item puis la demi-droite $[%s%s)$ en traçant l'angle~$\widehat{%s%s%s}$ ;"%(A,C,B,A,C)) cor.append(u"\\item puis la demi-droite $[%s%s)$ en traçant l'angle~$\widehat{%s%s%s}$ ;"%(B,C,A,B,C)) ## cor.append(u"\\item enfin je vérifie les trois {\\color{enonce}conditions de l'énoncé}.") cor.append("\\end{enumerate}\n") ## cor.append("\\end{multicols}") cor.append("}") def quest_rectangle_hypo_cote(exo,cor): """on donne un triangle ABC rectangle en B et l'hypotenuse AC et le coté AB""" A,B,C=geo.choix_points(3) nom=shuffle_nom([A,B,C]) c=0.2*random.randint(20,35)#longueur AB b=0.1*random.randint(int(10*(c))+1,100)#longueur AC angABC=90 #calcul pour tracer angBAC=math.degrees(math.acos(float(c)/float(b))) x_C=(c*tan(angABC))/(tan(angABC)+tan(angBAC)) y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un triangle $%s$ rectangle en $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$.\\par" %(nom,B,A,B,decimaux(c),A,C,decimaux(b))) cor.append(u"\\item Trace un triangle $%s$ rectangle en $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$.\\par" %(nom,B,A,B,decimaux(c),A,C,decimaux(b))) ## cor.append("\\begin{multicols}{2}") cor.append("\\figureadroite{") cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(c+0.4,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,c,B,x_C,y_C,C)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(C,B,A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(A,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(A,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(A)) cor.append(u"\\pstLineAB{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,B,B,C)) cor.append(cotation((0,0),(c,0),decimaux(c),couleur="enonce")) cor.append(cotation_h((0,0),(x_C,y_C),decimaux(b),couleur="enonce")) cor.append(u"\\end{pspicture}}{") cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,B,decimaux(c))) cor.append(u"\\item puis je trace l'angle droit $\\widehat{%s%s%s}$ ;"%(A,B,C)) cor.append(u"\\item enfin, je reporte au compas la longueur \\mbox{$%s%s=\\unit[%s]{cm}$} à partir de $%s$."%(A,C,decimaux(b),A)) cor.append("\\end{enumerate}}") ## cor.append("\\end{multicols}") ################################################################################################# # Les construction sont faites avec [AB] horizontale (ou avec la diagonale [AC] horizontale) # D-------C # / / # / / # A-------B # A est toujours l'origine : A(0,0) # # AB est la longueur AB : type(float) en cm # angBAC est la mesure de l'angle BAC : type(int) en degrés # x_C,y_C sont les coordonnées cartésiennes du point C # les coordonnées polaires sont notées (5 ; 60) # ################################################################################################### def exo_quadrilatere(test=False): exo=["\\exercice", "\\begin{enumerate}"] cor=["\\exercice*", "\\begin{enumerate}"] cor.append("\\definecolor{enonce}{rgb}{0.11,0.56,0.98}") #couleur pour reporter les informations de la consigne cor.append("\\definecolor{calcul}{rgb}{0.13,0.54,0.13}") #couleur pour reporter des informations déduites par raisonnement ou calcul cor.append(u"\\psset{MarkAngleRadius=0.7,PointSymbol=none,dotscale=2}") #MarkAngleRadius = rayon de l'arc marquant les angles #PointSymbol=none les points ne sont pas tracés #dotscale=2, grossit la croix si PointSymbol=x #liste des questions possibles questions=[quest_rectangle_diag, quest_rectangle_angle, quest_rectangle_angle_diag, quest_rectangle_diag_angle, quest_parallelogramme_CCA, quest_parallelogramme_CDA, quest_parallelogramme_DDA, quest_losange_DD, quest_losange_CD, quest_losange_CDbis, quest_losange_CC, carre_diag] if test:#toutes les constructions en test for quest in questions: quest(exo,cor) else: #on choisit un parallélogramme, un losange et un rectangle questions[random.randrange(4)](exo,cor) questions[random.randrange(4,7)](exo,cor) questions[random.randrange(7,11)](exo,cor) #questions[11], le carré n'est jamais proposé exo.append("\\end{enumerate}") cor.append("\\end{enumerate}") return exo,cor ################################################################ ####### RECTANGLES ############# def quest_rectangle_diag(exo,cor): """on donne un rectangle ABCD avec un côté AB et une diagonale AC""" A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) L=random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement Diag=0.1*random.randint(L+10,70)#+1.1 pour éviter les problèmes d'arrondi L=0.1*L #Calcul pour tracer angBAC=math.degrees(math.acos(float(L)/float(Diag))) x_C=L y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un rectangle $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $%s%s=\\unit[%s]{cm}$.\\par" %(nom,A,B,decimaux(L),A,C,decimaux(Diag))) cor.append(u"\\item Trace un rectangle $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $%s%s=\\unit[%s]{cm}$.\\par" %(nom,A,B,decimaux(L),A,C,decimaux(Diag))) #figure cor.append("\\figureadroite{") cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(L+0.4,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,L,B,x_C,y_C,C)) cor.append(u"\\pstGeonode[PosAngle=135](0,%s){%s}"%(y_C,D)) #codage cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(D,C,B)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(B,A,D)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(C,B,A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(A,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(A,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(A)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,D,C,D,A,B,B,C)) cor.append(cotation((0,0),(L,0),decimaux(L),couleur="enonce")) cor.append(cotation_h((0,0),(x_C,y_C),decimaux(Diag),couleur="enonce")) cor.append(u"\\end{pspicture}}{") #Programme de construction cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,B,decimaux(L))) cor.append(u"\\item puis je trace l'angle droit $\\widehat{%s%s%s}$ ;"%(A,B,C)) cor.append(u"\\item je reporte au compas la longueur $%s%s=\\unit[%s]{cm}$ à partir de $%s$ ;"%(A,C,decimaux(Diag),A)) cor.append(u"\\item je trace enfin les angles droits en $%s$ et en $%s$ pour placer le point $%s$."%(A,C,D)) cor.append("\\end{enumerate}}") def quest_rectangle_angle(exo,cor): """On donne un rectangle ABCD avec le côté AB et l'angle BAC""" A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) L=random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement angBAC=random.randint(25,65) L=0.1*L #Calcul pour tracer x_C=L y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un rectangle $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(L),B,A,C,angBAC)) cor.append(u"\\item Trace un rectangle $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(L),B,A,C,angBAC)) cor.append("\\figureadroite{") cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(L+0.4,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,L,B,x_C,y_C,C)) cor.append(u"\\pstGeonode[PosAngle=135](0,%s){%s}"%(y_C,D)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(D,C,B)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(B,A,D)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(C,B,A)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}" %(A,D,C,D,A,B,B,C,A,C)) cor.append(cotation((0,0),(L,0),decimaux(L),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\end{pspicture}}{") #Programme de construction cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,B,decimaux(L))) cor.append(u"\\item puis je trace l'angle droit $\\widehat{%s%s%s}$ ;"%(A,B,C)) cor.append(u"\\item la demi-droite $[%s%s)$ en mesurant $\\widehat{%s%s%s}=%s\\degres$."%(A,C,B,A,C,angBAC)) cor.append(u"\\item je trace enfin les angles droit en $%s$ et en $%s$ pour placer le point $%s$."%(A,C,D)) cor.append("\\end{enumerate}}") def quest_rectangle_angle_diag(exo,cor): """On donne un rectangle ABCD de centre E, la diagonale AC et l'angle AEB""" A,B,C,D,E=geo.choix_points(5) nom=shuffle_nom([A,B,C,D]) angAEB=2*random.randint(20,70) Diag=0.2*random.randint(25,45) #calcul pour tracer angBAC=(180-angAEB)/2 L=Diag*cos(angBAC) x_C=L y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un rectangle $%s$ de centre $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,E,A,C,decimaux(Diag),A,E,B,angAEB)) cor.append(u"\\item Trace un rectangle $%s$ de centre $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,E,A,C,decimaux(Diag),A,E,B,angAEB)) ## cor.append("\\begin{multicols}{2}") #Programme de construction cor.append("\\figureadroite{") ## cor.append("\columnbreak") cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(L+0.4,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,L,B,x_C,y_C,C)) cor.append(u"\\pstGeonode[PosAngle={135,0}](0,%s){%s}(%s,%s){%s}"%(y_C,D,x_C/2.0,y_C/2.0,E)) cor.append(u"\\pstLineAB{%s}{%s}"%(C,D)) cor.append(u"\\pstLineAB{%s}{%s}"%(A,D)) cor.append(u"\\pstLineAB[nodesep=-1]{%s}{%s}"%(B,D)) #codage cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(E,A)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(E,B)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(E,C)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(E,D)) cor.append(u"\\psarc[linecolor=calcul](%s,%s){%s}{%s}{%s} "%(x_C/2.0,y_C/2.0,Diag/2,angBAC-7,angBAC+7)) cor.append(u"\\psarc[linecolor=calcul](%s,%s){%s}{%s}{%s} "%(x_C/2.0,y_C/2.0,Diag/2,180-angBAC-7,180-angBAC+7)) cor.append(u"\\psarc[linecolor=calcul](%s,%s){%s}{%s}{%s} "%(x_C/2.0,y_C/2.0,Diag/2,-angBAC-7,-angBAC+7)) cor.append(u"\\psarc[linecolor=calcul](%s,%s){%s}{%s}{%s} "%(x_C/2.0,y_C/2.0,Diag/2,180+angBAC-7,180+angBAC+7)) cor.append("\\pcline[linestyle=none](0,0)(%s,%s)\\aput*{:U}{\\color{enonce}\\unit[%s]{cm}}"%(L,y_C,decimaux(Diag))) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(A,E,B,angAEB)) cor.append(u"\\end{pspicture}}{") cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,C,decimaux(Diag))) cor.append(u"\\item le centre du rectangle est le milieu des diagonales donc $%s$ est le milieu de $[%s%s]$ ;"%(E,A,C)) cor.append(u"\\item je trace la diagonale $(%s%s)$ passant par $%s$ en mesurant \\mbox{$\\widehat{%s%s%s}=%s\\degres$} ;" %(B,D,E,A,E,B,angAEB)) cor.append(u"\\item Comme les diagonales du rectangle sont de même longueur, je reporte les longueurs $%s%s=%s%s=\\unit[%s]{cm}$." %(E,D,E,B,decimaux(Diag/2))) ## cor.append(u"\\item je trace enfin les angles droits en $%s$ et en $%s$ pour palcer le point $%s$."%(A,C,D)) cor.append("\\end{enumerate}}") ## cor.append("\\end{multicols}") def quest_rectangle_diag_angle(exo,cor): """On donne un rectangle ABCD la diagonale AC et l'angle BAC""" A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) L=random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement angBAC=random.randint(25,65) Diag=0.1*random.randint(50,80) #Calcul L=Diag*cos(angBAC) x_C=L y_C=x_C*tan(angBAC) exo.append(u"\\item Trace un rectangle $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,C,decimaux(Diag),B,A,C,angBAC)) cor.append(u"\\item Trace un rectangle $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,C,decimaux(Diag),B,A,C,angBAC)) ## cor.append("\\begin{multicols}{2}") cor.append("\\figureadroite{") ## cor.append("\columnbreak") #figure cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(L+0.4,y_C+1)) cor.append(u"\\pstTriangle(0,0){%s}(%s,0){%s}(%s,%s){%s}"%(A,L,B,x_C,y_C,C)) cor.append(u"\\pstGeonode[PosAngle=135](0,%s){%s}"%(y_C,D)) #codage cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(D,C,B)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(B,A,D)) cor.append(u"\\color{enonce}\\pstRightAngle[linecolor=enonce]{%s}{%s}{%s}"%(C,B,A)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB[nodesep=-1]{%s}{%s}" %(A,D,C,D,A,B,B,C)) cor.append(cotation_h((0,0),(L,y_C),decimaux(Diag),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\end{pspicture}}{") #Programme de construction cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,C,decimaux(Diag))) cor.append(u"\\item la demi-droite $[%s%s)$ en mesurant \\mbox{$\\widehat{%s%s%s}=%s\\degres$} ;"%(A,B,B,A,C,angBAC)) cor.append(u"\\item puis la perpendiculaire à $[%s%s)$ passant par~$%s$ ;"%(A,B,C)) cor.append(u"\\item je trace enfin les angles droits en $%s$ et en $%s$ pour placer le point~$%s$."%(A,C,D)) cor.append("\\end{enumerate}}") ## cor.append("\\end{multicols}") ################## PARALLÉLOGRAMMES QUELCONQUES ########################### def quest_parallelogramme_CCA(exo,cor): """On donne un parallélogramme avec la longueur de deux côtés et un angle.""" #3 choix d'angle : CC ou un autre angle CC ou un angle Côté Diagonale A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) AB=0.1*random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement AD=0.1*random.randint(40,60)#AD mesure entre 4cm et 7cm, tracé horizontalement angBAD=random.randint(25,65) #Pour tracer x_C=AB+AD*cos(angBAD) y_C=AD*sin(angBAD) exo.append(u"\\item Trace un parallélogramme $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(AB),D,A,decimaux(AD),B,A,D,angBAD)) cor.append(u"\\item Trace un parallélogramme $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(AB),D,A,decimaux(AD),B,A,D,angBAD)) cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,B,decimaux(AB))) cor.append(u"\\item je mesure l'angle $\\widehat{%s%s%s}=%s\\degres$ puis je place le point~$%s$ ;"%(B,A,D,angBAD,D)) cor.append(u"\\item enfin je reporte les longueurs $%s%s=%s%s$ et $%s%s=%s%s$ pour place le point~$%s$." %(D,C,A,B,B,C,A,D,C)) cor.append("\\end{enumerate}\n") cor.append(u"\\begin{pspicture}(-0.4,-1)(%s,%s)"%(max(AB,x_C)+0.4,y_C+1)) cor.append(u"\\pstGeonode[PosAngle={-135,-45,45,135}](0,0){%s}(%s,0){%s}(%s,%s){%s}(%s;%s){%s}"%(A,AB,B,x_C,y_C,C,AD,angBAD,D)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}" %(A,D,C,D,A,B,B,C)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(D,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(D,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(D)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[D_1]"%(A,D)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[D_2]"%(A,D)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{D_2}{D_1}"%(A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_3]"%(B,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_4]"%(B,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_4}{C_3}"%(B)) cor.append(cotation_h((0,0),(x_C-AB,y_C),decimaux(AD),couleur="enonce")) cor.append(cotation((0,0),(AB,0),decimaux(AB),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,D,angBAD)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(A,D)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(B,C)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHash}"%(A,B)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHash}"%(D,C)) cor.append(u"\\end{pspicture}") def quest_parallelogramme_CDA(exo,cor): """On donne un parallélogramme avec la longueur d'un côté et une diagonale et l'angle entre ces deux segments""" A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) AB=0.1*random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement AC=0.1*random.randint(40,70)#AC mesure entre 4cm et 7cm, tracé horizontalement angBAC=random.randint(25,65) #Calcul pour tracer x_C=round(AC*cos(angBAC),4)#round() évite une écriture scientifique si x_D=2.4e-15, non reconnue par PSTricks y_D=y_C=AC*sin(angBAC) x_D=round(x_C-AB,4) exo.append(u"\\item Trace un parallélogramme $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(AB),C,A,decimaux(AC),B,A,C,angBAC)) cor.append(u"\\item Trace un parallélogramme $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(AB),C,A,decimaux(AC),B,A,C,angBAC)) #Programme de construction cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,B,decimaux(AB))) cor.append(u"\\item je trace la demi-droite $[%s%s)$ en mesurant $\\widehat{%s%s%s}=%s\\degres$ ;"%(A,C,B,A,C,angBAC)) cor.append(u"\\item je place le point $%s$ en mesurant $%s%s=\\unit[%s]{cm}$ ;"%(C,A,C,decimaux(AC))) cor.append(u"\\item je construis le point $%s$ en reportant au compas $%s%s=%s%s$ et $%s%s=%s%s$." %(D,C,D,B,A,A,D,B,C)) cor.append("\\end{enumerate}\n") #Figure cor.append(u"\\begin{pspicture}(%s,-1)(%s,%s)"%(min(0,x_C-AB)-0.4,max(AB,x_C)+0.4,y_C+1)) cor.append(u"\\pstGeonode[PosAngle={-135,-45,45,135}](0,0){%s}(%s,0){%s}(%s,%s){%s}(%s,%s){%s}"%(A,AB,B,x_C,y_C,C,x_D,y_D,D)) cor.append(u"\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB[nodesepB=-1]{%s}{%s}" %(A,D,C,D,A,B,B,C,A,C)) #Construction cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(A,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(A,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[D_1]"%(A,D)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[D_2]"%(A,D)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{D_2}{D_1}"%(A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[D_3]"%(C,D)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[D_4]"%(C,D)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{D_4}{D_3}"%(C)) #Codage cor.append(cotation_h((0,0),(x_C,y_C),decimaux(AC),couleur="enonce")) cor.append(cotation((0,0),(AB,0),decimaux(AB),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(A,D)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(B,C)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHash}"%(A,B)) cor.append(u"\\pstLineAB[linestyle=none]{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHash}"%(D,C)) cor.append(u"\\end{pspicture}") def quest_parallelogramme_DDA(exo,cor): """On donne un parallélogramme avec la longueur des deux diagonales et l'angle entre les diagonales""" # choix d'angle : on pourrait donner l'angle BAC #diagonale ou demi-diagonale A,B,C,D,E=geo.choix_points(5) nom=shuffle_nom([A,B,C,D]) BD=0.2*random.randint(20,40)#AB mesure entre 4cm et 8cm, tracé horizontalement AC=0.2*random.randint(20,40)#AC mesure entre 4cm et 8cm, tracé horizontalement angAEB=random.randint(35,145) AE=AC/2 BE=BD/2 #calcul pour tracer AB=math.sqrt(AE**2+BE**2-2*AE*BE*cos(angAEB)) angBAC=math.degrees(math.asin(BE*sin(angAEB)/AB)) x_C=AC*cos(angBAC) y_D=y_C=round(AC*sin(angBAC),4) x_D=round(x_C-AB,4) exo.append(u"\\item Trace un parallélogramme $%s$ de centre $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,E,A,C,decimaux(AC),B,D,decimaux(BD),A,E,B,angAEB)) cor.append(u"\\item Trace un parallélogramme $%s$ de centre $%s$ tel que $%s%s=\\unit[%s]{cm}$, $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,E,A,C,decimaux(AC),B,D,decimaux(BD),A,E,B,angAEB)) cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,C,decimaux(AC))) cor.append(u"\\item Dans un parallélogramme les diagonales se coupent en leur milieu donc $%s%s=%s%s=\\unit[%s]{cm}$ et $%s%s=%s%s=\\unit[%s]{cm}$ ;" %(A,E,C,E,decimaux(AC/2),B,E,E,D,decimaux(BD/2))) cor.append("\\end{enumerate}\n") cor.append(u"\\begin{pspicture}(%s,-1)(%s,%s)"%(min(0,x_D)-0.4,max(AB,x_C)+0.4,y_C+1)) cor.append(u"\\pstGeonode[PosAngle={-135,-45,45,135,%s}](0,0){%s}(%s,0){%s}(%s,%s){%s}(%s,%s){%s}(%s,%s){%s}" %([round(angBAC-(180-angAEB)/2),round(angBAC+(angAEB)/2)][angAEB>90],A,AB,B,x_C,y_C,C,x_D,y_D,D,x_C/2,y_C/2,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(A,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkHashh}"%(C,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(B,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(D,E)) cor.append(u"\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}\\pstLineAB{%s}{%s}" %(A,D,C,D,A,B,B,C)) cor.append(cotation_h((0,0),(x_C/2,y_C/2),decimaux(AC/2),couleur="enonce")) cor.append(cotation_h((x_C/2,y_C/2),(AB,0),decimaux(BD/2),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(A,E,B,angAEB)) cor.append(u"\\end{pspicture}") ###################### LOSANGES ######################## def quest_losange_DD(exo,cor): """On donne un losange avec la longueur des deux diagonales""" #diagonale ou demi-diagonale A,B,C,D,E=geo.choix_points(5) nom=shuffle_nom([A,B,C,D]) BD=0.2*random.randint(15,25)#AB mesure entre 4cm et 8cm, tracé horizontalement AC=0.2*random.randint(20,40)#AC mesure entre 4cm et 8cm, tracé horizontalement exo.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $%s%s=\\unit[%s]{cm}$.\\par" %(nom,A,C,decimaux(AC),B,D,decimaux(BD))) cor.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $%s%s=\\unit[%s]{cm}$.\\par" %(nom,A,C,decimaux(AC),B,D,decimaux(BD))) cor.append(u"Je note $%s$ le centre du losange.\\par"%E) cor.append("\\figureadroite{") cor.append(u"\\begin{pspicture}(%s,%s)(%s,%s)"%(-BD/2-0.7,-AC/2-0.4,BD/2+0.4,AC/2+0.4)) cor.append(u"\\pstGeonode[PosAngle={-90,0,90,180}](0,%s){%s}(%s,0){%s}(0,%s){%s}(%s,0){%s}" %(-AC/2,A,BD/2,B,AC/2,C,-BD/2,D)) cor.append("\\pstGeonode[PosAngle=-45](0,0){%s}"%E) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCross}"%(A,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCross}"%(C,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(B,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(D,E)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,B)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,D)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(D,A)) cor.append("\\pstRightAngle[linecolor=calcul]{%s}{%s}{%s}"%(B,E,C)) cor.append(cotation_h((-BD/2,0),(0,0),decimaux(BD/2),couleur="enonce")) cor.append(cotation_h((0,-AC/2),(0,0),decimaux(AC/2),couleur="enonce")) cor.append(u"\\end{pspicture}}{") cor.append(u"Les diagonales du losange se coupent perpendiculairement en leur milieu~$%s$ ; on a donc :"%E) cor.append(u"\\begin{enumerate}") cor.append(u"\\item $%s%s=%s%s=\\unit[%s]{cm}$ \\item $%s%s=%s%s=\\unit[%s]{cm}$ ;" %(A,E,C,E,decimaux(AC/2),B,E,E,D,decimaux(BD/2))) cor.append(u"\\item $(%s%s)\\perp(%s%s)$."%(A,C,B,D)) cor.append("\\end{enumerate}}\n") def quest_losange_CC(exo,cor): """On donne un losange avec la longueur d'un côté et un angle entre côtés""" #diagonale ou demi-diagonale A,B,C,D,E=geo.choix_points(5) nom=shuffle_nom([A,B,C,D]) AB=0.2*random.randint(15,25)#AB mesure entre 4cm et 8cm, tracé horizontalement angBAD=random.randint(30,150) #Calcul pour tracer x_D=AB*cos(angBAD) y_D=y_C=AB*sin(angBAD) x_C=x_D+AB exo.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(AB),B,A,D,angBAD)) cor.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,B,decimaux(AB),B,A,D,angBAD)) cor.append(u"Les quatre côtés du losange sont de même longueur donc $%s%s=%s%s=%s%s=%s%s=\\unit[%s]{cm}$ ;"%(A,B,B,C,C,D,D,A,decimaux(AB))) cor.append(u"\\begin{enumerate}") cor.append(u"\\item On trace le côté $[%s%s]$ puis on mesure l'angle $\\widehat{%s%s%s}=%s\\degres$ ;"%(A,B,B,A,D,angBAD)) cor.append(u"\\item ensuite on reporte au compas les longueurs $%s%s$ et $%s%s$ pour construire le point $%s$."%(C,D,B,C,C)) cor.append("\\end{enumerate}\n") cor.append(u"\\begin{pspicture}(%s,%s)(%s,%s)"%(min(0,x_D)-0.4,0-0.4,max(AB,x_C),y_D+0.4)) cor.append(u"\\pstGeonode[PosAngle={%s,%s,%s,%s}](0,0){%s}(%s,0){%s}(%s,%s){%s}(%s,%s){%s}" %(angBAD/2-180,angBAD/2-90,angBAD/2,angBAD/2+90,A,AB,B,x_C,y_C,C,x_D,y_D,D)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,B)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,D)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(D,A)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_1]"%(D,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_2]"%(D,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_2}{C_1}"%(D)) cor.append(u"\\pstRotation[RotAngle=7,PointSymbol=none,PointName=none]{%s}{%s}[C_3]"%(B,C)) cor.append(u"\\pstRotation[RotAngle=-7,PointSymbol=none,PointName=none]{%s}{%s}[C_4]"%(B,C)) cor.append(u"\\pstArcOAB[linecolor=calcul]{%s}{C_4}{C_3}"%(B)) cor.append(cotation((0,0),(AB,0),decimaux(AB),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(B,A,D,angBAD)) cor.append(u"\\end{pspicture}") def quest_losange_CD(exo,cor): """On donne un losange avec la longueur d'un côté et la mesure d'un angle entre un côté et une diagonale""" A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) AC=0.1*random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement angBAC=random.randint(25,75) #Calcul pour tracer x_D=AC/2 y_D=AC/2*tan(angBAC) exo.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,C,decimaux(AC),B,A,C,angBAC)) cor.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,C,decimaux(AC),B,A,C,angBAC)) #Rédaction cor.append(u" Comme $%s$ est un losange, je sais que $\\widehat{%s%s%s}=\\widehat{%s%s%s}=\\widehat{%s%s%s}=\\widehat{%s%s%s}=%s\\degres$." %(nom,B,A,C,A,C,B,A,C,D,C,A,D,angBAC)) #Programme de construction cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,C,decimaux(AC))) cor.append(u"\\item je trace $\\widehat{%s%s%s}$ et $\\widehat{%s%s%s}$ pour construire le point $%s$ ;"%(B,A,C,A,C,B,B)) cor.append(u"\\item je trace $\\widehat{%s%s%s}$ et $\\widehat{%s%s%s}$ pour construire le point $%s$ ;"%(A,C,D,C,A,D,D)) cor.append("\\end{enumerate}\n") cor.append(u"\\begin{pspicture}(-0.4,%s)(%s,%s)"%(-y_D-1,AC+0.4,y_D+1)) #figure cor.append(u"\\pstGeonode[PosAngle={-180,0,90,-90}](0,0){%s}(%s,0){%s}(%s,%s){%s}(%s,%s){%s}"%(A,AC,C,x_D,y_D,D,x_D,-y_D,B)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,B)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,D)) cor.append(u"\\pstLineAB[nodesepA=-1]{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append(u"\\pstLineAB[nodesepA=-1]{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(D,A)) cor.append(u"\\pstLineAB{%s}{%s}"%(A,C)) cor.append(cotation_h((0,0),(AC,0),decimaux(AC),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce,Mark=MarkHash]{%s}{%s}{%s}{%s\\degres}"%(B,A,C,angBAC)) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{}"%(C,A,D)) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{}"%(D,C,A)) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{}"%(A,C,B)) cor.append(u"\\end{pspicture}") def quest_losange_CDbis(exo,cor): """On donne un losange avec la longueur d'un côté et la mesure d'un angle entre un côté et une diagonale""" A,B,C,D=geo.choix_points(4) nom=shuffle_nom([A,B,C,D]) AC=0.1*random.randint(40,60)#AB mesure entre 4cm et 7cm, tracé horizontalement angCDA=2*random.randint(15,70) #Calcul pour tracer angCAD=(180-angCDA)/2 x_D=AC/2 y_D=AC/2*tan(angCAD) exo.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,C,decimaux(AC),C,D,A,angCDA)) cor.append(u"\\item Trace un losange $%s$ tel que $%s%s=\\unit[%s]{cm}$ et $\\widehat{%s%s%s}=%s\\degres$.\\par" %(nom,A,C,decimaux(AC),C,D,A,angCDA)) #Rédaction des calculs cor.append(u"Les quatre côtés du losange sont de même longueur donc $%s%s=%s%s=%s%s=%s%s$.\\par"%(A,B,B,C,C,D,D,A)) cor.append(u"Ainsi, le triangle $%s%s%s$ est isocèle en $%s$ et je peux calculer la mesure des angles $\\widehat{%s%s%s}=\\widehat{%s%s%s}$.\\par" %(A,C,D,A,A,C,D,C,A,D)) cor.append(u"Dans un triangle, la somme des angles du triangle est égale à 180\\degres\\\\") cor.append(u"donc $\\widehat{%s%s%s}=\\widehat{%s%s%s}=(180\\degres-%s)\\div2=%s\\degres$"%(A,C,D,C,A,D,angCDA,angCAD)) #Programme de construction cor.append(u"\\begin{enumerate}") cor.append(u"\\item Je trace le segment $[%s%s]$ mesurant $\\unit[%s]{cm}$ ;"%(A,C,decimaux(AC))) cor.append(u"\\item je trace $\\widehat{%s%s%s}$ et $\\widehat{%s%s%s}$ pour construire le point $%s$ ;"%(B,A,C,A,C,B,B)) cor.append(u"\\item je trace $\\widehat{%s%s%s}$ et $\\widehat{%s%s%s}$ pour construire le point $%s$ ;"%(A,C,D,C,A,D,D)) cor.append("\\end{enumerate}\n") cor.append(u"\\begin{pspicture}(-0.4,%s)(%s,%s)"%(-y_D-1,AC+0.4,y_D+1)) #Figure cor.append(u"\\pstGeonode[PosAngle={-180,0,90,-90}](0,0){%s}(%s,0){%s}(%s,%s){%s}(%s,%s){%s}"%(A,AC,C,x_D,y_D,D,x_D,-y_D,B)) cor.append(u"\\pstLineAB{%s}{%s}"%(A,C)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,B)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(C,B)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(C,D)) cor.append(u"\\pstLineAB[nodesepB=-1]{%s}{%s}"%(A,D)) #codage cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{}"%(B,A,C)) cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{%s\\degres}"%(C,A,D,angCAD)) cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{%s\\degres}"%(D,C,A,angCAD)) cor.append(u"\\color{calcul}\\pstMarkAngle[linecolor=calcul,Mark=MarkHash]{%s}{%s}{%s}{}"%(A,C,B)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,B)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,B)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,D)) cor.append(u"\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,D)) cor.append(cotation((0,0),(AC,0),decimaux(AC),couleur="enonce")) cor.append(u"\\color{enonce}\\pstMarkAngle[linecolor=enonce]{%s}{%s}{%s}{%s\\degres}"%(A,D,C,angCDA)) cor.append(u"\\end{pspicture}") ################### CARRÉ ####################### def carre_diag(exo,cor): """trace un carré dont on donne la longueur de la diagonale""" A,B,C,D,E=geo.choix_points(5) nom=shuffle_nom([A,B,C,D]) BD=AC=0.2*random.randint(20,40)#AC mesure entre 4cm et 8cm, tracé horizontalement exo.append(u"\\item Trace un carré $%s$ tel que $%s%s=\\unit[%s]{cm}$.\\par" %(nom,A,C,decimaux(AC))) cor.append(u"\\item Trace un carré $%s$ tel que $%s%s=\\unit[%s]{cm}$.\\par" %(nom,A,C,decimaux(AC))) cor.append(u"Je note $%s$ le centre du carré.\\par"%(E)) cor.append(u" Les diagonales du carré se coupent perpendiculairement en leur milieu $%s$ donc on a :"%E) cor.append("\\begin{enumerate}") cor.append(u"\\item $(%s%s)\\perp(%s%s)$."%(A,C,B,D)) cor.append(u"\\item $%s%s=%s%s=%s%s=%s%s=\\unit[%s]{cm}$ ;" %(A,E,C,E,B,E,D,E,decimaux(BD/2))) cor.append("\\end{enumerate}\n") cor.append("\\begin{pspicture}(%s,%s)(%s,%s)"%(-BD/2-0.4,-AC/2-0.4,BD/2+0.4,AC/2+0.4)) cor.append("\\pstGeonode[PosAngle={-90,0,90,180}](0,%s){%s}(%s,0){%s}(0,%s){%s}(%s,0){%s}" %(-AC/2,A,BD/2,B,AC/2,C,-BD/2,D)) cor.append("\\pstGeonode[PosAngle=-45](0,0){%s}"%E) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(A,E)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(C,E)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(B,E)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=calcul}\\MarkCros}"%(D,E)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(A,B)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(C,D)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(B,C)) cor.append("\\pstLineAB{%s}{%s}\\lput{:U}{\\psset{linecolor=enonce}\\MarkHashh}"%(D,A)) cor.append("\\pstRightAngle[linecolor=calcul]{%s}{%s}{%s}"%(B,E,C)) cor.append(cotation_h((-BD/2,0),(0,0),decimaux(BD/2),couleur="enonce")) cor.append(u"\\end{pspicture}") pyromaths/src/cinquiemes/._fractions.py0000644000175000017500000000031511702101415020771 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/._diagrammes.py0000644000175000017500000000031511702101415021112 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/relatifs.py0000644000175000017500000000777011702101415020411 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #---------------------------------------------------------------------- # Pyromaths : Poser des opérations #---------------------------------------------------------------------- from ..outils import Arithmetique from ..outils.Affichage import TeX, tex_coef import random def choix_trou(nb1, nb2, tot, operateur, exo, cor): nbaleatoire = random.randrange(4) if nbaleatoire > 1: exo.append("\\item $%s %s %s = \\ldots\\ldots\\ldots$" % (nb1, operateur, nb2)) cor.append("\\item $%s %s %s = \\mathbf{%s}$" % (nb1, operateur, nb2, tot)) elif nbaleatoire > 0: exo.append("\\item $%s %s \\ldots\\ldots\\ldots = %s$" % (nb1, operateur, tot)) cor.append("\\item $%s %s \\mathbf{%s} = %s$" % (nb1, operateur, nb2, tot)) else: exo.append("\\item $\\ldots\\ldots\\ldots %s %s = %s$" % (operateur, nb2, tot)) cor.append("\\item $\\mathbf{%s} %s %s = %s$" % (nb1, operateur, nb2, tot)) def plus(pyromax): (a, b) = (Arithmetique.valeur_alea(-pyromax, pyromax), Arithmetique.valeur_alea(-pyromax, pyromax)) return (a, b) def moins(pyromax): (a, b) = (Arithmetique.valeur_alea(-pyromax, pyromax), Arithmetique.valeur_alea(-pyromax, pyromax)) return (a + b, a) def plus_dec(pyromax): (a, b) = (Arithmetique.valeur_alea(-10*pyromax, 10*pyromax)/10.0, Arithmetique.valeur_alea(-10*pyromax, 10*pyromax)/10.0) return (a, b) def moins_dec(pyromax): (a, b) = (Arithmetique.valeur_alea(-10*pyromax, 10*pyromax)/10.0, Arithmetique.valeur_alea(-10*pyromax, 10*pyromax)/10.0) return (a + b, a) def main(): exo = ["\\exercice", "Effectuer sans calculatrice :", "\\begin{multicols}{3}\\noindent", " \\begin{enumerate}"] cor = ["\\exercice*", "Effectuer sans calculatrice :", "\\begin{multicols}{3}\\noindent", " \\begin{enumerate}"] modules = (plus, moins, ) modules_dec= (plus_dec, moins_dec, ) calculs = [i for i in range(20)] random.shuffle(calculs) for j in range(4): (a, b) = modules[calculs[j] // 10](10) choix_trou(a, tex_coef(b, '', bpn=1), a + b, '+', exo, cor) for j in range(4,14): (a, b) = modules[calculs[j] // 10](10) if calculs[j] // 10 == 0: choix_trou(a, tex_coef(b, '', bpn=1), a + b, '+', exo, cor) if calculs[j] // 10 == 1: choix_trou(a, tex_coef(b, '', bpn=1), a - b, '-', exo, cor) for j in range(14,20): (a, b) = modules_dec[calculs[j] // 10](10) if calculs[j] // 10 == 0: choix_trou(TeX(a), tex_coef(b, '', bpn=1), TeX(a + b), '+', exo, cor) if calculs[j] // 10 == 1: choix_trou(TeX(a), tex_coef(b, '', bpn=1), TeX(a - b), '-', exo, cor) exo.extend([" \\end{enumerate}", "\\end{multicols}"]) cor.extend([" \\end{enumerate}", "\\end{multicols}"]) return (exo, cor) pyromaths/src/cinquiemes/cinquiemes.py0000644000175000017500000000316311702101415020732 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # from . import priorites, symetrie, fractions, reperage, relatifs, construction, proportionnalite, aires, diagrammes def write(f0, f1, exos): f0.write("\n") f1.write("\n") f0.writelines(x + "\n" for x in exos[0]) f1.writelines(x + "\n" for x in exos[1]) def main(exo,f0, f1): modules = (priorites.main, symetrie.main, fractions.fractions_egales, fractions.sommes_fractions, fractions.produits_fractions, reperage.main, relatifs.main, construction.exo_triangle, construction.exo_quadrilatere, proportionnalite.exo_echelles, aires.exo_aire_diques, diagrammes.exo_diagrammes) write(f0, f1, modules[exo]()) pyromaths/src/cinquiemes/._cinquiemes.py0000644000175000017500000000031511702101415021143 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/._construction.py0000644000175000017500000000031511702101415021533 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/priorites.py0000644000175000017500000002326711702101415020617 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #from ..outils import ecrit_tex, valeur_alea, signe, pgcd, ppcm import random import string # # ------------------- ------------------- def valeurs(nb, entier=1): # renvoie les 2 listes contenant les opérateurs et les opérandes. listoperateurs = [ '+', '*', '-', '/', '(', '(', '(', '(', ')', ')', ')', ')', ] loperateurs = [] loperandes = [] i = 0 #nombre d'opérateurs créés p = 0 #nombre de parenthèses ouvertes cpt = 0 #compteur pour éviter que le programme ne boucle. while i < nb - 1: cpt = cpt + 1 if cpt > 10: #On recommence (cpt, i, p, loperateurs) = (0, 0, 0, []) if p: if loperateurs[-1] == '(': # On n'écrit pas 2 parenthèses à suivre operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(12)] elif loperateurs == []: # On ne commence pas par une parenthèse operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(8)] if nb > 3: test = ('-*/').find(operateur) >= 0 and \ loperateurs.count(operateur) < 1 or \ operateur == '+' and \ loperateurs.count(operateur) < 2 else: test = ('-*/+').find(operateur) >= 0 and \ loperateurs.count(operateur) < 1 if test: #On n'accepte pas plus de 1 produit, différence, quotient et de 2 #sommes ou parenthèses par calcul. if i == 0 or loperateurs[-1] != '(' or ('*/').find(operateur) < \ 0: #pas de * ou / dans une parenthèse. i = i + 1 loperateurs.append(operateur) elif operateur == '(' and (')+').find(loperateurs[-1]) < 0: #Il ne peut y avoir de ( après une ) ou après un + p = p + 1 loperateurs.append(operateur) elif operateur == ')': p = p - 1 loperateurs.append(operateur) while p > 0: loperateurs.append(')') p = p - 1 if entier: loperandes = [random.randrange(12) + 2 for i in range(nb)] else: loperandes = [((random.randrange(88) + 12) * 1.0) / 10 for i in range(nb)] return (loperateurs, loperandes) ####################### def affichage(loperateurs, loperandes): j = 0 #compteur des operateurs calcul = '%s' % nb_decimal((loperandes[0], )) for i in range(len(loperandes) - 1): if loperateurs[j] == ')': #Il reste une opération mais je ferme d'abord une ou plusieurs parenthèses cpt = 1 while loperateurs[j + cpt] == ')': cpt = cpt + 1 #j+cpt est la position de l'opération qui suit else: cpt = 0 if j + cpt < len(loperateurs) - 1: #Il reste au moins une opération, donc peut-etre une parenthèse ouvrante while loperateurs[j + cpt + 1] == '(': #j+cpt est la position de la dernière parenthèse ( cpt = cpt + 1 for k in range(cpt + 1): calcul = calcul + '%s' % loperateurs[j + k] calcul = calcul + '%s' % nb_decimal((loperandes[i + 1], )) j = j + cpt + 1 while j < len(loperateurs): calcul = calcul + '%s' % loperateurs[j] j = j + 1 calcul = ('\\times ').join(calcul.split('*', 2)) calcul = ('\\div ').join(calcul.split('/', 2)) return calcul def nb_decimal(a): # verifie si des nombres décimaux dans le tuple a sont en fait des nombres entiers et change leur type list = [] for i in range(len(a)): if str(a[i]).endswith('.0'): list.append(int(a[i] + .1)) else: list.append(('{,}').join(str(a[i]).split('.', 2))) return tuple(list) def verifie_calcul(listoperateurs, listoperandes, entier=1): #Vérifie que l'opération proposée est réalisable sans division # décimale ni nombre négatif p = 0 loperateurs = listoperateurs[-1] loperandes = listoperandes[-1] if len(loperandes) == 1: return (listoperateurs, listoperandes) else: nbpar = loperateurs.count('(') nbmul = loperateurs.count('*') nbdiv = loperateurs.count('/') if nbpar: index = -1 while p < nbpar: index = loperateurs[index + 1:].index('(') + index + 1 p = p + 1 if p < nbpar and loperateurs[index + 1:].index('(') > \ loperateurs[index + 1:].index(')'): nbpar = p if loperateurs[index + 2] == ')': a = calcul(loperandes[(index + 1) - nbpar], loperateurs[index + 1], loperandes[(index + 2) - nbpar], entier) if a != 'hp': al = loperateurs[:index] al.extend(loperateurs[index + 3:]) loperateurs = al al = loperandes[:(index + 1) - nbpar] al.append(a) al.extend(loperandes[index - nbpar + 3:]) loperandes = al listoperateurs.append(loperateurs) listoperandes.append(loperandes) return verifie_calcul(listoperateurs, listoperandes) elif nbmul or nbdiv: (indexm, indexd) = (100, 100) if nbmul: indexm = loperateurs.index('*') if nbdiv: indexd = loperateurs.index('/') index = min(indexm, indexd) a = calcul(loperandes[index], loperateurs[index], loperandes[index + 1], entier) if a != 'hp': al = loperateurs[:index] al.extend(loperateurs[index + 1:]) loperateurs = al al = loperandes[:index] al.append(a) al.extend(loperandes[index + 2:]) loperandes = al listoperateurs.append(loperateurs) listoperandes.append(loperandes) return verifie_calcul(listoperateurs, listoperandes) else: a = calcul(loperandes[0], loperateurs[0], loperandes[1], entier) if a != 'hp': loperateurs = loperateurs[1:] al = [a] al.extend(loperandes[2:]) loperandes = al listoperateurs.append(loperateurs) listoperandes.append(loperandes) return verifie_calcul(listoperateurs, listoperandes) def calcul(a, op, b, entier=1): #retourne 'hp' (hors programme) ou le résultat de l'opération if op == '+': return a + b elif op == '*': return a * b elif op == '-': if a > b: return a - b else: return 'hp' else: if (a * 100) % (b * 100) and entier: return 'hp' elif not entier and (a * 1000) % (b * 100): return 'hp' else: return a / b def main(): nb = 9 # nombre de calculs exo = ["\\exercice", u"Calculer les expressions suivantes en détaillant les calculs.\n", "\\begin{multicols}{3}", "\\noindent"] cor = ["\\exercice*", u"Calculer les expressions suivantes en détaillant les calculs.", "\\begin{multicols}{3}", "\\noindent"] i = 0 while i < nb: if i < 3: #Les 3 premiers calculs ne comportent que 3 nombres (loperateurs, loperandes) = valeurs(3) elif i > 6: (loperateurs, loperandes) = valeurs(5, 0) #Les derniers calculs comportent des nombres décimaux else: (loperateurs, loperandes) = valeurs(6) if i > 6: list = verifie_calcul([loperateurs], [loperandes], entier=0) else: list = verifie_calcul([loperateurs], [loperandes], entier=1) if list != None: i = i + 1 for j in range(len(list[0])): if j == 0: exo.append("\\[ \\thenocalcul = %s \\]" % affichage(list[0][j], list[1][j])) exo.append('\\stepcounter{nocalcul}%') if j == len(list[0]) - 1: cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % affichage(list[0][j], list[1][j])) cor.append('\\stepcounter{nocalcul}%') else: cor.append("\\[ \\thenocalcul = %s \\]" % affichage(list[0][j], list[1][j])) exo.append("\\end{multicols}") cor.append("\\end{multicols}") return (exo, cor) pyromaths/src/cinquiemes/._symetrie.py0000644000175000017500000000031511702101415020642 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/src/cinquiemes/diagrammes.py0000644000175000017500000001167011702101415020703 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random # # ------------------- Diagrammes ------------------- # def exo_diagrammes(): exo = ["\\exercice"] cor = ["\\exercice*"] h1 = random.randrange(2) + 5 h2 = 8 h3 = random.randrange(2) + 7 h5 = random.randrange(4)+1 h6 = random.randrange(3) h7 = random.randrange(2)+1 h4 = 30 - h1 - h2 - h3 - h5 - h6 - h7 basket = random.randrange(7) + 3 tennis = random.randrange(7) + 3 judo = random.randrange(7) + 3 football = 30 - tennis - basket - judo question1 = \ u"""\\renewcommand{\\arraystretch}{1.8} \\item On a demandé aux élèves d'une classe de cinquième combien de temps par semaine était consacré à leur sport favori.\\par \\begin{tabular}{|c|c|c|c|c|c|c|c|}\\hline Durée t (en h)& $0 \\le t < 1$ & $1 \\le t < 2$ & $2 \\le t < 3$ & $3 \\le t < 4$ & $4 \\le t < 5$ & $5 \\le t < 6$ & $6 \\le t < 7$ \\\\\\hline Effectif & %s & %s & %s & %s & %s & %s & %s \\\\\\hline \\end{tabular}\\par À partir de ce tableau, construire un histogramme pour représenter ces données.\\par""" % (h1, h2, h3, h4, h5, h6, h7) question2 = \ u"""\\item On a demandé aux élèves quel était leur sport préféré. %s élèves préfèrent le basket-ball, %s le tennis, %s le football et %s le judo. Construire un diagramme circulaire représentant cette répartion.\\par""" % (basket, tennis, football, judo) exo.append("\\begin{enumerate}") exo.append(question1) exo.append(question2) exo.append("\\end{enumerate}") cor.append("\\begin{enumerate}") cor.append(question1) cor.append(u"""\\begin{minipage}{10cm} \\begin{pspicture}(0,-1)(8.5,9.5) \\psaxes[showorigin=false]{->}(7.5,8.5) \\psset{fillstyle=solid, linewidth=0.5pt} \\psframe(0,0)(1,%s) \\psframe(1,0)(2,%s) \\psframe(2,0)(3,%s) \\psframe(3,0)(4,%s) \\psframe(4,0)(5,%s) \\psframe(5,0)(6,%s) \\psframe(6,0)(7,%s) \\rput(-0.2,-0.425){$0$} \\rput(8.3,0){Durée} \\rput(0,8.8){Effectif} \\end{pspicture} \\end{minipage} \\begin{minipage}{6cm} Sur l'axe horizontal, on représente les durées en heures et, sur l'axe vertical, on représente les effectifs. \\end{minipage}""" % (h1, h2, h3, h4, h5, h6, h7)) cor.append(question2) cor.append(u"L'effectif total est égal à $ %s + %s + %s + %s = 30$. La mesure d'angle d'un secteur circulaire est proportionnelle à l'effectif du sport qu'il représente. Le coefficient de proportionnalité est égal au quotient de l'effectif total par 360\\degre c'est à dire $360 \\div 30=12$.\\par" % (basket, tennis, football, judo)) cor.append(u"""\\renewcommand\\tabcolsep{10pt} \\begin{tabular}{|l|c|c|c|c|c|c} \\cline{1-6} Sport favori & Basket-ball & Tennis & Football & Judo & Total &\\rnode{plan1}{}\\\\ \\cline{1-6} Effectif & %s & %s & %s & %s & 30 &\\rnode{plan1}{}\\\\ \\cline{1-6} Mesure (en degré) & \\bf%s & \\bf%s & \\bf%s & \\bf%s & 360 &\\rnode{plan2}{}\\\\ \\cline{1-6} \\end{tabular} \\ncbar{->}{plan1}{plan2}\\Aput{$\\times 12$}\\par \\begin{minipage}{6cm} En utilisant les mesures d'angles obtenues dans le tableau de proportionnalité, on trace le diagramme circulaire. \\end{minipage}""" % (basket, tennis, football, judo, basket*12, tennis*12, football*12, judo*12)) cor.append(u"""\\begin{minipage}{13cm} \\psset{unit=3cm,fillstyle=solid} \\pspicture(-1.5,-1)(1,1.5) \\pswedge[fillcolor=Bisque]{1}{0}{%s} \\pswedge[fillcolor=LightSalmon]{1}{%s}{%s} \\pswedge[fillcolor=Chocolate]{1}{%s}{%s} \\pswedge{1}{%s}{360} \\rput(.6;%s){Basket} \\rput(.6;%s){Tennis} \\rput(.6;%s){\\white Football} \\rput(.6;%s){Judo} \\endpspicture \\end{minipage}""" %(basket*12, basket*12, basket*12+tennis*12, basket*12+tennis*12, basket*12+tennis*12+football*12, basket*12+tennis*12+football*12, basket*6, basket*12+tennis*6, basket*12+tennis*12+football*6, basket*6+tennis*6+football*6+180 )) cor.append(u"\\end{enumerate}") return (exo, cor) pyromaths/src/cinquiemes/reperage.py0000644000175000017500000001671211702101415020366 0ustar didrocksdidrocks# Pyromaths # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if notPopen, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import random from ..outils.Affichage import decimaux def noms_sommets(nb): """Renvoie nb noms de sommets""" (listenb, listepts) = ([], []) for i in range(26): listenb.append(i + 65) for i in range(nb): listepts.append(str(chr(listenb.pop(random.randrange(26 - i))))) listepts.sort() return tuple(listepts) def angle(coordo): """Angle pour placer le nom du point en fonction du quadrant""" l=[] for coord in coordo: if coord[0]>=0 and coord[1]>=0: ang='45' if coord[0]>=0 and coord[1]<0: ang='-45' if coord[0]<0 and coord[1]<0: ang='-135' if coord[0]<0 and coord[1]>=0: ang='135' l.append(ang) return l def place_points(coordo,points): """coordo: liste de coordonnées ; points : noms des points associés génère le code latex pour placer tous les points""" l= angle(coordo) text="\\pstGeonode[PointSymbol=x,PosAngle={" for ang in l : text=text+ang+',' text=text+"},PointNameSep=0.4]" i=0 while i=0 and coord[1]*c[1]>=0: rep=False break return rep def coordo_pts(nb): """Génère une liste de nb coordonnées. Je m'arrange pour avoir des points sur les 4 quadrants et sur les deux axes""" j=0 k=0 l=[] i=0 while i<4 and i=4: a=float(random.randrange(-9,10))/2 while not valide((0,a),l): a=float(random.randrange(-9,10))/2 rg=random.randrange(0,len(l)-1) l[rg:rg]=[(0,a)] i=i+1 if nb>=5: b=float(random.randrange(-9,10))/2 while not valide((b,0),l): b=float(random.randrange(-9,10))/2 rg=random.randrange(0,len(l)-1) l[rg:rg]=[(b,0)] i=i+1 while i>=6 and i=11 and len(l)==10: a=float(random.randrange(-9,10))/2 while not valide((0,a),l): a=float(random.randrange(-9,10))/2 rg=random.randrange(6,len(l)-1) l[rg:rg]=[(0,a)] i=i+1 if nb>=11 and len(l)==11: b=float(random.randrange(-9,10))/2 while not valide((b,0),l): b=float(random.randrange(-9,10))/2 rg=random.randrange(6,len(l)-1) l[rg:rg]=[(b,0)] i=i+1 while i>=12 and i}(-5,0)(5,0)", "\\psline[linewidth=1.2pt]{->}(0,-5)(0,5)", place_points(coord_pts[0:6],noms_pts[0:6]), "\\end{pspicture}}"] cor=["\\exercice*", "\\parbox{0.4\\linewidth}{", "\\psset{unit=0.8cm}", "\\begin{pspicture}(-5,-5)(5,5)", "\\psgrid[subgriddiv=2, subgridcolor=lightgray, gridlabels=8pt](0,0)(-5,-5)(5,5)", "\\psline[linewidth=1.2pt]{->}(-5,0)(5,0)", "\\psline[linewidth=1.2pt]{->}(0,-5)(0,5)", place_points(coord_pts[0:13],noms_pts[0:13]), "\\end{pspicture}}\\hfill", "\\parbox{0.5\\linewidth}{", "\\begin{enumerate}", u"\\item Donner les coordonnées des points %s, %s, %s, %s, %s et %s." % tuple(noms_pts[0:6])] i=0 while i<6: cor.append(u"Les coordonnées du point %s sont %s \n"%(noms_pts[i],affiche_coord(coord_pts[i]))) i=i+1 cor[len(cor):len(cor)]=[u"\\item Placer dans le repère les points %s, %s, %s, %s, %s et %s" %noms_pts[6:12] +u" de coordonnées respectives %s, %s, %s, %s, %s et %s. " %tuple(tex_liste_co(coord_pts[6:12])), u"\\item Placer dans le repère le point %s d'%s %s et d'%s %s" %(noms_pts[12],voc[rg1],decimaux(str(coord_pts[12][rg1])),voc[rg2],decimaux(str(coord_pts[12][rg2]))), "\\end{enumerate}"] cor.append("}") return(exo,cor) pyromaths/._COPYING0000644000175000017500000000031511702101415014531 0ustar didrocksdidrocksMac OS X  2ATTRGe55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/PKG-INFO0000644000175000017500000000175411560531274014402 0ustar didrocksdidrocksMetadata-Version: 1.0 Name: pyromaths Version: 11.05.1b1 Summary: Exerciseur de mathématiques créant des fiches aux formats LaTeX et PDF. Home-page: http://www.pyromaths.org Author: Jérôme Ortais Author-email: jerome.ortais@pyromaths.org License: GPL Description: Pyromaths est un programme qui a pour but de créer des exercices type de mathématiques niveau collège et lycée ainsi que leur corrigé. C’est ce qu’on appelle parfois un exerciseur. Contrairement à de nombreux autres projets, Pyromaths a pour objectif de proposer une correction véritablement détaillée des exercices proposés et pas seulement une solution. Il permet par exemple de proposer des devoirs maison aux élèves et de leur distribuer ensuite la correction. Il peut aussi servir à des familles afin qu’un élève puisse travailler un point du programme et se corriger ensuite. Platform: unix pyromaths/._.DS_Store0000644000175000017500000000012211734620665015177 0ustar didrocksdidrocksMac OS X  2 R@pyromaths/.DS_Store0000644000175000017500000001400411734620665014766 0ustar didrocksdidrocksBud1%  @ @ @ @ E%DSDB` @ @ @pyromaths/._src0000755000175000017500000000031511702412270014217 0ustar didrocksdidrocksMac OS X  2ATTRGk55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/._README0000644000175000017500000000031511702101415014356 0ustar didrocksdidrocksMac OS X  2ATTRGi55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/AUTHORS0000644000175000017500000000055311702412057014344 0ustar didrocksdidrocksAuthors of Pyromaths. Programming : ============= Jérôme Ortais (jerome.ortais[at]pyromaths.org) Arnaud Kientz (arnaud[at]pyromaths.org) Yves Gesnel Guillaume Barthélémy Nicolas Bissonnier MacOs X adaptation : ==================== Jacqueline Gouguenheim-Desloy (R.I.P.) Yves Gesnel Ubuntu packaging : ==================== Didier Roche pyromaths/setup.py0000644000175000017500000000367411702412057015015 0ustar didrocksdidrocks#!/usr/bin/python # -*- coding: utf-8 -*- from distutils.core import setup import glob from src.Values import VERSION setup(name = "pyromaths", version = VERSION, description = "Exerciseur de mathématiques créant des fiches aux formats " \ + "LaTeX et PDF.", license = "GPL", author = "Jérôme Ortais", author_email = "jerome.ortais@pyromaths.org", url = "http://www.pyromaths.org", package_dir={'pyromaths': 'src'}, packages=['pyromaths', 'pyromaths.troisiemes', 'pyromaths.quatriemes', 'pyromaths.cinquiemes', 'pyromaths.sixiemes', 'pyromaths.lycee', 'pyromaths.outils', 'pyromaths.classes'], data_files=[ ('share/pixmaps/', [ 'data/images/pyromaths.png' ] ), ('share/pyromaths/images', [ 'data/images/pyromaths-banniere.png', 'data/images/whatsthis.png' ] ), ('share/applications', ['data/linux/pyromaths.desktop']), ('share/man/man1', ['data/linux/pyromaths.1']), (r'share/pyromaths/images/vignettes', glob.glob(r'data/images/vignettes/*.png')), (r'share/pyromaths/templates', glob.glob(r'data/templates/*.tex')), (r'share/pyromaths/packages', glob.glob(r'data/packages/*')), ], scripts = ["pyromaths"], platforms = ['unix'], long_description = """Pyromaths est un programme qui a pour but de créer des exercices type de mathématiques niveau collège et lycée ainsi que leur corrigé. C’est ce qu’on appelle parfois un exerciseur. Contrairement à de nombreux autres projets, Pyromaths a pour objectif de proposer une correction véritablement détaillée des exercices proposés et pas seulement une solution. Il permet par exemple de proposer des devoirs maison aux élèves et de leur distribuer ensuite la correction. Il peut aussi servir à des familles afin qu’un élève puisse travailler un point du programme et se corriger ensuite.""" ) pyromaths/._data0000755000175000017500000000031511702101415014335 0ustar didrocksdidrocksMac OS X  2ATTRGf55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/._NEWS0000644000175000017500000000031511702101415014175 0ustar didrocksdidrocksMac OS X  2ATTRGg55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/COPYING0000644000175000017500000004310611702101415014321 0ustar didrocksdidrocks GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. pyromaths/._debian0000755000175000017500000000031511702101415014646 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbirdpyromaths/NEWS0000644000175000017500000002010611702101415013760 0ustar didrocksdidrocksVersion 11.05 * Sommes de vecteurs niveau lycée * Deux exercices sur le calcul littéral niveau quatrième * Quelques corrections de bugs et améliorations Version 10.10 * Représentation de données niveau cinquième * Calcul d'aire de disques niveau cinquième * Amélioration de la version Mac ** icône 512 pixels par 512 pixels ** Retour du look Aqua ** Position de la fenêtre à l'ouverture améliorée ** Ouverture automatique des fichiers pdf générés ** Pyromaths n'est plus lancé par un applescript ** Diverses améliorations cosmétiques ** Compatibilité avec Mac OS X 10.4 * Exercices de proportionnalités en cinquièmes ** Calcul de la quatrième proportionnelle ** Calculs avec les échelles * Conversions d'unités ** Exercices de conversions d'unités de volume ** Amélioration de la présentation du tableau de conversions * Exercice de géométrie dans l'espace niveau sixième * Visualisation des exercices grâce au bouton "Présentation" Version 10.06-1 * Correction d’un bug (il manquait un retour ligne après certains \par) dans les exercices de géométrie troisième. * Ajout de l’utilisation du paquet textcomp pour enjoliver les \degres Version 10.06 * Exercice de calcul d'aires niveau sixième * Correction d'un non sens dans les tableaux de conversion niveau sixième : le tableau de conversion se retrouvait parfois avec plusieurs chiffres dans la colonne des mL, mm ou mg. * Correction d'un bug dans l'affichage de la résolution d'une équation du second degré (merci à Marty de l'avoir signalé) Version 10.05 * Exercice de construction niveau cinquièmes : ** de triangles ** de parallélogrammes * Exercice sur les polynomes niveau Lycée ** Équation du second degré ** Factorisation degré 2 et degré 3. ** Étude de fonctions : sens de variation et calcul de limite *** Polynômes de degré 3 *** Fonction rationnelle * Exercice de conversion d'unités d'aire niveau sixième * Exercice sur les arrondis niveau sixième ( par défaut, par excès ) * Exercice sur l'arithmétique niveau troisième : ** Décomposition en facteurs premiers ** PGCD et PPCM avec plusieurs méthodes ** Réflexion sur la décomposition en facteurs premiers ** Applications aux fractions. * Suppression des exercices autour de Pythagore, niveau troisième * Amélioration de l'exercice sur les fonctions, niveau troisième * Correction d'un bug lié à l'encodage sous Windows Version 10.01 * Un exercice sur les probabilités niveau 3e - par Guillaume Barthélémy * Modification de l'exercice sur le théorème de Pythagore, niveau 4e : ** la figure n'est plus dessinée ** deux questions dans le même exercice : un calcul de l'hypoténuse et un calcul d'un côté de l'angle droit * Correction d'une erreur dans le corrigé de l'exercice "Écrire un nombre décimal" - merci à Samuel Coupey pour avoir signalé l'erreur * Correction d'une erreur dans le corrigé de l'exercice "Fonctions affines" - merci à Nicolas Bissonnier pour avoir signalé l'erreur * Passage à Python 2.6 ** Gestion des caractères accentués dans les noms de fichiers ** Passage à l'utf-8 pour l'encodage des fichiers. * Nouvelles fonctions et classes pour une utilisation prochaine dans de nouveaux exercices Version 09.09-1 * Ajout de python-lxml à la liste des dépendances pour le paquet deb de Pyromaths (merci à Cedrick) * Correction du chemin des icônes pour la version deb de Pyromaths Version 09.09 * Correction d'un bug de numérotation des calculs sur le niveau troisième * Correction d'un bug de chemin avec Windows Vista et Windows 7 * Envoi des logs de latex dans un fichier temporaire pour éviter l'ouverture de nombreuses fenêtres sous Windows * Permet le téléchargement automatique des paquets MikTeX sous Windows. Version 09.08 * Création de modèles pour choisir l'apparence des fiches - par Arnaud Kientz * Refonte complète de l'interface graphique : ** Passage à PyQt4 ** Possibilité de choisir le niveau affiché sur la fiche ** Utilisation d'un fichier de configuration pour enregistrer les options utilisateurs : *** Chemin par défaut *** Nom de fichier par défaut *** Titre de la fiche *** Créer un fichier pdf *** Créer ou non le corrigé *** Choix du modèle ** Choix de l'ordre des exercices * Niveau sixième : ** Correction d'un bug dans produits et quotients par 10, 100, 1000 * Niveau cinquième : ** Exercice sur le repérage dans le plan - par Guillaume Barthélémy * Niveau quatrième : ** Améliorations sur le choix des valeurs dans les exercices sur les fractions * Niveau troisième : ** Exercice sur les fonctions affines - par Guillaume Barthélémy Version 08.11 * Niveau sixième : ** Construction de l'image d'un pentagone par une symétrie axiale en utilisant un quadrillage * Niveau cinquième : ** Construction de l'image d'un pentagone par une symétrie centrale en utilisant un quadrillage ** Fractions égales ** Sommes et différences de fractions (dénominateur de l'une multiple de l'autre) ** Produits de fractions * Niveau quatrième : ** Sommes et différences de fractions ** Produits et quotients de fractions ** Priorités et fractions Version 08.05 * Niveau sixième : ** Écrire un nombre décimal en lettres ou en chiffres ** Fractions partage : colorier une fraction d'un rectangle quadrillé. ** Fractions et abscisses : donner l'abscisse de points et placer des points d'abscisse donnée. ** Mesurer, nommer et donner la nature d'angles construits. ** Classer des nombres décimaux dans l'ordre croissant ou décroissant. Version 08.03 * Niveau sixième : ** QCM : les nombres donnés sont-ils divisibles par 2, 3, 5, 9 ou 10. ** constructions de parallèles et de perpendiculaires. ** Propriétés sur les droites paralèles et perpendiculaires. * Niveau quatrième : ** trois nouveaux modules sur les puissances. * Ajout de l'appel au module "wasysym" dans les fichiers LaTeX afin de créer les cases à cocher du QCM. Version 08.01 * Niveau sixième : ** Donner l'écriture fractionnaire d'un nombre décimal ou l'inverse ; ** Écrire un nombre décimale à partir de sa décomposition décimale. ** Tracer et reconnaître des droites, demi-droites et segments. * Niveau quatrième : ** Modification du calcul mental pour que les opérations soient parfois des opérations à trous. Version 07.12.14 - Niveau sixième : . Convertir des unités de masse, contenance et longueur. . Placer une virgule dans un nombre entier pour que le chiffre x soit le chiffre des ... . Correction d'un bug dans les multiplications posées qui faisait planter Pyromaths quand le produit était inférieur à 1. . Modification du calcul mental pour que les opérations soient parfois des opérations à trous. Version 07.11.23 - Niveau sixième : . produits par 10 ; 100 ; 1000 et 0,1 ; 0,01 ; 0,001 et quotients par 10 ; 100 ; 1000. . correction d'un bug sur le calcul mental : la répartition des 4 opérations n'était pas correcte. . correction d'un bug sur les opérations à poser : les nombres dans l'énoncé pour la multiplication n'étaient pas les bons. - Niveau quatrième : . correction d'un bug sur le calcul mental : la répartition des 4 opérations n'était pas correcte. version 07.11.03 - Niveau troisième : . Correction d'un bug concernant les développements. version 07.11.01 - Niveau quatrième : . calcul mental sur les nombres entiers relatifs. - Niveau sixième : . calcul mental sur les nombres entiers ; . sommes, différence et produits à effectuer. version 07.02.23 - Le nom du fichier contenant le corrigé proposé par défaut est celui du fichier d'exercices auquel on ajoute '-corrige'. - Ajout du lien http://pyromaths.apinc.org dans le pied de page inférieur droit. - Des exercices ont été ajoutés au niveau quatrième : . fractions (copie du niveau 3e), . puissances de 10 (copie du niveau 3e), . développements (a+b)(c+d), . théorème de Pythagore (copie du niveau 3e), . triangle rectangle et cercle (copie du niveau 3e), . théorème de Thalès dans le triangle, . calcul de mesure d'angle et de longueur à l'aide du cosinus. - Un exercice a été ajouté au niveau cinquième : . priorités opératoires. pyromaths/setup.cfg0000644000175000017500000000013211702101415015077 0ustar didrocksdidrocks[install] prefix = /usr install-layout = deb [bdist_rpm] install_script = install-rpm.sh pyromaths/._MANIFEST.in0000644000175000017500000000031511702101415015234 0ustar didrocksdidrocksMac OS X  2ATTRG55com.apple.quarantineq/0000;4f731e97;Thunderbird;|org.mozilla.thunderbird