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