Muito bem pes­soal, chegou a hora de con­hecer os 3 vence­dores da pro­moção para gan­har o livro de RTOS da Micrium!

Primeira­mente, gostaria de agrade­cer à todos pela par­tic­i­pação. Recebi 85 respostas, e deu um pouco de tra­balho cor­ri­gir tudo! :)

A maio­ria acer­tou pelo menos 3 dos 4 desafios, e 38 acer­taram tudo. Den­tre estas 38 pes­soas, fiz o sorteio lá no http://www.random.org/.

Mas antes de dizer quem são os 3 felizar­dos, que tal dar­mos uma olhada nova­mente nos desafios?

DESAFIO 1

O desafio 1 dizia o seguinte:

O código abaixo tem um erro. Qual é este erro?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdlib.h>
#include <stdio.h>
 
#define SIZE 15 
 
int main()
{
    int *a, i;
 
    a = malloc(SIZE*sizeof(int));
 
    for (i = 0; i < SIZE; i++)
        *(a + i) = i * i;
 
    for (i = 0; i < SIZE; i++)
        printf("%dn", *a++);
 
    free(a);
 
    return 0;
}

A maio­ria acer­tou este desafio. Na linha 10 alo­camos uma região de memória e armazen­amos o endereço no pon­teiro “a”. Na linha 16 este pon­teiro é alter­ado, e quando ten­ta­mos desalocá-lo na linha 18 ter­e­mos prob­le­mas na certa, já que o pon­teiro “a” não armazena mais o endereço ini­cial retor­nado por mal­loc(). A solução aqui seria não alterar este pon­teiro. O código abaixo resolve o problema:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdlib.h>
#include <stdio.h>
 
#define SIZE 15 
 
int main()
{
    int *a, i;
 
    a = malloc(SIZE*sizeof(int));
 
    for (i = 0; i < SIZE; i++)
        *(a + i) = i * i;
 
    for (i = 0; i < SIZE; i++)
        printf("%dn", *(a + i));  // CORREÇÃO
 
    free(a);
 
    return 0;
}

Algu­mas pes­soas apon­taram ainda que fal­tou checar o retorno da função mal­loc() e fazer o cast para (int *). É ver­dade! O cast é necessário prin­ci­pal­mente se você ten­tar com­pi­lar em C++. Mas não con­sid­erei estes fatores para val­i­dar a resposta como certa.

DESAFIO 2

O desafio 2 dizia o seguinte:

O código abaixo tam­bém tem um erro. Qual?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
    int* ptr1, ptr2;
 
    ptr1 = malloc(sizeof(int));
 
    ptr2 = ptr1;
 
    *ptr2 = 10;
 
    return 0;
}

A maio­ria tam­bém acer­tou este exer­cí­cio. Uma coisa que aprendi deste quando come­cei a estu­dar C é que deve­mos colo­car o “*” sem­pre do lado do nome do pon­teiro, e não do lado do tipo. No código acima, ptr2 é um inteiro, e não um pon­teiro para inteiro como pre­tendi­amos, cau­sando erro na linha 11. Para cor­ri­gir este código, basta declarar ptr2 como ponteiro:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
    int *ptr1, *ptr2;  // CORREÇÃO
 
    ptr1 = malloc(sizeof(int));
 
    ptr2 = ptr1;
 
    *ptr2 = 10;
 
    return 0;
}

Assim como no primeiro exer­cí­cio, algu­mas pes­soas tam­bém apon­taram a ausên­cia da checagem do retorno da função mal­loc() e do cast para (int *). Mas tam­bém não con­sid­erei estes fatores para val­i­dar a resposta como certa.

Out­ros falaram da ausên­cia do free(). Sim, é sem­pre uma boa prática usar o free(), mas sua ausên­cia nem sem­pre sig­nifica erro. No nosso caso, como a apli­cação aloca e depois encerra, não ter­e­mos prob­lema com mem­ory leak pela ausên­cia do free().

DESAFIO 3

O desafio 3 dizia o seguinte:

A função abaixo recebe um vetor de números inteiros e tem o obje­tivo de retornar o menor número inteiro deste vetor. Imple­mente esta função sem usar nen­hum oper­ador de com­para­ção! Ou seja, você não pode usar nen­hum destes oper­adores: “==”, “!=”, “>”, “<”, “>=”, “<=”.

1
2
3
4
unsigned int menor(unsigned int buf[], size_t size)
{
 
}

Aqui o bicho pegou! Este é o típico “exer­cí­cio bom­bril”, que pode ser resolvido de 1001 maneiras. Recebi imple­men­tações de 5 lin­has e out­ras de 50 linhas! :)

Esta é a minha sug­estão de implementação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
unsigned int menor(unsigned int buf[], size_t size)
{
    unsigned int m = 0;
    int i;
 
    while(1) {
 
        for (i = size; i; i--) {
            if (!buf[i - 1]) return m;
            buf[i - 1]--;
        }
 
        m++;
    }
}

Eu faço uma varredura do vetor em um loop e decre­mento, um a um, cada ele­mento deste vetor. A quan­ti­dade de decre­men­tos real­iza­dos é armazenada na var­iável “m”. Quando um dos ele­men­tos do vetor atin­gir o valor 0, sig­nifica que desco­bri qual era o ele­mento de menor valor den­tro do vetor, e retorno este valor, que é exata­mente a quan­ti­dade de decre­men­tos real­izada, armazenada na var­iável “m”.

Recebi algu­mas imple­men­tações que usavam esta lóg­ica, mas tam­bém recebi out­ras imple­men­tações bem interessantes.

Achei bem legal esta imple­men­tação do Paulo Daniel:

1
2
3
4
5
6
7
8
unsigned int menor(unsigned int buf[], size_t size)
{
   unsigned int min = UINT_MAX;
   while(size) 
      if(!(buf[--size]/min))
         min = buf[size];
   return min;
}

Ele con­seguiu resolver em 5 lin­has, usando ape­nas uma oper­ação de divisão de inteiros!

Atu­al­iza­ção: Como bem obser­vado pelos leitores Fer­nando Bar­boza e Уθя¡ςκ, esta imple­men­tação tem uma falha, já que existe o risco de divisão por 0 na linha 5. Mas a forma como o prob­lema foi resolvido não deixa de ser bem interessante.

Já o Dou­glas Dru­mond preferiu esco­var alguns bits e tra­bal­har com com­ple­mento de 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
unsigned int menor(unsigned int buf[], size_t size)
{
    unsigned int shamt =  (sizeof(unsigned int) * 8 - 1);
    unsigned int mask = 0x01;
 
    size_t i = size - 1;
 
    unsigned int menor_item = buf[i];
    while (i--) {
        if(((buf[i] - menor_item) >> shamt) && mask) menor_item = buf[i];
    }
 
    return menor_item;
}

DESAFIO 4

Este desafio dizia o seguinte:

Escreva um pro­grama em C que imprima “Quero o meu livro!”, mas sem usar nen­hum ponto-e-vírgula no arquivo “.c”! Obs: o pro­grama deve com­pi­lar e fun­cionar normalmente.

A solução é bem simples:

1
2
3
4
5
6
#include <stdio.h>
 
void main()
{
    if (printf("Quero o livro!n")) {}
}

Você pode tro­car o “if” pelo “while” também.

Teve gente que que­ria tanto o livro que colo­cou em um loop infinito! :)

1
2
3
4
void main()
{
    while(printf("Quero o meu livro!n")){}
}

Mas aqui o pes­soal resolveu usar a cria­tivi­dade. Como falei ape­nas que não podia usar “;” no arquivo “.c”, e não men­cionei nada sobre o uso de arquivo “.h”, recebi respostas do tipo:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Author: Celso
// imprime.c
#include <stdio.h>
#include <stdlib.h>
 
#include "imprime.h"
void main()
{
  IMPRIME
}
 
// imprime.h
#define IMPRIME   printf("Quero o meu livro!n");

Ou então tro­cando o “;” por um define pas­sado pelo compilador:

1
2
3
4
5
6
7
8
9
10
11
/* Author: Fernando Martines
 *
 * Compilacao: gcc -DSPECIAL=";" desafio4.c -o desafio4
 */
#include <stdio.h>
 
int main()
{
    printf("Quero o meu livro!n") SPECIAL
    return 0 SPECIAL
}

Bom, gostei muito do resul­tado destes desafios. Aprendi bas­tante e espero que vocês ten­ham apren­dido tam­bém. Afi­nal, o que importa é par­tic­i­par. Gan­har é só um detalhe, não é ver­dade? O quê? Não!? :)

OK, chega de enro­lação, estes são os três par­tic­i­pantes que acer­taram os 4 desafios e foram sortea­dos para rece­ber o livro:

  • Rodrigo (a.k.a. Skhaz)
  • Eduardo Vieira
  • Rodolfo Pereira Araujo

Para aque­les que não gan­haram, não desanimem! Vocês podem baixar gra­tuita­mente o PDF do livro no site da Micrium aqui.

Ou então vocês podem esperar o próx­imo con­curso. Eu havia fal­ado que tinha 3 livros, não é ver­dade? Então… eu estava escon­dendo o jogo! :)

Na ver­dade, alem destes 3, tenho mais 1! E logo mais ter­e­mos um novo desafio por aqui. Mas desta vez não será tão fácil assim! :)

Um abraço!

Ser­gio Prado

VN:F [1.9.17_1161]
Rat­ing: 7.0/10 (3 votes cast)
Resul­tado do con­curso do livro uC/OS-III The Real-Time Ker­nel, 7.0 out of 10 based on 3 ratings

Posts rela­ciona­dos:

  1. Quer gan­har o livro uC/OS-III The Real-Time Kernel?
  2. Resul­tado do con­curso para gan­har o con­vite VIP
  3. Sis­temas de Tempo Real — Parte 2
Tags:  
  • Fer­nando Barboza

    Pena que não gan­hei!!
    Quem sabe tenho mais sorte no próx­imo sorteio.

    Tam­bém gostei da cria­tivi­dade do pes­soal.….. Mas o código do Paulo Daniel na 3 é ele­gante, mas perigo se o último ele­mento do vetor for 0.

    if (!(0/UINT_MAX))
    .…

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
    • Fer­nando Barboza

      Ou

      if (!(x/0))

      VA:F [1.9.17_1161]
      Rating: 0.0/5 (0 votes cast)
      • Paulo

        Sem­pre esqueço alguns detal­hes :P

        while(size && buf[–size])
           if(!(buf[size]/min))

        VA:F [1.9.17_1161]
        Rating: 0.0/5 (0 votes cast)
    • http://sergioprado.org/ Ser­gio Prado

      Bem obser­vado Fernando!

      Estou atu­al­izando o post com esta informação.

      Um abraço.

      VA:F [1.9.17_1161]
      Rating: 0.0/5 (0 votes cast)
  • Уθя¡ςκ

    haha, que legal vai ter “o retorno”.

    Uma coisa, a imple­men­tação do Paulo Daniel que vc men­cio­nou pode incor­rer em uma divisão por 0.

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • Gabriel Duarte

    Legal! Eu fiz todos, mas tive que via­jar a tra­balho e não enviei, que pena :( Mas ver os resul­ta­dos foi bem legal!

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • Terry Laun­dos

    Muito bom mesmo, não gan­hei o livro, mas jávou baixa-lo :D
    O Apren­dizado aqui foi imen­su­ravel, valeu demais.

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • Paulo

    Pois é, esqueci de checar o número zero, porém um sim­ples AND no while, já seria o sufi­ciente, afi­nal o tipo dos ele­men­tos do vetor é unsigned int, logo zero é menor valor possível.

    while(size && buff[size]){}

    Esperando pelo próx­imo desafio!

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • http://sergioprado.org/ Ser­gio Prado

    Olá Fabri­cio,

    Não sabia mesmo dos peri­gos de fazer um cast na chamada à mal­loc(). E olha que tem muito código open source por aí assim. Valeu pelo link.

    Um abraço.

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • http://sergioprado.org/ Ser­gio Prado

    Olá Fabri­cio,

    Não sabia mesmo dos peri­gos de fazer um cast na chamada à mal­loc(). E olha que tem muito código open source por aí assim. Valeu pelo link.

    Um abraço.

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • http://sergioprado.org/ Ser­gio Prado

    Olá Fabri­cio,
    Não sabia mesmo dos peri­gos de fazer um cast na chamada à mal­loc(). E olha que tem muito código open source por aí assim. Valeu pelo link.

    Um abraço.

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
  • Alfredo Miranda

    Ei Sér­gio, tem como divul­gar quan­tos desafios cada pes­soa que par­ticipou acertou!?(Na ver­dade, estou com inter­esse de saber se acertei todos mesmo!hehe)

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)
    • http://sergioprado.org/ Ser­gio Prado

      Olá Alfredo,

      Agora não da mais. Só salvei os nomes de quem acer­tou tudo. Mas olhei nova­mente suas respostas e vi que tem um bug na resposta do desafio 3. Te man­dei os detal­hes por email.

      Um abraço.

      VA:F [1.9.17_1161]
      Rating: 0.0/5 (0 votes cast)
  • http://profiles.google.com/drumond.douglas Dou­glas Drumond

    Os desafios 3 e 4 foram bem diver­tidos, prin­ci­pal­mente o 3.

    VA:F [1.9.17_1161]
    Rating: 0.0/5 (0 votes cast)