Pesquisar este blog

Livros Recomendados

Mostrando postagens com marcador ADHOC. Mostrar todas as postagens
Mostrando postagens com marcador ADHOC. Mostrar todas as postagens

quarta-feira, 20 de dezembro de 2023

URI (BEECROWD) - 1515 - Hello Galaxy - Ad-Hoc - C, C++ e Haskell

Hello Galaxy! Mais um exercício resolvido da categoria Ad-Hoc no Beecrowd. A solução desse exercício é bem simples, bora conferir?

Plataforma: Beecrowd (antiga URI)

Problema1515

Enunciado:

Atualmente, no ano de 2114, o conhecimento de que não estamos sozinhos no universo não é novidade, porém um século atrás isto ainda era um mistério. Diversas civilizações na Via Láctea já emitiram algum tipo de sinal provando sua existência, e outras até estabeleceram um contato aberto com a Terra em busca de informações sobre a tal Árvore Hexagonária (afinal, estamos em 2114).

Rafael tem muito interesse pelo assunto, e em um trabalho para a escola se encarregou de descobrir qual foi a civilização mais antiga que enviou um Hello Galaxy para toda a galáxia. Hello Galaxy nada mais é que o primeiro dos passos do Protocolo de Iniciação na Sociedade Via Láctea, PISVL, garantindo que a nova civilização possa entrar em contato com as demais caso necessário.

A mensagem Hello Galaxy traz consigo duas informações básicas: o texto “Hello Galaxy”, que faz parte da tradição, e o nome do planeta da civilização que enviou a mensagem. O CMSVL, Centro de Monitoramento da Sociedade Via Láctea, instalado, por algum motivo, na Terra, recebe tais mensagens, armazenando em um registro o ano em que foi recebida a mensagem e a quantidade de anos que tal mensagem levou para chegar até ali.

A tarefa de Rafael é simples: descobrir quem foi a primeira civilização a enviar a mensagem Hello Galaxy.

Linguagens: C, C++ e Haskell

Solução:

Basta remover o tempo do ano de chegada e verificar qual das entradas resulta em menor valor.

Código em C++:

Coloquei uma variável menor com um número bem grande, de forma que comparada com qualquer valor, na primeira comparação ela vai obter o primeiro valor informado pelo usuário (ano de chegada menos o tempo). Assim, basta fazer o mesmo procedimento de remover o tempo do ano de chegada a cada linha informada e comparar com o valor que está na variável menor. Sempre que essa variável for atualizada, o nome do planeta também precisa ser, pois a resposta será o nome do planeta.

#include <iostream>
#include <string>

using namespace std;

int main() {
    int n;
    while (cin >> n) {
        int menor = 99999;
        int anoChegada;
        int tempo;
        int resultado;
        string planeta;
        string resposta;

        if (!n)
            break;

        for (int i = 0; i < n; i++) {
            cin >> planeta >> anoChegada >> tempo;
            resultado = anoChegada - tempo;
            if (resultado < menor) {
                menor = resultado;
                resposta = planeta;
            }
        }

        cout << resposta << endl;
    }
    return 0;
}

Código em C:

Aqui a mesma lógica foi aplicada.

#include <stdio.h>
#include <string.h>

int main() {
    int n;
    int i;
    int anoChegada;
    int tempo;
    int resultado;
    char planeta[55];
    char resposta[55];
    int menor;

    while (scanf("%d", &n) != EOF) {
        menor = 99999;
        if (!n)
            break;

        for (i = 0; i < n; i++) {
            scanf("%s %d %d", planeta, &anoChegada, &tempo);
            resultado = anoChegada - tempo;
            if (resultado < menor) {
                menor = resultado;
                strcpy(resposta, planeta);
            }
        }

        printf("%s\n", resposta);
    }

    return 0;
}

Código em Haskell:

main :: IO ()
main = do
    n <- readLn
    if n == 0
      then return ()
      else do
         obtemResposta n 99999 ""
         main

obtemResposta :: Int -> Int -> [Char] -> IO ()
obtemResposta 0 _ p = putStrLn p
obtemResposta n menor p = do
   linha <- getLine
   let [planeta, anoChegada, tempo] = words linha
   let resultado = read anoChegada - (read tempo) :: Int
   if resultado < menor
      then obtemResposta (n-1) resultado planeta
      else obtemResposta (n-1) menor p

Chave PIX (chave aleatória) para doações: 6d8bc7a8-5d74-493a-ab7a-3515baf35956
Ajude o blog mais uma vez!

terça-feira, 19 de dezembro de 2023

URI (BEECROWD) - 2408 - Vice-Campeão - Ad-Hoc - C, C++ e Haskell

Agora vamos de "Vice-Campeão"! Um exercício muito fácil e bom para quem está começando na programação! Esse exercício está categorizado como ad-hoc.

Plataforma: Beecrowd (antiga URI)

Problema2408

Enunciado:

A OBI (Organização de Bocha Internacional) é responsável por organizar a competição mundial de bocha. Infelizmente esse esporte não é muito popular, e numa tentativa de aumentar a sua popularidade, ficou decidido que seriam chamados, para a Grande Final Mundial, o campeão e o vice-campeão de cada sede nacional, ao invés de apenas o primeiro lugar.

Tumbólia é um país pequeno que já havia realizado a sua competição nacional quando a nova regra foi instituída, e o comitê local não armazenou quem foi o segundo classificado. Felizmente eles armazenaram a pontuação de todos competidores – que foram apenas três, devido ao tamanho diminuto do país. Sabe-se também que as pontuações de todos jogadores foram diferentes, de forma que não ocorreu empate entre nenhum deles.

Resta agora descobrir quem foi o vice-campeão e para isso o comitê precisa de ajuda.

Linguagens: C, C++ e Haskell

Solução:

A solução é simples, basta ler os três valores e identificar qual é o segundo maior. 

Código em C++:

#include <iostream>

int main() {
	int a, b, c, resposta;
	std::cin >> a >> b >> c;
	resposta = a;
	if (a >= b && a >= c) {
		if (b >= c)
			resposta = b;
		else
			resposta = c;
	}
	else if (b >= a && b >= c) {
		if (c >= a)
			resposta = c;
	}
	else if (c >= a && c >= b) {
		if (b >= a)
			resposta = b;
	}
	std::cout << resposta << std::endl;
	return 0;
}

Código em C:

Em C, li os valores e por meio de estruturas condicionais avaliei quem é o segundo maior valor, colocando ele numa variável chamada resposta. Assim, no fim basta imprimir esta variável.

#include <stdio.h>
int main() {
	int a, b, c, resposta;
	scanf("%d %d %d", &a, &b, &c);
	resposta = a;
	if (a >= b && a >= c) {
		if (b >= c)
			resposta = b;
		else
			resposta = c;
	}
	else if (b >= a && b >= c) {
		if (c >= a)
			resposta = c;
	}
	else if (c >= a && c >= b) {
		if (b >= a)
			resposta = b;
	}
	printf("%d\n", resposta);
	return 0;
}

Código em Haskell:

No código Haskell basta ler a linha toda e ordenar os valores com a função sort (disponível em Data.List). Assim, o segundo valor da lista será o vice-campeão, basta imprimir este valor!

import Data.List (sort)

main :: IO ()
main = do
   linha <- getLine
   let numeros = map read (words linha) :: [Int]
   let [ultimo, vice, campeao] = sort numeros
   print vice

Chave PIX (chave aleatória) para doações: 6d8bc7a8-5d74-493a-ab7a-3515baf35956
Ajude o blog mais uma vez!

URI (BEECROWD) - 3059 - Pares de Números - Ad-Hoc - C, C++ e Haskell

Hoje, mais uma vez, resolvo um problema Ad-Hoc! É o problema "Pares de Números".

Plataforma: Beecrowd (antiga URI)

Problema3059

Enunciado:

Temos um vetor de N inteiros distintos e dois inteiros I e F. Precisamos computar quantos pares desses inteiros do vetor somam pelo menos I e no máximo F. Por exemplo, se o vetor for [45, 12, 11, 7, 83, 29, 5] e I = 19 e F = 52, temos exatamente 8 pares cuja soma está entre 19 e 52: {5, 29}, {5, 45}, {7, 12}, {7, 29}, {7, 45}, {11, 12}, {11, 29} e {12, 29}.

Linguagens: C, C++ e Haskell

Solução:

Nesta solução, fiz um array para ler os valores e verifiquei os pares por uma variável de soma, que somava v[j] e v[k]. Sempre que esse valor fosse >= i e <= f eu incrementava a variável de resposta.

Código em C++:

#include <iostream>
int main() {
   int n, i, f, soma;
   std::cin >> n >> i >> f;
   int v[n];
   for (int j = 0; j < n; j++)
      std::cin >> v[j];

   int resposta = 0;
   for (int j = 0; j < n - 1; j++)
      for (int k = j + 1; k < n; k++) {
         soma = v[j] + v[k];
         if (soma >= i and soma <= f)
            resposta++;
      }

   std::cout << resposta << std::endl;

   return 0;
}

Código em C:

#include <stdio.h>

int main() {
   int n, i, f, j, k, soma, resposta = 0;
   scanf("%d %d %d", &n, &i, &f);
   int v[n];
   for (j = 0; j < n; j++)
      scanf("%d ", &v[j]);
   for (j = 0; j < n - 1; j++)
      for (k = j + 1; k < n; k++) {
         soma = v[j] + v[k];
         if (soma >= i && soma <= f)
            resposta++;
      }

   printf("%d\n", resposta);
   return 0;
}

Código em Haskell:

Aqui usei uma compreensão de lista (list comprehension) para definir os pares x,y, onde x tem que ser diferente de y e a soma deles precisa satisfazer as condições em relação a i e f. Assim ficou fácil, pois a lista de pares resultantes tem tamanho igual ao dobro da resposta! Isso acontece porque ela vai pegar os pares x,y e y,x, ou seja, vai repetir porque em a tupla (x,y) e a tupla (y,x) são diferentes. Assim, a partir da lista gerada, basta obter o tamanho dela dividido por dois.

main :: IO ()
main = do
   linha <- getLine
   let [n, i, f] = map read (words linha) :: [Int]
   linha <- getLine
   let valores = map read (words linha) :: [Int]
   let comb = [(x, y) | x <- valores, y <- valores, x /= y, x + y >= i, x + y <= f]
   let qtdResultados = length comb
   print (div qtdResultados 2)

Chave PIX para doações: 6d8bc7a8-5d74-493a-ab7a-3515baf35956
Ajude o blog!

segunda-feira, 18 de dezembro de 2023

URI (BEECROWD) - 2376 - World Cup (Copa do Mundo) - Ad-Hoc - C e C++

Hoje o problema solucionado é da categoria ad-hoc, e é o problema "Copa do Mundo". Esse é um problema que envolve estruturas condicionais. Vamos ver como eu resolvi?

Plataforma: Beecrowd (antiga URI)

Problema2376

Enunciado:

Este ano tem Copa do Mundo! O país inteiro se prepara para torcer para a equipe canarinho conquistar mais um título, tornando-se hexacampeã.

Na Copa do Mundo, depois de uma fase de grupos, dezesseis equipes disputam a Fase final, composta de quinze jogos eliminatórios. A figura abaixo mostra a tabela de jogos da Fase final:

Na tabela de jogos, as dezesseis equipes finalistas são representadas por letras maiúsculas (de A a P), e os jogos são numerados de 1 a 15. Por exemplo, o jogo 3 é entre as equipes identificadas por E e F; o vencedor desse jogo enfrentará o vencedor do jogo 4, e o perdedor será eliminado. A equipe que vencer os quatro jogos da Fase final será a campeã (por exemplo, para a equipe K ser campeã ela deve vencer os jogos 6, 11, 14 e 15.

Dados os resultados dos quinze jogos da Fase final, escreva um programa que determine a equipe campeã.

Linguagens: C e C++

Solução:

Nesta solução, a proposta foi basicamente analisar todos os caminhos possíveis com estruturas condicionais, assim sabendo quem foi o vencedor. Os códigos em C e C++ adotam essa mesma estratégia.

Já peço desculpas pela baguncinha do código, não ficou tão bem organizado aqui. Mas jogue numa ferramenta embelezadora e ficará bem legível :)

Código em C++:

#include <iostream>
using namespace std;

int main() {
   int jogos[2][15];
   char resposta = 'P';
   for (int i = 0; i < 15; i++)
      cin >> jogos[0][i] >> jogos[1][i];
      if (jogos[0][14] > jogos[1][14]) {
         if (jogos[0][12] > jogos[1][12]) {
            if (jogos[0][8] > jogos[1][8]) {
               if (jogos[0][0] > jogos[1][0])
                  resposta = 'A';
               else
                  resposta = 'B';
	 }
	 else if (jogos[0][1] > jogos[1][1])
                resposta = 'C';
	      else
	        resposta = 'D';
      }
      else if (jogos[0][9] > jogos[1][9]) {
         if (jogos[0][2] > jogos[1][2])
	    resposta = 'E';
	 else
	    resposta = 'F';
      }
      else if (jogos[0][3] > jogos[1][3])
            resposta = 'G';
	   else
	      resposta = 'H';
   }
   else if (jogos[0][13] > jogos[1][13]) {
      if (jogos[0][10] > jogos[1][10]) {
         if (jogos[0][4] > jogos[1][4])
	    resposta = 'I';
	 else
	    resposta = 'J';
      }
      else if (jogos[0][5] > jogos[1][5])
              resposta = 'K';
	   else
              resposta = 'L';
   }
   else if (jogos[0][11] > jogos[1][11]) {
      if (jogos[0][6] > jogos[1][6])
	 resposta = 'M';
      else
         resposta = 'N';
   }
   else if (jogos[0][7] > jogos[1][7])
         resposta = 'O';
   cout << resposta << endl;
   return 0;
}

Código em C:

#include <stdio.h>

int main() {
   int jogos[2][15], i;
   char resposta = 'P';
   for (i = 0; i < 15; i++)
      scanf("%d %d", &jogos[0][i], &jogos[1][i]);
	if (jogos[0][14] > jogos[1][14]) {
		if (jogos[0][12] > jogos[1][12]) {
			if (jogos[0][8] > jogos[1][8]) {
				if (jogos[0][0] > jogos[1][0])
				resposta = 'A';
				else
					resposta = 'B';
			}
			else if (jogos[0][1] > jogos[1][1])
				resposta = 'C';
			else

			resposta = 'D';
		}
		else if (jogos[0][9] > jogos[1][9]) {
			if (jogos[0][2] > jogos[1][2])
				resposta = 'E';
			else
				resposta = 'F';
		}
		else if (jogos[0][3] > jogos[1][3])
				resposta = 'G';
		else
				resposta = 'H';
	}
	else if (jogos[0][13] > jogos[1][13]) {
		if (jogos[0][10] > jogos[1][10]) {
			if (jogos[0][4] > jogos[1][4])
				resposta = 'I';
			else
				resposta = 'J';
		}
		else if (jogos[0][5] > jogos[1][5])
			resposta = 'K';
		else
			resposta = 'L';
	}
	else if (jogos[0][11] > jogos[1][11]) {
		if (jogos[0][6] > jogos[1][6])
			resposta = 'M';
		else
			resposta = 'N';
	}
	else if (jogos[0][7] > jogos[1][7])
		resposta = 'O';
	printf("%c\n", resposta);
	return 0;
}

Chave PIX para doações: 6d8bc7a8-5d74-493a-ab7a-3515baf35956
Ajude o blog!

domingo, 17 de dezembro de 2023

URI (BEECROWD) - 2567 - Vírus - Ad-Hoc - C, C++ e Haskell

Aqui vai mais uma solução, pessoal! O problema Vírus ainda não tinha sido resolvido por mim.  Ele é bem simples, basicamente precisa usar ordenação. Fiz ele em três linguagens, aquelas três que eu mais uso por aqui... então, vamos ao que interessa!

Plataforma: Beecrowd (antiga URI)

Problema2567

Enunciado:

A secretaria de saúde pública da Nlogônia acabou de emitir um alerta. Um vírus está contagiando toda a população.

Após muitos estudos, os pesquisadores do país determinaram que, após infiltrarem o corpo hospedeiro, os virus se juntam dois a dois para tornarem-se letais. O nível de letalidade de uma infecção é determinado pela soma da diferença da idade, em dias, dos vírus pareados. Os vírus sem pares não influenciam no nível.

Desta forma, se existem 4 vírus no corpo hospedeiro com idades (em dias), iguais a

4, 10, 9, 43

E eles se paream da seguinte forma:

4 com 9, 43 com 10

Então nível de letalidade seria (9 - 4) + (43 - 10) = 38.

A secretaria de saúde pública da Nlogônia pediu para que você escrevesse um programa que, dado a contagem de vírus em um corpo e a idade de cada um deles, calcule o nível máximo de letalide que a infecção pode assumir.

Linguagens: C, C++ e Haskell

Solução:

Nesse exercício, portanto, bastava unir os valores dois a dois, sempre o maior com o menor e assim por diante, subtraindo e acumulando a resposta. É muito fácil! Pra isso, resolvi com ordenação, mas há outras formas de resolver. E você, como fez? Veja na sequência os três códigos disponíveis em C, C++ e Haskell.

Código em C++:

Aqui eu acabei usando uma estrutura vector para armazenar os valores e depois ordenei esses valores da estrutura com a função pronta sort, da biblioteca algorithm. Após essa ordenação, casei os valores inicial e final, depois o segundo e o penúltimo, e assim por diante, para fazer a subtração desejada no exercício, acumulando esses resultados e obtendo assim a resposta final.

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main () {
   int n;
   while (cin >> n) {
      vector<int> valores;
      int v;
      for (int i = 0; i < n; i++) {
         cin >> v;
         valores.push_back(v);
      }
      sort(valores.begin(), valores.end());
      int metade = n / 2;
      int resposta = 0;
      for (int i = 0; i < metade; i++ )
         resposta += valores.at(n-i-1) - valores.at(i);
      cout << resposta << endl;
   }
   return 0;
}

Código em C:

Aqui eu usei a função pronta qsort, de stdlib.h, e só criei a função compara para dizer como deve ser a comparação entre os valores. Isso porque após ordenar, basta unir sempre os pares do primeiro com o último, o segundo com o penúltimo e assim por diante.

#include <stdio.h>
#include <stdlib.h>
int compara(const void *a, const void *b) {
   return (*(int*)a - *(int*)b);
}

int main () {
   int n;
   while (scanf("%d", &n) != EOF) {
      int valores[n];
      for (int i = 0; i < n; i++)
         scanf("%d", &valores[i]);
      qsort(valores, n, sizeof(int), compara);
      int metade = n / 2;
      int resposta = 0;
      for (int i = 0; i < metade; i++ )
         resposta += valores[n-i-1] - valores[i];
      printf("%d\n", resposta);
   }
   return 0;
}

Código em Haskell:

A lógica adotada no código Haskell foi a mesma. Aqui também há função pronta para ordenação, bem como há função pronta para obter o primeiro valor de uma lista (init) como o último valor (last), o que facilita nessa junção de valores.

import Data.List (sort)
import System.IO (isEOF)

obtemResposta :: [Int] -> Int
obtemResposta [] = 0
obtemResposta (x:[]) = 0
obtemResposta (x:xs) = last xs - x + obtemResposta (init xs)

main :: IO ()
main = do
   concluido <- isEOF
   if concluido
      then return ()
      else do
         n <- readLn :: IO Int
         linha <- getLine
         let valores = map read (words linha) :: [Int]
         let valoresOrdenados = sort valores
         let resposta = obtemResposta valoresOrdenados
         print resposta
         main

Apoie o blog colaborando com qualquer quantia. A chave pix (chave aleatória) é 6d8bc7a8-5d74-493a-ab7a-3515baf35956

Obrigado!

URI (BEECROWD) - 2451 - PacMan - Ad-Hoc - C e C++

Vamos a mais uma solução por aqui!? Dessa vez o problema "PacMan", da categoria Ad-hoc. É um problema que vale poucos pontos, mas que apresenta uma solução interessante por manipular strings. Vamos ver como se resolve, na sequência desse post.

Plataforma: Beecrowd (antiga URI)

Problema2451

Enunciado:

Pacman é um jogo muito conhecido, onde o personagem tenta comer a maior quantidade possível de bolinhas, tendo ao mesmo tempo que fugir de vários fantasmas. Dessa vez, nosso personagem quer carregar a comida coletada para casa, mas o encontro com um fantasma, ao invés de terminar o jogo, faz com que toda a comida coletada seja roubada.

Neste problema os fantasmas não se movem, e o jogador sempre faz o Pacman percorrer o seguinte caminho:

O Pacman começa no canto superior esquerdo do tabuleiro.
O Pacman percorre toda a linha, da esquerda para direita, até chegar ao lado direito do tabuleiro.
O jogador desce uma posição, e percorre toda a linha, desta vez da direita para a esquerda.
As etapas 2 e 3 se repetem até que todo o tabuleiro tenha sido percorrido.
Infelizmente, Pacman não pode ignorar os comandos do usuário para fugir dos fantasmas ou pegar mais comida, mas ele pode, a qualquer momento, se aproveitar de um bug de implementação e interromper o jogo, levando consigo toda a comida que estiver carregando.

Você deve escrever um programa que determine a maior quantidade de comida que o Pacman pode levar, se escolher a melhor hora possível para sair. Note que o jogador também tem a opção de não sair antes do final do jogo.

Linguagens: C e C++

Solução:

Nesta solução, a proposta foi basicamente ler todas as linhas na ordem natural. Para isso, as linhas ímpares (considerando que se começa em uma linha par -- zero) foram invertidas. Isso facilita a busca para depois não precisar calcular os índices de forma diferente entre linhas pares e ímpares. Assim, basta percorrer o tabuleiro do jogo normalmente, na ordem natural, e procurar pelas maiores sequências de "o" até que um "A" seja encontrado. A maior sequência deve ser sempre armazenada (max) e comparada com a sequência atual (variável "atual"), que, se for maior, é atribuída à variável max também, bem como é zerada após esta ação para que se comece uma nova sequência a partir da posição atual no tabuleiro.

As soluções em C e C++ seguem a mesma lógica, mas você pode analisar as funções de reversão de string, que são diferentes. Em C++ eu aproveitei uma função já existente, reverse(). Em C eu mesmo implementei, para dar um toque especial e diferenciar as soluções .:)

Código em C++:

#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

int main () {
   int n, max = 0, atual = 0;
   string str;
   cin >> n;

   for (int i = 0; i < n; i++) {
      cin >> str;
      if (i & 1)
         reverse(str.begin(), str.end()); 

      for (int j = 0; j < n; j++) {
         if (str.at(j) == 'A') {
            if (atual > max)
               max = atual;
            atual = 0;
         }
         else if (str.at(j) == 'o')
            atual++;
      }
   }
   if (atual > max)
      cout << atual << endl;
   else
      cout << max << endl;

   return 0;
}


Código em C:


#include <stdio.h>

void reverteString (char *str, int n) {
    int i, temp;
    for (i = 0; i < n / 2; i++) {  
        temp = str[i];  
        str[i] = str[n - i - 1];  
        str[n - i - 1] = temp;  
    }  
}  

int main () {
   int n, max = 0, atual = 0, i, j;
   scanf("%d", &n);
   char str[n+1];
   for (i = 0; i < n; i++) {
      scanf("%s", str);
      if (i & 1)
         reverteString(str, n);
      for (j = 0; j < n; j++) {
         if (str[j] == 'A') {
            if (atual > max)
	       max = atual;
            atual = 0;
	 }
	 else if (str[j] == 'o')
         atual++;
      }
   }
   if (atual > max)
      printf("%d\n", atual);
   else
      printf("%d\n", max);

   return 0;

}

Novamente, segue os dados para apoio:

Chave aleatória (PIX) para doações: 6d8bc7a8-5d74-493a-ab7a-3515baf35956
Ajude-nos a manter o blog!

Postagem em destaque

URI (BEECROWD) - 2158 - Helping Uncle Cláudio (Ajudando o Tio Cláudio) - Matemática - C, C++ e Haskell

Buenas! Estou aqui mais uma vez para resolver um problema de Matemática! Agora tenho resolvido alguns dessa categoria, pra que vocês possam ...

Postagens mais visitadas