[白俊アルゴリズム]平均値を超えるでしょう


ソース
白駿-平均を超えるでしょう。

🔎 質問する


大学生の新入生の90%が、自分がクラスにいる平均数を超えたと考えている.
あなたは彼らに悲しい真実を伝えるべきだ.

🚫 入力と出力


<入力>
第1行は、試験例の個数Cを与える.
2行目から、各テストケースには、学生数N(1≦N≦1000、Nは整数)の最初の数字が与えられ、次いでN名の点数が与えられる.
分数が0以上、100以下の整数.
<出力>
それぞれの場合、平均値の1行を超える学生の比率を四捨五入し、小数点を3位に出力します.

💻 I/O例



📄🤔 コードと解釈プロセス


🔹 1番

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Baekjoon4344 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int c = Integer.parseInt(br.readLine());

		int[][] cases = new int[c][];
		int[] scoreArr = null;
		for (int i = 0; i < c; i++) {
			String[] input = br.readLine().split(" ");
			scoreArr = new int[input.length];
			for (int k = 0; k < input.length; k++) {
				scoreArr[k] = Integer.parseInt(input[k]);
			}
			cases[i] = scoreArr;
		}
		
        	int sum, count;
		double avg;

		for (int i = 0; i < c; i++) {
        		sum = 0; avg = 0; count = 0;
			for (int k = 1; k < cases[i].length; k++) {
				sum += cases[i][k];
			}
			avg = (double)sum / cases[i][0];
			for (int k = 1; k < cases[i].length; k++) {
				if(cases[i][k] > avg) count++;
			}
			System.out.printf("%.3f%%\n", (count / (double)cases[i][0] * 100));
			
		}
	}
}

🔸 1号解


最初のコードは
入力した各キャビネットをint型に分割します.
scoreAr配列で
各ケースのスコアを保存するケースの配列に入れます.
次に、次のfor文で各ケースの点数の和を求め、平均値を求めます.
平均点と点数を比較し,平均点より高い点数を算出した.
そしてcountとcaseの点数を100で割った
問題における所望の出力結果に従って出力した.
これらの論理を通過した.
メモリ13584 KB/処理時間144 ms.
通過しましたが、残念な点が多いようです.
コードを修正することにしました.

🔹 2番

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Baekjoon4344 {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
        
		int c = Integer.parseInt(br.readLine());
		int[][] cases = new int[c][];
		int[] scoreArr = null;
	    	double[] avg = new double[c];
		double sum;
		int num, score, scoreCount; 
		
		for (int i = 0; i < c; i++) {
			st = new StringTokenizer(br.readLine());
			scoreCount = st.countTokens();
			scoreArr = new int[scoreCount];
			num = 0; sum = 0;
			while (st.hasMoreTokens()) {
				score = Integer.parseInt(st.nextToken());
				if(num != 0) { sum += score; }
				scoreArr[num++] = score;
			}
			cases[i] = temp;
			avg[i] = sum / (scoreCount-1);
		}
        
		double count;
		for (int i = 0; i < c; i++) {
			count = 0;
			for (int k = 1; k < cases[i].length; k++) {
				if(cases[i][k] > avg[i]) count++; 
			}
			System.out.printf("%.3f%%\n", (count / cases[i][0] * 100));
		}
	}
}

🔸 第二題


今回はStringTokenizerを使った経験はほとんどありません.
勉強のためにsplitの代わりに使いました.
複雑な文字列グループ化を行う場合はsplitを使用することが望ましい.
split正規化式を使用する単純な文字列分割:
StringTokenizerの速度はもっと速いです.
旧時代の遺物とも言われるStringTokenizer.
状況に応じて何かを使ってより良い結果を生み出すことができれば.
無視すべきではなく、よく勉強し、よく利用すべきだと思います.
StringTokenizer以外にfor文も多すぎるようです少し減らすために
スコアの和と平均値を上のfor文に加算し,繰返し回数を減らした.
このほか、繰り返し文にはcast演算子による変換もあります.
sumとcountを二重形として使用して、異形変換を除去します.
cast演算子は必要ありません.
結果は1348 KB/処理時間124ミリ秒に減少した.
StringTokenizerをほとんど使っていないからかわかりませんが
1番コードより汚く、読みやすさが悪い感じがします.
コードの可読性と不要なコードを減らすために
もう一度挑戦しました.

🔹 3番

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st = null;
		int c = Integer.parseInt(br.readLine());

		int[] scoreArr = null;
		double sum, avg, count;
		int score, scoreCount;

		for (int i = 0; i < c; i++) {
			st = new StringTokenizer(br.readLine());
			scoreCount = Integer.parseInt(st.nextToken());
            
			scoreArr = new int[scoreCount];
			sum = 0;
			for (int k = 0; k < scoreCount; k++) {
				score = Integer.parseInt(st.nextToken());
				sum += score;
				scoreArr[k] = score;				
			}
			avg = sum / scoreCount;
			count = 0;
			for (int k = 0; k < scoreCount; k++) {
				if(scoreArr[k] > avg) count++; 
			}
			bw.write(String.format("%.3f%%\n", count / scoreCount * 100));
		}
		bw.flush();
		bw.close();
		br.close();
	}
}

🔸 第三題


この3番のコードが完成する前に、数十回コードを交換したようです.
読みやすさを向上させるために、初めて構造を分解して修理します.
不要なストレージを回避するためにcase配列を削除した.
上下2つのドアもあります.
歯を合わせた.
ドアを二つに分ける理由は
同じドアに出力を入力すると、問題が発生するからです.
入力と出力は、すべての入力を受信してから正常に入力と出力される必要があります.
既存のコードでfor文を1つに結合すると、入力が受信されます.
次の入力を受信する前に出力
最後の入力が正常でないという問題があります.
したがってprintlnのようにすぐに出力するのではなく、ある場所に格納されます.
一度に印刷する方法はありますか?します
BufferedWriterというソリューションを思いついた.
BufferedWriterは書き込み時のみバッファに保持されます.
出力するにはリフレッシュが必要なので利用します
入出力for文を1つにまとめる
彼はドアの中で一言だけ書いたので、ドアに着いたら、水を流した.
既存の問題を解決しました!
BufferedReaderの速度はprintlnより速い.
不要な浪費を減らし、
メモリ13284 KB/処理時間116ミリ秒.
コードもより簡潔:

😳❕ 感想&感想


知っているのは力だ!
この言葉はどんな分野でも通じる.
これは開発者にとって本当に重要だと思います.
1段目のコードや2段目のコードを見ると、本当に不要なところがたくさんあります.
私自身もコードを書いています.「これは本当に最善の方法ですか?」
彼は自分のコードに非常に不満を持っている.
StringTokenizerをもう一度勉強したいのですが、
Buffered Writerを思い出して利用しました
より簡潔なコードとより速い処理速度を得ることができます.
もちろん、最後に書いた3番コードも不要な部分があります.
より優れた機能を備えたAPIとクラスの利用
より速く、より効率的なコードを書くことができるかもしれません.
だからこれからももっと良い知識を吸収しなければなりません.
努力を止めないで、それを利用できる開発者になります.:)