Задаци: Разни задаци са гранањем

Алгоритми и програми у програмском језику C: Разни задаци са гранањем.

Сутрашњи датум

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

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

Да бисмо одредили сутрашњи дан, прво ћемо увећати дан. У највећем броју случајева то је довољно, међутим, ако се након увећања дана добије непостојећи датум тј. ако увећани дан прелази број дана у том месецу, тада се прелази на први дан наредног месеца (тако што се месец увећа за један). Опет је у највећем броју (преосталих) случајева то довољно. Једини случај који још није покривен настаје ако је данашњи дан 31. децембар тј. ако се увећањем броја месеца добије месец који је већи од 12. У том случају се прелази на први јануар наредне године (тако што се месец постави на један, а година увећа за један).

Једно решење је такво да се за представљање сутрашњег дана користе посебне променљиве, независне од оних за представљање данашњег дана.

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int d, m, g, ds, ms, gs, p = 0, dum = 0;
    scanf("%d%d%d", &d, &m, &g);
    if ((g % 4 == 0 && g % 100 != 0) || (g % 400) == 0)
        p = 1;
    switch (m)
    {
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:dum = 31; break;
    case 4: case 6: case 9: case 11:dum = 30; break;
    case 2:dum = p ? 29 : 28;
    }
    if (d + 1 <= dum)
    {
        ds = d + 1;
        ms = m;
        gs = g;
    }
    else if (m + 1 <= 12)
    {
        ds = 1;
        ms = m + 1;
        gs = g;
    }
    else
    {
        ds = 1;
        ms = 1;
        gs = g + 1;
    }
    printf("%d.%d.%d.", ds, ms, gs);
    return 0;
}

Једно могуће решење је да се мењају вредности променљивих које репрезентују данашњи дан, чиме се можда мало штеди меморија (мада је то занемариво) и добија мало краћи програмски кôд, али се губи информација о данашњем дану након одређивања сутрашњег, што је лоше.

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int d, m, g, p = 0, dum = 0;
    scanf("%d%d%d", &d, &m, &g);
    if ((g % 4 == 0 && g % 100 != 0) || (g % 400) == 0)
        p = 1;
    switch (m)
    {
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:dum = 31; break;
    case 4: case 6: case 9: case 11:dum = 30; break;
    case 2:dum = p ? 29 : 28;
    }
    d++;
    if (d > dum)
    {
        d = 1;
        m++;
        if (m > 12)
        {
            m = 1;
            g++;
        }
    }
    printf("%d.%d.%d.", d, m, g);
    return 0;
}

Јучерашњи датум

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

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

Да бисмо одредили јучерашњи дан, прво ћемо умањити дан. У највећем броју случајева то је довољно, међутим, ако се након умањења дана добије непостојећи датум тј. ако је умањени дан једнак нули, тада се прелази на последњи дан претходног месеца. То се ради тако што се најпре месец умањи за један. Потенцијални проблем настаје ако је умањени месец једнак нули (то се дешава само ако је данашњи дан први јануар) и тада треба прећи на децембар претходне године (постављањем месеца на 12, и умањењем године за један).

Једно решење је такво да се за представљање јучерашњег дана користе посебне променљиве, независне од оних за представљање данашњег дана.

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int d, m, g, dj, mj, gj, p = 0, dupm = 0;
    scanf("%d%d%d", &d, &m, &g);
    if ((g % 4 == 0 && g % 100 != 0) || (g % 400) == 0)
        p = 1;
    switch (m)
    {
    case 1: case 2: case 4: case 6: case 8: case 9: case 11:dupm = 31; break;
    case 5: case 7: case 10: case 12:dupm = 30; break;
    case 3:dupm = p ? 29 : 28;
    }
    if (d > 1)
    {
        gj = g;
        mj = m;
        dj = d - 1;
    }
    else if (m > 1)
    {
        gj = g;
        mj = m - 1;
        dj = dupm;
    }
    else
    {
        gj = g - 1;
        mj = 12;
        dj = dupm;
    }
    printf("%d.%d.%d.", dj, mj, gj);
    return 0;
}

Друго решење је такво да се мењају вредности променљивих које репрезентују данашњи дан, чиме се можда мало штеди меморија (мада је то занемариво) и добија мало краћи програмски кôд, али се губи информација о данашњем дану након одређивања јучерашњег, што је лоше.

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int d, m, g, p = 0, dupm = 0;
    scanf("%d%d%d", &d, &m, &g);
    if ((g % 4 == 0 && g % 100 != 0) || (g % 400) == 0)
        p = 1;
    switch (m)
    {
    case 1: case 2: case 4: case 6: case 8: case 9: case 11:dupm = 31; break;
    case 5: case 7: case 10: case 12:dupm = 30; break;
    case 3:dupm = p ? 29 : 28;
    }
    d--;
    if (d == 0)
    {
        m--;
        if (m == 0)
        {
            m = 12;
            g--;
        }
        d = dupm;
    }
    printf("%d.%d.%d.", d, m, g);
    return 0;
}

Врста троугла на основу углова

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

Три угла могу бити углови троугла ако ако су сви већи од нуле и ако је њихов збир 180 степени. Ако услов постојања троугла није испуњен (негација претходног услова тражи да је неки од углова мањи или једнак нули или ако је збир углова у троуглу различит од 180 степени) треба на стандардном излазу исписати реч ne. У супротном потребно је извршити анализу величине углова како би утврдили врсту троугла (ако постоји угао већи од 90 степени троугао је тупоугли, ако постоји угао од 90 степени троугао је правоугли, а иначе је оштроугли).

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

Услов да постоји угао већи од 90 степени можемо изразити тако што проверимо да ли је било који од три угла већи од 90 степени (везавши услове оператором дисјункције тј. логичким везником или).

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int u1s, u1m, u2s, u2m, u3s, u3m;
    scanf("%d%d%d%d%d%d", &u1s, &u1m, &u2s, &u2m, &u3s, &u3m);
    int u1 = u1s * 60 + u1m;
    int u2 = u2s * 60 + u2m;
    int u3 = u3s * 60 + u3m;
    if (u1 == 0 || u2 == 0 || u3 == 0 || u1 + u2 + u3 != 180 * 60)
        printf("ne");
    else if (u1 > 90 * 60 || u2 > 90 * 60 || u3 > 90 * 60)
        printf("tupougli");
    else if (u1 == 90 * 60 || u2 == 90 * 60 || u3 == 90 * 60)
        printf("pravougli");
    else
        printf("ostrougli");
    return 0;
}

Уместо да проверавамо све углове, можем да пронађемо највећи од три угла (неким од уобичајених начина за израчунавање максимума) и само њега поредимо са 90 степени (сви бројеви су мањи од неке вредности ако и само ако је највећи од њих мањи од те вредности).

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int u1s, u1m, u2s, u2m, u3s, u3m;
    scanf("%d%d%d%d%d%d", &u1s, &u1m, &u2s, &u2m, &u3s, &u3m);
    int u1 = u1s * 60 + u1m;
    int u2 = u2s * 60 + u2m;
    int u3 = u3s * 60 + u3m;
    if (u1 == 0 || u2 == 0 || u3 == 0 || u1 + u2 + u3 != 180 * 60)
        printf("ne");
    else
    {
        int mu = (u1 > u2) ? ((u1 > u3) ? u1 : u3) : ((u2 > u3) ? u2 : u3);
        if (mu > 90 * 60)
            printf("tupougli");
        else if (mu == 90 * 60)
            printf("pravougli");
        else
            printf("ostrougli");
    }
    return 0;
}

Тенис

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

Треба да проверимо да ли је први играч победио другог, а затим и да ли је други играч победио првог, односно да ли је играч који је освојио \(a\) гемова победио играча који је освојио \(b\) гемова и обрнуто. Играч са освојених \(a\) гемова је победио ако и само ако је освојио \(6\) гемова, док је онај други освојио највише \(4\), или је освојио \(7\) гемова, док је онај други освојио \(5\) или \(6\).

Нико не може да има више од \(7\) освојених гемова, тако да ако је већи број већи од \(7\) резултат је неисправан. Ако је један играч освојио \(7\) гемова, други је морао да освоји или \(6\) или \(5\). У супротном су оба играча освојила највише \(6\) гемова и у том случају је сваки резултат исправан (ако је други освојио највише \(4\) гема, сет је завршен, а ако је освојио \(5\) или \(6\), још се игра).

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int p, d;
    scanf("%d%d", &p, &d);
    if (p > 7 || d > 7 || (p == 7 && d < 5) || (d == 7 && p < 5))
        printf("neispravno");
    else if (p > d && ((p == 6 && d < 5) || p == 7))
        printf("pobedio prvi");
    else if (d > p && ((d == 6 && p < 5) || d == 7))
        printf("pobedio drugi");
    else
        printf("nije zavrseno");
    return 0;
}