JAVA—— 運用ArrayList實現邏輯推理題(誰養魚)
阿新 • • 發佈:2018-11-10
運用ArrayList實現邏輯推理題(誰養魚)
1.窮舉法
窮舉法的基本思想是根據題目的部分條件確定答案的大致範圍,並在此範圍內對所有可能的情況逐一驗證,直到全部情況驗證完畢。若某個情況驗證符合題目的全部條件,則為本問題的一個解;若全部情況驗證後都不符合題目的全部條件,則本題無解。
2.誰養魚
用筆窮舉的速度非常慢,《誰養魚》是愛因斯坦在20世紀初出的謎語,他說世界上有百分之98的人答不出來。你能答出來嗎?
這道邏輯性很強的題是:
1)在一條街上有5座房子,噴了5種顏色。
2)每個房子裡住著不同國籍的人.
3)每個人喝不同的飲料,抽不同品牌的香菸,養不同的寵物。
問題是:誰養的是魚?
所列舉項應該滿足如下15個要求:
- 英國人住紅色房子;
- 瑞典人養狗;
- 丹麥人喝茶;
- 綠色房子在白色房子左邊;
- 綠色房子主人喝咖啡;
- 抽PalMal香菸的人養鳥;
- 黃色房子主人抽Dunhill香菸;
- 住在中間房子的人喝牛奶;
- 挪威人住第一間房;
- 抽Blends香菸的人住在養貓的人隔壁;
- 養馬的人住抽Dunhill香菸的人隔壁;
- 抽BlMt的人喝啤酒;
- 德國人抽Prince香菸;
- 挪威人住藍色房子隔壁;
- 抽Blends香菸的人有一個喝水的鄰居。
3.原理
- Init()方法中建立ArrayList列表集合,運用多種迴圈進行判斷獲得各組資料之間的組合方式,並將符合要求的組合方式放入列表集合中。迴圈遍歷列表集合,將元素放入顏色、人員、飲料等陣列中。
- calculate()方法呼叫init()方法對陣列元素進行初始化。迴圈判斷比較各陣列元素的關係獲得符合原題要求的元素的索引,再根據 show()方法迴圈將指定素引的元素列印到控制檯。
4.語法
- ArrayList是List介面的一個可變長陣列實現,實現了所有List介面的操作,並允許儲存空(null)值。除沒有進行同步,ArrayList基本等同於Vector。在Vectors中幾乎對所有的方法都進行同步,但ArrayList僅對writeObject()和readObject()進行同步。其他如add()、remove()等都沒有同步。
- ArrayList實現了Java.io.Serializable介面,所以ArrayList物件可以序列化到持久儲存介質中。
- 例項化一個ArrayList物件時,可以指定一個初始容量,預設的容量為10。當元素超過ArrayList物件的初始大小時,容器容量大小増加原來的50%。
5.程式碼
主程式:
public static void main(String args[]) {
//Java程式主入口
rw33 test=new rw33();//例項化物件
long l=System.currentTimeMillis();//獲得系統時間
test.calculate();//呼叫的方法進行計算統計
System.out.println("計算共用時:"+(System.currentTimeMillis()-l)+"ms");//獲得計算所花費的時間
}
計算一組資料的組合方式:
public void init() {
//計算一組資料的組合方式
ArrayList array=new ArrayList();//建立集合陣列
for(int num1=0;num1<5;num1++) {
for(int num2=0;num2<5;num2++) {
if(num2==num1)
continue;
for(int num3=0;num3<5;num3++) {
if(num3 ==num2||num3==num1)
continue;
for(int num4 =0;num4<5;num4++) {
if(num4==num3||num4==num2||num4==num1)
continue;
for (int num5=0;num5<5;num5++) {
if(num5==num4||num5==num3||num5==num2||num5==num1)
continue;
int oneArray[]= {num1,num2,num3,num4,num5};
array.add(oneArray);
}
}
}
}
}
color=new int[array.size()][5];//建立顏色的二維陣列
for(int count=0;count<array.size();count++) {
//迴圈陣列時初始化房子顏色資料
color[count]=(int[])array.get(count);
}
person=color;
drink=color;
smoke=color;
pet = color;
}
判斷運算:
public void calculate() {
//判斷運算
init();//呼叫方法時初始化資料
for(int num1=0;num1<color.length;num1++) {
if(!con4(num1))
continue;
if(!con14(num1))
continue;
for(int num2=0;num2<person.length;num2++) {
if(!con1(num2,num1))
continue;
if(!con9(num2))
continue;
for(int num3=0;num3<drink.length;num3++) {
if(!con3(num2,num3))
continue;
if(!con5(num1,num3))
continue;
if(!con8(num3))
continue;
for(int num4=0;num4<smoke.length;num4++) {
if(!con7(num1,num4))
continue;
if(!con12(num4,num3))
continue;
if(!con13(num2,num4))
continue;
if(!con15(num4,num3))
continue;
for(int num5=0;num5<pet.length;num5++) {
if(!con2(num2,num5))
continue;
if(!con6(num4,num5))
continue;
if(!con10(num4,num5))
continue;
if(!con11(num5,num4))
continue;
total++;
show(num1,num2,num3,num4,num5);
}
}
}
}
}
}
滿足所列舉項的條件:
- 英國人住紅色房子
public boolean con1(int cy,int cl) {
//英國人住紅色房子
for(int i=0;i<5;i++) {
if(person[cl][i]==0) {
if(color[cy][i]==0) {
return true;
}else
break;
}
}
return false;
}
- 瑞典人養狗
public boolean con2(int cy,int p) {
//瑞典人養狗
for(int i=0;i<5;i++) {
if(person[cy][i]==1) {
if(pet[p][i]==0) {
return true;
}else
break;
}
}
return false;
}
- 丹麥人喝茶
public boolean con3(int cy,int d) {
//丹麥人喝茶
for(int i=0;i<5;i++) {
if(person[cy][i]==2) {
if(drink[d][i]==0) {
return true;
}else
break;
}
}
return false;
}
- 綠色房子在白色房子左面
public boolean con4(int cl) {
//綠色房子在白色房子左面
int c1=0;//白房子
int c2=0;//綠房子
for(int i=0;i<5;i++) {
if(color[cl][i]==1) {
c1=i;
}
if(color[cl][i]==2) {
c2=i;
}
}
if(c2<c1)
return true;
else
return false;
}
- 綠色房子的主人喝咖啡
public boolean con5(int cl,int d) {
//綠色房子的主人喝咖啡
for(int i=0;i<5;i++) {
if(color[cl][i]==2) {
if(drink[d][i]==1) {
return true;
}else
break;
}
}
return false;
}
- 抽PalMal香菸的人養鳥
public boolean con6(int s,int p) {
//抽PalMal香菸的人養鳥
for(int i=0;i<5;i++) {
if(smoke[s][i]==0) {
if(pet[p][i]==1) {
return true;
}else
break;
}
}
return false;
}
- 黃色房子主人抽Dunhill香菸
public boolean con7(int cl,int s) {
//黃色房子主人抽Dunhill香菸
for(int i=0;i<5;i++) {
if(color[cl][i]==4) {
if(smoke[s][i]==1) {
return true;
}else
break;
}
}
return false;
}
- 住在中間房子的人喝牛奶
public boolean con8(int d) {
//住在中間房子的人喝牛奶
if(drink[d][2]==2)
return true;
else
return false;
}
- 挪威人住第一間房
public boolean con9(int cy) {
//挪威人住第一間房
if(person[cy][0]==3)
return true;
else
return false;
}
- 抽Blends香菸的人住在養貓人隔壁
public boolean con10(int s,int p) {
//抽Blends香菸的人住在養貓人隔壁
for(int i=0;i<5;i++) {
if(smoke[s][i]==4) {
if(i<4&&pet[p][i+1]==2) {
return true;
}
if(i>0&&pet[p][i-1]==2) {
return true;
}
break;
}
}
return false;
}
- 養馬的人住抽Dunhill香菸的人隔壁
public boolean con11(int p,int s) {
//養馬的人住抽Dunhill香菸的人隔壁
for(int i=0;i<5;i++) {
if(pet[p][i]==3) {
if(i<4&&smoke[s][i+1]==1) {
return true;
}
if(i>0&&smoke[s][i-1]==1) {
return true;
}
break;
}
}
return false;
}
- 抽BlMt的人喝啤酒
public boolean con12(int s,int d) {
//抽BlMt的人喝啤酒
for(int i=0;i<5;i++) {
if(smoke[s][i]==2) {
if(drink[d][i]==3) {
return true;
}else
break;
}
}
return false;
}
- 德國人抽Prince香菸
public boolean con13(int cy,int s) {
//德國人抽Prince香菸
for(int i=0;i<5;i++) {
if(person[cy][i]==4) {
if(smoke[s][i]==3) {
return true;
}else
break;
}
}
return false;
}
- 挪威人住藍色房子隔壁
public boolean con14(int c) {
//挪威人住藍色房子隔壁
if(color[c][1]==3)
return true;
else
return false;
}
- 抽Blends香菸的人有一個喝水的鄰居
public boolean con15(int s,int d) {
//抽Blends香菸的人有一個喝水的鄰居
for(int i=0;i<5;i++) {
if(smoke[s][i]==4) {
if(i<4&&drink[d][i+1]==4) {
return true;
}
if(i>0&&drink[d][i-1]==4) {
return true;
}
break;
}
}
return false;
}
顯示計算之後的每個陣列找出對應答案:
public void show(int n1,int n2,int n3,int n4,int n5) {
//顯示計算之後的每個陣列找出對應答案
System.out.println("第"+total+"組:>");
System.out.println("1\t\t2\t\t3\t\t4\t\t5\t\t");
for(int i=0;i<5;i++)//迴圈顯示房子陣列資料
System.out.print(HOUSES[color[n1][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//迴圈顯示人員陣列資料
System.out.print(PERSONS[person[n2][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//迴圈顯示飲料陣列資料
System.out.print(DRINKS[drink[n3][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//迴圈顯示煙陣列資料
System.out.print(SMOKES[smoke[n4][i]]+"\t\t");
System.out.println