# 計算機程式設計HW ## 共五題 1. 賓果遊戲 2. 部落旅遊(BFS Application) 3. 理想大學環境 4. 黃金分配 5. 基因序列 ### 賓果遊戲 第一行,輸入整數 N、M ( 1 <= M < N×N )。 第二行,輸入 A 的 N×N 個數字,代表 A 的賓果宮格。 第三行,輸入 B 的 N×N 個數字,代表 B 的賓果宮格。 第四行,輸入M 個數字,表示賓果數字。 輸入範例: 3 7 1 2 3 4 5 6 7 8 9 2 3 4 5 1 6 9 7 8 7 2 3 6 9 8 4 輸出範例: A Win ```python= def checkBingo(data, store, num, N): row, col = data.index(num)//N, data.index(num)%N store[row] += 1 store[col + N] += 1 #從N開始紀錄col的value if row == col: store[N*2] += 1 if row == (N-1-col): store[N*2+1] += 1 def compute(data, selected, N): store = [0 for i in range(2*N+2)]#init 連線紀錄 for num in selected: checkBingo(data, store, num, N) print(store) if N in store:return 'Bingo' return 'sorry' #print(compute([1,3,5,7,9,2,4,6,8],[1,2,3,5],3)) def compete(dataA, dataB, selected, N, M): storeA = [0 for i in range(2*N+2)] storeB = [0 for i in range(2*N+2)] for num in selected: checkBingo(dataA, storeA, num, N) checkBingo(dataB, storeB, num, N) if N in storeA and N in storeB: return 'Tie' elif N in storeA: return 'A win' elif N in storeB: return 'B win' return 'Tie' def main(): inputData = input().split() N, M = int(inputData[0]), int(inputData[1]) dataA = input().split() dataB = input().split() selected = input().split() print(compete(dataA, dataB, selected , N, M)) main() ``` ### 部落旅遊 輸入說明: 第一行 N, X, Z, Y,N 是道路數量,X 代表起始點城市,Z 代表終點城市,Y 代表必經城市, 若沒有 Y,則不考慮中途點。 其後 N 行,每一行輸入格式為 A B,代表 A 城市與 B 城市間有道路相連接。 輸出說明: 找出 X 中途經過 Y 城市抵達 Z 的路徑, 若存在,則輸出走過最少通道個數與最短路徑。 若不存在此路徑,輸出 NO。 輸入範例 1: 6 1 3 1 5 7 5 4 5 3 5 2 3 4 3 輸出範例 1: 2 1 5 3 -------------------------------------------------------------------------------------------------------------- 輸入範例 2: 6 1 4 3 1 2 1 3 2 4 2 5 3 5 5 4 輸出範例 2: 3 1 3 5 4 ```python= def addAdj(graph, edge, y):#adjacent Adj = graph[edge] if edge in graph.keys() else []#'1':[2,5] #'1':[] if y not in Adj: Adj.append(y)#'1':[2,5,3] graph[edge] = Adj#restored def addPair(graph, pair):#[1, 3] cuz of undirected graph addAdj(graph,pair[0],pair[1]) addAdj(graph,pair[1],pair[0]) def BFS(graph, source, target):#graph, 1, 3 visitedNodes = dict() #拜訪過(black) queue = [[source, 0]] #gray while True: if len(queue) == 0: return -1 #此圖空了 currentNode = queue.pop(0) currentNodeName = currentNode[0]#node = '1' level = currentNode[1]#level = 0 if currentNodeName == target: #find it path = findPath(graph, visitedNodes, currentNodeName, level - 1) return level, path visitedNodes[currentNodeName] = level #存入至拜訪過的node for node in graph[currentNodeName]:#visit adj node if node not in visitedNodes.keys():#if the node haven't visited queue.append([node, level + 1]) def findPrevNode(graph, visitedNodes:dict, targetNode, level): nodeCandidate = [] for nodeName, nodeLevel in visitedNodes.items(): if nodeLevel == level: nodeCandidate.append(nodeName) for nodeName in nodeCandidate: if targetNode in graph[nodeName]: return nodeName def findPath(graph, visitedNodes:dict, currentNodeName, level): path = [] while level >= 0: nodeName = findPrevNode(graph, visitedNodes, currentNodeName, level) path.append(nodeName) level = level - 1 currentNodeName = nodeName#將現在的點作為基準點 return path #top down method def main(): graph = dict() #eg.{'1':[3,5,6], # '3':[1,2,4] # '4':[3]} edge = [] par = input().split()#eg.6 1 3 implies 6(edges),1 to 3 #preprocessing for i in range(int(par[0])): edge.append(input().split()) for pair in edge: addPair(graph, pair) #start if len(par) == 3: res = BFS(graph, par[1], par[2]) #print('start') if res == -1:#level = -1 不存在 print('No') else: res[1].reverse() print(res[0]) print(*res[1], par[2]) elif len(par) == 4: resFirstHalf = findAdj(graph,par[1],par[3])#前半段 resSecondHalf = findAdj(graph,par[3],par[2])#後半段 if resFirstHalf == -1 or resSecondHalf == -1: print('NO') else: resFirstHalf[1].reverse() resSecondHalf[1].reverse() print(resFirstHalf[0]+resSecondHalf[0]) print(*resFirstHalf[1],*resSecondHalf[1],par[2]) main() ``` ### 理想大學環境 輸入說明: 第一行,輸入一個正整數 N,代表房屋個數 N ,( 1<= N <=10 )。 其後 N 行,每一行第一項為房屋名稱,接著為其屬性。 房屋名稱最多有 15 個字母,各屬性為 2 個字母。 房屋與屬性資料均為英文字母組成,房屋名稱及各屬性間以 1 個空白分隔。 接下來一行,輸入一個正整數 M,為查詢條件,( 1<= M <=10 ) 其後 M 行,每一行有一個查詢。查詢條件為房屋屬性組成,每個房屋屬性為 2 個字元。 用 + 號區格的條件代表"或" 的關係,沒有 + 區隔的條件代表 "且" 的關係。 屬性間及 + 之間有 1 個空白間隔。例如: GF BS + CT RH 代表需找出【有美食且為學區房】或【交通方便且為毛胚屋】的所有房屋名稱。 其格式如下:XX YY + AA BB 意思為屬性條件為: XX 且 YY,或是 AA 且 BB。 最後一 行輸入一個正整數 b, 當 b=0時,代表輸出能符合條件的房屋。 例如:條件 GF BS + CT RH,房屋屬性 PMansion CT BS PS RH , 則 PMansion 符合條件。 當 b=1,代表輸出符合最多條件的房屋。 例如:條件 GF BS + CT RH,房屋屬性 PMansion CT BS PS RH、 AgoraGarden GF CT BS RH PS,則輸出 AgoraGarden。 輸出說明: 根據每個查詢條件輸出所有符合之房屋名稱。如有 M 個查詢條件,即會有 M 行輸出。 若一個查詢條件中有多個房屋符合,請按照字典序排序各房屋名稱,房屋間以一個空白分隔。 -------------------------------------------------------------------------------------------------------------- 輸入範例 1: 5 AgoraGarden GF CT BS RH PS PMansion CT BS PS RH JingAnMansion BS NP CT DaAnPark NP CT SH SinZhangCity NH BS SH 2 BS RH + CT SH GF + NM BS + NH SH 0 輸出範例 1: AgoraGarden DaAnPark PMansion AgoraGarden SinZhangCity ```python= def getData(): mapTable = {} n = int(input()) for i in range(n): item = input().split() mapTable[item[0]] = set(item[1:]) return mapTable def match(requirements, feature, b): clauses = requirements.split('+') maxNum = 0 for i in range(len(clauses)): if b == 0: if feature.issuperset((set(clauses[i].split()))):#物件的特徵是否超過要求 return -1 if b == 1: k = len(feature&set(clauses[i].split()))#看多少set重複 if k >= len(clauses[i].split()):maxNum += 1#此物件特徵滿足該clause中所有要求 return maxNum def compute(requirements, unsortedMapTable, b): data = {} #原傳入unsorted sortedMapTable = {} for key in sorted(unsortedMapTable): sortedMapTable[key] = unsortedMapTable[key] for name, feature in sortedMapTable.items(): data[name] = match(requirements, feature, b) if b == 0: for name in data.keys(): if data[name] == -1: print(name, end = ' ') if b == 1: value = max(data.values()) for key, v in data.items(): if v == value:print(key,end=' ') print() def main(): mapTable = getData() n = int(input()) dataList = [] for i in range(n): dataList.append(input()) b = int(input()) for i in range(n): compute(dataList[i], mapTable, b) main() ``` ### 黃金分配 N塊黃金,每一塊黃金range1~X公克「平均」分給x,y,z三個人,每人最多不得拿M塊,有幾種分法 N=5,重=[1, 2, 3, 4, 5],每人最多拿2塊,6種分法 [A, B, C]={( [1, 4], [2, 3], [5]), ( [1, 4], [5], [2, 3]) , ( [2, 3], [1, 4], [5]), ([2, 3], [5], [1, 4]),( [5],[1, 4], [2, 3])} 輸入範例: [1, 2, 3, 4, 5],2 輸出範例: ((2, 3), (1, 4), (5,)) ((1, 4), (5,), (2, 3)) ((5,), (2, 3), (1, 4)) ((2, 3), (5,), (1, 4)) ((1, 4), (2, 3), (5,)) ((5,), (1, 4), (2, 3)) ```python= def check(partition, value, M): return (sum(partition[0])==value and sum(partition[1]) ==value and sum(partition[2])==value and len(partition[0])<=M and len(partition[1])<=M and len(partition[2])<=M) def push(result, answer):#each partition should be ordered then push into the ans d = (tuple(sorted(answer[0])),tuple(sorted(answer[1])),tuple(sorted(answer[2]))) result.add(d) def allocateObj(result, array, x, y, z, value, M): n = len(array) if n == 0:#base case:已經分完了 if check([x,y,z], value, M):#Is it legal? push(result,[x, y, z])#add to the ans return True t = array[1:] allocateObj(result, t, x + array[:1] , y, z, value, M) allocateObj(result, t, x, y+ array[:1], z, value, M) allocateObj(result, t, x, y, z+ array[:1], value, M) return True def main(array, M): result = set() x, y, z = [[],[],[]] value = sum(array)//3 if value*3 == sum(array):#make sure the num is integer allocateObj(result, array, x, y, z, value, M) for i in result: print(i) main([1, 2, 3, 4, 5],2) ``` ### 基因序列 找基因序列 * 若DNA序列由A, C, G, T四個字元組成的字串(string), 基因(gene)是隱藏於DNA序列中的部分片段(子字串)。給定一DNA序列(長度小於50),找出在裡面的基因;規則: 1.前面是ATG,後面接TAG、TAA、或TGA;– 例如ATGTTTTAA。 * 2.長度為3的倍數,其中未含有ATG、TAG、TAA或TGA。例如,給定DNA序列,其中包含兩個基因, CCATGTTTTAACCATGCCTAAATGGGGCGTTAGTT: * 基因TTT前面為ATG,後面接著TAA,長度3,其中未含ATG、 TAG、TAA或TGA。 * 基因GGGCGT前面為ATG,後面接著TAG,長度6,其中未含 ATG、TAG、TAA或TGA。 * 撰寫程式輸入DNA序列,找出該序列中所有基因。 輸入範例: findAllGen('CCATGTTTTAACCATGCCTAAATGGGGCGTTAGTT') findAllGen('TAAGATGAATGA') findAllGen('ATGAAATGA') findAllGen('ATGTGAATGAAATGA') findAllGen('TTATGTTAAAAGGATGTTAATGTAAGGGCGTTAGTT') fin 輸出範例: ==> TTT GGGCGT ==> 沒有基因 ==> AAA ==> AAA ==> 沒有基因 ==> TCA CCCTTCACC ```python= def check(gen): if len(gen)==0: #空的基因 return False for tag in ['ATG', 'TAG','TAA','TGA']: #不能含有這些tag if gen.find(tag) > -1: return False if len(gen)%3==0: #長度3倍數 return True return False def findGen(dna): startTag, endTags = 'ATG', ['TAG','TAA','TGA'] length = len(dna) startIndex = dna.find(startTag)+3#基因前面是startTag 'ATG' endIndex = length+1#初始化結束點 for tag in endTags: #從三個 end tag 找出最小符合基因字串 endTemp = dna.find(tag, startIndex) if endTemp!=-1 and endTemp < endIndex: #找最小符合的 end tag 的點 endIndex = endTemp if endIndex==length+1 or startIndex < 3: #找不到前後tag return 0, 0, 'None' gen = dna[startIndex:endIndex] #找到基因 if check(gen): #驗證基因 return 1, endIndex+3, gen return 2, startIndex+3, 'None' #繼續往下找 def findAllGen(dna): i, count = 0, 0 print('==>') while True: dna=dna[i:] #往後找基因 b, i, gen = findGen(dna) #b=1找到, i往後找索引 if (b==1): print(gen) count=count+1#找到幾個基因 elif (b==0): #找到最後沒找到 break if count==0: print('沒有基因')#完全沒找到 findAllGen('CCATGTTTTAACCATGCCTAAATGGGGCGTTAGTT') findAllGen('TAAGATGAATGA') findAllGen('ATGAAATGA') findAllGen('ATGTGAATGAAATGA') findAllGen('TTATGTTAAAAGGATGTTAATGTAAGGGCGTTAGTT') findAllGen('AATAGATGTTTAAGTGATATGGGGATGTCATAGATGCCCTTCACCTAA') ``` ### 山洞找黃金