sur plusieurs topics, j'ai vu que le fait d'automatiser des créations comme des losanges en console en fonction de la hauteur était populaire. J'ai ainsi eu l'idée de créer des défis de difficultés progressives. Il faudra essayer de trouver la solution la plus courte possible, d'un point de vue algorithmique. Bonne chance !
Défi 1 : Carré
h = 3
ooo
ooo
ooo
h = 5
ooooo
ooooo
ooooo
ooooo
ooooo
h = 7
ooooooo
ooooooo
ooooooo
ooooooo
ooooooo
ooooooo
ooooooo
h = 9
ooooooooo
ooooooooo
ooooooooo
ooooooooo
ooooooooo
ooooooooo
ooooooooo
ooooooooo
ooooooooo
Défi 2 : Damier
h = 3
o o o
o o o
o o o
h = 5
o o o o o
o o o o o
o o o o o
o o o o o
o o o o o
h = 7
o o o o o o o
o o o o o o o
o o o o o o o
o o o o o o o
o o o o o o o
o o o o o o o
o o o o o o o
h = 9
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
o o o o o o o o o
Défi 3 : Sapin
h = 3
o
ooo
ooooo
o
o
h = 5
o
ooo
ooooo
ooooooo
ooooooooo
o
o
h = 7
o
ooo
ooooo
ooooooo
ooooooooo
ooooooooooo
ooooooooooooo
o
o
h = 9
o
ooo
ooooo
ooooooo
ooooooooo
ooooooooooo
ooooooooooooo
ooooooooooooooo
ooooooooooooooooo
o
o
Défi 4 : Triangle étiré
h = 3
o
o o o
o o o o o
h = 5
o
o o o
o o o o o
o o o o o o o
o o o o o o o o o
h = 7
o
o o o
o o o o o
o o o o o o o
o o o o o o o o o
o o o o o o o o o o o
o o o o o o o o o o o o o
h = 9
o
o o o
o o o o o
o o o o o o o
o o o o o o o o o
o o o o o o o o o o o
o o o o o o o o o o o o o
o o o o o o o o o o o o o o o
o o o o o o o o o o o o o o o o o
Défi 5 : Losange
h = 3
o
ooo
o
h = 5
o
ooo
ooooo
ooo
o
h = 7
o
ooo
ooooo
ooooooo
ooooo
ooo
o
h = 9
o
ooo
ooooo
ooooooo
ooooooooo
ooooooo
ooooo
ooo
o
Défi 6 : Sablier
h = 3
o
ooo
o o
h = 5
o
ooo
ooooo
o o
oo oo
h = 7
o
ooo
ooooo
ooooooo
o o
oo oo
ooo ooo
h = 9
o
ooo
ooooo
ooooooo
ooooooooo
o o
oo oo
ooo ooo
oooo oooo
Défi 7 : Losange & Damier
h = 3
o
o o
o
h = 5
o
o o
o o o
o o
o
h = 7
o
o o
o o o
o o o o
o o o
o o
o
h = 9
o
o o
o o o
o o o o
o o o o o
o o o o
o o o
o o
o
Défi 8 : Zigzag
h = 3
ooo
o
ooo
h = 5
ooooo
o
ooooo
o
ooooo
h = 7
ooooooo
o
ooooooo
o
ooooooo
o
ooooooo
h = 9
ooooooooo
o
ooooooooo
o
ooooooooo
o
ooooooooo
o
ooooooooo
Défi 9 : Spirale
h = 3
ooo
o
ooo
h = 5
ooooo
o
ooo o
o o
ooooo
h = 7
ooooooo
o
ooooo o
o o o
o ooo o
o o
ooooooo
h = 9
ooooooooo
o
ooooooo o
o o o
o ooo o o
o o o o
o ooooo o
o o
ooooooooo
A vous de trouver les subtilités de chaque figure. Les prototypes des fonctions ressemblent à voidcarre(inth);où h est un nombre naturel impair supérieur ou égal à 3 pour éviter des bugs. Votre algorithme devra fonctionner pour n'importe quel h entrant dans les conditions ci-dessus.
Si vous trouvez trop facile ces défis, je peux en concocter de bien plus dur. Mais les dernier défis devraient vous poser quelques problèmes.
"If debbugging is the process of removing bugs, then programming must be the process of putting them in." (Edsger Dijkstra)
C'est sympathique. Mais je pense qu'il aurait été plus intéressant de proposer ce sujet dans le forum Autres langages, de manière à avoir un public et un panel de langage plus large puisque le but recherché et de trouver l'algorithme de génération plutôt que son implémentation en C (qui ne vient que dans un second temps).
J'ai trouvé un peu plus court: voidcarre(intn){for(inti=0;i<n*n;++i)printf("\no"+!!(i%n));}
La principale subtilité est dans "\no"+!!(i%n), qui est équivalent à "\no"+(i%n!=0). Comme (i%n!=0) vaut 0 ou 1, ça revient à "\no"+0</code>ou<minicodetype="c">"\no"+1, qui est de la simple arithmétique de pointeur (avec conversion du tableau "\no" en pointeur sur son élément initial).
Bref, "\no"+!!(i%n) est un pointeur sur le \n quand i modulo n vaut 0, et c'est un pointeur sur le o le reste du temps.
J'adore le "\no"+!!(i%n), bien joué Maître Mongenet (il manque au SdZ un smiley "vénération").
Je tente les exercices et je poste ma solution. Il ne m'ont pas l'air bien compliqués, mis à part la spirale).
ÉDIT: Voilà mon code :
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int Uint;
#define CAR 219 // caractère utilisé pour dessiner les formes
/* en ASCII étendu, 219 correspond à '█'
(j'avais initialement mis '*', mais finalement
c'est plus joli avec '█' (mais non portable) */
#define BLK '.' // espace blanc
void carre(Uint n) {
const Uint N= n*n;
for(Uint i=0; i<N; ++i) { // boucle "linéaire" (ligne*colonnes)
if(i && !(i%n)) putchar('\n');
putchar(CAR);
}
putchar('\n');
}
void damier(Uint n) {
const Uint N= 2*n;
for(Uint i=0; i<N*n; ++i) { // boucle "linéaire" (ligne*colonnes)
if(i && !(i%N)) putchar('\n');
putchar((i+(i/N))&1 ? BLK:CAR);
/* ^ si i/N (ligne) et i (la colonne est i%N, mais le résultat
est inchangé) sont de parités différentes */
}
putchar('\n');
}
void sapin(Uint n) {
Uint i;
/* feuillage */
for(i=0; i<n; ++i) { // boucle lignes
for(Uint j=0; j<n+i; ++j) // boucle colonnes
putchar(j+1>n-i-1 ? CAR:BLK);
putchar('\n');
}
/* tronc */
for(i=0; i<2*n; ++i) { // boucle "linéaire" (ligne*colonnes)
putchar((i+1)%n ? BLK:CAR);
if(!((i+1)%n)) putchar('\n');
}
}
void triangle(Uint n) {
for(Uint i=0; i<n; ++i) { // boucle ligne
for(Uint j=0; j<n+3*i; ++j) // boucle colonne
putchar((j+i)&1 || j+1<=n-i-1 ? BLK:CAR);
// ^ si i et j sont de parités différentes
putchar('\n');
}
putchar('\n');
}
void losange(Uint n) {
Uint i;
const Uint N= n/2+1;
/* partie supérieure */
for(i=0; i<N; ++i) { // boucle ligne
for(Uint j=0; j<N+i; ++j) // boucle colonne
putchar(j<N-1-i ? BLK:CAR);
putchar('\n');
}
/* partie inférieure */
for(i=1; i<N; ++i) { // boucle ligne
for(Uint j=0; j<n-i; ++j) // boucle colonne
putchar(j<i ? BLK:CAR);
putchar('\n');
}
}
void sablier(Uint n) {
Uint i;
const Uint N= n/2+1;
/* partie supérieure */
for(i=0; i<N; ++i) { // boucle ligne
for(Uint j=0; j<N+i; ++j) // boucle colonne
putchar(j<N-1-i ? BLK:CAR);
putchar('\n');
}
/* partie inférieure */
for(i=1; i<N; ++i) { // boucle ligne
for(Uint j=0; j<n; ++j) // boucle colonne
putchar(j<i || j>=n-i ? CAR:BLK);
putchar('\n');
}
}
void losangeDamier(Uint n) {
Uint i;
const Uint N= n/2+1;
/* partie supérieure */
for(i=0; i<N; ++i) { // boucle ligne
for(Uint j=0; j<N+i; ++j) // boucle colonne
putchar((j+i+n/2)&1 || j<N-1-i ? BLK:CAR);
/* ^ si i et j sont de même parité et que n/2 est impair,
ou que i et j sont de parité différentes et que n/2
est pair */
putchar('\n');
}
/* partie inférieure */
for(i=1; i<N; ++i) { // boucle ligne
for(Uint j=0; j<n-i; ++j) // boucle colonne
putchar((j-i)&1 || j<i ? BLK:CAR);
// ^ si i et j sont de parités différentes
putchar('\n');
}
}
void zigzag(Uint n) {
for(Uint i=0; i<n; ++i) { // boucle ligne
for(Uint j=0; j<((i+1)&3?n:1); ++j) // boucle colonne
putchar(i&1 && (j||(i+1)&3) && j!=n-1 ? BLK:CAR);
/** non simplifié :
putchar(!(i&1) || !((i+3)&3)&&(j==n-1) || !((i+1)&3)&&!j ? CAR:BLK); **/
/* ↑ ↑ ^ si i+1 est multiple de 4
| | et qu'on est au 1er caractère
| | si i+1 est pair mais pas multiple de 4
| et qu'on est au dernier caractère
| si i est pair */
putchar('\n');
}
}
void spirale(Uint n) {
char** tab= NULL;
Uint i, j, k, jLast;
/* allocation */
tab= malloc(n*sizeof(char*));
for(i=0; i<n; ++i) {
tab[i]= malloc(n*sizeof(char));
for(j=0; j<n; ++j) tab[i][j]= BLK;
}
/* remplissage de la grille */
for(i=0, j=0, k=0; k<n ; ++k) {
/* Chaque tour de boucle correspond à l'écriture d'une ligne droite ;
k est donc le n° de la ligne actuelle.
On utilise 2 coordonnée pour écrire la ligne : i est la coordonnée
fixe, j celle qui varie.
jLast est la dernière valeur (exclue) prise par j.
*/
/* calcul de jLast en fonction de la direction */
switch(k&3) {
case 0: // si on va vers la droite
jLast= n-k/2;
break;
case 1: // si on va vers le bas
jLast= n-k/2;
break;
case 2: // si on va vers la gauche
jLast= k==2? -1 : (k-4)/2;
break;
case 3: // si on va vers le haut
jLast= k/2;
break;
default:break;
}
/* écriture de la ligne */
while(j!=jLast) {
tab[k&1?j:i][k&1?i:j]= CAR;
if((k&3)<2) ++j; // on incrémente ou décrémente j, selon le sens
else --j;
}
/* mise à jour des coordonnées */
j= i;
i= jLast -((k&3)<2) +((k&3)>1);
}
/* affichage */
for(i=0; i<n; ++i) {
for(j=0; j<n; ++j) putchar(tab[i][j]);
putchar('\n');
}
/* libération */
for(i=0; i<n; ++i) free(tab[i]);
free(tab);
}
typedef void (*fPtr)(Uint);
const fPtr fTab[9]= { carre,
damier,
sapin,
triangle,
losange,
sablier,
losangeDamier,
zigzag,
spirale };
int main(void) {
Uint n;
Uint i;
puts("Entrez un nombre impair plus grand que 2 :");
do {
putchar('>');
if(!scanf(" %u", &n)) return -1;
} while(n<3 || ~n&1);
for(i=0; i<9; ++i) {
printf("forme %u :\n---------\n", i+1);
fTab[i](n);
putchar('\n');
}
return 0;
}
Toutes mes fonctions se ressemblent beaucoup. Il ne s'agit en fait que de variantes : double boucle avec un unique putchar et une expression ternaire pour choisir le caractère à afficher (espace ou '*') ; ce n'est en gros que la condition du ternaire qui change (et éventuellement le nombre de tours de boucle à effectuer). J'ai "linéraisé" certaines de mes fonctions (carre, damier) qui n'ont qu'une seule boucle ; ce serait possible de le faire avec toutes, mais le code serait beaucoup moins clair.
La fonction spirale est à part. Je n'ai pas vraiment essayé de la réaliser en calquant son principe (double boucle, ternaire, etc.) sur les autres : j'alloue un tableau 2D de char (je ne vérifie pas le retour de malloc d'ailleurs mais bon) pour y écrire tranquillement la spirale avant de l'afficher
Mes fonctions pourraient, je pense, être optimisées, mais il était demandé dans les consignes de garder le code le plus simple et clair possible, donc voilà.
Les conditions dans les ternaires peuvent paraître obscures, j'en suis navré, j'ai tenté d'en commenter certaines mais j'ai vraiment la flemme de toutes les expliquer en détail (il me faudrait 200 lignes de commentaires...)
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.