`
qdzheng
  • 浏览: 67744 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

趣味编程:24点算法实现

    博客分类:
  • Java
阅读更多
24点游戏规则:任取1-9之间的4个数字,用+-*/()连结成算式,使得式子的计算结果为24。估计很多人都玩过用扑克牌玩的那种,印象中10也算在内的,两人各出2张牌,谁先算出来谁赢,赢家收回已经算过的4张牌。最后看谁手里的牌多。
这个程序实现使用穷举的方法,将所有可能的排列穷举出来,最后将每个排列中计算出结果。计算结果时,将前两个作为一组、后两个数作为一组,分别计算出各组的结果,再对获得的两个组结果进行计算。由于是排列,分前后两组进行计算就可满足所有可能的计算。

改进后的代码见回复中。

package fun.twentyfour;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TwentyFour {
	public static void main(String[] args){
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String line;
		try{
			while((line=br.readLine())!=null){
				try{
					if ("exit".equals(line)) break;
					
					String[] s=line.split("\\s");
					int[] v=new int[4];
					for(int idx=0;idx<4;idx++) {
						v[idx]=Integer.parseInt(s[idx]);
						if (v[idx]<=0||v[idx]>=10) throw new Exception("Input error.");
					}
					evaluate(v);
					
				}catch(Exception ex){
					ex.printStackTrace();
				}
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
	public static void evaluate(int[] v){
		int idx=0;
		for(int a=0;a<4;a++)
			for(int b=0;b<4;b++)
				for (int c=0;c<4;c++)
					for (int d=0;d<4;d++){
					if (a!=b && a!=c && a!=d && b!=c && b!=d && c!=d){
						idx++;
						check(v,new int[]{a,b,c,d});
					}
				}
	}
	static char[] op={'+','-','*','/'};
	public static void check(int[] v,int[] idx){
		
		for(int o=0;o<4;o++){
			for(int p=0;p<4;p++){
				for(int t=0;t<4;t++){
					if (op(op[p],op(op[o],v[idx[0]],v[idx[1]]),op(op[t],v[idx[2]],v[idx[3]]))==24){
						System.out.println(String.format("(%1$d %2$c %3$d) %4$c (%5$d %6$c %7$d)",
								v[idx[0]],op[o],v[idx[1]],op[p],v[idx[2]],op[t],v[idx[3]]));
					}
				}
			}
		}
	}

	public static int op(char op,int v1,int v2){
		switch(op){
		case '+':
			return v1+v2;
		case '-':
			return v1-v2;
		case '*':
			return v1*v2;
		case '/':
			if (v2==0) return -111;
			if (v1%v2!=0) return -111;
			return v1/v2;
		default:
				return 0;
		}
	}
}
分享到:
评论
65 楼 night_stalker 2009-12-12  
大坟啊 ……

class Hash
  def * ys  # returns a new hash of {result => expression}
    inject({}){|hash, (x, x_expr)|
      ys.each{|y, y_expr| ['+', '-', '*', '/'].each {|op|
        (res = x.send(op, y) rescue nil) and hash[res] = "(#{x_expr} #{op} #{y_expr})"
        (res = y.send(op, x) rescue nil) and hash[res] = "(#{y_expr} #{op} #{x_expr})"
      }}
      hash
    }
  end
end
r = (1..9).to_a
tested = {}
r.each{|a| (r-[a]).each{|b| (r-[a,b]).each{|c| (r-[a,b,c]).each{|d|
  next if tested[[a,b,c,d].sort]
  if expr = ({a=>a} * {b=>b} * {c=>c} * {d=>d})[24] || (({a=>a} * {b=>b}) * ({c=>c} * {d=>d}))[24]
    puts expr
    tested[[a,b,c,d].sort] = true
  end
}}}}
puts "#{tested.size} results found" #=> 125 results found


ps:ruby 1.9
64 楼 syre 2009-12-11  
我写的那个算24的程序,1369的结果就两条,其余的都消掉了
9+3*(6-1)
(6-3)*(9-1)

1234的结果
(1+3)*(2+4)
4*(1+2+3)
1*2*3*4
63 楼 XMLDB 2009-03-17  
最简单的验证方法是大家把每一种算法的计算结果贴出来
62 楼 richardhochou 2009-03-16  
好久没有去考虑这种东东了...
61 楼 leiwuluan 2009-03-04  
可以用递归吗
60 楼 o0o0o0o0 2009-02-18  
这算什么 啊 !
有人用汇编吗?
59 楼 shenkun_918 2009-02-17  
早些时候写过一个,可以去掉重复的如 1118 1181之类只能算一个
http://shenkun-918.iteye.com/admin/blogs/254770
#  public static void main(String[] args){ 
#          
#         int a=0,b=0,c=0,d=0; 
#         //将a,b,c,d取由1到13的数字 
#         for(int i=1;i<=13;i++){ 
#                 a = i; 
#             for(int j=1;j<=13;j++){ 
#                     b = j; 
#                 for(int k=1;k<=13;k++){ 
#                         c = k; 
#                     for(int l=1;l<=13;l++){ 
#                             d = l; 
#                              outs(a,b,c,d); 
#                     } 
#                 }    
#             } 
#         } 
#     } 
#      
#     //将四个数带入计算,判断是否可以组成24,可以则输出 
#     @SuppressWarnings("unused") 
#     public static void outs(int a,int b,int c,int d){ 
#         int count = 0; 
#         //两个数计算的结果是ab,三个数计算的结果是abc,最终结果是abcd 
#         double ab=0, abc=0, abcd=0; 
#         boolean todo = false; 
#         String[] s = new String[]{"+","-","*","/"}; 
#         int[] content; 
#         for(int i=0;i<s.length;i++){ 
#             ab = account(a,b,s[i]); 
#             for(int j=0;j<s.length;j++){ 
#                 abc = account(ab,c,s[j]); 
#                 for(int k=0;k<s.length;k++){ 
#                     abcd = account(abc,d,s[k]); 
#                     if(abcd == 24){ 
#                         content = new int[]{a,b,c,d}; 
#                         //排序,这样利于比较 
#                         Arrays.sort(content); 
#                         count++; 
#                         Iterator iter = lists.iterator(); 
#                         while(iter.hasNext()){ 
#                             int[] list = (int[])iter.next(); 
#                             if(list[0]==content[0]&list[1]==content[1]&list[2]==content[2]&list[3]==content[3]){ 
#                                 todo = true; 
#                             } 
#                         } 
#                         if(!todo){ 
#                             lists.add(content); 
#                             System.out.println(lists.size()); 
#                             System.out.println(a + " "+ b +" " + c + " " + d + "经过四则混合运算可以组成24"); 
#                         } 
#                     } 
#                 }        
#             } 
#         }    
#     } 
#      
#     //具体的计算 
#     public static double account(double i, double j, String d){ 
#         double k = 0; 
#         if(d.compareTo("+")==0){ 
#             k = i + j; 
#         }else if(d.compareTo("-")==0){ 
#             k = Math.abs(i - j); 
#         }else if(d.compareTo("*")==0){ 
#             k = i * j; 
#         }else if(d.compareTo("/")==0){ 
#             k = i / j; 
#         } 
#         return k; 
#     } 
# } 
58 楼 kjj 2009-01-21  
cloverprince 写道
我的思路:

穷举所有数字的组合,穷举所有运算的组合,穷举运算符与数字的组合方式,求出表达式的值,过滤出值为24的表达式。

不同运算符有优先级问题,但是我可以避免这个问题。方法就是用“逆波兰式”。
给定4个数字和3个运算符,可以试图找到所有合法的逆波兰式。逆波兰式合法的定义就是不会使得遇到操作符时,堆栈里却没有足够的操作数。只要在生成逆波兰式的时候小心一点,记得判断就可以了。

我的实现:

module Main where

import List
import Ratio

main = putStr $ unlines $ map show $ work

work = filter (\x -> eval x == 24) $
       concat [applyAll nums ops | nums <- numPerms, ops<-opPerms]

numRange = [1..9]
numPerms = [[a,b,c,d] | a<-numRange, b<-numRange, c<-numRange, d<-numRange]

opList = ['+','-','*','/']
opPerms = [[x,y,z] | x<-opList, y<-opList, z<-opList]

opMap '+' = (+)
opMap '-' = (-)
opMap '*' = (*)
opMap '/' = (/)

type NumType = Double
data Elem = Num NumType | Op Char deriving (Show)

-- Given 4 numbers and 3 operators, generate all valid RPNs
applyAll :: [NumType] -> [Char] -> [[Elem]]
applyAll nums ops = applyAll' nums ops [] 0

applyAll' :: [NumType] -> [Char] -> [Elem] -> Int -> [[Elem]]
applyAll' []     []       sofar 1 = [reverse sofar]
applyAll' []     (op:ops) sofar sz = applyAll' [] ops ((Op op):sofar) (sz-1)
applyAll' (n:ns) (op:ops) sofar sz | sz>=2 =
    applyAll' (n:ns) ops      ((Op op):sofar) (sz-1) ++
    applyAll' ns     (op:ops) ((Num n):sofar) (sz+1) 
applyAll' (n:ns) ops sofar sz | otherwise = 
    applyAll' ns     ops      ((Num n):sofar) (sz+1)
applyAll' _      _   _     _ = []

-- Evaluate RPN
eval :: [Elem] -> NumType
eval es = head (foldl step [] es) where
    step stack (Num n) = (n:stack)
    step (n1:n2:ns) (Op op) = ((opMap op) n2 n1):ns




好,我正好和这位同志到想法一致,这样可以不用考虑运算符优先级问题了,我到算法就是这么搞的,有空验证一下完整性!
57 楼 andyjojo 2009-01-21  
package com.onezero;
/**
 * <b>计算24游戏</b>
 * <br/>
 * 给出四张1到13之间的整数,通过+、-、*、/、()组合成合法表达式并使结果等于24;
 * 如给出1、3、4、6,可以组合乘6/(1-(3/4))
 * <br/>
 * 算法仍然是穷举法,不过删除了一些重复的式子。
 * 为了精确表示除法结果,这里实现<code>有理数</code>类。
 * 基本思想:先在四张牌中选出两张,有6种,再计算这两张牌的值,有5种;
 * 剩下两张牌及刚才计算的值可看作三张牌。在选择两张,有3种;
 * 再计算,又有5种,最后剩下两张,在计算,又是5种;最后比较这些值是否等于24即可。
 * 共有6*5*3*5*5=2250
 * <br/>
 * <b>没有除去连乘和连加的重复</b>
 * <br/>
 * <b>使用方法:</b><code>com.onezero.算24.计算二十四(new int[]{1,3,4,6})</code>
 * @see com.onezero.有理数
 * @version 	1.0, 2009年1月18日
 * @author Anguo Wen
 *
 */
public final class 算24 {
	private static int[] 四选二 = { 0, 1, 2, 3,  0, 2, 1, 3,  0, 3, 1, 2,  
		1, 2, 0, 3,  1, 3, 0, 2,  2, 3, 0, 1 };
	private static int[] 三选二 = { 0, 1, 2,  0, 2, 1,  1, 2, 0 };
	private static StringBuilder 表达式;
	
	/**
	 * 计算二十四,如果有解,打印出所有的解(删除部分重复解)
	 * 
	 * @param 四张牌 输入的四张1到13之间的牌
	 * @return 是否可以算的24
	 * @throws  ArithmeticException  如果参数 <code>四张牌</code> 少于四个数.
	 */
	public static boolean 计算二十四(final int[] 四张牌) {
		if(四张牌.length<4)throw new ArithmeticException("必须为四张牌");
		有理数[] 纸牌 = new 有理数[4];
		for(int h=0;h<4;h++)纸牌[h] = new 有理数(四张牌[h]);
		boolean 成功 = false;
		有理数[] 临时 = new 有理数[4];
		String[] 输出 = new String[4];
		有理数 结果;
		四张: for (int i = 0; i < 四选二.length; i += 4) {
			for (int t = 0; t < i; t += 4) {
				if (重复(纸牌[四选二[i]], 纸牌[四选二[i + 1]], 纸牌[四选二[t]], 纸牌[四选二[t + 1]]))
					continue 四张;
			}
			for (int j = 0; j < 5; j++) {
				if (继续(纸牌[四选二[i]], 纸牌[四选二[i + 1]], j))
					continue;
				临时[0] = 计算(纸牌[四选二[i]], 纸牌[四选二[i + 1]], j,
						纸牌[四选二[i]].toString(), 纸牌[四选二[i + 1]].toString());
				输出[0] = 表达式.toString();
				临时[1] = 纸牌[四选二[i + 2]];
				输出[1] = 临时[1].toString();
				临时[2] = 纸牌[四选二[i + 3]];
				输出[2] = 临时[2].toString();

				三张: for (int k = 0; k < 三选二.length; k += 3) {
					for (int s = 0; s < k; s += 3) {
						if (重复(临时[三选二[k]], 临时[三选二[k + 1]], 临时[三选二[s]],
								临时[三选二[s + 1]]))
							continue 三张;
					}

					if (k >= 6)
						for (int r = 0; r < i; r += 4) {
							if (重复(临时[三选二[k]], 临时[三选二[k + 1]], 纸牌[四选二[r]],
									纸牌[四选二[r + 1]]))
								continue 三张;
						}
					for (int l = 0; l < 5; l++) {
						if (继续(临时[三选二[k]], 临时[三选二[k + 1]], l))
							continue;
						临时[3] = 计算(临时[三选二[k]], 临时[三选二[k + 1]], l, 输出[三选二[k]],
								输出[三选二[k + 1]]);
						输出[3] = 表达式.toString();
						for (int m = 0; m < 5; m++) {
							if (继续(临时[三选二[k + 2]], 临时[3], m))
								continue;
							结果 = 计算(临时[三选二[k + 2]], 临时[3], m, 输出[三选二[k + 2]],
									输出[3]);

							if (结果.等于(24)) {
								System.out.print(表达式.substring(1,
										表达式.length() - 1) + "\t");
								成功 = true;
							}
						}

					}
				}
			}
		}
		return 成功;
	}

	private static boolean 重复(有理数 数一, 有理数 数二, 有理数 数三, 有理数 数四) {
		return (数一.equals(数三) && 数二.equals(数四))
				|| (数一.equals(数四) && 数二.equals(数三));
	}

	private static boolean 继续(有理数 数一, 有理数 数二, int 运算符) {
		switch (运算符) {
		case 1:
			return 数一.equals(数二);
		case 2:
			return 数一.等于(2) && 数二.等于(2);
		case 3:
			return 数二.等于(1);
		case 4:
			return 数一.等于(1) || 数一.equals(数二);
		default:
			return false;
		}
	}

	private static 有理数 计算(有理数 分数一, 有理数 分数二, int 运算符, String 式一, String 式二) {
		表达式 = new StringBuilder("(");
		switch (运算符) {
		case 0:// 分数一+分数二
			表达式.append(式一).append("+").append(式二).append(")");
			return 分数一.加(分数二);
		case 1:// |分数一-分数二|
			有理数 结果 = 分数一.减(分数二);
			if (结果.小于零()) {
				结果.负();
				表达式.append(式二).append("-").append(式一).append(")");
			} else 
				表达式.append(式一).append("-").append(式二).append(")");
			return 结果;
		case 2:// 分数一*分数二
			表达式.append(式一).append("*").append(式二).append(")");
			return 分数一.乘(分数二);
		case 3:// 分数一/分数二
			表达式.append(式一).append("/").append(式二).append(")");
			return 分数一.除(分数二);
		default:// 分数二/分数一
			表达式.append(式二).append("/").append(式一).append(")");
			return 分数二.除(分数一);
		}
	}
	
	/**
	 * 主函数 测试用
	 * 打印出所有的可能组合的解及有解组合的总数
	 * 输入命令java -cp 24点游戏.jar com.onezero.算24
	 * @param args
	 */
	public static void main(String[] args) {
		int 有解 = 0;
		for (int i = 1; i < 14; i++)
			for (int j = i; j < 14; j++)
				for (int k = j; k < 14; k++)
					for (int l = k; l < 14; l++)
						if (计算二十四(new int[] { i, j, k, l })) {
							System.out.println();
							有解++;
						}
		System.out.println(有解);
	}
}

class 有理数 {
	private int 分子;
	private int 分母 = 1;

	有理数(int 分子) {
		this.分子 = 分子;
	}

	有理数(int 分子, int 分母) {
		if (分母 <= 0)
			throw new ArithmeticException("分母不可小于等于零!");
		int 公约数 = 最大公约数(分子 < 0 ? -分子 : 分子, 分母);
		this.分子 = 分子 / 公约数;
		this.分母 = 分母 / 公约数;
	}

	public boolean 等于(int 整数) {
		return 整数 == this.分子 && 1 == this.分母;
	}

	private int 最大公约数(int 数一, int 数二) {
		if (数一 == 数二) {
			if (数一 == 0)
				throw new ArithmeticException("求最大公约数不可同时为零!");
			return 数一;
		}
		if (数一 == 0)
			return 数二;
		if (数二 == 0)
			return 数一;
		else if (数一 > 数二)
			return 最大公约数(数二, 数一 % 数二);
		else
			return 最大公约数(数一, 数二 % 数一);
	}

	public 有理数 加(有理数 分数二) {
		return new 有理数(this.分子 * 分数二.分母 + this.分母 * 分数二.分子, this.分母 * 分数二.分母);
	}

	public 有理数 减(有理数 分数二) {
		return new 有理数(this.分子 * 分数二.分母 - this.分母 * 分数二.分子, this.分母 * 分数二.分母);
	}

	public 有理数 乘(有理数 分数二) {
		return new 有理数(this.分子 * 分数二.分子, this.分母 * 分数二.分母);
	}

	public 有理数 除(有理数 分数二) {
		if (分数二.分子 == 0)
			throw new ArithmeticException("不可除零!");
		return new 有理数(this.分子 * 分数二.分母, this.分母 * 分数二.分子);
	}

	public boolean 小于零() {
		return this.分子 < 0;
	}

	public void 负() {
		this.分子 = -this.分子;
	}

	public String toString() {
		if (this.分母 == 1)
			return Integer.toString(this.分子);
		return this.分子 + "/" + this.分母;
	}

	public boolean equals(Object 数) {
		if (!(数 instanceof 有理数))
			return false;
		有理数 数二 = (有理数) 数;
		return this.分子 == 数二.分子 && this.分母 == 数二.分母;
	}
}
56 楼 cloverprince 2009-01-20  
我的思路:

穷举所有数字的组合,穷举所有运算的组合,穷举运算符与数字的组合方式,求出表达式的值,过滤出值为24的表达式。

不同运算符有优先级问题,但是我可以避免这个问题。方法就是用“逆波兰式”。
给定4个数字和3个运算符,可以试图找到所有合法的逆波兰式。逆波兰式合法的定义就是不会使得遇到操作符时,堆栈里却没有足够的操作数。只要在生成逆波兰式的时候小心一点,记得判断就可以了。

我的实现:

module Main where

import List
import Ratio

main = putStr $ unlines $ map show $ work

work = filter (\x -> eval x == 24) $
       concat [applyAll nums ops | nums <- numPerms, ops<-opPerms]

numRange = [1..9]
numPerms = [[a,b,c,d] | a<-numRange, b<-numRange, c<-numRange, d<-numRange]

opList = ['+','-','*','/']
opPerms = [[x,y,z] | x<-opList, y<-opList, z<-opList]

opMap '+' = (+)
opMap '-' = (-)
opMap '*' = (*)
opMap '/' = (/)

type NumType = Double
data Elem = Num NumType | Op Char deriving (Show)

-- Given 4 numbers and 3 operators, generate all valid RPNs
applyAll :: [NumType] -> [Char] -> [[Elem]]
applyAll nums ops = applyAll' nums ops [] 0

applyAll' :: [NumType] -> [Char] -> [Elem] -> Int -> [[Elem]]
applyAll' []     []       sofar 1 = [reverse sofar]
applyAll' []     (op:ops) sofar sz = applyAll' [] ops ((Op op):sofar) (sz-1)
applyAll' (n:ns) (op:ops) sofar sz | sz>=2 =
    applyAll' (n:ns) ops      ((Op op):sofar) (sz-1) ++
    applyAll' ns     (op:ops) ((Num n):sofar) (sz+1) 
applyAll' (n:ns) ops sofar sz | otherwise = 
    applyAll' ns     ops      ((Num n):sofar) (sz+1)
applyAll' _      _   _     _ = []

-- Evaluate RPN
eval :: [Elem] -> NumType
eval es = head (foldl step [] es) where
    step stack (Num n) = (n:stack)
    step (n1:n2:ns) (Op op) = ((opMap op) n2 n1):ns


55 楼 kjj 2009-01-17  
andyjojo 写道
http://andyjojo.iteye.com/upload/picture/pic/29827/ef25018e-f28c-3dda-a306-65ea3d1fd3e6.bmp

I 'm in linux without input method ,your result has duplicate at line 2 and last line !
54 楼 lcllcl987 2009-01-16  
有趣, 如果有空我上一个Drools的实现
53 楼 andyjojo 2009-01-16  
http://andyjojo.iteye.com/upload/picture/pic/29827/ef25018e-f28c-3dda-a306-65ea3d1fd3e6.bmp
52 楼 andyjojo 2009-01-16  
很早之前的穷举法,没有考虑重复
51 楼 andyjojo 2009-01-16  
for (z = 0; z < 3; z++) {
  for (y = z + 1; y < 4; y++) {
    b[0] = a[z] + a[y];
    str1[0] = "( " + i[z] + " + " + i[y] + " )";

    b[1] = a[z] - a[y];
    str1[1] = "( " + i[z] + " - " + i[y] + " )";
    if (b[1] < 0) {
      b[1] = -b[1];
      str1[1] = "( " + i[y] + " - " + i[z] + " )";
    }

    b[2] = a[z] * a[y];
    str1[2] = "( " + i[z] + " * " + i[y] + " )";

    b[3] = a[z] / a[y];
    str1[3] = "( " + i[z] + " / " + i[y] + " )";

    b[4] = a[y] / a[z];
    str1[4] = "( " + i[y] + " / " + i[z] + " )";

    w = 0;
    for (x = 0; x < 4; x++) {
      if (x != z && x != y) {
        c[w] = x;
        w++;
      }
    }
    u = c[0];
    q = c[1];

    for (x = 0; x < 5; x++) {
      g[0] = a[u];
      str4[0] = "" + i[u] + "";
      g[1] = a[q];
      str4[1] = "" + i[q] + "";
      g[2] = b[x];
      str4[2] = "" + str1[x] + "";

      for (t = 0; t < 2; t++) {
        for (s = t + 1; s < 3; s++) {

          f[0] = g[t] + g[s];
          str2[0] = "( " + str4[t] + " + " + str4[s] + " )";

          f[1] = g[t] - g[s];
          str2[1] = "( " + str4[t] + " - " + str4[s] + " )";
          if (f[1] < 0) {
            f[1] = -f[1];
            str2[1] = "( " + str4[s] + " - " + str4[t] + " )";
          }

          f[2] = g[t] * g[s];
          str2[2] = "( " + str4[t] + " * " + str4[s] + " )";

          if (g[s] != 0) {
            f[3] = g[t] / g[s];
            str2[3] = "( " + str4[t] + " / " + str4[s] + " )";
          }

          if (g[t] != 0) {
            f[4] = g[s] / g[t];
            str2[4] = "( " + str4[s] + " / " + str4[t] + " )";
          }

          for (r = 0; r < 3; r++) {
            if (r != t && r != s) {
              n = r;
            }
          }

          for (p = 0; p < 5; p++) {
            h[0] = f[p] + g[n];
            str3[0] = " " + str2[p] + " + " + str4[n] + " = 24\n\r";
            if (Math.round(h[0]*1000000)== 24000000) {
                    System.out.println(str3[0]);
            }

            h[1] = f[p] - g[n];
            str3[1] = " " + str2[p] + " - " + str4[n] + " = 24\n\r";
            if (h[1] < 0) {
              h[1] = -h[1];
              str3[1] = " " + str4[n] + " - " + str2[p] + " = 24\n\r";
            }
            if (Math.round(h[1]*1000000)== 24000000) {
                    System.out.println(str3[1]);
            }

            h[2] = f[p] * g[n];
            str3[2] = " " + str2[p] + " * " + str4[n] + " = 24\n\r";
            if (Math.round(h[2]*1000000)== 24000000) {
                    System.out.println(str3[2]);
            }

            if (g[n] != 0) {
              h[3] = f[p] / g[n];
              str3[3] = " " + str2[p] + " / " + str4[n] + " = 24\n\r";
              if (Math.round(h[3]*1000000)== 24000000) {
                    System.out.println(str3[3]);
              }
            }

            if (f[p] != 0) {
              h[4] = g[n] / f[p];
              str3[4] = " " + str4[n] + " / " + str2[p] + " = 24\n\r";
              if (Math.round(h[4]*1000000)== 24000000) {
                    System.out.println(str3[4]);
              }
            }
          }
        }
      }
    }
  }
}
50 楼 liaogege 2009-01-16  
gbb21 写道
sdh5724 写道
谁能把代码控制在20行之内, 又有一定可读性。
比赛开始, 楼下继续。

把我python代码里面的记忆处理/或者表达式输出 去掉就20行以内了~

看来你python很不错哦!
49 楼 qdzheng 2009-01-16  
这儿的高手很多啊,本来想发个实现表达式计算的例子,不敢现丑啦。
48 楼 xnnyygn 2009-01-16  
基本思想是差不多,不过实现有些不同。

基本穷举想法是24点共有3次运算(加减乘除),假如原始数字为A,B,C,D,可得到的3次运算主要是两种,
((H,I)(J,K))或者,(((H,I),J),K),其中,A,B,C,D和H,I,J,K的映射有24种(4*3*2*1),运算共有6种(加减乘除、反减、反除,这里其实可以做优化,因为映射变了以后,减和反减其实多做了,不过是否可以完全去掉没有做过试验),则穷举的主要步骤是:

按照映射取得数据
第一种,两重循环(6*6)
取H,I的值,6种运算,得到E,
取J,K的值,6种运算,得到F
计算,E,F的6种运算。
第二种,类似的想法。

不过以上代码很长,考虑到这里主要是穷举计算式子的代码,所以,可以考虑把穷举出来的计算式子按照波兰式或者逆波兰式或者你自己喜欢的方式写到一个文件中去,程序在运行的时候读取就可以了。这是一个偏方,因为这个保存了半次结果,xy自己也只做到这一步(20行以内没有太大的问题)。
47 楼 iwfy 2009-01-15  
我的方法差不多可以压缩成20行,因为前面一大半代码都是判断4个1--9的数字。后面的js部分查不多是20行
46 楼 抛出异常的爱 2009-01-15  
sam.ds.chen 写道
抛出异常的爱 写道

	


果然算命的善用随机数。该算法唯一的不足就是当输入无解时程序会进入死循环(或者说程序通过这种进入死循环的方式来告诉我们“此题无解”)

下回给你免费算.....

有人说要用20行来写这个....
所以就不考虑遍历所有的内容了.
主要为好读.

如果遍历所有内容的话.没大可能写的太少了
-----------------------------------------------------

a b c d 原数据
Map map



第一次在adcd中取两个数放到e中(ab)(ba)(ac)(ca)(ad)(da)(bc)(cb)(bd)(db)(cd)(dc)a b c d
第二次 ........
第三次........

这样就得出来所有的可能组合了
之后循环4*4次就ok了.

相关推荐

    小学生C++趣味编程配套教学资源

    以知识点为中心,《小学生C++趣味编程》适D地弱化语法,注重算法。利用流程图厘清思路,激发学习兴趣,培养计算思维。 本资源为官方正版配套教学资源,包含: 1)全书涉及的所有源代码(包含完整代码和不完整代码[即...

    python趣味编程100例(99个)

    "Python趣味编程100例(99个)"这个资源显然是为了帮助初学者通过一系列有趣的实践例子来学习Python编程。 在Python编程中,基础是非常重要的。例如,了解变量的声明和使用,数据类型如整型(int)、浮点型(float)、...

    青少年趣味编程Python系列课程--2019-09-23.pdf

    标题《青少年趣味编程Python系列课程--2019-09-23》以及描述《青少年趣味编程Python系列课程--2019-09-23》揭示了该文件是一份针对青少年的Python编程课程计划,时间为2019年9月23日。文档的标签为“python学习 系列...

    《Scratch趣味编程》.pdf

    《Scratch趣味编程》 《Scratch趣味编程》是一种图形化的编程语言,由美国麻省理工学院研发,可以轻松地创建自己互动故事、动画、游戏、音乐和艺术。 Scratch将程序语言设计成一块块积木,你只要用拖拉的方式,将...

    c++趣味编程配套课件

    C++趣味编程是一门引人入胜的课程,旨在帮助初学者理解编程基础,并通过实践探索编程的乐趣。在这个配套课件中,我们将深入探讨C++语言的各个方面,使其成为掌握编程概念的有效工具。 首先,我们要了解C++的基本...

    趣味矩阵算法实现源代码

    标题中的“趣味矩阵算法实现源代码”意味着我们将探讨一种用编程语言实现的,能够打印或操作特定模式矩阵的方法。这可能包括递归、循环或其他控制结构,以按照预设的规则填充和展示矩阵。 描述中的“算法分析与设计...

    小学生C++趣味编程 C++源代码(2021.11.22).rar

    标题中的“小学生C++趣味编程 C++源代码(2021.11.22).rar”表明这是一个专为小学生设计的C++编程学习资源包,包含了2021年11月22日更新的源代码。这个资源旨在以有趣的方式介绍C++编程基础,帮助孩子们在早期阶段...

    24点游戏的算法及实现

    24点游戏是一种深受人们喜爱的智力挑战游戏,它的...总的来说,24点游戏的算法实现是一个涉及排列组合、数学运算和递归编程的有趣课题。通过学习和实践,我们可以不仅提高编程技巧,还能增强逻辑推理和问题解决能力。

    《小学生C++趣味编程》-C++、Scratch(2023.09.24)C.pdf

    《小学生C++趣味编程》是一本面向初学者,特别是小学生的教材,旨在通过结合C++编程语言和Scratch可视化编程工具,激发孩子们对编程的兴趣。该书内容涵盖基础的编程概念,逐步引导学生掌握编程思维和技能。以下是书...

    python算法趣味题目

    ### Python算法趣味题目详解 #### 题目背景与概述 本文将介绍并解析两道有趣的Python算法题目,旨在帮助读者更好地理解Python语言的特点及其在处理字符串方面的优势。通过具体的示例代码,我们将深入探讨Python...

    python趣味编程100例.7z

    《Python趣味编程100例》是一份专为Python初学者设计的学习资源,它通过100个精心挑选的编程实例,旨在帮助新手快速掌握Python编程的基础知识和实践技巧。这个压缩包包含了丰富的源代码,并且每个示例都有详细的注释...

    Scratch编程入门与算法进阶.pptx

    第二部分是算法进阶,详细介绍了几个经典的算法问题及其对应的Scratch实现。这些问题包括约瑟夫环问题、最长回文子串、0/1背包问题、拓扑排序等。通过这些实例,读者可以深入理解算法的本质和实现方法,提高解决问题...

    Java趣味编程100例 清华大学出版社.zip

    本书取材注重趣味性与实用性,内容涵盖了Java编程的基础知识和常用算法,讲解时给出了实例的详细代码及注释。本书附带1张光盘,收录了本书配套多媒体教学视频及实例源文件,可大大方便读者高效、直观地学习本书内容...

    Scratch编程入门与算法进阶.docx

    Scratch 编程入门与算法进阶 Scratch 是一款为青少年设计的编程语言和平台,由麻省理工学院的媒体实验室(Media Lab)和哈佛大学的实验室(Graduate School of Education)联合开发。Scratch 的起源与发展可以追溯...

    “编”玩边学:Scratch趣味编程进阶妙趣横生的数学和算法.pptx

    "编"玩边学:Scratch趣味编程进阶妙趣横生的数学和算法 《“编”玩边学:Scratch趣味编程进阶妙趣横生的数学和算法》是一本旨在通过Scratch编程语言教授数学和算法知识的书籍。这本书的内容丰富、生动有趣,适合中...

    C/C++趣味编程100例

    《C/C++趣味编程100例》一书精选了100个经典、实用且充满趣味性的程序设计实例,旨在通过实践加深读者对C/C++语言的理解与掌握。本书覆盖了从基本图形绘制到复杂算法实现的广泛内容,不仅适合初学者入门,也能够帮助...

    教学论文:利用Scratch趣味编程与Pascal语言互动教学例谈.docx

    本文主要探讨了如何利用Scratch趣味编程与Pascal语言的互动教学方法,以提高小学生对编程的理解和兴趣。以下是对标题和描述中关键知识点的详细说明: 1. **Scratch趣味编程**:Scratch是一种面向儿童的图形化编程...

    趣味编程百例

    "趣味编程百例"是一个可能包含一系列有趣且富有挑战性的编程练习的集合,旨在帮助学习者提高编程技能,同时享受编程的乐趣。这些编程题目通常涵盖了基础到进阶的各种难度,适合不同程度的程序员进行实践和提升。 在...

    java趣味算法经典趣味算法

    6. **位操作**:Java的位操作可以用于高效地处理二进制数据,如快速幂运算、奇偶性检查等,是实现一些趣味算法的有效手段。 7. **模拟算法**:模拟真实世界的情况,如抛硬币、抽卡等概率问题,可以通过Java程序进行...

    JAVA趣味编程100实例

    在标题“JAVA趣味编程100实例”下,描述中提到“很实用的java趣味编程小程序”,这说明本文件旨在通过有趣的编程实例来帮助学习者加深对Java语言的理解和应用能力。通过解决实际问题来提高编程技能,这些实例很可能...

Global site tag (gtag.js) - Google Analytics