challenge 与えた条件を満たす候補

['and', 'or', 'not', 'and']
のような入力が与えられた場合に、
式 x1 and x2 or not x3 and x4 の値が
Trueとなるような、x1~x4の組み合わせを全て
出力するプログラムを作成してください。
x1~x4には真と偽の2通りの値だけが入るものとします。

Pythonであれば上の入力に対し、
(True, True, True, True)
(True, True, False, True)
(True, False, False, True)
(False, True, False, True)
(False, False, False, True)
と出力します。

andとorの優先順位は同じで左結合性、
つまりa and b or c and dは
(((a and b) or c) and d)
という順番で評価されるものとします。

参考:
d.y.d.

キミならどう書く2.0の小町算問題と似てますが。
このお題はmorchinさんの投稿をもとに作成しました。 ご投稿ありがとうございました。
元ネタの 充足可能性問題 - Wikipedia は、 同じリテラル(x1とかnot x2とか)が複数回出てくることを想定しているので、 今回の問題のようにそれぞれ別の変数でだと乗法標準形 - Wikipediaにした場合に、答えが…と色々悩みどころでした。

Posted feedbacks - D

文字列処理だけで計算してみた。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import std.stdio;
import std.regexp;
import std.string;

void main(){
    string[] operators = ["and", "or", "not", "and"];
    string operatorsStr;  // 各演算子の頭文字からなる文字列 (e.g. "aona")
    foreach(operator; operators){
        operatorsStr ~= operator[0];
    }
    operatorsStr = operatorsStr.sub("nn", "", "g");  // 2 連続の not はないのと同じ

    int requiredOperandNum = operatorsStr.sub("n", "", "g").length + 1;
    for(int i = (1 << requiredOperandNum) - 1; i >= 0; i--){
        string operands = format("%0*b", requiredOperandNum, i);  // オペランドからなる文字列 (e.g. "1011")

        // 式を生成
        string expression;
        int j;
        foreach(operator; operatorsStr){
            if(operator == 'n'){
                expression ~= operator;
            }
            else{
                expression ~= [operands[j++], operator];
            }
        }
        expression ~= operands[j];  // e.g. "1a0on1a1"

        // eval
        expression = expression.sub("n0", "1", "g").sub("n1", "0", "g");  // 先に not を処理 (e.g. "1a0o0a1")
        while(expression.length > 1){  // 式左端の 2 項演算だけを順に
            expression = expression.sub("^1a1", "1").sub("^.a.", "0")
                                   .sub("^0o0", "0").sub("^.o.", "1");
        }  // e.g. "1a0o0a1"=>"0o0a1"=>"0a1"=>"0"

        if(expression == "1"){
            bool[] operandsArray;
            foreach(operand; operands){
                operandsArray ~= (operand == '1');
            }
            writefln(operandsArray);
        }
    }
}

Index

Feed

Other

Link

Pathtraq

loading...