wangflood

精心维护一个技术blog,为了工作,也是爱好。

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  14 Posts :: 19 Stories :: 8 Comments :: 0 Trackbacks
前些日子在群里讨论,有一个哥们出一道题:5,6,7,8,9,10按顺序插入+-*/和括号,得到结果2000.
大家的先沉默了一会,二分钟后,有人说这题没意思。呵呵。口算还是有点难的。于是我说,可以写个程序试一试。结果,花了三个小时,写完了
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * 
@author Sam Wang
 * 
@since Mar 22, 2011
 
*/
public class Demo {

    
public static void main(String[] args) {

        
double[] arr = { 5678910 };
        
double[] arrTemp = null;
        
int random = 0;
        
double last = 0;
        StringBuffer sb 
= null;
        Set
<String> results = new HashSet<String>();

        
for (int i = 0; i < 100000; i++) {
            arrTemp 
= arr.clone();
            shuffle(arrTemp);
            sb 
= new StringBuffer();
            sb.append(arrTemp[
0]);
            
for (int j = 1; j < arrTemp.length; j++) {
                random 
= (int) (Math.random() * 4);
                
switch (random) {
                
case 0:
                    sb.append(
"+").append(arrTemp[j]);
                    arrTemp[j] 
= arrTemp[j - 1+ arrTemp[j];
                    
break;
                
case 1:
                    sb.append(
"-").append(arrTemp[j]);
                    arrTemp[j] 
= arrTemp[j - 1- arrTemp[j];
                    
break;
                
case 2:
                    sb.append(
"*").append(arrTemp[j]);
                    arrTemp[j] 
= arrTemp[j - 1* arrTemp[j];
                    
break;
                
case 3:
                    sb.append(
"/").append(arrTemp[j]);
                    arrTemp[j] 
= arrTemp[j - 1/ arrTemp[j];
                    
break;

                
default:
                    
break;
                }
            }

            last 
= arrTemp[arrTemp.length - 1];
            System.out.println(last);
            
if (last == 2000) {
                sb.append(
"=2000");
                results.add(sb.toString());
            }
        }

        
for (Iterator<String> it = results.iterator(); it.hasNext();) {
            String item 
= it.next();
            System.out.println(item);

        }
    }

    
/**
     * 
@param arrTemp
     * 
@return void 打乱数组元素顺序。
     
*/
    
private static void shuffle(double[] arrTemp) {
        
int index = 0;

        
for (int i = 0; i < arrTemp.length; i++) {
            index 
= (int) (Math.random() * arrTemp.length);
            swap(arrTemp, i, index);
        }
    }

    
/**
     * 
@param arrTemp
     * 
@param i
     * 
@param index
     *            交换数据元素
     
*/
    
private static void swap(double[] arrTemp, int i, int index) {
        
double temp = arrTemp[i];
        arrTemp[i] 
= arrTemp[index];
        arrTemp[index] 
= temp;
    }

}
有两个技巧:在不确定是+-*/哪种情况下,可以random一下,多for几次,那么这几种情况大致上可以照顾到。
                      ()在算法里面的体现是,使用()我发现,数字的前后顺序可以混乱。打印出结果不行的话再删除不迟。
打印结果:
9.0*8.0-7.0*6.0+10.0*5.0=2000
8.0*9.0-7.0*6.0+10.0*5.0=2000
7.0*8.0+9.0*6.0+10.0*5.0=2000
打印出来的效果不太好,我组织一下:
5*(6*(-7+8*9)+10)=2000;
5*(6*(7*8+9)+10)=2000;
如果,不允许取负数的话,当然就只有一个结果了。

有点疑惑,为什么Collection.shuffle()可以,Array.shuffle()却不提供。

当然,算法肯定有可以改进的地方。



posted on 2011-03-29 12:31 wangflood 阅读(359) 评论(1)  编辑  收藏

Feedback

# re: 56789+-*/() 2000 2011-03-30 13:12 wangflood
赵靖 5:47:53 AM
这题用逆波兰(后缀)式再枚举即可,然后转化为带括号的中缀式
赵靖 5:48:17 AM
就可以绕过括号,这样就变成一道体力活了
荞叶 5:52:07 AM
哈哈。
荞叶 5:52:49 AM
那晚,我写了三个小时。
赵靖 5:53:27 AM
完全做出来三个小时不算多,但是有正确的方向要坚定的多
赵靖 5:54:51 AM
数字是排定的,符号插入其中,再构造图求路径的话就更清晰了
荞叶 5:55:04 AM
http://www.blogjava.net/wangflood/articles/Demo.html
荞叶 5:55:06 AM
呵呵。
赵靖 5:56:39 AM
这样做法可能是错误的,设想如果(5+6)*(7+8)+9+10这个顺序是shuffle不出来的
赵靖 5:57:21 AM
后缀应为56+78+*9+10+
赵靖 5:57:46 AM
要去掉括号,后缀是一个绝佳的选择
荞叶 5:58:01 AM
不允许56这样的组合。
赵靖 5:58:13 AM
我写的是后缀式
荞叶 5:58:18 AM
shuffle是把[5,6,7,8,9,10]的前后顺序弄乱。
荞叶 5:58:27 AM
发来看看啊。
荞叶 5:58:35 AM
不懂后缀式是什么意思。、
赵靖 5:58:52 AM
逆波兰式呀
赵靖 5:59:08 AM
就是后根遍历表达式
赵靖 6:01:35 AM
看看你的程序能不能找到184
荞叶 6:02:03 AM
为什么要找到184
赵靖 6:02:20 AM
这个说明你shuffle是不能表达括号的优先级的
荞叶 6:03:48 AM
shuffle,比括号得到了更多的结果。
荞叶 6:03:59 AM
但括号可以做到的,shuffle都给办到。
赵靖 6:04:31 AM
你怎么表达这种括号呢(5+6)*(7+8)
赵靖 6:04:52 AM
shuffle 去掉括号看看
荞叶 6:05:22 AM
对噢。
荞叶 6:06:35 AM
可以这样,5+6)*(7+8)
算出5+6后,就是[11,7,8,9,10]再次shuffle
赵靖 6:06:51 AM
那算法也太猥琐了些
荞叶 6:06:56 AM
哈哈。就期望能算出第二个结果来。
荞叶 6:06:59 AM
我也这么觉得啊。
赵靖 6:09:47 AM
这个式子的通用格式是

5678910
abcdef
然后吧abcde查到合适的位置去,其中至少f是最后面的
如56+67+*8+9+10+就表达了(5+6)*(7+8)+9+10
赵靖 6:10:19 AM
后缀计算是最快的,仅仅需要一个栈
  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: