Algoritmo com a classe Random

Olá a todos GUJ!!! Boa noite. Pessoal eu tenho um algoritmo que usa a classe Random que em partes eu consegui fazer e outras coisas(por pouco conhecimento sobre a classe Random) que pede nesse algoritmo eu não consegui resolver. O algoritmo é esse:

Uma fábrica de auto-peças usa uma matriz 4x12 para armazenar a produtividade anual. Cada linha indica uma semana e cada coluna indica um mês. A tabela abaixo ilustra um exemplo desta matriz.
(VER IMAGEM)
Escreva um programa que gere randomicamente esta matriz (valores menores que 90) e em seguida calcule e mostre:
a) O total de peças produzidas em cada mês.
b) A produção do ano.
c) A melhor produção semanal de todas as semanas e, em que semana e em que mês ela ocorreu.

E o que eu consegui fazer foi isso(pode ser que em algumas coisas eu errei nesse algoritmo ou tem uma forma melhor pra mim fazer ele, mas daí eu não sei):

package calc.produção;

import java.util.Random;

public class Producao {

public static void main(String[] args) {
	// TODO Auto-generated method stub
	
	int x [] = new int[12]; // x é a quantidade de meses
	int y,z; // y é a produção mensal e z a melhor produção semanal
	int resultado;
	
	Random gerador = new Random();
	
	for (y = 0; y < x.length; y ++) {
	System.out.println(gerador.nextInt(89));

}
}

As minhas dúvidas são:

1 - Como que eu conseguiria fazer o cálculo de produção anual de peças utilizando a classe Random ou para esse cálculo eu precisaria instanciar uma outra classe?

2 - Como também eu conseguiria pegar e mostrar a melhor produção semanal de peças da classe Random?

3 -Como está escrito no meu código acima, eu estou usando o System.out.println pra imprimir os resultados no console, será que não seria melhor usar a classe JOptionPane.showMessageDialog?

Quem pode me ajudar, por favor?

Onde está a imagem?[quote=“Eder32, post:1, topic:351255”]
package calc.produção;
[/quote]

Não use acentos ao nomear as coisas do código.

A classe Random será usada apenas para preencher a tabela. Depois disso, você precisará pegar os dados dela e efetuar cálculos e comparações (ifs) normais sobre eles.

você pode criar métodos assim:

/**Retorna um Map onde a chave é o nome de um mês e o value é o total de peças produzidas neste mês*/
public Map<String, Integer> obterTotalDePecasProduzidasEmCadaMes() {...}

/**Retorna o total de peças produzidas no ano (é isso mesmo que se deseja?)*/
public int calcularProducaoAnual() {...}

/**Retorna um Objeto com: a melhor produção semanal de todas as semanas e, em que semana e em que mês ela ocorreu.*/
public ProducaoSemanal getMelhorProducaoSemanalDeTodasAsSemanas() {...}

A Classe “ProducaoSemanal” simplesmente tem os atributos “int producaoNestaSemana”, “int idDaSemanaNoMes” (semana 1 do mês, 2 do mês, 3 do mês, ou 4 do mês), e “String mesQueTemEstaSemana”.

Cada um desses métodos será usado para atender a um dos requisitos a), b) e c), e, cada um precisará ler a Tabela preenchida através de Random.

Criar e prencher a Tabela usando Random é a primeira coisa que seu código fará, e será a única coisa usando Random (os métodos acima não usarão Random).

Por enquanto muito obrigado pelas respostas, Douglas. Eu vou enviar a imagem da tabela que ilustra um exemplo desta Matriz

Essa tabela e o enunciado estão praticamente te dizendo que você deve criar uma matriz bidimensional, como “int[][] tabela = new int[4][12];”, mas eu provavelmente não faria assim, iria criar uma Classe “Tabela”.

Entendi, mas porque criar uma classe Tabela? O código ficaria mais enxuto ou por qual razão criar uma classe tabela? E como seria instanciar a classe tabela?

Você só precisa da classe Random para gerar os números aleatoriamente.

  1. Para calcular o total de peças produzido em cada mês, é só você percorrer as colunas da matriz somando os valores das linhas. A soma das linhas de cada coluna representa o total do mês.

  2. A produção do ano é a soma de todos os valores da matriz.

  3. É só procurar o maior valor na matriz, e de acordo com a linha e coluna você sabe responder a semana e o mês.

Para terminar, deixo aqui um desafio para os curiosos, envolvendo a resolução do problema desse post. Esse programa cria uma matriz com tamanho 10000x10000, e a percorre duas vezes. Na primeira, percorre linha a linha (ou semana a semana). Na segunda, percorre coluna a coluna (ou mês a mês). Porque a segunda forma demora cerca de 30x mais tempo para executar? :zipper_mouth:

class Main {
    public static void main(String[] args) {
        int N = 10000;
        int x[][] = new int[N][N];

        long startHorizontal = System.currentTimeMillis();

        for(int i = 0; i < N; i++)
            for (int j = 0; j < N; j++) 
                int val = x[i][j];

        long endHorizontal = System.currentTimeMillis();
         /* ------------------------------------------- */
        long startVertical = System.currentTimeMillis();

        for(int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                int val = x[j][i];

        long endVertical = System.currentTimeMillis();

        System.out.println("Tempo de execucao variando as colunas: " + (endHorizontal - startHorizontal) + " ms");
        System.out.println("Tempo de execucao variando as linhas: " + (endVertical - startVertical) + " ms");
    }
}

Criaria uma classe tabela por motivos como:

  • Ficaria mais fácil entender o código e a estrutura dos dados. Por exemplo, numa matriz int[][] como você vai saber que a primeira dimensão é da semana e não do mês? afinal, ao ver uma variavel int[][] chamada “tabelaComRelatorioAnual” ela pode ser int[4][12] ou int[12][4]. Além disso, não fica explicito que esta matriz esta guardando uma Tabela com esses dados, uma Classe com bom nome e bons nomes de métodos deixaria tudo isso explicito;
  • Você pode garantir a validação dos dados, como evitar inserir valores negativos (faria sentido a fábrica produzir -5 peças? Não!);
  • Você pode criar métodos para obter exatamente o que você quer, encapsulando, sem precisar de código externo que teria uma “intimidade inapropriada”; assim você foge do “Modelo Anêmico” e da programação procedural (vc não precisa entender isso agora);

Criar uma Classe pra isso pode te trazer vários benefícios e é uma abordagem mais O.O., mas não vai deixar o código mais enxuto, pelo contrário, vc vai ter mais código e a aplicação ficará mais complexa (o que são os pontos negativos).

Muito obrigado IvBarbosa!!! Uma pergunta: para fazer a soma dos valores das linhas de cada coluna, o melhor ou pra especificamente esse algoritmo seria usar o Random pra gerar números fixos, né?

@lvbarbosa imagino que tenha a ver com a forma como as matrizes são estruturadas, uma matriz bidimensional deve ser uma “matriz de matrizes”, ou seja, tem uma matriz em cada índice.

Na primeira forma vc pega uma matriz interna, percorrendo essa matriz interna até finalizar, então pega a próxima. Como a matriz interna foi toda carregada na memória e é percorrida até o fim, há melhor desempenho.

Na segunda, vc pega a matriz interna, pega o que tem no primeiro indice, e então vai pra proxima matriz interna, e pega o que tem no primeiro indice, e segue assim… depois de percorrer todas as matrizes vc volta a pegar a primeira e então pega o que ela tem no segundo indice, e vai seguindo assim. Isso de pegar a matriz interna pra pegar só o o que tem em um indice e jogá-la fora do heap deve entupir o heap de matrizes e pressionar o Garbage Colector.

É isso?

int[][] matriz = new int[4][12];

    Random gerador = new Random();

    for (int semana = 0; semana < 4; semana++) {
        for (int mes = 0; mes < 12; mes++) {
            matriz[semana][mes] = gerador.nextInt(90) + 1;
        }
    }

    int producaoMes = 0, maior = matriz[0][0], l = 0, col = 0;
    
    for(int semana = 0; semana < 4; semana++){
        for(int mes = 0; mes < 12; mes++){
            producaoMes += matriz[semana][mes];
            
            if(matriz[semana][mes] > maior){
                maior = matriz[semana][mes];
                
                l = semana;
                col = mes;
            }
        }
    }
    
    int producaoAno = producaoMes * 12;

    System.out.println("O total de peças produzidas em cada mês: " + producaoMes
            + "\nA produção do ano: " + producaoAno
            + "\nA melhor produção foi de " + maior + " peças e ocoreu na semana " + l + " do mês: " + col);

Você está falando de usar Random na hora de fazer a soma dos valores das linhas de cada coluna? [quote=“Eder32, post:8, topic:351255”]
para fazer a soma dos valores das linhas de cada coluna, o melhor ou pra especificamente esse algoritmo seria usar o Random pra gerar números fixos, né?
[/quote]

Como eu disse, vc só usa Random pra preencher os dados da tabela, depois esquece o Random. Crie um método pra preencher a tabela (isso se vc for usar matriz mesmo), ele vai ser o único a usar Random, e será o primeiro a ser chamado.

Tem a ver, mas não é exatamente isso. Chegou bem perto. A matriz inteira já está na heap a partir do momento que a gente usa o new int[N][N]. Pular de um endereço pro outro, em termos de memória RAM, deveria custar o mesmo tempo.

O que será que é diferente, então? :stuck_out_tongue:

Uma dica: começa com C.

Certo Douglas, isso eu entendi( só usar a classe Random pra preencher os dados da tabela), portanto, a minha dúvida não é quanto a isso. Por eu ter estudado um pouco a Classe Random, eu aprendi que a mesma gera diversos tipos distintos de números aleatórios, um tipo é, por exemplo: ESPECIFICANDO A SEMENTE, ou seja, o programa sempre gerará os mesmos números(números fixos) para a sequência a cada execução, e esse algoritmo, por se tratar da produtividade anual duma fábrica de auto-peças que usa uma matriz 4x12, eu fiquei com a seguinte dúvida: a forma do Random que eu vou usar pra preencher os dados da tabela não seria um pra gerar sequências fixas ao invés de um pra gerar sequências aleatórias?

Por exemplo: Listagem 3: Especificando a semente

import java.util.Random;

public class Random3 {

public static void main(String[] args) {

	//instância um objeto da classe Random especificando a semente
	Random gerador = new Random(19700621);
    
	//imprime sequência de 10 números inteiros aleatórios entre 0 e 25
    for (int i = 0; i < 10; i++) {
    	System.out.println(gerador.nextInt(26));
	 }
}

}

Neste caso, o programa sempre gerará os mesmos 10 números para a sequência a cada execução.

Execução do programa da Listagem 3

Ou pra o enunciado desse algoritmo, não importa ou não tem problema qual a forma do Random que eu vou usar, seja pra gerar sequências fixas ou pra gerar sequências aleatórias?

Olá Blayd2015!!! Eu testei o seu algoritmo aqui no ECLIPSE,compilou e executou certo. Muito obrigado pela sua resposta. Eu vejo que eu estava perdido por entender pouco sobre Matrizes. Mas Deus te abençoe e abençoe a todos que me ajudaram na resolução desse enunciado.

Eu que somente, até pouco tempo atrás, só tinha estudado e praticado linguagem procedural, como o pascal, agora que eu estou estudando o JAVA, por ser POO, eu estou apanhando um pouco pra aprender. Mas agradeço pela ajuda de todos

Se o enunciado ou seu professor pedir pra determinar os dados de entrada do algoritmo (que no caso são os dados da tabela) com Random, provavelmente se está pedindo isso para que você crie um algoritmo que possa ser testado e funcionar com diversos valores; basicamente deve ser pra impedir que você faça algo como “System.out.println("A produção do ano foi de 345 peças");”, onde você define a entrada e dá a resposta certa na saída sem processar nada, sem calcular, de modo que seu algoritmo não funcionaria no mundo real, pois não funcionaria com entradas diferentes.

Gerar números randômicos deve ser pra testar seu algoritmo com diferentes entradas, portanto, acredito que faz muito mais sentido vc não usar semente e deixar os valores serem randômicos a cada execução. Assim, a cada execução você poderia imprimir a tabela gerada e as saídas pedidas, e, seria possível verificar manualmente se a saída corresponde corretamente a entrada que foi gerada.

Mas imagino que seu professor só vai prestar atenção no código mesmo, observando seu código ele perceberá se vc fez certo ou não.