master > master: code - suchalgorithmus für poison-Aufgabe
This commit is contained in:
		
							parent
							
								
									ecbf274be6
								
							
						
					
					
						commit
						01f69adcfb
					
				| @ -12,3 +12,5 @@ from code.algorithms.search.jump import JumpSearchLinear; | ||||
| from code.algorithms.search.jump import JumpSearchExponentiell; | ||||
| from code.algorithms.search.ith_smallest import FindIthSmallest; | ||||
| from code.algorithms.search.ith_smallest import FindIthSmallestDC; | ||||
| from code.algorithms.search.poison import FindPoison; | ||||
| from code.algorithms.search.poison import FindPoisonFast; | ||||
|  | ||||
							
								
								
									
										138
									
								
								code/algorithms/search/poison.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								code/algorithms/search/poison.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,138 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # IMPORTS | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| from local.maths import *; | ||||
| from local.typing import *; | ||||
| 
 | ||||
| from code.core.log import *; | ||||
| from code.algorithms.methods import *; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # GLOBAL VARIABLES/CONSTANTS | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| # | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # CHECKS | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def preChecks(L: List[int], **_): | ||||
|     # TODO | ||||
|     return; | ||||
| 
 | ||||
| def postChecks(L: List[int], indexes: List[int], **_): | ||||
|     if sum(L) > 0: | ||||
|         assert [ k for k in range(len(L)) if L[k] == True ] == indexes, 'Der Algorithmus hat die vergifteten Getränke nicht erfolgreich bestimmt.'; | ||||
|     else: | ||||
|         assert len(indexes) == 0, 'Der Algorithmus sollte erkennen, dass Gift nicht vorhanden ist.'; | ||||
|     return; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # ALGORITHM find poison | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| @algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames='indexes', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) | ||||
| def FindPoison(L: List[bool]) -> List[int]: | ||||
|     ''' | ||||
|     Inputs:  L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist. | ||||
|     Outputs: Die Liste aller Indexes i mit L[i] == true, was den vergifteten Getränken entspricht. | ||||
| 
 | ||||
|     NOTE: Zeitkosten hier messen nur die Anzahl der Vorkoster. | ||||
|     ''' | ||||
|     logDebug('Bereite Vorkoster vor'); | ||||
|     n = len(L); | ||||
|     testers = []; | ||||
|     for i in range(n): | ||||
|         AddToCounter(); | ||||
|         logDebug('Füge Vorkoster hinzu, der nur Getränk {i} testet.'.format(i=i)) | ||||
|         testers.append([i]); | ||||
|     logDebug('Warte auf Effekte'); | ||||
|     effects = waitForEffect(L, testers); | ||||
|     logDebug('Effekte auswerten, um vergiftete Getränke zu lokalisieren.'); | ||||
|     poisened = evaluateEffects(testers, effects); | ||||
|     return poisened; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # ALGORITHM find poison fast | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| @algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames='indexes', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) | ||||
| def FindPoisonFast(L: List[bool]) -> List[int]: | ||||
|     ''' | ||||
|     Inputs:  L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist. | ||||
|     Outputs: Die Liste aller Indexes i mit L[i] == true, was den vergifteten Getränken entspricht. | ||||
| 
 | ||||
|     NOTE: Zeitkosten hier messen nur die Anzahl der Vorkoster. | ||||
|     ''' | ||||
|     logDebug('Bereite Vorkoster vor'); | ||||
|     n = len(L); | ||||
|     p = math.floor(math.log2(n)); | ||||
|     testers = []; | ||||
|     ## Für jedes Bit i=0 bis p ... | ||||
|     for i in range(p+1): | ||||
|         AddToCounter(2); | ||||
|         logDebug('Füge Vorkoster hinzu, der alle Getränke k testet mit {i}. Bit = 1.'.format(i=i)) | ||||
|         testers.append([ k for k in range(n) if nthBit(number=k, digit=i) == 1 ]); | ||||
|         logDebug('Füge Vorkoster hinzu, der alle Getränke k testet mit {i}. Bit = 0.'.format(i=i)) | ||||
|         testers.append([ k for k in range(n) if nthBit(number=k, digit=i) == 0 ]); | ||||
|     logDebug('Warte auf Effekte'); | ||||
|     effects = waitForEffect(L, testers); | ||||
|     logDebug('Effekte auswerten, um vergiftete Getränke zu lokalisieren.'); | ||||
|     poisened = evaluateEffects(testers, effects); | ||||
|     return poisened; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # AUXILIARY METHOD wait for effects, evaluate effects | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def waitForEffect(L: List[bool], testers: List[List[int]]) -> List[int]: | ||||
|     ''' | ||||
|     Inputs: | ||||
|     - L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist. | ||||
|     - testers = Liste von Vorkostern. Jeder Vorkoster kostet eine 'Teilliste' der Getränke. | ||||
| 
 | ||||
|     Outputs: effects = eine Liste, die jedem Vorkoster zuordnet, wie viele vergiftete Getränke er konsumiert hat. | ||||
|     ''' | ||||
|     m = len(testers); | ||||
|     effects = []; | ||||
|     for i in range(m): | ||||
|         effect = sum([L[k] for k in testers[i]]); | ||||
|         effects.append(effect); | ||||
|     return effects; | ||||
| 
 | ||||
| def evaluateEffects(testers: List[List[int]], effects: List[int]) -> List[int]: | ||||
|     ''' | ||||
|     Inputs: | ||||
|     - testers = Liste von Vorkostern. Jeder Vorkoster kostet eine 'Teilliste' der Getränke. | ||||
|     - effects = eine Liste, die jedem Vorkoster zuordnet, wie viele vergiftete Getränke er konsumiert hat. | ||||
| 
 | ||||
|     Annahmen: Vorkoster wurden so angewiesen, dass es garantiert ist, vergiftete Getränke zu finden, wenn es die gibt. | ||||
| 
 | ||||
|     Outputs: Liste der Indexes aller vergifteten Getränke. | ||||
|     ''' | ||||
|     ## Werte Effekte aus, um Gift zu lokalisieren: | ||||
|     search = set([]); | ||||
|     ## Zuerst die Indexes der Getränke bei allen vergifteten Tester zusammenführen: | ||||
|     for i in range(len(testers)): | ||||
|         if effects[i] > 0: | ||||
|             search = search.union(testers[i]); | ||||
|     ## jetzt eliminieren wir alle Getränke, die von nicht vergifteten Testern konsumiert wurden: | ||||
|     for i in range(len(testers)): | ||||
|         if effects[i] == 0: | ||||
|             search = search.difference(testers[i]); | ||||
|     return list(search); | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # AUXILIARY METHOD n. Bit der binären Darstellung einer Zahl | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def nthBit(number: int, digit: int) -> int: | ||||
|     number_binary = bin(number)[2:][::-1]; | ||||
|     if digit < len(number_binary): | ||||
|         return int(number_binary[digit]); | ||||
|     return 0; | ||||
| @ -37,6 +37,7 @@ def postChecks(L: List[int], **_): | ||||
| def MaxSubSum(L: List[float]) -> Tuple[float, int, int]: | ||||
|     ''' | ||||
|     Inputs:  L = Liste von Zahlen | ||||
| 
 | ||||
|     Outputs: | ||||
|     - maxSum = Wert der maximalen Summe einer Teilliste aufeinanderfolgender Elemente | ||||
|     - u, v = Indexes so dass die Teilliste [L[u], L[u+1], ..., L[v]] die maximale Summe aufweist | ||||
| @ -61,6 +62,7 @@ def MaxSubSum(L: List[float]) -> Tuple[float, int, int]: | ||||
| def MaxSubSumDC(L: List[float]) -> Tuple[float, int, int]: | ||||
|     ''' | ||||
|     Inputs:  L = Liste von Zahlen | ||||
| 
 | ||||
|     Outputs: | ||||
|     - maxSum = Wert der maximalen Summe einer Teilliste aufeinanderfolgender Elemente | ||||
|     - u, v = Indexes so dass die Teilliste [L[u], L[u+1], ..., L[v]] die maximale Summe aufweist | ||||
| @ -157,3 +159,21 @@ def rRandSum(L: List[float]) -> Tuple[float, int, int]: | ||||
|             u = i; | ||||
|             maxSum = total; | ||||
|     return maxSum, u, v; | ||||
| 
 | ||||
| # Sei N ∈ ℕ⁺ | ||||
| # Sei p so, dass 2^p ≤ N < 2^{p+1}, | ||||
| # Also p = floor(log₂(N)). | ||||
| # Setze | ||||
| #     B(i,d) := {k < N | bit(k, i) = d} | ||||
| # für i ∈ {0, 1, ..., p-1} | ||||
| # und setze | ||||
| #     𝒜 = {B(i,d) : i ∈ {0, 1, ..., p-1}, d ∈ {0,1}}. | ||||
| # Seien k1, k2 ∈ N mit k1 ≠ k2. | ||||
| # Dann existiert i ∈ {0, 1, ..., p-1}, | ||||
| # so dass | ||||
| #     d := bit(k1, i) ≠ bit(k2, i). | ||||
| # Also | ||||
| #     k1 ∈ B(i, d) ∌ k2. | ||||
| # Darum erfüllt 𝒜 die erwünschte Eigenschaft. | ||||
| # Es gilt | ||||
| #     |𝒜| = 2p = 2·floor(log₂(N)) ∈ O(log(N)). | ||||
|  | ||||
| @ -32,6 +32,16 @@ parts: | ||||
|         L: [1, 3, 5, 7, 11, 13, 16, 17, 23, 33, 34, 35] | ||||
|         x: 17 | ||||
|         m: 3 | ||||
|     ## Freiwilliges ÜB 2, Aufgabe 4, Beispiel | ||||
|     - command: 'algorithm-search-poison' | ||||
|       description: 'Freiwilliges ÜB2, A4, Beispiel' | ||||
|       inputs: &ref_inputs_ueb2_4 | ||||
|         L: [ false, false, false, false, false, false, false, false, true, false, false, false, false, false ] | ||||
|         # L: [ false, false, false, false, false, false, false, false, true, false, false, false, true, false ] | ||||
|         # L: [ false, false, false, false, false, false, false, false, false, false, false, false, false, false ] | ||||
|     - command: 'algorithm-search-poison-fast' | ||||
|       description: 'Freiwilliges ÜB2, A4, Beispiel' | ||||
|       inputs: *ref_inputs_ueb2_4 | ||||
|     ## Freiwilliges ÜB 2, Aufgabe 5 | ||||
|     - command: 'algorithm-search-binary' | ||||
|       description: 'Freiwilliges ÜB2, A5a' | ||||
|  | ||||
| @ -72,6 +72,10 @@ def LoopThroughCases(path: str): | ||||
|                 FindIthSmallest(L=inputs['L'], i=inputs['i']); | ||||
|             elif command == 'algorithm-search-ith-element-dc': | ||||
|                 FindIthSmallestDC(L=inputs['L'], i=inputs['i']); | ||||
|             elif command == 'algorithm-search-poison': | ||||
|                 FindPoison(L=inputs['L']); | ||||
|             elif command == 'algorithm-search-poison-fast': | ||||
|                 FindPoisonFast(L=inputs['L']); | ||||
|             else: | ||||
|                 raise ValueError('Command \033[1m{}\033[0m nicht erkannt'.format(command)); | ||||
|         except Exception as e: | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user