#!/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;