solution_276.py

#!/usr/bin/python
# ==========================================================
# based on:
#   www.youtube.com/watch?v=MXveVqBxFow
#   Ancient trick to calculate ANY square root
# ==========================================================

import math
import user_interface as ui

# ----------------------------------------------------------
# ---- Find the nearest perfect square to a given number.
# ---- Using it makes the video's algorithm more efficient.
# ---- -----------------------------------------------------
# ---- Apparently the Babylonians used a table to do this.
# ---- A table is simple, fast and only needs to be
# ---- done one time.
# ---- -----------------------------------------------------
# ---- This algorithm was found on the web
# ---- 1. calculate the square root of the number
# ---- 2. round it to the nearest integer
# ---- 3. square that rounded integer to get the closest
# ----    perfect square
# ----------------------------------------------------------

def nearest_perfect_square(num):
    sqrt_num = math.sqrt(num)
    rnd_sqrt_num = round(sqrt_num)
    return (rnd_sqrt_num,
            rnd_sqrt_num*rnd_sqrt_num)

# ----------------------------------------------------------
# ---- Test if a string is a number greater than zero.
# ---- If true, return the number.
# ----------------------------------------------------------
    
def positive_number_greater_than_zero(string):
    
    tf,n = ui.is_integer(string)    
    if tf:
        if n > 0: return (True,n)
        return (False,0)

    tf,n = ui.is_float(string)
    if tf:
        if n > 0.0: return (True,n)

    return (False,0.0)

# ----------------------------------------------------------
# ---- Babylonian (Video's) square root algorithm
# ----------------------------------------------------------

def video_square_root_algorithm(num,loop):

    # ---- generate algorithm seed (nearest perfect square)

    nps_root,nps = nearest_perfect_square(num)

    print()
    print('nearst perfect square root')
    print(f'root = {nps_root} (squared = {nps})')

    # ---- algorithm loop (increase accuracy)

    estimate = nps_root     # initial estimated squae root

    for i in range(loop):
        ##print()
        ##print(f'loop={i}  estimate={estimate}')
        new_estimate = estimate + \
        (num - (estimate*estimate))/(2*estimate)
        ##print(f'loop={i}  new estimate={new_estimate}')
        estimate = new_estimate
        
    return estimate

# ----------------------------------------------------------
# ---- Main
# ----------------------------------------------------------

loop_count = 4

while True:

    # ---- get user input

    print()
    s = ui.get_user_input(
        'Enter a positive number greater that 0: ')
    if not s: break             # empty string?
    tf,num = positive_number_greater_than_zero(s)
    if not tf:
        print()
        print('Bad input. Try again.')
        continue

    # ---- estimate the number's square root

    estimated_square_root = \
        video_square_root_algorithm(num,loop_count)

    print()
    print(f'loop count          = {loop_count}')
    print(
        f'algorithm square root = {estimated_square_root}')
    print(
        f'math.sqrt(num)        = {math.sqrt(num)}')