同學幫他侄兒問我一個問題:
資源:
1、小明的錢可以購買50瓶汽水。
2、老闆搞促銷,兩個空汽水瓶子可以換一瓶汽水。
問:小明最多能喝多少瓶汽水?
開始還楞了一下, 現在的小學題目還真不簡單。不過馬上給出答案:
先是50瓶,然後用50個空瓶換來25瓶,喝完後用25個空瓶換12瓶再多個空瓶,
喝完後用13個空瓶換6瓶,然後是7個空瓶換3瓶,然後是4個空瓶換2瓶,
然後是2個空瓶換1瓶,最後問老闆借1個空瓶,再用2個空瓶換1瓶,
剩下來那個空瓶還給老闆。所以喝到50+25+12+6+3+2+1+1=100
不過最近在學習規則引擎, 於是就想到了怎麼用規則引擎來實現。
我的想法是:
1: 假設汽水一元一瓶, 則小明最初有50元。
2: 如果兜裏有超過一元錢, 則買一瓶汽水喝, 此時:
錢減少一元,同時擁有的空瓶增加一個。
3: 如果擁有至少兩個空瓶, 則兩個空瓶賣給老闆, 兜裏的錢加一。
根據如上想法, 有了如下規則引擎的實現的實現(Drool):
java文件SodaWater.java:
package org.drools.examples;
import java.io.InputStreamReader;
import java.io.Reader;
import org.drools.FactHandle;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import org.drools.WorkingMemory;
import org.drools.compiler.PackageBuilder;
import org.drools.rule.Package;
public class SodaWater
{
public static final void main(String[] args) throws Exception {
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( SodaWater.class.getResourceAsStream( "SodaWater.drl" ) ) );
final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( builder.getPackage() );
final StatefulSession session = ruleBase.newStatefulSession();
Customer customer = new Customer( "XiaoMing", 50);
session.insert(customer);
session.fireAllRules();
}
public static class Customer
{
private String name;
private int money;
private int drinkSum;
private int blankCup;
public Customer(String name, int money)
{
this.name = name;
this.money = money;
this.drinkSum = 0;
this.blankCup = 0;
}
public int getMoney()
{
return money;
}
public void setMoney(int money)
{
this.money = money;
}
public int getBlankCup()
{
return blankCup;
}
public void setBlankCup(int blankCup)
{
this.blankCup = blankCup;
}
public int getDrinkSum()
{
return drinkSum;
}
public void setDrinkSum(int drinkSum)
{
this.drinkSum = drinkSum;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
}
rule文件:
package org.drools.examples
dialect "mvel"
import org.drools.examples.SodaWater.Customer
rule "buy a soda water and drink"
when
$c : Customer(money > 0, $m:money, $b:blankCup, $d:drinkSum)
then
$c.money = $m - 1;
$c.blankCup = $b + 1;
$c.drinkSum = $d + 1;
System.out.println( "Customer " + $c.name + " now buy a soda water and drink: money=" + $c.money + " and blankCup=" + $c.blankCup);
update($c);
end
rule "sale blank cup and get money"
when
$c : Customer(blankCup > 1, $b:blankCup, $m:money )
then
$c.blankCup = $b - 2;
$c.money = $m + 1;
System.out.println("Customer " + $c.name + " now sale 2 cups and get money: money=" + $c.money + ", blankCup=" + $c.blankCup);
update($c);
end
rule "finish drink"
no-loop true
dialect "java"
when
$c : Customer(blankCup < 2, money == 0)
then
System.out.println( "Customer " + $c.getName() + " finished drink, and drink number is " + $c.getDrinkSum() + " blankCup=" + $c.getBlankCup());
end
運行結果如下:
Customer XiaoMing now buy a soda water and drink: money=49 and blankCup=1
Customer XiaoMing now buy a soda water and drink: money=48 and blankCup=2
Customer XiaoMing now sale 2 cups and get money: money=49, blankCup=0
Customer XiaoMing now buy a soda water and drink: money=48 and blankCup=1
Customer XiaoMing now buy a soda water and drink: money=47 and blankCup=2
...
Customer XiaoMing now buy a soda water and drink: money=1 and blankCup=1
Customer XiaoMing now buy a soda water and drink: money=0 and blankCup=2
Customer XiaoMing now sale 2 cups and get money: money=1, blankCup=0
Customer XiaoMing now buy a soda water and drink: money=0 and blankCup=1
Customer XiaoMing finished drink, and drink number is 99 blankCup=1
不過小明最後手上還有最後一個瓶子, 計算機只能到此了。
向老闆借一個瓶子換一瓶汽水,喝完在還一個空瓶子,估計就是人類智慧來。
此程序需要drools的jar包,具體可見:
http://lcllcl987.iteye.com/blog/254381
看看大家還有什麼好的算法。