Pesquisar este blog

Livros Recomendados

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

quarta-feira, 12 de abril de 2023

URI (BEECROWD) - 1022 - TDA Rational (TDA Racional) - Estruturas e Bibliotecas - Haskell

Fala, pessoal!

Nesse post resolvo um problema da categoria "Estruturas e Bibliotecas". Esses problemas costumam ser um pouco mais difíceis em relação aos da categoria Iniciante, e costumam envolver o uso de alguma estrutura de dados ou biblioteca diferente das padrão. Não é exatamente o caso para resolver ele em Haskell, já que conseguimos definir nossas funções e usar algumas outras que estão disponíveis no módulo padrão 😎

Abaixo você tem acesso a uma das possíveis soluções.

Ah, não esqueça de ajudar o blog!!!

Plataforma: URI (BEECROWD)

Problema1022

Enunciado:
In english:

You were invited to do a little job for your Mathematic teacher. The job is to read a Mathematic expression in format of two rational numbers (numerator / denominator) and present the result of the operation. Each operand or operator is separated by a blank space. The input sequence (each line) must respect the following format: number, (‘/’ char), number, operation char (‘/’, ‘*’, ‘+’, ‘-‘), number, (‘/’ char), number. The answer must be presented followed by ‘=’ operator and the simplified answer. If the answer can’t be simplified, it must be repeated after a ‘=’ operator. Considering N1 and D1 as numerator and denominator of the first fraction, follow the orientation about how to do each one of these 4 operations: Sum: (N1*D2 + N2*D1) / (D1*D2) Subtraction: (N1*D2 - N2*D1) / (D1*D2) Multiplication: (N1*N2) / (D1*D2) Division: (N1/D1) / (N2/D2), that means (N1*D2)/(N2*D1)

Linguagem: Haskell


Solução: 

A ideia do exercício é realizar os cálculos desejados pelo usuário, que resultarão em uma fração, e então exibir a fração também em formato simplificado. Para isso é necessário saber qual é o maior valor que pode dividir numerador e denominador, ou seja, o máximo divisor comum (mdc).

A estratégia utilizada foi criar várias funções para auxiliar a encontrar a resposta.

A função main apenas lê o valor de n e o passa como parâmetro para a função reading.

Na função reading as expressões são lidas linha a linha e então os números informados são extraídos e colocados em uma lista. Na linha, todas as "palavras" (expressões separadas por espaço) pares são números. Entre os números (palavras ímpares) estão os operadores, sendo que o único operador que importa neste exercício é o do meio, pois o primeiro e o último são sempre "/", garantindo que as entradas são frações.

Para pegar o n-ésimo elemento de uma lista, usa-se nome-lista!!n.

Criei duas funções, getNum e getDen para obter o numerador e o denominador a depender da operação realizada, seguindo as fórmulas do enunciado.

Após obter numerador e denominador, o primeiro valor pode ser impresso. Depois disso, para calcular o número simplificado, basta obter o mdc dos valores e dividir os números obtidos após o primeiro cálculo pelo mdc.

A única condição antes de exibir o valor simplificado é identificar se o numerador obtido no primeiro passo é zero. Isso deve ser feito porque zero no numerador com qualquer denominador (que só não pode ser zero) pode ser simplificado para 0/1.

Veja como ficou o código:

main :: IO ()
main = do
   n <- readLn :: IO Int
   reading n

mdc :: Int -> Int -> Int
mdc 0 _ = 0
mdc a b
   | a == b = a
   | a < b = mdc a (b-a)
   | otherwise = mdc b (a-b)

getNum :: String -> Int -> Int -> Int -> Int -> Int
getNum op n1 d1 n2 d2
   | op == "+" = n1 * d2 + n2 * d1
   | op == "-" = n1 * d2 - n2 * d1
   | op == "*" = n1 * n2
   | otherwise = n1 * d2

getDen :: String -> Int -> Int -> Int -> Int
getDen op n2 d1 d2
   | op == "/" = n2 * d1
   | otherwise = d1 * d2

reading :: Int -> IO ()
reading n = do
   if n == 0
      then return ()
      else do
         line <- getLine
         let list = words line
         let [n1, d1, n2, d2] = [read x | (x, i) <- zip list [0..], even i]
         let op = list!!3
         let numFinal = getNum op n1 d1 n2 d2
         let denFinal = getDen op n2 d1 d2
         if numFinal == 0
            then putStrLn ("0/" ++ show (denFinal) ++ " = 0/1")
            else do
               let divisor = mdc (abs numFinal) denFinal
               let numSim = div numFinal divisor
               let denSim = div denFinal divisor
               putStrLn (show (numFinal) ++ "/" ++ show (denFinal) ++ " = " ++ show (numSim) ++ "/" ++ show (denSim))
         reading (n-1)

sábado, 26 de dezembro de 2020

URI - 1022 - Estruturas e Bibliotecas - TDA Racional - C

Plataforma: URI

Problema1022

Enunciado:

A tarefa aqui neste problema é ler uma expressão matemática na forma de dois números Racionais (numerador / denominador) e apresentar o resultado da operação. Cada operando ou operador é separado por um espaço em branco. A sequência de cada linha que contém a expressão a ser lida é: número, caractere, número, caractere, número, caractere, número. A resposta deverá ser apresentada e posteriormente simplificada. Deverá então ser apresentado o sinal de igualdade e em seguida a resposta simplificada. No caso de não ser possível uma simplificação, deve ser apresentada a mesma resposta após o sinal de igualdade.

Considerando N1 e D1 como numerador e denominador da primeira fração, segue a orientação de como deverá ser realizada cada uma das operações:

Soma: (N1*D2 + N2*D1) / (D1*D2)

Subtração: (N1*D2 - N2*D1) / (D1*D2)

Multiplicação: (N1*N2) / (D1*D2)

Divisão: (N1/D1) / (N2/D2), ou seja (N1*D2)/(N2*D1)

Linguagem: C

Solução:

#include <stdio.h>
int mdc(int x, int y) {
    if (x < y) {
        int troca = y;
        y = x;
        x = troca;
    }
    if (x % y == 0)
        return y;
    return mdc(y, x % y);
}
int main() {
    int n, num1, den1, num2, den2, numFinal, denFinal, menor;
    char op1, op2, op3;
    scanf("%d", &n);
    while (n--) {
        scanf("%d %c %d %c %d %c %d", &num1, &op1, &den1, &op2, &num2, &op3, &den2);
        switch (op2) {
            case '+':
                numFinal = den2*num1 + den1*num2;
                denFinal = den1*den2;
                break;
            case '-':
                numFinal = den2*num1 - den1*num2;
                denFinal = den1*den2;
                break;
            case '*':
                numFinal = num1*num2;
                denFinal = den1*den2;
                break;
            default:
                numFinal = num1*den2;
                denFinal = num2*den1;
                break;
        }
        menor = mdc((numFinal < 0? -numFinal : numFinal), denFinal);
        printf("%d/%d = %d/%d\n", numFinal, denFinal, numFinal/menor, (!numFinal? 1 : denFinal/menor));
    }
    return 0;
}

URI - 1022 - Estruturas e Bibliotecas - TDA Racional - C++

Plataforma: URI

Problema1022

Enunciado:

A tarefa aqui neste problema é ler uma expressão matemática na forma de dois números Racionais (numerador / denominador) e apresentar o resultado da operação. Cada operando ou operador é separado por um espaço em branco. A sequência de cada linha que contém a expressão a ser lida é: número, caractere, número, caractere, número, caractere, número. A resposta deverá ser apresentada e posteriormente simplificada. Deverá então ser apresentado o sinal de igualdade e em seguida a resposta simplificada. No caso de não ser possível uma simplificação, deve ser apresentada a mesma resposta após o sinal de igualdade.

Considerando N1 e D1 como numerador e denominador da primeira fração, segue a orientação de como deverá ser realizada cada uma das operações:

Soma: (N1*D2 + N2*D1) / (D1*D2)

Subtração: (N1*D2 - N2*D1) / (D1*D2)

Multiplicação: (N1*N2) / (D1*D2)

Divisão: (N1/D1) / (N2/D2), ou seja (N1*D2)/(N2*D1)

Linguagem: C++

Solução:

#include <iostream>
using namespace std;
int mdc(int x, int y) {
    if (x < y) {
        int troca = y;
        y = x;
        x = troca;
    }
    if (x % y == 0)
        return y;
    return mdc(y, x % y);
}
int main() {
    int n, num1, den1, num2, den2, numFinal, denFinal, menor;
    char op1, op2, op3;
    cin >> n;
    while (n--) {
        cin >> num1 >> op1 >> den1 >> op2 >> num2 >> op3 >> den2;
        switch (op2) {
            case '+':
                numFinal = den2*num1 + den1*num2;
                denFinal = den1*den2;
                break;
            case '-':
                numFinal = den2*num1 - den1*num2;
                denFinal = den1*den2;
                break;
            case '*':
                numFinal = num1*num2;
                denFinal = den1*den2;
                break;
            default:
                numFinal = num1*den2;
                denFinal = num2*den1;
                break;
        }
        menor = mdc((numFinal < 0? -numFinal : numFinal), denFinal);
        cout << numFinal << "/" << denFinal << " = " << numFinal/menor << "/" << (!numFinal? 1 : denFinal/menor) << endl;
    }
    return 0;
}

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