質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

2回答

2545閲覧

条件判定のifブロックを含むテキストを処理するための定石的な手法、またはアイディアをご教示ください。

jun68ykt

総合スコア9058

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

2クリップ

投稿2015/05/20 02:58

こんにちは。

いつもお世話になっております。
首題の件ですが、質問の前提を説明するために長文になりました。何卒、ご了承ください。

質問の趣旨としては、後述するある問題(要件)を解決するために、

(1) 情報科学の何らかの分野の教科書に載っているような、よく知られている定石となっている
アルゴリズムやデータ構造があればご教示ください。

⇒ 定石というのは、たとえば、「あるオブジェクトの配列をソートしたいときは、クイックソート
という定石を使える。(なので、そのオブジェクト(のクラス)に比較演算子を定義すればよい。)」
というのと同様に、という趣旨です。

(2) 定石といえるほどの知られ方でなくても、その問題(要件)を解決するには、こういうデータ構造
(やクラス設計)なら良質なコードとして実装できるというようなアイディアがあれば、ぜひ
ご教示ください。(「こうすればうまくいく気がする」レベルでもかまいません。)

というものになります。

まず、説明の便宜上、問題(要件)を満たすプログラムの名前を、

IF-Reducer(IFブロック減少器)

と称します。
このように称する理由は、以降の説明にある、仕様(9)で明らかになります。
(もっとぴったりした名前があるかもしれませんが、とりあえず、以降の説明では
このように称します。)

IF-Reducerの仕様は以下です。

仕様(1):2つのテキストファイルAとBを入力として受け取ります。

仕様(2):1つのテキストファイルCを出力します。

仕様(3):入力として受け取る2つのファイルのうちの1つAと、出力されるCは、通常の
可読な文字(半角英数字+全角文字)による文字列が並んでいるテキストの中に
IFタグと呼ばれる制御構文が挿入されています。

仕様(4):AとCは、上記のように、通常のテキストに制御構文が入っていることから、
便宜上、「テンプレートファイル」または単に「テンプレート」と呼びます。

仕様(5):AとCに挿入されるIFタグは以下の形式をとります。

**{if $<変数>}**

または、
{/if}

・ただし、上記で、<変数>は、通常のプログラミング言語での識別子として
有効な文字列を指定します。

・タグの文字列としての形式は、Smartyの{if と類似するものです。

・以下はテンプレートファイルの一例です。

lang

1打ち合わせメモ 2{if $header} 3 {if $date}2015/05/20{/if} 4新プロジェクトの体制について 5{/if} 6参加者:田中、鈴木

上記のように、{if と {/if がプログラミング言語のように入れ子になって
ブロック構造を構成します。

仕様(6):入力されるもう1つのファイルBは以下のような形式の行

$<変数名>=(true|false)

が0以上並んでいるものとします。また、= の前後には任意の数のタブおよびスペースを
許容します。

説明の便宜上ファイルBのことを変数定義ファイル(または単に変数ファイル)と呼びます。
以下は変数定義ファイルの一例です。

変数定義ファイル(例1)

lang

1$header = true 2$date = false

仕様(7):IF-Reducerは、上記で例示したテンプレートファイルと、変数定義ファイルを読み、
以下を出力します。

lang

1打ち合わせメモ 2 3新プロジェクトの体制について 4参加者:田中、鈴木

上記のように、IF-Reducerは、テンプレートAに出現する {if タグの<変数>を
変数定義ファイルから trueなのかfalseなのかを解決し、かつ、そのifを囲む
(親の)ifブロックがあれば、その真偽も考慮して、{ifブロックで囲まれる部分を
出力テンプレートCに出力するかどうかを決めます。

仕様(8):もし変数ファイルに記述されてしない変数が{if タグに出現した場合、対応する
閉じタグ {/if とともに、未解決のタグとして、Cに出力されます。

たとえば上記の例で、変数ファイルに $date=false がなく

変数定義ファイル(例2)

lang

1$header = true

となっている場合、出力されるテンプレートC は

lang

1打ち合わせメモ 2 {if $date}2015/05/20{/if $date} 3新プロジェクトの体制について 4参加者:田中、鈴木

となるものとします。

仕様(9):上記のように、IF-Reducerによって、「Aに含まれる{if ・・{/if タグが
完全になくなるとは限らないが少なくとも減らされて、Cとして出力する。」ことから、
当該プログラムを 「IFブロック減少器」の意図で
IF-Reducer
としました。

仕様(10):入力されるテンプレートの空白文字(改行、スペース、タブ)については
出力時に、適切に調整されて出力されます。
(この”適切に”の具体的な内容は、本質問の主旨ではないので、説明を割愛します。)

IF-Reducer の説明は以上になりますが、仕様説明として不足な部分があれば
ぜひご指摘ください。

上記をふまえて、冒頭に書きましたとおり、質問としては
以下の2点です。

(1)上記のような、制御構造としてifブロックを含むテキストファイル(典型的なものは
プログラムコードですが。)を処理する、よく知られた方法はありますか?

if <変数> 、あるいは、もっと一般的にいって if <式> (に加えて、必要によっては、
elseifやelse )によって構成される if ブロックを適切に処理するための定石のような
手法(アルゴリズム、データ構造、クラス設計、それらを設計するためのコンセプトなど)
があれば、ご教示頂きたいです。

あるいは、「こういう本(or サイト)のこの辺あたりに書いてある」といった
ご示唆でも大変ありがたいです。

※なお、上記で想定しているIF-Reducer では、{if が評価する対象として、<式>ではなくて
<変数>としているのは、<式>にすると評価のための実装が大変そうだ、という
単にそれだけの理由です。

(2)(ソートにおけるクイックソートのような)定石というレベルではなくても
「こういうデータ構造(やクラス設計)なら良質なコードになる(気がする)」
というようなアイディアがあればぜひご教示ください。

コードのスニペットで示して頂ければ嬉しいですが、単に考え方を記述した文章でも
ありがたいです。

以上です。

皆様のお知恵を拝借できましたら幸いです。
よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

yacc/lexという手もありますね。

投稿2015/05/20 06:18

wakuwaku

総合スコア386

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun68ykt

2015/05/20 08:46

こんにちは。 ご回答ありがとうございます。 yaccとlexというコマンドがあることは知っていましたが、 使ったことは一度もありませんでした。ですので、 もちろん、今回の質問で挙げている問題の解決に役立つものとは 知りませんでしたので、この機会に調べてみようと思います。 ご教示ありがとうございました。
guest

0

ベストアンサー

プッシュダウン・オートマトン...でだめでしょうか。
詳しく必要であれば、詳しく書きます。

変数定義ファイル(例2) での "{/if $date}" は "{/lf}" の書き間違いと解釈して、コメントします。

私ならどう実装するか、簡単に書きますね。Java はしばらく触っていないので、用語が間違っていたら教えて下さい。
まず、変数定義ファイルからデータを読みます。variables_map Map<String, boolean> を用意しておきます。
出力用に、StringWriter を1つ確保しておきます。その後で、処理用の関数を一つ呼びます。

関数は、出力有無を覚えておくためにスタック一つ state_stackint state、文字列インデックス int index、一時的な文字列 String var_str を持ちます。state の初期値は 1 とします。
0 が FALSE、1 が TRUE、2 が「FALSE かつ、変数がない状態」、3 が「TRUE かつ、変数がない状態」に対応しているとします。

まず、関数内では、"{if " または "{/if}" という文字列を探します。読んでいる位置を new_index とします。String.indexOf(String str, int fromIndex) を使えばよいですね。もし、state が TRUEであれば、この間の文字列は全部出力として有効なので、substring で切り出して、StringWriter に書き出します。FALSE なら、読み捨てます。

続いて、"{if " か "{/if}" かによって、処理を変えます。

"{if " であったら

続いて、"$***}" が来るはずなので、そこまで読んでおきましょう。var_str に代入します。スタックに現在の state を積みます。それ以外の場合は「たまたま "{if " という文字列が来た」と解釈するか、「文法エラー」かどちらかです。適当に決めて下さい。

"{if " で変数が存在する

variables_map.containKey(var_str) が TRUE の時は、普通のときです。

state が TRUE(1, 3) の場合、続いて、variables_map を使って
state = variables_map.get(var_str) ? 1 : 0;
とします。要するに、変数が TRUE なら 1にします。内側も出力するからです。

state が FALSE(2, 4) の場合、内側は出力しないと思うので、
state = 2;
とします。

"}" の終わりまで読んで終了です。

"{if " で変数が存在しない

variables_map.containKey(var_str) が FALSE の時は、残ります。
state が TRUE(1, 3) の場合
"{if $***}" を出力し、 state = 3; とします。仮置きの状態です。

state が FALSE(0, 2) の場合
出力せずに、state = 2; とします。

"}" の終わりまで読んで終了です。

"{/if}" であったら

state の値が TRUE(1) か FALSE(0, 2) の場合、読み捨てます。
state の値が 3 の場合、{/if} を出力します。
state = state_stack.pop();
で、更新します。state_stack が空の場合は異常です。

これで、動くんじゃないかな…。

lang

1A 2{if $v1} 3 B 4 {if $v2} 5 C 6 {if $v3} 7 D 8 {if $v4} 9 E 10 {/if} 11 D 12 {/if} 13 C 14 {/if} 15 B 16{/if} 17A

上記で、2つのA, B, C, D が「出力されるかどうか」は必ず一致しているのが理解できるでしょうか。それを担保するのが stack への push と pop です。

$v1=TRUE, $v2 未定義, $v3=FALSE, $v4=TRUE の状態で、各A, B, C, D は出力されるかどうか、考えてみて下さい。さらに、A, B, C, D で stack 及び内部状態がどうなっているか、考えて下さい。
答え…いりますか?

投稿2015/05/20 03:42

編集2015/05/21 23:38
takotakot

総合スコア1111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun68ykt

2015/05/20 07:10

こんにちは。 ご回答ありがとうございます。 >プッシュダウン・オートマトン 自分の「オートマトン」についての知識レベルは、約4半世紀前に 読んだ学校の教科書に書いてあったのを覚えているくらいで、 ご回答いただいてから「プッシュダウン・オートマトン」と 「有限オートマトン」をwikipediaでざっと読んで、 「そういえば確かこんなようなのあったな」 ぐらいです。不勉強で申し訳ありません。m(_ _)m 実は、質問に挙げている、IF_Reducerに相当するものを今(Javaで)書いて おりまして、ifブロックの処理を我流で作成することに着手してのですが、 うまくいかなかった(=簡単な{if ... {/if のテストケースは処理できても、 ちょっと複雑になると微妙におかしな出力になる)ので、我流で進めるよりも 離散数学で習得する何らかの基礎概念を適用すれば、すっきり書けるのではないか と思っての質問だったのですが、 >プッシュダウン・オートマトン は思いつきませんでした。 >詳しく必要であれば、詳しく書きます。 とのことなので、お言葉に甘えさせていただきまして、 また質問なのですが、このプログラムを >プッシュダウン・オートマトン として実装する場合に、状態集合はどう定義すればよろしいでしょうか? 状態集合={ TRUE, FALSE } と思っているのですがダメでしょうか? また、スタックに積むものは何でしょうか? このあたり、少し自分で考えてみようとは思うものの、 ヒントを頂けると幸いです。 よろしくお願い致します。
takotakot

2015/05/20 10:51

慣れるまでは、紙とペンを使って、「この時にこれがきたらこうする」と処理の流れを追ってみて下さい。
jun68ykt

2015/05/21 08:36

こんにちは。 コードを示して頂き、ありがとうございました!・・・なのですが、 現時点では、私のオートマトンの知識が浅く、 挙げて頂いたコードを読むことで、頭の中で 「ステートマシーンが動くイメージ」を持つに至ってません m(_ _)m ただ、挙げて頂きましたコードのstateとして、単にtrueとfalseの2値だけ ではなく、「かつ、変数がない状態」も含めて異なる状態とすることが キモのように思いました。 オートマトンの基礎知識など、色々と自分に宿題が課せられたと 思った次第です。 ありがとうございました。
takotakot

2015/05/21 23:42

例題を追記しました。考えてみて下さい。 オートマトンという言葉にはまずこだわらず、アウトプットがどうなるか、プログラムがどう、動作するか、シミュレートしてみて下さい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問