ページ 11

すみません。2つめですが…課題教えてください!

Posted: 2012年1月28日(土) 14:24
by 背水の陣
問題2
あなたはプリンタの管理者である。プリンタには一日に消費する用紙数を記録する機能があり、 日付と消費用紙数をスペースを区切りとして
2008/4/1 3870
2008/4/2 2126
のように時系列で継続的に記録している。それぞれ 2008 年 4 月 1 日に 3870 枚、2008 年 4 月 2 日に 2126 枚消費したことを表している。時系列とは、新しいデータが一番最後に追記されるこ とを意味している。どの時期にプリンタがよく使われるのか、そしてどの時期にあまり使われ ていないかを調べることになったため、あなたは消費用紙数が多い順にデータを並べ変えるプ ログラムを作ることになった。プログラム名を(pc:paper consumption)とするとプログラム pc の仕様は以下である。

(1) 時系列の消費用紙数データを記録したファイルをコマンドラインで読み込んで、消費用紙 数が多い順に並び変えること。たとえば消費用紙数データを記録したファイル名が printer1.dat で与えられる時に、プログラムは以下のように使用する。サンプルデータファイ ル printer1.dat は課題ページにアップロードしてある。
ccx01:~/dsap11> pc printer1.dat

(2) 並び変えたデータは消費用紙数が多い順に
日付 空白 消費枚数 の順で標準出力(画面)に出力する。同じ枚数の日付が有る場合には、同じ行に横に並べる。 出力イメージは以下である。
2009/3/19
2008/8/16
2009/9/1
2009/8/1
2009/8/6
2011/2/17
2010/3/9
170 2010/8/21 170
169 2010/3/27 169
168
166 2010/11/22 166
165
164 163


再度申し上げますと、C言語は初心者です。
この課題については、何から始めたら良いのかすら分かりません。
(scanf ?で)コマンドラインを読み込む、読み込んだものを消費枚数の多い順に並び替え、出力する。
このイメージはできるのですが、プログラムそもそもの書き方が分かりません。

提出期限は明日となっており、苦戦していますが解決できません。
どうか、よろしくお願いします。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月28日(土) 14:42
by beatle
背水の陣 さんが書きました: 出力イメージは以下である。
2009/3/19
2008/8/16
2009/9/1
2009/8/1
2009/8/6
2011/2/17
2010/3/9
170 2010/8/21 170
169 2010/3/27 169
168
166 2010/11/22 166
165
164 163
この出力の意味が僕には良くわかりません.説明してもらえますか?

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月28日(土) 14:56
by 紫針
課題の丸投げはフォーラムルールで禁止されています
背水の陣さんがわからないところを教えてください

あと前の質問、解決したならそう書きこんでください

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月28日(土) 15:06
by みけCAT
背水の陣 さんが書きました: 出力イメージは以下である。
2009/3/19
2008/8/16
2009/9/1
2009/8/1
2009/8/6
2011/2/17
2010/3/9
170 2010/8/21 170
169 2010/3/27 169
168
166 2010/11/22 166
165
164 163
この出力に対応する入力例はありませんか?

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月28日(土) 15:08
by たかぎ
背水の陣 さんが書きました:この課題については、何から始めたら良いのかすら分かりません。
出力イメージが本当にこれで正しいのかどうか確認するところから始めましょう。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月28日(土) 17:33
by non
pdfファイルなどで与えられた課題をコピーして貼り付けたのでしょうか。
出力データは最初の7行の右側に次の7行がきそうですね。
それは、そうと急ぐと言いながら、スレッドを立てたきりで、マナーがなってないですね。
もうひとつのスレッドもそのままだし。最近このような質問者が増えてますね。
というより、授業で全く理解していない人が増えているというか。何のために大学や学校に
行っているのでしょうか?親父の嘆きです。

スレ主さん、はやく取り掛からないと間に合わないよ~

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 00:58
by 背水の陣
前回のトピックについて、ご返信をしていない状態になっていたようで申し訳ありません。
解決と、感謝の言葉を返信したつもりでしたが、上手く送信出来ていなかったようです。
すみませんでした。

また、出力イメージがおかしくなっていました。
申し訳ありません。
以下に訂正をさせてください。

また、授業についてですが、残念ながら初心者の私にはハイレベルでついていけませんでした。
C言語やプログラミングは勉強したいと強く思っていますが、
今回の授業は残念ながらそういった類のものではありませんでした。

ただ、何とか課題を解決していきたいと思っております。
是非、皆様のお力添えをいただけると助かります。
どうぞ、よろしくお願いします。


以下、訂正した出力イメージです。

(2) 並び変えたデータは消費用紙数が多い順に
日付 空白 消費枚数 の順で標準出力(画面)に出力する。
同じ枚数の日付が有る場合には、同じ行に横に並べる。 出力イメージは以下である。

2009/3/19 170 2010/8/21  170
2008/8/16 169 2010/3/27  169
2009/9/1 168
2009/8/1  166 2010/11/22 166
2009/8/6  165
2011/2/17 164
2010/3/9 163

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 09:25
by non
質問です。データの量に制限はありますか?オンメモリで一度に読み込める量でしょうか?
並び替えの方法について何か指示はありましたか?
また、言語はC(C90仕様)ですよね。
提出日は今日(日曜)ですか?何時まで?

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 10:59
by たかぎ
背水の陣 さんが書きました: 2009/3/19 170 2010/8/21  170
2008/8/16 169 2010/3/27  169
2009/9/1 168
2009/8/1  166 2010/11/22 166
2009/8/6  165
2011/2/17 164
2010/3/9 163
全角スペースが入ったり入らなかったりするようですが、どんなルールがあるのでしょうか?

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 12:29
by 背水の陣
すみません。
出力例では全て列が整った形でした。

送信の際に列を整えようとしましたが、うまくいきませんでした。
つまり、スペースには特に意味はありません。
混乱を与えてしまい申し訳ありません。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 13:06
by non
non さんが書きました:質問です。データの量に制限はありますか?オンメモリで一度に読み込める量でしょうか?
並び替えの方法について何か指示はありましたか?
また、言語はC(C90仕様)ですよね。
提出日は今日(日曜)ですか?何時まで?
午前中は暇だったので作ってあげようと思ったけど、レスがないので時間切れ。がんばってね。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 13:49
by たかぎ
とりあえず作ってみました。
言語不明、入力データの詳細不明なので、こちらで適当に決めました。

コード:

#include <cstdlib>
#include <stdexcept>
#include <utility>
#include <map>
#include <string>
#include <iostream>
#include <fstream>

int main(int argc, char* argv[])
try
{
	if (argc != 2)
		throw std::invalid_argument("no input files");
	std::ifstream ifs(argv[1]);
	ifs.exceptions(std::ios::badbit);
	std::multimap<unsigned long, std::string> m;
	std::string str;

	while (std::getline(ifs, str))
	{
		auto pos = str.find(' ') + 1;
		auto count = std::stoul(str.substr(pos));
		m.insert(std::make_pair(count, str));
	}
	for (auto first = m.crbegin(), last = m.crend(); first != last; )
	{
		auto count = first->first;
		do
		{
			std::cout << first->second;
			++first;
		} while (first != last && first->first == count && std::cout << ' ');
		std::cout << std::endl;
	}
}
catch (std::exception& e)
{
	std::cerr << argv[0] << ": " << e.what() << std::endl;
	return EXIT_FAILURE;
}

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 16:12
by かずま
たかぎ さんが書きました:言語不明、入力データの詳細不明なので、こちらで適当に決めました。
入力データは時系列とあり、出力イメージで同じ枚数の日付が行内でもやはり
時系列なっているんですが、たかぎさんのプログラムでは逆順になってしまいました。
おそらく multimap の key の sort が stable なのではないかと思われるので、
次のようにしてみました。

コード:

struct rulong {
    unsigned long x;
    rulong(unsigned long x) : x(x) { }
    operator unsigned ulong() const { return x; }
    bool operator<(const rulong y) const { return y.x < x; }
};
を追加し、
std::multimap<unsigned long, std::string> m; を
std::multimap<rulong, std::string> m; に、
for (auto first = m.crbegin(), last = m.crend(); first != last; ) を
for (auto first = m.cbegin(), last = m.cend(); first != last; ) に変えます。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 16:40
by かずま
かずま さんが書きました:

コード:

    operator unsigned ulong() const { return x; }
operator unsigned long() const { return x; } の間違いです。
でも、g++ 4.4.3 でコンパイルエラーにならなかったということは,
どこかで ulong が typedef されているんでしょうね。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 18:33
by たかぎ
かずま さんが書きました:入力データは時系列とあり、出力イメージで同じ枚数の日付が行内でもやはり
時系列なっているんですが、たかぎさんのプログラムでは逆順になってしまいました。
イメージはあくまでもイメージなので、まあいいかと考えました。
入力データに関しては、nonさんが指摘されているように量の問題があるのと、枚数の上限が見えないことですね。
さすがに一日に何十億枚も消費することはないだろうということでunsigned longにしました。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 18:39
by かずま

コード:

#include <stdio.h>
#include <string.h>

#define N 1000

struct { int count; char *date; } m[N];

int main(void)
{
    int i, n, count;  char date[16];

    for (n = 0; n < N && scanf("%s%d", date, &count) == 2; n++) {
        for (i = n; i > 0 && m[i-1].count < count; i--) m[i] = m[i-1];
        m[i].count = count,  m[i].date = strdup(date);
    }
    for (i = 0; i < n; i++)
        printf("%s %d%s", m[i].date, m[i].count,
            i+1 < n && m[i+1].count == m[i].count ? "\n" : "  ");
    return 0;
}
このプログラムは、次のようにいろいろ問題がありますが、参考にはなるかもしれません。
- 入力データファイルの指定がない
- データが 1000件に限られていて、超えた場合にメッセージも出ない。
- 標準関数でない strdup を使用し、かつエラーチェックも行っていない。

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 18:41
by たかぎ
日付も昇順にするのであれば、次のようにすればOKですね。

コード:

#include <cstdlib>
#include <stdexcept>
#include <utility>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include <functional>

int main(int argc, char* argv[])
try
{
	if (argc != 2)
		throw std::invalid_argument("no input files");
	std::ifstream ifs(argv[1]);
	ifs.exceptions(std::ios::badbit);
	std::multimap<unsigned long, std::string, std::greater<unsigned long>> m;
	std::string str;

	while (std::getline(ifs, str))
	{
		auto pos = str.find(' ') + 1;
		auto count = std::stoul(str.substr(pos));
		m.insert(std::make_pair(count, str));
	}
	for (auto first = m.cbegin(), last = m.cend(); first != last; )
	{
		auto count = first->first;
		do
		{
			std::cout << first->second;
			++first;
		} while (first != last && first->first == count && std::cout << ' ');
		std::cout << std::endl;
	}
}
catch (std::exception& e)
{
	std::cerr << argv[0] << ": " << e.what() << std::endl;
	return EXIT_FAILURE;
}

Re: すみません。2つめですが…課題教えてください!

Posted: 2012年1月29日(日) 18:50
by かずま
かずま さんが書きました:

コード:

            i+1 < n && m[i+1].count == m[i].count ? "\n" : "  ");
このプログラムは、次のようにいろいろ問題がありますが、参考にはなるかもしれません。
大問題がありました。 "\n" と " " が逆ですね。