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 - Java

起動パラメータで条件を与えます。
and and and
を与えれば、出力は
(true, true, true, true)
となり、
not and not and not and not
を与えると、
(false, false, false, false)
になります。
 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class Sample {
    interface Command {
        boolean operate(boolean org, boolean para);
    }
    private static Command[] cmd = new Command[4];
    private Command[] exp = new Command[4];
    private static final int AND = 0;
    private static final int OR = 1;
    private static final int NOT = 2;
    static {
        cmd[AND] = new Command() {
                public boolean operate(boolean org, boolean para) {
                    return (org && para);
                }
            };
        cmd[OR] = new Command() {
                public boolean operate(boolean org, boolean para) {
                    return (org || para);
                }
            };
        cmd[AND | NOT] = new Command() {
                public boolean operate(boolean org, boolean para) {
                    return (org && !para);
                }
            };
        cmd[OR | NOT] = new Command() {
                public boolean operate(boolean org, boolean para) {
                    return (org || !para);
                }
            };
    }
    public Sample(String[] args) {
        int lastCommand = AND;
        int n = 0;
        for (int i = 0; i < args.length; i++) {
            if (args[i].equalsIgnoreCase("NOT")) {
                lastCommand += NOT;
            } else {
                exp[n++] = cmd[lastCommand];
                if (args[i].equalsIgnoreCase("AND")) {
                    lastCommand = AND;
                } else if (args[i].equalsIgnoreCase("OR")) {
                    lastCommand = OR;
                }
            }
        }
        exp[n++] = cmd[lastCommand];
    }

    public boolean eval(boolean[] x) {
        boolean val = true;
        for (int i = 0; i < x.length; i++) {
            val = exp[i].operate(val, x[i]);
        }
        return val;
    }

    public void work(boolean... x) {
        if (eval(x)) {
            System.out.printf("(%b, %b, %b, %b)%n", x[0], x[1], x[2], x[3]);
        }
    }

    public static void main(String[] args) {
        Sample s = new Sample(args);
        for (int i = 0; i < 16; i++) {
            s.work((i & 8) > 0, (i & 4) > 0, (i & 2) > 0, (i & 1) > 0);
        }
    }
}

だいぶ長くなってしまいましたけどJavaなのでその辺りは多めに見てもらって、ちゃんと対応版を書いてみました。 それと無駄に、enumやIteratorを使ってみました。

でも、eval関数が DRY原則に反してるのがイケてない・・・。

  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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Answer43 {
    public enum BoolOperator {
        not(1) {
            @Override
            public boolean operate(boolean... bs) {
                return !bs[0];
            }
        },
        and(2) {
            @Override
            public boolean operate(boolean... bs) {
                return bs[0] && bs[1];
            }
        },
        or(2) {
            @Override
            public boolean operate(boolean... bs) {
                return bs[0] || bs[1];
            }
        };

        private int count_;
        private BoolOperator(int count) {
            count_ = count;
        }
        public int operateCount() {
            return count_;
        }
        public abstract boolean operate(boolean... bs);
    }

    public static class BooleanArrayIterator implements Iterator<boolean[]> {
        private long counter_;
        private final int arrayLength_;

        public BooleanArrayIterator(int arrayLength) {
            arrayLength_ = arrayLength;
            counter_ = (long) (Math.pow(2, arrayLength) - 1);
        }
        public boolean hasNext() {
            return counter_ > 0;
        }
        public boolean[] next() {
            boolean[] bs = new boolean[arrayLength_];
            for (int index = 0; index < arrayLength_; index++) {
                bs[index] = (counter_ & (1 << index)) > 0;
            }
            counter_--;
            return bs;
        }
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }


    public static List<boolean[]> searchTrueList(BoolOperator[] boolOperators) {
        if (boolOperators.length == 0) return new ArrayList<boolean[]>();

        int resultLength = getResultLength(boolOperators);
        BooleanArrayIterator iterator = new BooleanArrayIterator(resultLength);
        List<boolean[]> result = new ArrayList<boolean[]>();
        while (iterator.hasNext()) {
            boolean[] bs = iterator.next();
            if (eval(boolOperators, bs)) {
                result.add(bs);
            }
        }
        return result;
    }
    private static int getResultLength(BoolOperator[] boolOperators) {
        int length = 1;
        for (BoolOperator op: boolOperators) {
            length += (op.operateCount() - 1);
        }
        return length;
    }
    private static boolean eval(BoolOperator[] boolOperators, boolean[] bs) {
        int index = 0;
        boolean result = bs[0];
        BoolOperator op = boolOperators[index];
        if (op.operateCount() == 1) {
            while (index < boolOperators.length - 1) {
                BoolOperator opNext = boolOperators[++index];
                if (opNext.operateCount() > 1) break;
                result = opNext.operate(result);
            }
            result = op.operate(result);
        }
        for (int bIndex = 1; bIndex < bs.length; bIndex++) {
            boolean x = bs[bIndex];
            op = boolOperators[index];
            while (index < boolOperators.length - 1) {
                BoolOperator opNext = boolOperators[++index];
                if (opNext.operateCount() > 1) break;
                x = opNext.operate(x);
            }
            result = op.operate(result, x);
        }
        return result;
    }


    public static void print(String... args) {
        List<BoolOperator> ops = new ArrayList<BoolOperator>();
        for (String str: args) {
            try {
                BoolOperator op = BoolOperator.valueOf(str);
                ops.add(op);
            } catch (IllegalArgumentException ex) {
            }
            System.out.print(str);
            System.out.print(", ");
        }
        System.out.println();
        List<boolean[]> result = searchTrueList(ops.toArray(new BoolOperator[0]));
        
        for (boolean[] bs: result) {
            System.out.print('(');
            for (int index = 0; index < bs.length; index++) {
                if (index > 0) System.out.print(", ");
                System.out.print(bs[index]);
            }
            System.out.print(')');
            System.out.println();
        }
        System.out.println();
    }
    public static void main(String[] args) {
        print("and");
        print("or");
        print("not");
        print("not", "not");
        print("not", "not", "not");
        print("and", "or", "not", "and");
    }
}

Index

Feed

Other

Link

Pathtraq

loading...