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

総当たりではなく後ろから逆算してみた。
explorecaseの'or'の場合と'and'の場合の処理はまとめることも出来るけど
実験コードなので見やすいようにそのままにした。
結果に影響を与えない条件は全てのパターンを表示する代わりに
手を抜いて'no care'と表示する。
 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
<?php
function printresult(&$a,$i)
{
	$res=array();
	for($j=0;$j<$i;++$j)
		$res[]='no care';
	for(;isset($a[$i]);++$i)
		$res[]=(!$a[$i][2]==!$a[$i][1])?'false':'true';
	echo implode(',',$res),"\n";
}

function explorecase(&$a,$i,$condition)
{
	if(!$i)
	{	$a[$i][2]=$condition;
		printresult($a,$i);
		return;
	}
	switch($a[$i][0])
	{
	case 'or':
		if($condition)
		{	$a[$i][2]=true;
			printresult($a,$i);
			$a[$i][2]=false;
			explorecase($a,$i-1,true);
		}
		else
		{	$a[$i][2]=false;
			explorecase($a,$i-1,false);
		}
		break;
	case 'and':
		if($condition)
		{	$a[$i][2]=true;
			explorecase($a,$i-1,true);
		}
		else
		{	$a[$i][2]=false;
			printresult($a,$i);
			$a[$i][2]=true;
			explorecase($a,$i-1,false);
		}
		break;
	}
}

function conditionexplorer($cond)
{
	$a=array(array('',false,false));
	$i=0;
	while(list(,$v)=each($cond))
	{	switch($v=strtolower($v))
		{
		case 'not':
			$a[$i][1]=!$a[$i][1];
			break;
		case 'and':
		case 'or':
			$a[++$i]=array($v,false,false);
			break;
		}
	}
	explorecase($a,$i,true);
}

conditionexplorer(array('and', 'or', 'not', 'and'));

?>

'no care'表示だと題意を満たさないので
全てのパターンを表示するprintresultも
用意してみました…。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
function printresult(&$a,$i)
{
	if($i>0)
	{	$a[--$i][2]=false;
		printresult($a,$i);
		$a[$i][2]=true;
		printresult($a,$i);
		return;
	}
	$res=array();
	for(;isset($a[$i]);++$i)
		$res[]=(!$a[$i][2]==!$a[$i][1])?'false':'true';
	echo implode(',',$res),"\n";
}
?>

Index

Feed

Other

Link

Pathtraq

loading...