%%% % Pyramide de calculs %%% \def\filedatePyraCalc{2025/05/29}% \def\fileversionPyraCalc{0.2a}% \message{-- \filedatePyraCalc\space v\fileversionPyraCalc}% % \setKVdefault[PyraCrea]{ValeurMin=1,ValeurMax=10,NbEtages=5,Graine=1,Solution=false,Largeur=1cm,Hauteur=8mm,Multiplication=false,Litteral=false,Lettre=x,Fond=false,Couleur={},CouleurSolution={}}% \defKV[PyraCrea]{% CouleurSolution=\ifempty{#1}{}{\setKV[PyraCrea]{Solution}},% Couleur=\ifempty{#1}{}{\setKV[PyraCrea]{CouleurSolution=#1}}% }% % \NewDocumentCommand\PyramideNombreCreation{o}{% \useKVdefault[PyraCrea]% \setKV[PyraCrea]{#1}% \xdef\PyraCreaEtages{\useKV[PyraCrea]{NbEtages}}% \xdef\PyraCreaVMin{\useKV[PyraCrea]{ValeurMin}}% \xdef\PyraCreaVMax{\useKV[PyraCrea]{ValeurMax}}% \PfCGraineAlea{\useKV[PyraCrea]{Graine}}% \ChoixAleaMultiMix{\PyraCreaEtages}{\PyraCreaVMin}{\PyraCreaVMax}{0}{\ListeNombresAv}% \ifboolKV[PyraCrea]{Litteral}{% \ChoixAleaMultiMix{\PyraCreaEtages}{\PyraCreaVMin}{\PyraCreaVMax}{0}{\ListeCoefAv}% \BuildMPPyraCreaRegroupe{\PyraCreaEtages}{\ListeNombresAv}{\ListeCoefAv}% }{% \BuildMPPyraCreaRegroupe{\PyraCreaEtages}{\ListeNombresAv}{}% }% }% % \NewDocumentCommand\BuildMPPyraCreaRegroupe{mmm}{% \ifluatex% \mplibforcehmode% \mplibnumbersystem{double}% \begin{mplibcode} randomseed:=\useKV[PyraCrea]{Graine}; boolean Solution,Multiplication,Litteral,Fond; Solution=\useKV[PyraCrea]{Solution}; Multiplication=\useKV[PyraCrea]{Multiplication}; Litteral=\useKV[PyraCrea]{Litteral}; Fond=\useKV[PyraCrea]{Fond}; if Solution: color CouleurSolution; CouleurSolution=\useKV[PyraCrea]{CouleurSolution}; fi; NbEtages=#1; numeric Lignes[][]; numeric PyraNombre[]; numeric Allumage[][];%etage/colonne picture RetiensEtiquette[][]; Largeur=\useKV[PyraCrea]{Largeur}; Hauteur=\useKV[PyraCrea]{Hauteur}; def ChoixAlea=ceiling(uniformdeviate(2)) enddef; Allumage[1][1]=ChoixAlea; for k=2 upto NbEtages-1: Allumage[k][1]=ChoixAlea; for l=2 upto k: if (Allumage[k][l-1]+Allumage[k-1][l-1])=4: Allumage[k][l]=1; else: Allumage[k][l]=ChoixAlea; fi; endfor; endfor; if Allumage[NbEtages-1][1]=1: Allumage[NbEtages][1]=2; else: Allumage[NbEtages][1]=ChoixAlea; fi; for k=2 upto NbEtages: if Allumage[NbEtages][k-1]=1: Allumage[NbEtages][k]=2; else: if Allumage[NbEtages-1][k-1]=1: Allumage[NbEtages][k]=2; else: Allumage[NbEtages][k]=1; fi; fi; endfor; % Definition première ligne nb=0; for p_=#2: nb:=nb+1; Lignes[NbEtages][nb]=p_; endfor; nb:=0; if Litteral: for p_=#3: nb:=nb+1; LignesLitteral[NbEtages][nb]=p_; endfor; fi; % %Dessin path Case[][]; for k=1 upto NbEtages: Case[NbEtages][k]=(unitsquare xscaled Largeur yscaled Hauteur) shifted((k-1)*(Largeur,0)); RetiensEtiquette[NbEtages][k]=image( if Litteral: label(TEX("\Affichage[Lettre=\useKV[PyraCrea]{Lettre}]{0}{"&decimal(LignesLitteral[NbEtages][k])&"}{"&decimal(Lignes[NbEtages][k])&"}"),center Case[NbEtages][k]); else: label(TEX("\num{"&decimal(Lignes[NbEtages][k])&"}"),center Case[NbEtages][k]); fi; ); if Allumage[NbEtages][k]=1: if Solution: if Fond: fill Case[NbEtages][k] withcolor CouleurSolution; else: drawoptions(withcolor CouleurSolution); fi; draw RetiensEtiquette[NbEtages][k]; drawoptions(); fi; else: draw RetiensEtiquette[NbEtages][k]; fi; endfor; for k=NbEtages-1 downto 1: for l=1 upto k: if Multiplication: Lignes[k][l]=Lignes[k+1][l]*Lignes[k+1][l+1]; else: Lignes[k][l]=Lignes[k+1][l]+Lignes[k+1][l+1]; if Litteral: LignesLitteral[k][l]=LignesLitteral[k+1][l]+(LignesLitteral[k+1][l+1]); fi; fi; Case[k][l]=(unitsquare xscaled Largeur yscaled Hauteur) shifted(((l-1)*Largeur,(NbEtages-k)*Hauteur)+(NbEtages-k)*(0.5*Largeur,0)); %trace Case[k][l]; RetiensEtiquette[k][l]=image( if Litteral: label(TEX("\Affichage[Lettre=\useKV[PyraCrea]{Lettre}]{0}{"&decimal(LignesLitteral[k][l])&"}{"&decimal(Lignes[k][l])&"}"),center Case[k][l]); else: label(TEX("\num{"&decimal(Lignes[k][l])&"}"),center Case[k][l]); fi; ); if Allumage[k][l]=1: if Solution: if Fond: fill Case[k][l] withcolor CouleurSolution; else: drawoptions(withcolor CouleurSolution); fi; draw RetiensEtiquette[k][l]; drawoptions(); fi; else: draw RetiensEtiquette[k][l]; fi; endfor; endfor; for k=NbEtages downto 1: for l=1 upto k: trace Case[k][l]; endfor; endfor; \end{mplibcode}% \mplibnumbersystem{scaled}% \fi% }% % \newcommand\DessinePyramideNombreMul[1]{% \ifluatex% \mplibforcehmode% \begin{mplibcode}% pair A[],B[],O; cote:=\useKV[ClesPyramide]{Cote}; boolean Aide,Produit,Solution,Vide; Aide:=\useKV[ClesPyramide]{Aide}; Vide:=\useKV[ClesPyramide]{Vide}; Produit:=\useKV[ClesPyramide]{Produit}; Solution:=\useKV[ClesPyramide]{Solution}; A1=u*(1,1); A2-A1=cote*(1,0); A3=rotation(A2,A1,60); A4=A1; B1=iso(A1,A2); B2=iso(A2,A3); B3=iso(A3,A1); O=iso(A1,A2,A3); path BoiteRec; BoiteRec=((-0.4,-0.5)--(0.4,-0.5){dir0}..{dir90}(0.5,-0.4)--(0.5,0.4){dir90}..{dir180}(0.4,0.5)--(-0.4,0.5){dir180}..{dir-90}(-0.5,0.4)--(-0.5,-0.4){dir-90}..cycle) scaled 1u; % On trace et on affiche...éventuellement :) trace polygone(A1,A2,A3); for k=1 upto 3: trace segment(O,B[k]) dashed withdots scaled 0.25; draw BoiteRec shifted (1.75[O,B[k]]-center BoiteRec) dashed evenly scaled 0.5; endfor; if Vide: else: % On récupère les valeurs pour déterminer les produits k=0; for p_=#1: k:=k+1; Facteur[k]=p_; endfor; Produit[1]=Facteur[1] * Facteur[2]; Produit[2]=Facteur[2] * Facteur[3]; Produit[3]=Facteur[3] * Facteur[1]; for k=1 upto 3: if Produit or Solution: label(TEX("\num{"&decimal(Produit[k])&"}"),(1.75[O,B[k]]-center BoiteRec)); fi; if Produit: else: label(TEX("\num{"&decimal(Facteur[k])&"}"),(0.5[O,A[k]]-center BoiteRec)); fi; endfor; fi; if Aide: for k=1 upto 3: drawarrow (0.5[O,A[k]]--1.75[O,B[k]]) cutbefore segment(A[k],A[k+1]) cutafter BoiteRec shifted (1.75[O,B[k]]-center BoiteRec) dashed evenly scaled 0.5; drawarrow (0.5[O,A[k+1]]--1.75[O,B[k]]) cutbefore segment(A[k],A[k+1]) cutafter BoiteRec shifted (1.75[O,B[k]]-center BoiteRec) dashed evenly scaled 0.5; endfor; fi; \end{mplibcode}% \else% \begin{mpost}[mpsettings={cote:=\useKV[ClesPyramide]{Cote}; boolean Aide,Produit,Solution,Vide; Aide:=\useKV[ClesPyramide]{Aide}; Vide:=\useKV[ClesPyramide]{Vide}; Produit:=\useKV[ClesPyramide]{Produit}; Solution:=\useKV[ClesPyramide]{Solution};}] pair A[],B[],O; A1=u*(1,1); A2-A1=cote*(1,0); A3=rotation(A2,A1,60); A4=A1; B1=iso(A1,A2); B2=iso(A2,A3); B3=iso(A3,A1); O=iso(A1,A2,A3); path BoiteRec; BoiteRec=((-0.4,-0.5)--(0.4,-0.5){dir0}..{dir90}(0.5,-0.4)--(0.5,0.4){dir90}..{dir180}(0.4,0.5)--(-0.4,0.5){dir180}..{dir-90}(-0.5,0.4)--(-0.5,-0.4){dir-90}..cycle) scaled 1u; % On trace et on affiche...éventuellement :) trace polygone(A1,A2,A3); for k=1 upto 3: trace segment(O,B[k]) dashed withdots scaled 0.25; draw BoiteRec shifted (1.75[O,B[k]]-center BoiteRec) dashed evenly scaled 0.5; endfor; if Vide: else: % On récupère les valeurs pour déterminer les produits k=0; for p_=#1: k:=k+1; Facteur[k]=p_; endfor; Produit[1]=Facteur[1] * Facteur[2]; Produit[2]=Facteur[2] * Facteur[3]; Produit[3]=Facteur[3] * Facteur[1]; for k=1 upto 3: if Produit or Solution: label(LATEX("\num{"&decimal(Produit[k])&"}"),(1.75[O,B[k]]-center BoiteRec)); fi; if Produit: else: label(LATEX("\num{"&decimal(Facteur[k])&"}"),(0.5[O,A[k]]-center BoiteRec)); fi; endfor; fi; if Aide: for k=1 upto 3: drawarrow (0.5[O,A[k]]--1.75[O,B[k]]) cutbefore segment(A[k],A[k+1]) cutafter BoiteRec shifted (1.75[O,B[k]]-center BoiteRec) dashed evenly scaled 0.5; drawarrow (0.5[O,A[k+1]]--1.75[O,B[k]]) cutbefore segment(A[k],A[k+1]) cutafter BoiteRec shifted (1.75[O,B[k]]-center BoiteRec) dashed evenly scaled 0.5; endfor; fi; \end{mpost}% \fi% }% \newcommand\DessinePyramideNombre[1]{% \ifluatex% \mplibforcehmode% \begin{mplibcode}% pair A[][],B[]; path Case[]; color CaseCouleur; nbetages:=\useKV[ClesPyramide]{Etages}; largeur:=\useKV[ClesPyramide]{Largeur}; hauteur:=\useKV[ClesPyramide]{Hauteur}; CaseCouleur:=\useKV[ClesPyramide]{Couleur}; boolean Double; Double=\useKV[ClesPyramide]{Double}; Nbeb:=0;%Pour associer les textes avec les points. Plus facile :) if Double: for k=nbetages downto 1: for l=0 upto (k-1): Nbeb:=Nbeb+1; A[k][l]=(0,0)+(nbetages-k)*(largeur/2,0)+(l*largeur,(nbetages-k)*hauteur); B[Nbeb]=A[k][l]; Case[Nbeb]=((unitsquare xscaled largeur) yscaled hauteur) shifted (A[k][l]-0.5*(largeur,hauteur)); trace Case[Nbeb]; endfor; endfor; for k=nbetages-1 downto 1: for l=0 upto (k-1): Nbeb:=Nbeb+1; A[-k][l]=(0,0)+(nbetages-k)*(largeur/2,0)+(l*largeur,-(nbetages-k)*hauteur); B[Nbeb]=A[-k][l]; Case[Nbeb]=((unitsquare xscaled largeur) yscaled hauteur) shifted (A[-k][l]-0.5*(largeur,hauteur)); trace Case[Nbeb]; endfor; endfor; else: if \useKV[ClesPyramide]{Inverse}: change:=-1; else: change=1; fi; for k=nbetages downto 1: for l=0 upto (k-1): Nbeb:=Nbeb+1; A[k][l]=(0,0)+(nbetages-k)*(largeur/2,0)+(l*largeur,change*(nbetages-k)*hauteur); B[Nbeb]=A[k][l]; Case[Nbeb]=((unitsquare xscaled largeur) yscaled hauteur) shifted (A[k][l]-0.5*(largeur,hauteur)); trace Case[Nbeb]; endfor; endfor; fi; if \useKV[ClesPyramide]{Vide}: else: Nbeb:=0; for p_=#1: Nbeb:=Nbeb+1; if (substring(0,1) of p_)="*": fill Case[Nbeb] withcolor CaseCouleur; trace Case[Nbeb]; label(TEX(substring(1,length p_) of p_),B[Nbeb]); elseif (substring(0,1) of p_)="!": drawoptions(withcolor \useKV[ClesPyramide]{CouleurNombre}); label(TEX(substring(1,length p_) of p_),B[Nbeb]); drawoptions(); else: label(TEX(p_),B[Nbeb]); fi; endfor; fi; \end{mplibcode}% \else% \begin{mpost}[mpsettings={nbetages:=\useKV[ClesPyramide]{Etages};largeur:=\useKV[ClesPyramide]{Largeur};hauteur:=\useKV[ClesPyramide]{Hauteur};boolean Vide,Inverse,Double;Vide=\useKV[ClesPyramide]{Vide};Inverse=\useKV[ClesPyramide]{Inverse};Double=\useKV[ClesPyramide]{Double};color CaseCouleur;CouleurNombre; CaseCouleur:=\useKV[ClesPyramide]{Couleur};CouleurNombre=\useKV[ClesPyramide]{CouleurNombre};}] pair A[][],B[]; path Case[]; Nbeb:=0; if Double: for k=nbetages downto 1: for l=0 upto (k-1): Nbeb:=Nbeb+1; A[k][l]=(0,0)+(nbetages-k)*(largeur/2,0)+(l*largeur,(nbetages-k)*hauteur); B[Nbeb]=A[k][l]; Case[Nbeb]=((unitsquare xscaled largeur) yscaled hauteur) shifted (A[k][l]-0.5*(largeur,hauteur)); trace Case[Nbeb]; endfor; endfor; for k=nbetages-1 downto 1: for l=0 upto (k-1): Nbeb:=Nbeb+1; A[-k][l]=(0,0)+(nbetages-k)*(largeur/2,0)+(l*largeur,-(nbetages-k)*hauteur); B[Nbeb]=A[-k][l]; Case[Nbeb]=((unitsquare xscaled largeur) yscaled hauteur) shifted (A[-k][l]-0.5*(largeur,hauteur)); trace Case[Nbeb]; endfor; endfor; else: if Inverse: change:=-1; else: change=1; fi; for k=nbetages downto 1: for l=0 upto (k-1): Nbeb:=Nbeb+1; A[k][l]=(0,0)+(nbetages-k)*(largeur/2,0)+(l*largeur,change*(nbetages-k)*hauteur); B[Nbeb]=A[k][l]; Case[Nbeb]=((unitsquare xscaled largeur) yscaled hauteur) shifted (A[k][l]-0.5*(largeur,hauteur)); trace Case[Nbeb]; endfor; endfor; fi; if Vide: else: Nbeb:=0; for p_=#1: Nbeb:=Nbeb+1; if (substring(0,1) of p_)="*": fill Case[Nbeb] withcolor CaseCouleur; trace Case[Nbeb]; label(LATEX(substring(1,length p_) of p_),B[Nbeb]); elseif (substring(0,1) of p_)="!": drawoptions(withcolor CouleurNombre); label(LATEX(substring(1,length p_) of p_),B[Nbeb]); drawoptions(); else: label(LATEX(p_),B[Nbeb]); fi; endfor; fi; \end{mpost}% \fi% }% \setKVdefault[ClesPyramide]{ToutesOperations=false,Etages=5,Largeur=2cm,Hauteur=1cm,Vide=false,Inverse=false,Double=false,Couleur=Crimson,Multiplication=false,CouleurNombre=blue,Produit=false,Solution=false,Aide=false,Cote=4cm,Creation=false}% \newtoks\toklistecaseP% \def\UpdatetoksPyramide#1\nil{\addtotok\toklistecaseP{"#1",}}% \def\UpdatetoksPyramideMul#1\nil{\addtotok\toklistecaseP{#1,}}% \NewDocumentCommand\PyramideNombre{o m}{% \useKVdefault[ClesPyramide]% \setKV[ClesPyramide]{#1}% \ifboolKV[ClesPyramide]{Creation}{% \PyramideNombreCreation[#1]% }{% \ifboolKV[ClesPyramide]{ToutesOperations}{% \PyramideOp[#1]{#2}% }{% \ifboolKV[ClesPyramide]{Multiplication}{% \ifx\bla#2\bla% \setKV[ClesPyramide]{Vide=true}% \DessinePyramideNombreMul{\the\toklistecaseP}% \else \setsepchar{,}% \readlist*\ListePyramide{#2}% \DessinePyramideNombreMul{\ListePyramide[1],\ListePyramide[2],\ListePyramide[3]}% \fi }{% \ifx\bla#2\bla% \setKV[ClesPyramide]{Vide=true}% \DessinePyramideNombre{\the\toklistecaseP}% \else% \setsepchar{,}% \readlist*\ListePyramide{#2}% \ifboolKV[ClesPyramide]{Double}{% \def\CalculNombreComposants{\fpeval{\useKV[ClesPyramide]{Etages}*\useKV[ClesPyramide]{Etages}}}% }{% \def\CalculNombreComposants{\fpeval{\useKV[ClesPyramide]{Etages}*(\useKV[ClesPyramide]{Etages}+1)/2}}% }% \xintifboolexpr{\ListePyramidelen==\CalculNombreComposants}{% \toklistecaseP{}% \foreachitem\compteur\in\ListePyramide{\expandafter\UpdatetoksPyramide\compteur\nil}% \DessinePyramideNombre{\the\toklistecaseP}% }{Le nombre d'éléments dans la liste des propositions n'est pas compatible avec le nombre d'étages choisi.}% \fi% }% }% }% }% \setKVdefault[PyramideOp]{Rayon=5mm,Graines=false,Etages=5,Solution=false,Relatifs=false,Case=-1,Graine={},CouleurSolution={}} \defKV[PyramideOp]{% Graine=\ifempty{#1}{}{\setKV[PyramideOp]{Graines}},% CouleurSolution=\ifempty{#1}{}{\setKV[PyramideOp]{Solution}}% }% \NewDocumentCommand\PyramideOp{om}{% \useKVdefault[PyramideOp]% \setKV[PyramideOp]{#1}% \ifboolKV[PyramideOp]{Relatifs}{% \BuildPyramideOpRelatifs{#2}% }{% \BuildPyramideOp{#2}% }% }% \NewDocumentCommand\BuildPyramideOp{m}{% \ifluatex% \mplibforcehmode% \mplibnumbersystem{double}% \begin{mplibcode} Etages=\useKV[PyramideOp]{Etages}; Rayon=\useKV[PyramideOp]{Rayon}; % Case=\useKV[PyramideOp]{Case}; boolean Graines,Solution;%,Allume[][]; numeric Allume[][]; Graines=\useKV[PyramideOp]{Graines}; if Graines: randomseed:=\useKV[PyramideOp]{Graine}; fi; Solution=\useKV[PyramideOp]{Solution}; if Solution: color CouleurSolution; CouleurSolution=\useKV[PyramideOp]{CouleurSolution}; fi; vardef ChoixOperation(expr Nba,Nbb)= if (Nba200: ChoixOp:=ceiling(uniformdeviate(1)); else: ChoixOp:=ceiling(uniformdeviate(2)); fi; else: if (Nba mod Nbb)<>0: if Nba*Nbb>200: ChoixAleaA:=uniformdeviate(1); if ChoixAleaA<0.5: ChoixOp:=1; else: ChoixOp:=3; fi; else: ChoixOp:=ceiling(uniformdeviate(3)); fi; else: if Nba*Nbb>200: ChoixAleaA:=uniformdeviate(1); if ChoixAlea<0.5: ChoixOp:=1; else: ChoixOp:=ceiling(2+uniformdeviate(2)); fi; else: ChoixOp:=ceiling(uniformdeviate(4)); fi; fi; fi; enddef; numeric Nb[][],ChoixOp[][]; pair M[][],N[][]; for k=0 upto Etages-1: for l=0 upto Etages-1-k: M[k][l]=Rayon*(1,1)+2*Rayon*(l,k)+k*2*Rayon*(0.5,-1+cosd(30)); Allume[k][l]:=1; endfor; endfor; for k=0 upto Etages-2: for l=0 upto Etages-2-k: N[k][l]=Rayon*(1,1)+(Rayon,0)+2*Rayon*(l,k)+k*2*Rayon*(0.5,-1+cosd(30)); endfor; endfor; %%%%%%%%%%%%%%%%%%%%%%%%%%%%% def ChoixAlea=ceiling(uniformdeviate(2)) enddef; Allume[Etages-1][0]:=ChoixAlea; for k=Etages-2 downto 1: Allume[k][0]:=ChoixAlea; for l=1 upto k-1: if (Allume[k][l-1]+Allume[k-1][l-1])=4: Allume[k][l]:=1; else: Allume[k][l]:=ChoixAlea; fi; endfor; endfor; if Allume[1][0]=1: Allume[0][0]:=2; else: Allume[0][0]:=ChoixAlea; fi; for k=1 upto Etages-1: if Allume[0][k-1]=1: Allume[0][k]:=2; else: if Allume[1][k-1]=1: Allume[Etages][k]:=2; else: Allume[Etages][k]:=1; fi; fi; endfor; %%%%%%%%%%%%%%%%%%%%%%%%%% n:=0; for p_=#1: Nb[0][n]=p_; % if n=Case: % if n200: ChoixOp:=ceiling(uniformdeviate(1)); else: ChoixOp:=ceiling(uniformdeviate(2)); fi; elseif (Nba+Nbb=0): if abs(Nba*Nbb)>200: ChoixOp:=3; else: ChoixAlea:=uniformdeviate(1); if ChoixAlea<0.5: ChoixOp:=2; else: ChoixOp:=3; fi; fi; else: if (abs(Nba) mod abs(Nbb))<>0: if abs(Nba*Nbb)>200: ChoixAlea:=uniformdeviate(1); if ChoixAlea<0.5: ChoixOp:=1; else: ChoixOp:=3; fi; else: ChoixOp:=ceiling(uniformdeviate(3)); fi; else: if abs(Nba*Nbb)>200: ChoixAlea:=uniformdeviate(1); if ChoixAlea<0.5: ChoixOp:=1; else: ChoixOp:=ceiling(2+uniformdeviate(2)); fi; else: ChoixOp:=ceiling(uniformdeviate(4)); fi; fi; fi; enddef; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% numeric Nb[][],ChoixOp[][]; pair M[][],N[][]; for k=0 upto Etages-1: for l=0 upto Etages-1-k: M[k][l]=Rayon*(1,1)+2*Rayon*(l,k)+k*2*Rayon*(0.5,-1+cosd(30)); Allume[k][l]=false; endfor; endfor; for k=0 upto Etages-2: for l=0 upto Etages-2-k: N[k][l]=Rayon*(1,1)+(Rayon,0)+2*Rayon*(l,k)+k*2*Rayon*(0.5,-1+cosd(30)); endfor; endfor; n:=0; for p_=#1: Nb[0][n]=p_; if n=Case: if n