【漢文】読む順番から返り点

みなさん、学校などで習ったことをプログラムにしてみませんか?
プログラムの勉強にも、習ったことの復習にもなって一石二鳥かもしれません。
自分が投稿しまくるだけになったらすみません...
フォーラム(掲示板)ルール
トピック名はなるべく
[b]【教科/科目名】簡単な内容[/b]
の形にしてください。
重複したトピックはなるべく作らないよう気をつけてください。
(重複した内容を投稿したい時は返信の形でお願いします。
重複したからといって削除や移動は原則として行いません)
コードは正しくcodeタグで囲みましょう。
プログラミングの授業の内容ををそのままや移植して投稿するのはご遠慮ください。
間違っていたら返信で指摘してあげてください。
返信
アバター
Cr
記事: 93
登録日時: 8年前

【漢文】読む順番から返り点

#1

投稿記事 by Cr » 7年前

以前質問フォーラムのところで書き方など質問させてもらった奴です。
漢文の文字数、読む順番を入力すると、各漢字につく返り点(レ点、一二点、ハイフン)を改行区切りで表示します。

コード:

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;

string moji[8][10]={{"上","中","下"},
					{"一","二","三","四","五","六","七"},
					{"上","下"},
					{"甲","乙","丙","丁","戊","己","庚","辛","任","癸"},
					{"天","地","人"},
					{"元","亨","利","貞"},
					{"春","夏","秋","冬"},
					{"木","火","土","金","水"}
};

struct OneTwo
{
	int level;		//一、二、三の違い
	int nest;		//一、上、甲の違い
};

typedef vector<int> VecInt;
typedef vector<OneTwo> VecOneTwo;

void solve(int n ,VecInt turn_to_point ,VecInt next_point ,VecOneTwo *edge);
void PrintVector(VecInt vec);
void SetReadOrderToPoint(VecInt *turn_to_point ,VecInt next_point ,int n);


int main(){
//宣言
	VecInt turn_to_point;		//添え字:読む順番 	値:場所
	VecInt next_point;			//添え字:場所  	値:次の場所
	int n;						//漢文の文字数
	VecOneTwo edge;				//添え字:場所 	値:一二点系の返り点の種類

	
//入力
{
	cout <<"漢文の文字数を入力"<<endl;
	cin >> n;
	next_point.resize(n);

	cout << "漢文の読む順番を半角スペースで区切って入力"<<endl;
	for (int i = 0; i < n; i++)
	{
		int a;
		cin >> a;
		next_point[a-1] = i;
	}
}

//初期化
{
	for (int i = 0; i < n; i++){
		OneTwo start;
		start.level = -1;
		start.nest = -1;
		edge.push_back(start);
	}
	
	SetReadOrderToPoint(&turn_to_point, next_point, n);
}

	solve(n ,turn_to_point ,next_point ,&edge);//計算

//表示
{
	for (int i = 0; i < n; i++)
	{
	
		//レ点
		if (i != n && turn_to_point[i+1] == -1)	//次に進む場所が一つ前なら
			cout <<"レ";
		else
			cout <<"  ";
			
		//一二点系返り点
		if (edge[i].nest != -1)	//nestが初期値と違ったら
		{
			cout << moji[ edge[i].nest ][ edge[i].level ];	//一二点系返り点表示
			if (turn_to_point[i] == 1)		//一二点の後、行き先が一つ下なら
				cout <<"|";		//ハイフン表示
			else
				cout <<" ";
		}
		else
		{
			cout <<"   ";
		}
		cout<<":"<<endl;
	}
}

	return 0;
}



void solve(int n ,VecInt turn_to_point,VecInt next_point,VecOneTwo *edge){
//初期化
	int level = 0;
	int nest = 1;
	VecInt check_same_nest;

	for (int i = 0; i < n; i++)
	{
		if (turn_to_point[ next_point[i] ] >= -1)//返り点が連続しなかったら
		{
			check_same_nest.clear();	//データオール初期化
			level = 0;
			nest = 1;
			continue;
		}
		
		//一、上などだけがここから下の処理を受ける
		
		check_same_nest.push_back( next_point[i] );	//通った点を記録

		for (int now = next_point[i]-1; now > next_point[i+1]; now--)		//返り点の間に別の返り点があるかチェック
		{
			if ( (*edge)[now].nest >= nest)			//自分以上にnestの高いのがいれば
			{
				nest = (*edge)[now].nest + 1;		//それ+1を代入
			}
		}
				
		if ( (*edge)[ check_same_nest[0] ].nest < nest)  //昔のネストが今より低かった時
		{											
			for (int i = 0; i < check_same_nest.size(); i++)
			{
				(*edge)[ check_same_nest[i] ].nest = nest;	//過去の地点に今のネストを代入
			}
		
		}
		
//上下点処理
{		
		if (nest == 2)
		{
			switch (level)
			{
				case 1:			//返り点が計3つになったら
					nest = 0;		//上中下点へ(上点は変わらないので無視)
					break;
				case 2:			//返り点が計4つになったら
					nest = 3;	//過去のもさかのぼって甲乙点へ
					for (int i = 0; i < 2; i++)
					{
						(*edge)[ check_same_nest[i] ].nest=3;
					}
					break;
			}
		}
}
		

		OneTwo now;
		now.level = level;		//level引き継ぎ
		now.nest = nest;		//nestを引き継ぎ
		(*edge)[ next_point[i] ] = now;		//答えに代入

		now.level++;			
		(*edge)[ next_point[i+1] ] = now;	//返る場所にも返り点をつける ex:二,下

	}
		
}


void SetReadOrderToPoint(VecInt *turn_to_point, VecInt next_point, int n)//read_order_to_pointを初期化
{
	(*turn_to_point).resize(n);	

	for (int i = 0; i < n - 1; i++)
	{
		(*turn_to_point)[ next_point[i] ] = next_point[i+1] - next_point[i];//相対距離を代入
	}
	
	(*turn_to_point)[ next_point[n-1] ] = 0;//終点には0を代入
}

void PrintVector(VecInt vec)		//与えられた配列の全要素を表示
{
	for(int i = 0; i < vec.size(); i++)cout <<setw(2) <<internal <<vec[i] <<endl;
	cout <<endl;
}


アバター
みけCAT
記事: 6246
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 【漢文】読む順番から返り点

#2

投稿記事 by みけCAT » 7年前

Runtime Errorが出てしまいました。
http://ideone.com/SlP1A
入力のチェックはしたほうがいいと思います。
入力によっては解がないので、そのチェックもあったほうがいいと思います。
また、出力が変な場合もあります。

撃墜例
► スポイラーを表示
そもそも不正入力(チェックするべき)
► スポイラーを表示
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
Cr
記事: 93
登録日時: 8年前

Re: 【漢文】読む順番から返り点

#3

投稿記事 by Cr » 7年前

以前綺麗に書こうと書き方を書き直してるときにどうやらミスったっぽいです。
元のぐちゃぐちゃの読みづらいソースコードだと100の例以外は正しく出力されました。
綺麗な方のどこがミスなのか見比べてきます。

アバター
みけCAT
記事: 6246
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 【漢文】読む順番から返り点

#4

投稿記事 by みけCAT » 7年前

撃墜例を追加します。

コード:

20
20 18 16 14 12 10 8 6 4 2 1 3 5 7 9 11 13 15 17 19
→RE
ネストが深すぎるので、できないと出力するべきです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

“習ったことをプログラムで表してみよう!” へ戻る