来,讨论一个遇到的实际问题,关于逻辑表达式的简化

helloyou0 2007-10-04 10:34:27
简单地说, 就是比如给出一个逻辑表达式 ( & 表示 and , | 表示 or )
A & ( X & Y | ( B | G & ( J | K ) | I ) ) | ( M & N | O & ( ( P | Q ) & ( R | S | T ) ) ) | E & F
需要简化成没有括号的形式,
对上面的表达式:
A & ( X & Y | ( B | G & ( J | K ) | I ) ) | ( M & N | O & ( ( P | Q ) & ( R | S | T ) ) ) | E & F
=> A & ( X & Y | ( B | G & J | G & K ) | I ) ) | ( M & N | O & ( P | Q ) & ( R | S | T ) ) | E & F
=> A & ( X & Y | B | G & J | G & K | I ) | ( M & N | O & ( P | Q ) & ( R | S | T ) ) | E & F
=> A & ( X & Y | B | G & J | G & K | I ) | M & N | O & ( P | Q ) & ( R | S | T ) | E & F
=> A & X & Y | A & B | A & G & J | A & G & K | A & I | M & N | O & ( P | Q ) & ( R | S | T ) | E & F
=> A & X & Y | A & B | A & G & J | A & G & K | A & I | M & N | O & P & ( R | S | T ) | O & Q & ( R | S | T ) | E & F
=> A & X & Y | A & B | A & G & J | A & G & K | A & I | M & N | O & P & ( R | S | T ) | O & Q & ( R | S | T ) | E & F
=> A & X & Y | A & B | A & G & J | A & G & K | A & I | M & N | O & P & R | O & P & S | O & P & T | O & Q & R | O & Q & S | O & Q & T | E & F
这个太长了点,自己都搞昏了
再写几个简单的:
A & ( B | C) => A & B | A & C
A | B & ( C & D | E ) => A | B & C & D | B & E
( A & B ) | D => A & B | D (因为&的优先级高)
....

欢迎大家踊跃参与, 谈谈具体算法及数据结构,
这是我实际应用中遇到的问题, 目前还没有写出比较好的办法


...全文
181 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
helloyou0 2007-10-14
  • 打赏
  • 举报
回复
没想到连来接分的都不多
helloyou0 2007-10-11
  • 打赏
  • 举报
回复
补充以下, 我的a,b,c等都是数字, 测试可以用这样的例子:
simple('1|(2&(3&(4|5&6|7|8&9|11)&12&(13|14)|15))|(16&(17|18&19))&20');
=> 1|2&3&4&12&13|2&3&4&12&14|2&3&5&6&12&13|2&3&5&6&12&14|2&3&7&12&13|2&3&7&12&14|2&3&8&9&12&13|2&3&8&9&12&14|2&3&11&12&13|2&3&11&12&14|2&15|16&17&20|16&18&19&20
helloyou0 2007-10-11
  • 打赏
  • 举报
回复
先鄙视一下php版的ID们, 都这么懒,
看C版贴个算法题,讨论得热火朝天的

再把自己的贴出来, 写得有点乱, 谁有好建议可以简化的奖励

写的这个受到楼上fxs_2008的一点启发,先谢谢

大致是先给 x&y&z 这样的加上括号 => (x&y)&z , 或 x&y|z => (x&y)|z
然后递归调用, 直到最简单的几种情况 (x&y)&z, (x|y)&(a|b), ... 直接去括号



function simple($logic){ // convert logic to simple

//echo $logic."\n";

$left_count = substr_count($logic,'(');
$right_count= substr_count($logic,')');
if($left_count!=$right_count){
return false;
}
if($left_count==0){
return $logic;
}

$exist_nest=preg_match('/\([^\)]*?\(/',$logic);


if($left_count==1){

$temp=preg_replace('/\(.*?\)/','',$logic);

if(empty($temp)){
$str=trim(trim($logic,')'),'(');
return $str;
}

$and_count=substr_count($temp,'&');
$or_count=substr_count($temp,'|');

if( $and_count==0 || $and_count==1 && $or_count==0 ){ // x&(...) or (...)&x or y|x|(..)|z

// only 1 pair ( and ) , remove them
if(strpos($logic,'&(')!==false){
list($left,$right)=explode('&(',$logic);
$right=trim($right,')');
$right_elements=explode('|',$right);
$str='';
foreach($right_elements as $r){
$str.=$left.'&'.$r.'|';
}
$str=rtrim($str,'|');
return $str;

}elseif(strpos($logic,')&')!==false ){
list($left,$right)=explode(')&',$logic);
$left=trim($left,'(');
$left_elements=explode('|',$left);
$str='';
foreach($left_elements as $r){
$str.=$r.'&'.$right.'|';
}
$str=rtrim($str,'|');
return $str;

}else{
$str=str_replace(array('(',')'),'',$logic);
return $str;
}
}
}


if($left_count>=2){ // ()&() or ()|()|x|y|()....


if(!$exist_nest){

$temp=preg_replace('/\(.*?\)/','',$logic);
$and_count=substr_count($temp,'&');
$or_count=substr_count($temp,'|');

//if( $and_count==0 || $and_count==1 && $or_count==0 ){

if($temp=='&' || $and_count==0 ){


if($and_count==0){ // ()|()|()|x|()|y...
$str=str_replace(array('(',')'),'',$logic);
return $str;
}

if($temp=='&'){
list($left,$right)=explode(')&(',$logic);
$left=trim($left,'(');
$right=trim($right,')');
$left_elements=explode('|',$left);
$right_elements=explode('|',$right);
$str='';
foreach($left_elements as $l){
foreach($right_elements as $r){
$str.=$l.'&'.$r.'|';
}
}
$str=trim($str,'|');
return $str;
}

}


}
}



$strs=preg_split('/(\)|\(|&|\|)/',$logic,-1,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

$result=array();
$stack=array();
$level=0;
$mark=0;


//find a matched ( and )
$strs=array_reverse($strs);

while($str=array_pop($strs)){
//echo 'RESULT:'.implode('',$result)."\t\t".implode('',$stack)."\n";

if($str=='('){
$level++;
if($level>1 || $mark==1) array_push($stack,$str);
continue;
}

if($str==')'){
$level--;
if($level>0 || $mark==1) array_push($stack,$str);

if($mark==1 && $level==0){
$mark=0;
//$level--;
}

if($level==0){ // end of ()
$temp=implode('',$stack);
$stack=array();
$mid=simple($temp);
array_push($result,'('.$mid.')');

}

continue;
}

if($level==0){

if($str=='&' && !$exist_nest ){
$left=array_pop($result); //echo '['.$left.']';
array_push($stack,$left);
array_push($stack,'&');
//$level++;
$mark=1;
continue;
}

if($str!='|' && $str!='&'){ // is a number
if($mark==1){
$mark=0;
array_push($stack,$str);

array_push($result,'('.implode('',$stack).')');
$stack=array();

continue;

//array_push($stack,')');
//$level--;
}
array_push($result,$str);
}else{
array_push($result,$str);
}
}else{
array_push($stack,$str);
}

}

if($level!=0) {
return false;
}

return simple(implode('',$result));

}


总哈哈 2007-10-11
  • 打赏
  • 举报
回复
........看得头昏了。精神上支持回复的phper!
axaw 2007-10-07
  • 打赏
  • 举报
回复
有啥意思呢。用括号不是很好吗。

懒得动脑了。
cuidenghong123 2007-10-07
  • 打赏
  • 举报
回复
太复杂了
帮顶啊
helloyou0 2007-10-06
  • 打赏
  • 举报
回复
唉~
ruanchao 2007-10-05
  • 打赏
  • 举报
回复
有意思,搞的这么复杂哈
yorry 2007-10-04
  • 打赏
  • 举报
回复
gz
mingxuan3000 2007-10-04
  • 打赏
  • 举报
回复
假期不动脑筋
fxs_2008 2007-10-04
  • 打赏
  • 举报
回复
国庆节快乐!接分了!

好象和学校里的学的集合操作差不多!不知道算法
从最里面的括号展开
1、A | ( B | C) 则直接括号=A|B|C
2、 A& ( B ¦ C) 如果括号前的符号为& ,则=A&B|A&C
3、A|(B&C) =A|b&c,直接地括号
4、A&(B&C)=A&B&C 直接却括号
5、A&B|C 如果有,则相当于(a&B)|C,即&两边加上括号

这说明,如果符号相同,直接去括号;如查符号相异,只有A& ( B ¦ C)时,要分等于 A&B|A&C
zeroleonhart 2007-10-04
  • 打赏
  • 举报
回复
首先要定义运算符的优先级
然后开始读取表达式
从最深的括号开始
将括号外的运算符和括号内的运算符作比较,
如果外符优先级高于内符,则分解为外参,外符, 内参1, 内符, 外参, 外符, 内参2....
否则就直接去掉括号
再逐级返回
数据结构的确比较复杂,应该是一个树的遍历过程,

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧