---
tags: AI
disqus: HackMD
---
人工智慧 Homework #1 #2
===
In the circles of A to J, fill in numbers from 1 to 10 randomly
such that the values in the triangles are equal to the summations
of the values filled in the circles surrounding the triangles,
for example A+D+E= 18 and so on.
Part 1: Due in 12/Nov./2020 midnight.
(a) Use Breadth First Search, Uniform Cost Search (deep level as cost),
and Depth First Search to find out possible solution(s).
(b) For these three methods also count the nodes expanded
for finding the solution(s).
Part 2: Due in 19/Nov./2020 midnight
Using the solution found in Part 1,
invent a heuristic function f (e.g. node level + f(n) or others )
to find the route to the solution. Also count the nodes expanded
for finding the solution(s).
加載程式所需的函示庫
---
```python=
import collections
import numpy as np
from itertools import permutations
```

將上圖中所用到的數值存入容器
---
```python=
nodeValues = {}
initNodesSum = {
'ACD': 19, 'ADE': 18,
'BCF': 11, 'DEG': 16,
'FHI': 17, 'GHJ': 22
}
triangleNodes = {
'ACD': ['BCF', 'ADE', 'DEG'],
'ADE': ['DEG'],
'BCF': ['FHI'],
'DEG': ['GHJ'],
'FHI': ['GHJ'],
'GHJ': ['FHI']
}
NextNodes = {
'A': ['B', 'C', 'D', 'E'],
'B': ['C', 'F', 'I'],
'C': ['B', 'D', 'F'],
'D': ['C', 'E', 'G'],
'E': ['D', 'G', 'J'],
'F': ['H', 'I'],
'G': ['H', 'J'],
'H': ['I', 'J'],
'I': ['J'],
'J': []
}
```
將圖中三角形周圍節點 A-J 以 1-10 數字填滿
並滿足三角形周圍三個節點相加等於三角形中的數字
例如:A+C+D=19
以窮舉法計算出三角形周圍節點數字
避免浪費計算時間,遇到相鄰數字相同則跳過
並排除計算三角形周圍節點相加不等於欲求總和的組合
例如:A+C+D=19 非19則跳過不處理
```python=
def get_random_dict():
for kA in range(1, 11):
for kB in range(1, 11):
if kA == kB:
continue
for kC in range(1, 11):
if kC == kA or kC == kB:
continue
for kD in range(1, 11):
if kD == kC or kD == kB or kD == kA or kA + kC + kD != initNodesSum.get('ACD'):
continue
for kE in range(1, 11):
if kE == kD or kE == kC or kE == kB or kE == kA or kA + kD + kE != initNodesSum.get('ADE'):
continue
for kF in range(1, 11):
if kF == kE or kF == kD or kF == kC or kF == kB or kF == kA or kB + kC + kF != initNodesSum.get('BCF'):
continue
for kG in range(1, 11):
if kG == kF or kG == kE or kG == kD or kG == kC or kG == kB or kG == kA or kD + kE + kG != initNodesSum.get('DEG'):
continue
for kH in range(1, 11):
if kH == kG or kH == kF or kH == kE or kH == kD or kH == kC or kH == kB or kH == kA:
continue
for kI in range(1, 11):
if kI == kH or kI == kG or kI == kF or kI == kE or kI == kD or kI == kC or kI == kB or kI == kA or kF + kH + kI != initNodesSum.get('FHI'):
continue
for kJ in range(1, 11):
if kJ == kI or kJ == kH or kJ == kG or kJ == kF or kJ == kE or kJ == kD or kJ == kC or kJ == kB or kJ == kA or kG + kH + kJ != initNodesSum.get('GHJ'):
continue
if kA + kC + kD == initNodesSum.get('ACD') and \
kA + kD + kE == initNodesSum.get('ADE') and \
kB + kC + kF == initNodesSum.get('BCF') and \
kD + kE + kG == initNodesSum.get('DEG') and \
kF + kH + kI == initNodesSum.get('FHI') and \
kG + kH + kJ == initNodesSum.get('GHJ'):
nodeValues['A'] = kA
nodeValues['B'] = kB
nodeValues['C'] = kC
nodeValues['D'] = kD
nodeValues['E'] = kE
nodeValues['F'] = kF
nodeValues['G'] = kG
nodeValues['H'] = kH
nodeValues['I'] = kI
nodeValues['J'] = kJ
return
```
搭配隊列結構容器執行BFS及DFS演算法
---
```python=
def getflow(root, method):
visited = set() # 暫存所有訪問過的節點紀錄
queue = collections.deque([root]) # 將起始節點加入隊列結構容器
flow = collections.deque() # 紀錄訪問流程
visited.add(root)
while queue:
triangle = queue.popleft() # 從隊列頭部(左端)取出進行後續演算法處理
flow.append(triangle)
IsFirst = True # DFS用於紀錄節點處理相鄰之集合
for next_triangle in triangleNodes[triangle]: # 處理節點所有相鄰之集合
if next_triangle not in visited: # 訪問過的節點跳過不處理
if method == 'BFS':
queue.append(next_triangle)
elif method == 'DFS':
if IsFirst:
queue.appendleft(next_triangle) # 加入到隊列左端,走到盡頭時可往返到上一層
else:
queue.insert(1, next_triangle) # 加入到處理中的隊列左端下一個節點
IsFirst = False
visited.add(next_triangle)
return flow
```
使用貪婪優先搜尋法找出最短路徑
---
```python=
visited = set()
flow = collections.deque()
flow.append(startNode)
while True:
neighborDist = 10
visited.add(startNode)
for nodes in NextNodes[startNode]:
if nodes not in visited:
if abs(nodeValues['A'] - nodeValues[nodes]) < neighborDist:
neighborDist = abs(nodeValues['A'] - nodeValues[nodes])
nextNode = nodes
startNode = nextNode
flow.append(nextNode)
if nextNode in endNode:
break
return list(flow)
```
主程式開始
---
```python=
if __name__ == '__main__':
get_random_dict()
print('Nodes value:', end=' ')
IsFirst = True
for val in nodeValues:
if IsFirst:
IsFirst = False
print(val + ': ' + str(nodeValues.get(val)), end='')
else:
print(', ' + val + ': ' + str(nodeValues.get(val)), end='')
print()
print()
BFSFlow = getflow('ACD', 'BFS')
print('BFS Path:', end=' ')
for path in BFSFlow:
if path == BFSFlow[-1]:
print(path)
else:
print(path, '->', end=' ')
print()
DFSFlow = getflow('ACD', 'DFS')
print('DFS Path:', end=' ')
for path in DFSFlow:
if path == DFSFlow[-1]:
print(path)
else:
print(path, '->', end=' ')
print()
shortestPath = getShortestPath('A', ['I', 'J'])
print('Shortest Path: ', end=' ')
for path in shortestPath:
if path == shortestPath[-1]:
print(path)
else:
print(path, '->', end=' ')
```
result
---
:::info
Nodes value: A: 9, B: 6, C: 2, D: 8, E: 1, F: 3, G: 7, H: 10, I: 4, J: 5
BFS Path: ACD -> BCF -> ADE -> DEG -> FHI -> GHJ
DFS Path: ACD -> BCF -> FHI -> GHJ -> DEG -> ADE
Shortest Path: A -> D -> G -> H -> J
:::