Задаци: Цртежи помоћу карактера

Алгоритми и програми у програмском језику C: Цртежи помоћу карактера.

Квадрат од звездица

Прочитај текст задатка.

Можемо приметити да се квадрат састоји од \(n\) редова, а да се у сваком реду налази \(n\) звездица. Зато програм можемо организовати помоћу угнежђених петљи. Спољна петља се извршава \(n\) пута и у њеном телу се исписује један ред. То се врши тако што се у телу унутрашње петље која се извршава \(n\) пута исписује једна звездица, а након те унутрашње петље се исписује прелазак у нови ред.

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("*");
        printf("\n");
    }
    return 0;
}

Троугао од звездица

Прочитај текст задатка.

За дати број \(n\) троугао садржи \(n\) редова. Сваки ред ћемо исписивати у петљи у којој променљива \(i\) мења вредност од 0 до \(n-1\). Размотримо случај \(n=4\). У првом реду (када је \(i=0\)) потребно је исписати три размака и једну звездицу, у другом (када је \(i=1\)) потребно је исписати два размака и три звездице, у трећем (када је \(i=2\)) потребно је један размак и пет звездица и у четвртом (када је \(i=3\)) потребно је исписати нула размака и седам звездица. Може се закључити да је број размака једнак \(n-i-1\), а број звездица једнак \(2i+1\) (иако је извођење ових релација прилично очигледно, можемо приметити да број размака чини аритметички низ који креће од \(n-1\) и чија је разлика суседних елемената \(-1\), док број звездица чини аритметички низ који креће од 1 и чија је разлика суседних елемената \(2\)). Исписивање датог броја појављивања неког карактера можемо реализовати једноставно у петљи. Тако задатак можемо решити помоћу две унутрашње петље (једне у којој се исписују размаци и једне у којој се исписују звездице).

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - i - 1; j++)
            printf(" ");
        for (int j = 0; j < 2 * i + 1; j++)
            printf("*");
        printf("\n");
    }
    return 0;
}

Број звездица и размака није неопходно експлицитно израчунавати, већ је могуће одржавати две посебне променљиве у којима се памте ови бројеви.

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    int br = n - 1, bz = 1;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < br; j++)
            printf(" ");
        br -= 1;
        for (int j = 0; j < bz; j++)
            printf("*");
        bz += 2;
        printf("\n");
    }
    return 0;
}

Ромб од звездица

Прочитај текст задатка.

Ромб се састоји од \(n\) редова, а у сваком реду се прво исписује одређени број размака, а затим и \(n\) звездица. Претпоставимо да ћемо то остварити спољашњом петљом у којој \(i\) узима вредности од \(0\) до \(n-1\). Обележимо за сваки ред вредност бројача \(i\), број звездица и број размака.

             i   br  bz
    *****    0   4   5
   *****     1   3   5
  *****      2   2   5
 *****       3   1   5
*****        4   0   5

Можемо приметити да је у сваком реду збир броја размака и бројача \(i\) константан и једнак вредности \(n-1\), па је стога број размака увек једнак \(n-1-i\). Дакле у телу спољашње петље имаћемо унутрашњу петљу која исписује \(n-1-i\) размака, а затим и другу унутрашњу петљу која исписује \(n\) звездица. На крају тела спољашње петље (након обе унутрашње) прелазимо у нови ред.

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - 1 - i; j++)
            printf(" ");
        for (int j = 0; j < n; j++)
            printf("*");
        printf("\n");
    }
    return 0;
}

Спољашњу петљу можемо реализовати тако да бројач \(i\) креће од \(n-1\) и спушта се до \(0\) и тада би број размака био једнак \(i\).

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = n - 1; i >= 0; i--)
    {
        for (int j = 0; j < i; j++)
            printf(" ");
        for (int j = 0; j < n; j++)
            printf("*");
        printf("\n");
    }
    return 0;
}

Једно могуће решење је и да број размака пратимо помоћу посебне променљиве коју иницијализујемо на \(n-1\) и умањујемо је за 1 на крају тела унутрашње петље.

Предложено решење задатка (3)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0, r = n - 1; i < n; i++, r--)
    {
        for (int j = 0; j < r; j++)
            printf(" ");
        for (int j = 0; j < n; j++)
            printf("*");
        printf("\n");
    }
    return 0;
}

Ћилим од звездица

Прочитај текст задатка.

Приметимо да се ћилим може хоризонталном линијом поделити на два дела. Нумеришимо редове бројевима од \(0\) до \(2n-2\). Пошто је цртеж симетричан, пожељно је да креирамо нумерацију која то осликава тј. да првих \(n\) редова нумеришемо бројевима од \(0\) до \(n-1\), а затим да наредних \(n-1\) редова нумеришемо бројевима који опадају од \(n-2\) до \(0\). Један начин да се то уреди је да се набрајање редова врши у две независне петље (прва која броји унапред од \(0\) до \(n-1\) и друга која броји уназад од \(n-2\) до \(0\)), но пошто би те петље имале идентична тела, ефикасније решење добијамо ако конструишемо функцију која нумерацију од \(0\) до \(2n-2\) пресликава у нашу жељену нумерацију. Једна таква функција је \(j=n-1-|n-1-i|\) (за \(i\leq n-1\) њена вредност једнака је \(n-1-(n-1-i)=i\), док је за \(i\geq n\) њена вредност једнака \(n-1-(1+i-n)=2n-2-i\)).

n = 4

i j           r  z
0 0 ********  0  4
1 1 ***  ***  2  3
2 2 **    **  4  2
3 3 *      *  6  1
4 2 **    **  4  2
5 1 ***  ***  2  3
6 0 ********  0  4

У сваком реду ћемо прво исписивати \(z\) звездица, затим \(r\) размака, затим поново \(z\) звездица и након тога прећи у нови ред. Уочимо како број звездица \(z\) и број размака \(r\) зависе од вредности \(j\) и \(n\).

Пошто бројање \(j\) креће од нуле, важи да је \(r=2\cdot j\). Приметимо да у претходном примеру у сваком реду важи \(j+z=4=n\) и зато је \(z=n-j\).

У телу петље исписујемо један ред (петља у себи садржи неколико угнежђених петљи или позиве функција у којима се те угнежђене петље реализују). Прво се исписује \(z=n-j\) звездица, затим \(r=2\cdot j\) размака, затим поново \(z=n-j\) звездица и на крају се прелази у нови ред.

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < 2 * n - 1; i++)
    {
        int j = n - 1 - abs(n - 1 - i);
        for (int z = 0; z < n - j; z++)
            printf("*");
        for (int r = 0; r < 2 * j; r++)
            printf(" ");
        for (int z = 0; z < n - j; z++)
            printf("*");
        printf("\n");
    }
    return 0;
}