問題の詳細はこちらより確認できる(要TopCoder登録)。
問題の大まかな訳は以下の通り。
コンピュータのインストール作業のプログレスバーを実装する。進捗状況に応じて"######.............."のように、#が終了部分、.が終了していない部分として、それらを用いて20文字で表すクラスshowProgressを作成せよ。taskTimes[]が作業一つのタスクにかかる時間、taskCompletedは先頭から順にいくつタスクを終えたかという数を示している。タスクの進捗状況はインストールにかけた時間/インストール終了までにかかる時間である。また、進捗状況の#の数は小数点以下を切り捨てた整数にする。taskCompletedはtaskTimesの要素数を上回らない1以上の数とする。
例えば、taskTimes={20,35,15}、taskCompleted=1とすると、20/(20+35+15)*20=40/7=5.7なので、#は5個、.は15個になる。
Javaで実装すると以下のようになった。
public class ProgressBar { public String showProgress(int[] taskTimes, int tasksCompleted) { int taskSum=0; int taskCompSum=0; for( int i=0 ; i<taskTimes.length ; i++){ taskSum += taskTimes[i]; } for( int i=0 ; i<tasksCompleted ; i++){ taskCompSum += taskTimes[i]; } int igetaNum = 20*taskCompSum/taskSum; int dotNum = 20-igetaNum; String result = ""; for( int i=0 ; i<igetaNum ; i++){ result = result + "#"; } for( int i=0 ; i<dotNum ; i++){ result = result + "."; } return result; } }
得点は235.80/250。素直な算数の実装なので、まずまずの速さ。上位者のコードでためになるものがあったので、メソッドだけ紹介。前回のArrays.sortに続いて、配列操作のメソッドを集めたクラスArraysが再度登場。
import java.util.*; public String showProgress(){ int done = 0, total = 0; for( int i=0; i<taskTimes.length ; i++ ){ total += taskTimes[i]; if( i<tasksCompleted ) done += taskTimes[i]; } char[] r = new char[20]; Arrays.fill(r, '.'); Arrays.fill(r, 0, done * 20 / total , '#'); return new String(r); }
メモリの節約方法で参考になったものがあったのでこちらも紹介。Stringクラスは値が変更されると、別のメモリ領域に変更された値を割り当てるので、提出したコードのように、Stringクラスの変数に1文字ずつ追加するコードだとメモリを無駄に利用してしまうのである。以下のコードはそれに対策を施したものである。
StringBuffer buf = new StringBuffer(""); for( int i=0 ; i<20 ; i++ ){ if( i<igetaNum ){ buf.append("#"); }else{ buf.append("."); } } return buf.toString();
上位の人の書き方にはArrays.fillを使っているものが多かった。行数も少ないし、可読性が高く参考になる。
0 件のコメント:
コメントを投稿