#!/usr/bin/python3 import sys from typing import List, Sequence import numpy import time def overlap(arg1: str, arg2: str) -> str: overlap_result = '' arg1_as_string = str(arg1) arg1_integer_part = arg1_as_string arg1_decimal_part = '' arg1_is_full_integer = True arg1_is_negative = True if arg1_integer_part.startswith('-') else False try: arg1_integer_part, arg1_decimal_part = arg1_as_string.split(".") if arg1_decimal_part==len(arg1_decimal_part)*'0': arg1_is_full_integer = True else: arg1_is_full_integer = False except: pass#nothing to do if arg1_is_negative: arg1_integer_part = arg1_integer_part.replace('-', '') # transform arg2 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg2_as_string = str(arg2) arg2_integer_part = arg2_as_string arg2_decimal_part = '' arg2_is_full_integer = True arg2_is_negative = True if arg2_integer_part.startswith('-') else False try: arg2_integer_part, arg2_decimal_part = arg2_as_string.split(".") if arg2_decimal_part==len(arg2_decimal_part)*'0': arg2_is_full_integer = True else: arg2_is_full_integer = False except: pass#nothing to do if arg2_is_negative: arg2_integer_part = arg2_integer_part.replace('-', '') # making integer and decimal parts same size max_integer_part_size = max( len(arg1_integer_part), len(arg2_integer_part) ) arg1_integer_part = '0'*(max_integer_part_size-len(arg1_integer_part)) + arg1_integer_part arg2_integer_part = '0'*(max_integer_part_size-len(arg2_integer_part)) + arg2_integer_part #--------- max_decimal_part_size = max(len(arg1_decimal_part),len(arg2_decimal_part)) arg1_decimal_part = arg1_decimal_part + '0'*(max_decimal_part_size-len(arg1_decimal_part)) arg2_decimal_part = arg2_decimal_part + '0'*(max_decimal_part_size-len(arg2_decimal_part)) #--------- if not(arg1_is_negative) and arg2_is_negative: #arg1 positive - arg2 negative overlap_result += '1' elif not(arg1_is_negative) and not(arg2_is_negative): #arg1 positive - arg2 positive overlap_result += '2' elif arg1_is_negative and not(arg2_is_negative): #arg1 negative - arg2 positive overlap_result += '3' elif arg1_is_negative and arg2_is_negative: #arg1 negative - arg2 negative overlap_result += '4' #--------- for index in range(max_integer_part_size): overlap_result += arg1_integer_part[index] overlap_result += arg2_integer_part[index] if not(arg1_is_full_integer) or not(arg2_is_full_integer): overlap_result += "." for index in range(max_decimal_part_size): overlap_result += arg1_decimal_part[index] overlap_result += arg2_decimal_part[index] return overlap_result def unoverlap(arg: str, apply_format: bool=True) -> Sequence[str]: arg1 = '' #for stocking unoverlapped values arg2 = '' arg_as_string = str(arg) # MUST TRY TO PAD THE STRING HERE IN CASE good_format were applied on it during operations (I verified and not need for the moment) arg_integer_part = arg_as_string arg_decimal_part = '' arg_is_full_integer = True try: arg_integer_part, arg_decimal_part = arg_as_string.split(".") if arg_decimal_part==len(arg_decimal_part)*'0': arg_is_full_integer = True else: arg_is_full_integer = False except: pass#nothing to do if arg_integer_part[0]=='1': #arg1 must be positive - arg2 must be negative arg2 += '-' elif arg_integer_part[0]=='2': #arg1 must be positive - arg2 must be positive pass elif arg_integer_part[0]=='3': #arg1 must be negative - arg2 must be positive arg1 += '-' elif arg_integer_part[0]=='4': #arg1 must be negative - arg2 must be negative arg1 += '-' arg2 += '-' arg_integer_part = arg_integer_part[1:] #ignoring signs' digit now as it's already used for index in range(len(arg_integer_part)): if index%2==0: arg1 += arg_integer_part[index] else: arg2 += arg_integer_part[index] if not(arg_is_full_integer): arg1 += '.' arg2 += '.' for index in range(len(arg_decimal_part)): if index%2==0: arg1 += arg_decimal_part[index] else: arg2 += arg_decimal_part[index] if apply_format: arg1 = good_format(arg1); arg2 = good_format(arg2) return arg1, arg2 def sb_addition(arg1: str, arg2: str, apply_format: bool=True) -> str: result = '' # the addition will be a substraction if (arg1 is negative and arg2 is positive) or (arg1 is positive and arg2 is negative) if str(arg1).startswith('-') and not(str(arg2).startswith('-')): # arg1 is negative and arg2 is positive return sb_substract(str(arg2), str(arg1).replace('-','')) elif not(str(arg1).startswith('-')) and str(arg2).startswith('-'): # arg1 is positive and arg2 is negative return sb_substract(str(arg1), str(arg2).replace('-','')) # transform arg1 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg1_as_string = str(arg1) arg1_integer_part = arg1_as_string arg1_decimal_part = '' arg1_is_full_integer = True arg1_is_negative = True if arg1_integer_part.startswith('-') else False try: arg1_integer_part, arg1_decimal_part = arg1_as_string.split(".") if arg1_decimal_part==len(arg1_decimal_part)*'0': arg1_is_full_integer = True else: arg1_is_full_integer = False except: pass#nothing to do if arg1_is_negative: arg1_integer_part = arg1_integer_part.replace('-', '') # transform arg2 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg2_as_string = str(arg2) arg2_integer_part = arg2_as_string arg2_decimal_part = '' arg2_is_full_integer = True arg2_is_negative = True if arg2_integer_part.startswith('-') else False try: arg2_integer_part, arg2_decimal_part = arg2_as_string.split(".") if arg2_decimal_part==len(arg2_decimal_part)*'0': arg2_is_full_integer = True else: arg2_is_full_integer = False except: pass#nothing to do if arg2_is_negative: arg2_integer_part = arg2_integer_part.replace('-', '') # making integer and decimal parts same size max_integer_part_size = max( len(arg1_integer_part), len(arg2_integer_part) ) arg1_integer_part = '0'*(max_integer_part_size-len(arg1_integer_part)) + arg1_integer_part arg2_integer_part = '0'*(max_integer_part_size-len(arg2_integer_part)) + arg2_integer_part #--------- max_decimal_part_size = max(len(arg1_decimal_part),len(arg2_decimal_part)) arg1_decimal_part = arg1_decimal_part + '0'*(max_decimal_part_size-len(arg1_decimal_part)) arg2_decimal_part = arg2_decimal_part + '0'*(max_decimal_part_size-len(arg2_decimal_part)) # making real addition operation # when here, it means both numbers are positives OR both numbers are negatives rem = '0' if not(arg1_is_full_integer) or not(arg2_is_full_integer): for i in range(max_decimal_part_size-1, -1, -1): res = int( eval('(' + arg1_decimal_part[i] + '+' + arg2_decimal_part[i] + '+' + str(rem) + ')%10') ) result = str(res) + result rem = int( eval('((' + arg1_decimal_part[i] + '+' + arg2_decimal_part[i] + '+' + str(rem) + ') - ' + str(res) + ')//10') ) result = '.' + result for i in range(max_integer_part_size-1, -1, -1): res = int( eval('(' + arg1_integer_part[i] + '+' + arg2_integer_part[i] + '+' + str(rem) + ')%10') ) result = str(res) + result rem = int( eval('((' + arg1_integer_part[i] + '+' + arg2_integer_part[i] + '+' + str(rem) + ') - ' + str(res) + ')//10') ) if str(rem) != '0': result = str(rem) + result if arg1_is_negative and arg2_is_negative: result = '-' + result # treat the case both numbers are negative if apply_format: result = good_format(result) return result def sb_substract(arg1: str, arg2: str, apply_format: bool=True) -> str: result = '' # will be arg1-arg2 # the substraction will be an addition if (arg1 is negative and arg2 is positive) or (arg1 is positive and arg2 is negative) if str(arg1).startswith('-') and not(str(arg2).startswith('-')): # arg1 is negative and arg2 is positive return sb_addition(str(arg1), '-'+str(arg2)) elif not(str(arg1).startswith('-')) and str(arg2).startswith('-'): # arg1 is positive and arg2 is negative return sb_addition(str(arg1), str(arg2).replace('-','')) # transform arg1 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg1_as_string = str(arg1) arg1_integer_part = arg1_as_string arg1_decimal_part = '' arg1_is_full_integer = True arg1_is_negative = True if arg1_integer_part.startswith('-') else False try: arg1_integer_part, arg1_decimal_part = arg1_as_string.split(".") if arg1_decimal_part==len(arg1_decimal_part)*'0': arg1_is_full_integer = True else: arg1_is_full_integer = False except: pass#nothing to do if arg1_is_negative: arg1_integer_part = arg1_integer_part.replace('-', '') # transform arg2 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg2_as_string = str(arg2) arg2_integer_part = arg2_as_string arg2_decimal_part = '' arg2_is_full_integer = True arg2_is_negative = True if arg2_integer_part.startswith('-') else False try: arg2_integer_part, arg2_decimal_part = arg2_as_string.split(".") if arg2_decimal_part==len(arg2_decimal_part)*'0': arg2_is_full_integer = True else: arg2_is_full_integer = False except: pass#nothing to do if arg2_is_negative: arg2_integer_part = arg2_integer_part.replace('-', '') # making integer and decimal parts same size max_integer_part_size = max( len(arg1_integer_part), len(arg2_integer_part) ) arg1_integer_part = '0'*(max_integer_part_size-len(arg1_integer_part)) + arg1_integer_part arg2_integer_part = '0'*(max_integer_part_size-len(arg2_integer_part)) + arg2_integer_part #--------- max_decimal_part_size = max(len(arg1_decimal_part),len(arg2_decimal_part)) arg1_decimal_part = arg1_decimal_part + '0'*(max_decimal_part_size-len(arg1_decimal_part)) arg2_decimal_part = arg2_decimal_part + '0'*(max_decimal_part_size-len(arg2_decimal_part)) # making real substraction operation # when here, it means both numbers are positives OR both numbers are negatives result_needs_negative_sign_in_font = False if arg1_is_negative and arg2_is_negative: if eval( 'abs('+arg2 + ')>=abs(' + arg1 + ')' ): temp = arg1_integer_part arg1_integer_part = arg2_integer_part arg2_integer_part = temp #--------- temp = arg1_decimal_part arg1_decimal_part = arg2_decimal_part arg2_decimal_part = temp else: result_needs_negative_sign_in_font = True elif not(arg1_is_negative) and not(arg2_is_negative): if eval( 'abs('+arg1 + ')>=abs(' + arg2 + ')' ): pass # nothing to do else: temp = arg1_integer_part arg1_integer_part = arg2_integer_part arg2_integer_part = temp #--------- temp = arg1_decimal_part arg1_decimal_part = arg2_decimal_part arg2_decimal_part = temp result_needs_negative_sign_in_font = True rem = '0' if not(arg1_is_full_integer) or not(arg2_is_full_integer): for i in range(max_decimal_part_size-1, -1, -1): upper_digit_to_consider = int( eval( arg1_decimal_part[i] + '+' + '10 if ' + arg1_decimal_part[i] + '<(' + arg2_decimal_part[i] + '+' + str(rem) + ') else ' + arg1_decimal_part[i] ) ) res = int( eval( str(upper_digit_to_consider) + '-(' + arg2_decimal_part[i] + '+' + str(rem) + ')' ) ) result = str(res) + result rem = int( eval( '1 if ' + arg1_decimal_part[i] + '<(' + arg2_decimal_part[i] + '+' + str(rem) + ') else 0' ) ) result = '.' + result for i in range(max_integer_part_size-1, -1, -1): upper_digit_to_consider = int( eval( arg1_integer_part[i] + '+' + '10 if ' + arg1_integer_part[i] + '<(' + arg2_integer_part[i] + '+' + str(rem) + ') else ' + arg1_integer_part[i] ) ) res = int( eval( str(upper_digit_to_consider) + '-(' + arg2_integer_part[i] + '+' + str(rem) + ')' ) ) result = str(res) + result rem = int( eval( '1 if ' + arg1_integer_part[i] + '<(' + arg2_integer_part[i] + '+' + str(rem) + ') else 0' ) ) if str(rem) != '0': result = str(rem) + result if result_needs_negative_sign_in_font: result = '-' + result if apply_format: result = good_format(result) return result def sb_multiply(arg1: str, arg2: str, apply_format: bool=True) -> str: # transform arg1 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg1_as_string = str(arg1) arg1_integer_part = arg1_as_string arg1_decimal_part = '' arg1_is_full_integer = True arg1_is_negative = True if arg1_integer_part.startswith('-') else False try: arg1_integer_part, arg1_decimal_part = arg1_as_string.split(".") if arg1_decimal_part==len(arg1_decimal_part)*'0': arg1_is_full_integer = True else: arg1_is_full_integer = False except: pass#nothing to do if arg1_is_negative: arg1_integer_part = arg1_integer_part.replace('-', '') # transform arg2 to string if not already in string and test if it's a full integer (without decimal part or decimal part equals zero) arg2_as_string = str(arg2) arg2_integer_part = arg2_as_string arg2_decimal_part = '' arg2_is_full_integer = True arg2_is_negative = True if arg2_integer_part.startswith('-') else False try: arg2_integer_part, arg2_decimal_part = arg2_as_string.split(".") if arg2_decimal_part==len(arg2_decimal_part)*'0': arg2_is_full_integer = True else: arg2_is_full_integer = False except: pass#nothing to do if arg2_is_negative: arg2_integer_part = arg2_integer_part.replace('-', '') # making integer and decimal parts same size max_integer_part_size = max( len(arg1_integer_part), len(arg2_integer_part) ) arg1_integer_part = '0'*(max_integer_part_size-len(arg1_integer_part)) + arg1_integer_part arg2_integer_part = '0'*(max_integer_part_size-len(arg2_integer_part)) + arg2_integer_part #--------- max_decimal_part_size = max(len(arg1_decimal_part),len(arg2_decimal_part)) arg1_decimal_part = arg1_decimal_part + '0'*(max_decimal_part_size-len(arg1_decimal_part)) arg2_decimal_part = arg2_decimal_part + '0'*(max_decimal_part_size-len(arg2_decimal_part)) # making real multiplication operation rem = '0' intermediate_numbers = [] if arg2_is_full_integer: down_number_in_multiplication = arg2_integer_part else: down_number_in_multiplication = arg2_integer_part+arg2_decimal_part if arg1_is_full_integer: up_number_in_multiplication = arg1_integer_part else: up_number_in_multiplication = arg1_integer_part+arg1_decimal_part #---------------- for j in range(len(down_number_in_multiplication)-1, -1, -1): current_intermediate_number = '0'*( (len(down_number_in_multiplication)-1) - j ) for i in range(len(up_number_in_multiplication)-1, -1, -1): res = int( eval( '((' + down_number_in_multiplication[j] + '*' + up_number_in_multiplication[i] + ')+' + str(rem) + ')%10' ) ) current_intermediate_number = str(res) + current_intermediate_number rem = int( eval( '(((' + down_number_in_multiplication[j] + '*' + up_number_in_multiplication[i] + ')+' + str(rem) + ') - ' + str(res) + ')//10') ) if rem != '0': current_intermediate_number = str(rem) + current_intermediate_number intermediate_numbers.append(current_intermediate_number) result = intermediate_numbers[0] for k in range(1, len(intermediate_numbers)): result = sb_addition(result, intermediate_numbers[k], apply_format=False) if not(arg1_is_full_integer) and arg2_is_full_integer: result = result[:-len(arg1_decimal_part)]+'.'+result[len(result)-len(arg1_decimal_part):] elif arg1_is_full_integer and not(arg2_is_full_integer): result = result[:-len(arg2_decimal_part)]+'.'+result[len(result)-len(arg2_decimal_part):] elif not(arg1_is_full_integer) and not(arg2_is_full_integer): #was or result = result[:-len(arg1_decimal_part+arg2_decimal_part)]+'.'+result[len(result)-len(arg1_decimal_part+arg2_decimal_part):] #here to modifiy if (arg1_is_negative and not(arg2_is_negative)) or (not(arg1_is_negative) and arg2_is_negative): result = '-' + result if apply_format: result = good_format(result) return result def good_format(result: str) -> str: # order of following instructions is very important while result.startswith('0') and len(result)>=2 and result[1] != '.': result = result[1:] while result.startswith('-0') and len(result)>=3 and result[2] != '.': result = result.replace('-0','-') if '.' in result and result.split('.')[1]=='0'*len(result.split('.')[1]): result = result.split('.')[0] while '.' in result and result.endswith('0'): result = result[:-1] return result def is_well_written(arg: str) -> bool: pass def sb_division(arg1: str, arg2: str, digits_after_decimal_point: int=5, apply_format: bool=True) -> str: assert good_format(arg2)!='0' result = '' #--------- arg1_as_string = str(arg1) arg2_as_string = str(arg2) #--------- arg1_is_negative = False if arg1_as_string.startswith('-'): arg1_is_negative = True arg1_as_string = arg1_as_string.replace('-','') #--------- arg2_is_negative = False if arg2_as_string.startswith('-'): arg2_is_negative = True arg2_as_string = arg2_as_string.replace('-','') #--------- while '.' in arg2_as_string: arg1_as_string = good_format( sb_multiply(arg1_as_string,'10') ) arg2_as_string = good_format( sb_multiply(arg2_as_string,'10') ) #--------- arg1_integer_part = arg1_as_string arg1_decimal_part = '' arg1_is_full_integer = True try: arg1_integer_part, arg1_decimal_part = arg1_as_string.split(".") if arg1_decimal_part==len(arg1_decimal_part)*'0': arg1_is_full_integer = True else: arg1_is_full_integer = False except: pass#nothing to do #========= arg1_as_string = arg1_integer_part+arg1_decimal_part #current_number_to_consider = arg1_as_string[0] current_number_to_consider = '0' #for digit in arg1_as_string[1:]: for digit in arg1_as_string+'0'*(digits_after_decimal_point): if current_number_to_consider=='0': current_number_to_consider = digit else: current_number_to_consider = current_number_to_consider + digit #--------- if eval( current_number_to_consider + '<' + arg2_as_string ): result = result + '0' else: result = result + str( eval(current_number_to_consider+'//'+arg2_as_string) ) current_number_to_consider = str( eval(current_number_to_consider+'-(('+current_number_to_consider+'//'+arg2_as_string+')*'+arg2_as_string+')') ) result = result[0:len(arg1_integer_part)]+'.'+result[len(arg1_integer_part):] if (arg1_is_negative and not(arg2_is_negative)) or (not(arg1_is_negative) and arg2_is_negative): result = '-' + result if apply_format: result = good_format(result) return result #when encoding, verify overlap_result being even as def encode(data: List[str]): assert len(data) >= 2 code = overlap( sb_addition(data[0], data[1]), sb_substract(data[0], data[1]) ) if len(data)>2: for element in data[2:]: code = overlap( sb_addition(code, element), sb_substract(code, element) ) return code def decode(code: str, size): data = [] r1 = '' r2 = '' while len(data)!=(size-2): r1, r2 = unoverlap(code) code = sb_division( sb_addition(r1,r2), '2' ) element = sb_division( sb_substract(r1,r2), '2' ) data.append(element) r1, r2 = unoverlap(code) data.append(sb_division( sb_substract(r1,r2), '2' )) data.append(sb_division( sb_addition(r1,r2), '2' )) result = [] for index in range(len(data)-1,-1,-1): result.append(data[index]) return result if __name__=='__main__': #print("add", sb_addition("2222222222222222222222222222222222222222.55", "2.55") ) #print("add", sb_addition("3.8257", "0.8257") ) #print( type(sb_substract("9999999.019999", "99999.99999993")) ) #print("sub", sb_substract("12", "78.9999") ) #print(greater_than("0","1110", "0","1112", True, True)) #print(greater_than("0","0", "1110","1112")) #print(greater_than('9001','9003')) #print("mul", sb_multiply('123','123.0')) #======================= #print("sb_addition('14','19977.67')", sb_addition('14','19977.67')) #print("sb_substract('559.1','6.98')", sb_substract('559.1','6.98')) #print("sb_multiply( sb_addition('14','19977.67') , sb_substract('559.1','-6.98') )",sb_multiply( sb_addition('14','19977.67') , sb_substract('559.1','-6.98') )) #print("cmplx:", sb_multiply( sb_multiply( sb_addition('14','19977.67') , sb_substract('559.1','6.98') ),'0.1459')) #print("format", good_format('10.0')) #print("overlap",overlap('-12512.252','125')) #ov_r = overlap('-12512.252','-125') #print(unoverlap(ov_r)) #print("mult", sb_multiply('-125.32564','100000.0')) #print(sb_division('22','7', digits_after_decimal_point=15)) #print(sb_multiply('100000.00000','-0111111.0001')) #print(unoverlap('132.1230010')) c = encode(['2.55','1.27','0.50','0.25','0.01','1.27','0','0.78','0.99','0.54','2.31','2.55','1.27','0.50','0.50','0.50']) print("c",c) print(decode(c, size=16))