ads1_2021/code/algorithms/search/jump.py

93 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from local.maths import *;
from local.typing import *;
from code.core.log import *;
from code.algorithms.search.sequential import SequentialSearch;
from code.algorithms.methods import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES/CONSTANTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CHECKS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def preChecks(L: List[int], **_):
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
assert L == sorted(list(set(L))), 'Ungültiger Input: L darf keine Duplikate enthalten!';
return;
def postChecks(L: List[int], x: int, index: int, **_):
value = L[index] if index >= 0 else None;
assert value == x, 'Der Algorithmus hat versagt.';
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM jump search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl, m = lineare Sprunggröße.
Annahmen:
- L sei aufsteigend sortiert.
- L enthält keine Duplikate.
Outputs: Position von x in L, sonst 1 wenn x nicht in L.
'''
i = 0;
while i*m < len(L):
AddToCounter();
offset = i*m;
block = L[offset:][:m];
elementAfterBlock = block[-1] + 1;
if x < elementAfterBlock:
logDebug('Element muss sich im Block [{i0}, {i1}) befinden.'.format(i0 = i*m, i1 = (i+1)*m));
index = SequentialSearch(L=block, x=x);
return offset + index; # NOTE: muss wegen Offset kompensieren
logDebug('Element befindet sich nicht im im Block [{i0}, {i1}) befinden.'.format(i0 = i*m, i1 = (i+1)*m));
i += 1;
return -1;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM jump search - exponentiell
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def JumpSearchExponentiell(L: List[int], x: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl.
Annahmen:
- L sei aufsteigend sortiert.
- L enthält keine Duplikate.
Outputs: Position von x in L, sonst 1 wenn x nicht in L.
'''
i0 = 0;
i1 = 1;
while i0 < len(L):
AddToCounter();
block = L[i0:i1];
elementAfterBlock = block[-1] + 1;
if x < elementAfterBlock:
logDebug('Element muss sich im Block [{i0}, {i1}) befinden.'.format(i0 = i0, i1 = i1));
index = SequentialSearch(L=block, x=x);
return i0 + index; # NOTE: muss wegen Offset kompensieren
logDebug('Element befindet sich nicht im Block [{i0}, {i1}) befinden.'.format(i0 = i0, i1 = i1));
i0 = i1;
i1 *= 2;
return -1;