- PR -

お手本になるようなソースコード

投稿者投稿内容
Anonymous Coward
会議室デビュー日: 2007/05/09
投稿数: 8
投稿日時: 2007-05-10 00:44
こんばんは。日頃この会議室は参考にさせて頂いております。

この会議室の基本的な図式は、初心者(そうでない方も)の質問に、
知識/経験豊かな方々が回答していく、というものです。

そして回答者の中には、非常に優秀な技術者と見受けられる方々が大勢いらっしゃいます。
そういった方々は、一体どんなソースコードを書くのか、非常に興味があり、スレを立てさせて頂きました。
#中にはご自身のブログやサイトをお持ちで、その中でソースコードを拝見できる場合もありますし、
#この会議室の各スレッド内にもサンプルコードがたくさんありますが、
#今回は教育向けの簡単なお題に対する理想解を一箇所に固めてみたいと思いました。

基本的な流れとしては、

(1)誰かがお題を出す⇒(2)誰かが解を示す
⇒(3)問題や改良の余地があれば誰かが突っ込む⇒(4)突っ込み者または他の誰かがより良い解を示す
⇒(3)(4)がループ⇒(5)落ち着いたら誰かが別のお題を出す⇒(1)に戻る

みたいになれば良いな、と考えております。

言うまでもないことですが、理想解は一つとは限りません。
拡張性、可読性、実行速度、生産性など、何を優先するかによっても変わってくると思います。

なお、使用するプログラミング言語は基本的にはなんでも構いませんが、
できれば型の概念があり、使用人口の多いメジャーなものを希望します。

また、お題は解が1投稿で収まる程度の、教育向けのものを希望します。
#お題を考えるのがある意味いちばん難しいかもしれません。

最初のお題は、恐縮ながら私から出します。
テスト的な意味も兼ねまして、極々簡単なものにします。

<お題>
第一引数が0以上の整数であれば、
その表す金額を日本円で現金化したときに、
その枚数が最小となる紙幣と硬貨の組み合わせを、
標準出力に出力するコンソールアプリケーションを作ってください。

例)1625⇒1000*1+500*1+100*1+10*2+5*1

なお、表示形式は例と同じでなくて構いません。
わかりやすければどんな形式でも良いです。


最後に、私はこのスレの内容を自分の所属する組織の教育に活用しようとか、
あるいは何らかの営利を目的として立てたわけではありません。
息抜き/頭の体操として捉えて頂ければ幸いです。
それでは、よろしくお願い致します。
さいくろう
大ベテラン
会議室デビュー日: 2005/11/19
投稿数: 170
お住まい・勤務地: 川崎市
投稿日時: 2007-05-10 01:08
引用:

Anonymous Cowardさんの書き込み (2007-05-10 00:44) より:

最後に、私はこのスレの内容を自分の所属する組織の教育に活用しようとか、
あるいは何らかの営利を目的として立てたわけではありません。


ごめんなさい。m(_ _)m
目玉も性根も腐っている私には、褒め殺しにしか見えないです。

[ メッセージ編集済み 編集者: さいくろう 編集日時 2007-05-10 01:13 ]
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-05-10 01:16
引用:

Anonymous Cowardさんの書き込み (2007-05-10 00:44) より:
この会議室の基本的な図式は、初心者(そうでない方も)の質問に、
知識/経験豊かな方々が回答していく、というものです。



私はここは「教室」ではなく「会議室」だと認識しています。
あげられた議題について議論する場であり、回答を請う場ではないと解釈しています。
ですから「誰か教えて」というスレッドや「誰か私の代わりに解決して」といった
スレッドについては辛らつな返答が返ってくる傾向にあるのではないでしょうか。

ただし、自力でなにかをしようという人に対しては比較的親切にアドバイスする
というものだとも思っています。(少なくとも私はそのようにしてきたつもりです)

引用:

(1)誰かがお題を出す⇒(2)誰かが解を示す
⇒(3)問題や改良の余地があれば誰かが突っ込む⇒(4)突っ込み者または他の誰かがより良い解を示す
⇒(3)(4)がループ⇒(5)落ち着いたら誰かが別のお題を出す⇒(1)に戻る

みたいになれば良いな、と考えております。



教育的な意義があるのであれば面白そうだと思いますね。

[quote]
<お題>
第一引数が0以上の整数であれば、
その表す金額を日本円で現金化したときに、
その枚数が最小となる紙幣と硬貨の組み合わせを、
標準出力に出力するコンソールアプリケーションを作ってください。

例)1625⇒1000*1+500*1+100*1+10*2+5*1
[quote]

眠くて頭が働いていませんが、僭越ながらコードを書くとすれば
コード:
// 入力値
int input = 1625;
// 紙幣、硬貨の単位
int[] unit = new int[]{10000, 5000, 2000, 1000, 500, 100, 50, 10, 5, 1};
int[] count = new int[unit.length];
for (int i=0; i<unit.length; i++) {
  count[i] = input / unit[i];
  input %= unit[i];
}


ってな感じでしょうか。デバッグはしていません。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-05-10 01:16
お遊びでやってみた。
コード:
public class Test {

	static int[] units = { 10000, 5000, 1000, 500, 100, 50, 10, 5, 1 };

	public static void main(String[] args) {
		out(56547, 0);
	}

	static void out(int money, int index) {
		if (money <= 0) {
			return;
		}

		int unit = units[index];
		int count = money / unit;
		if (count > 0) {
			System.out.println(unit + "=" + count);
		}

		out(money - (unit * count), index + 1);
	}
}

unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-05-10 10:20
引用:

Anonymous Cowardさんの書き込み (2007-05-10 00:44) より:
<お題>
第一引数が0以上の整数であれば、
その表す金額を日本円で現金化したときに、
その枚数が最小となる紙幣と硬貨の組み合わせを、
標準出力に出力するコンソールアプリケーションを作ってください。

例)1625⇒1000*1+500*1+100*1+10*2+5*1


(1) 「その枚数が最小」というのが自明なような気もするけど、設計段階かコーディングの時点のどこかで、アルゴリズムを考えてそれが正しいことを証明しないといけないわけですよね。こういうアルゴリズムレベルの仕様はどう書けばいいもんでしょう。
(2) この仕様どおりに作った後、運用直前になって、「あっ、2千円札の扱いはどうするんだ?」などで、そういった仕様の抜けが発覚して悩むかも。(2千円札の存在そのものを無視するのなら楽ですが。)

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
TAD
ベテラン
会議室デビュー日: 2007/03/20
投稿数: 52
お住まい・勤務地: 海のそば
投稿日時: 2007-05-10 10:40
組み込み野郎は割り算が嫌い(笑)。ライブラリも出来るだけ使わない。
まぁ、そんなのが気になる場合はprintfすら使えないことの方が多いけど、一応"コンソールアプリケーション"ということなので。
とりあえず変数をintにしたんで入力の桁数はシステムのintのサイズにご注意。
printfをなんとかすればハンドコンパイル&アセンブルも可?


そういえばこういうアルゴリズムでお釣りの計算をするのが主流の国もあると聞いたことがあったけか。

コード:
#include <stdio.h>

#define ERR_ARG -1;
/* #define NULL 0;*/ /* コンパイラによっては必要 */

/* 2000円札は必要に応じて */
const int units[] = { 10000, 5000, /* 2000,*/ 1000, 500, 100, 50, 10, 5, 1, 0};

int main( int argc, char** argv){
	int i=0;
	int input=0;
	char* inPtr;
	/* 入力取得 */
	if(argc<2){
		return ERR_ARG;
	}
	inPtr=argv[1];
	while( *inPtr ){
		if( '0' <= *inPtr  && *inPtr <='9' ){
			input *= 10;
			input += *inPtr++ - '0';
		} else {
			return ERR_ARG;
		}
	}

	/* 計算本体 */
	while( units[i]){
		int count;
		count=1;
		while( input >= count*units[i] ){
			count++;
		}
		if(count>1){
			--count;
			printf( "%d x %d\n", units[i], count);
			input -= count*units[i];
		}
		i++;
	}
	return 0;
}


#プレビューの度に\が増えていくんだけどどうやってエスケープするんだろ...
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-05-10 11:03
引用:

unibonさんの書き込み (2007-05-10 10:20) より:
(2) この仕様どおりに作った後、運用直前になって、「あっ、2千円札の扱いはどうするんだ?」などで、そういった仕様の抜けが発覚して悩むかも。(2千円札の存在そのものを無視するのなら楽ですが。)



だから紙幣・硬貨について配列で定義しているわけですよね。
変更がありそうな箇所は一箇所にまとめてメンテナンス性を確保しているわけです。
米ドルにするのであれば
int[] units = new int[]{10000, 5000, 2000, 1000, 500, 200, 100, 50, 25, 10, 5, 1};
となりますし。
ドル-セントのような処理は入っていないのでセント単位になっています(苦笑)
まじめに実装するならこの部分を外から受けるようにもできます。
ただし、外から受け取る場合は大きい順にソートしてやらないといけませんね。

# ちなみに私のコードは「デバッグしていないJava」です

> Anonymous Coward氏
ここの会議室ではお題を決めたからあとはよろしく!って感じの
投げっぱなしのスレッドは好かれませんので適時コメントするなりしてくださいね
shimix
ぬし
会議室デビュー日: 2004/08/05
投稿数: 512
お住まい・勤務地: 大分市
投稿日時: 2007-05-10 11:10
言語指定がないようですので、ちょっとDelphiで書いてみました。

#メジャーな言語ではないですけどね(汗

コード:

program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
const unitcnt = 9;
const units:array[1..unitcnt]of integer =(10000, 5000, 1000, 500, 100, 50, 10, 5, 1);
var
i: integer;
money: integer;
begin
money := strtointdef(paramstr(1),0);
if money = 0 then exit;
for i := 1 to unitcnt do
begin
writeln(inttostr(units[i]) + ':' + inttostr(money div units[i]));
money := money mod units[i];
end;
end.



[ メッセージ編集済み 編集者: shimix 編集日時 2007-05-10 11:13 ]

スキルアップ/キャリアアップ(JOB@IT)