# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# IPython code repository
# experiment with FOR and WHILE loops
# build test data with generators and iterators
#
#

# !pip3 install --upgrade pip
# !pip3 install StringGenerator

from random import randint, randrange, uniform
import string
from strgen import StringGenerator as SG
import numpy as np

# %pdb

print(randint(234, 567))

irand = randrange(0, 10)
frand = uniform(0, 10)

irand

frand

A = [randint(0, 999) for p in range(0, 11)]
C = [randint(0,  999) for q in range(0,11)]
D = [randint(0,  999) for q in range(0,11)]

A.sort()

print(A)
print(C)


#selection sort: find the minimal value and switch it with the first element
#of an array, then sort the rest of the array.
def  coconut__Sort(C):
    n = len(C)
    for d in range(n):
        minimal = d
        for e in range(d + 1, n):
            if C[e] < C[minimal]:
                minimal = e
        C[d], C[minimal] = C[minimal], C[d]
    print(C)



coconut__Sort(C)


#count the elements in the array, iterate through in increasing order
def count_sort(D, k):
    n = len(D)
    count = [0] * (k +1)
    for i in range(n):
        count[D[i]] += 1
    p = 0
    for i in range(k +1):
        for j in range(count[i]):
            D[p] = i
            p += 1
    print(D)


count_sort(D, 10)


#return the number of unique values in an array
def distinct(E):
    n = len(E)
    E.sort()
    result = 1
    for f in range(1, n):
        if E[f] != E[f -1]: 
            result += 1
    return result


E = [randint(0,  999) for q in range(0,11)]

# %time distinct(E)

# %%time
#import numpy as np
print(len(np.unique(E)))

np.random.shuffle(A)


def id_generator(size=16, chars=string.ascii_uppercase + string.digits):
    #return ''.join(random.choice(chars) for _ in range(size))
    #return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(size)
    #return ''.join(random.choices(string.ascii_uppercase + string.digits, k=size))
    return ''.join(random.choices(string.ascii_uppercase + string.digits, k=size))


id_generator()



 SG("[\l\d]{10}").render_list(5,unique=True)

SG("[\l\d]{10}&[\p]").render()

import uuid; uuid.uuid4().hex.upper()[0:6]

# +
import uuid

def my_random_string(sl):
    string_length = sl
    """Returns a random string of length string_length."""
    random = str(uuid.uuid4()) # Convert UUID format to a Python string.
    random = random.upper() # Make all characters uppercase.
    random = random.replace("-","") # Remove the UUID '-'.
    return random[0:string_length] # Return the random string.

print(my_random_string(10))
# -

# %time my_random_string(113)

A = [1, 3, 6, 4, 1, 2]


def michael_ellis(e):
    # write your code in Python 3.6
    min = np.min.A
    #while min not in a:
    max     


    pass


def smallest_missing_positive_integer(A):
    A.sort()
    N = len(A)
    
    i = 0
    previous = 0
    while i < N:
        current = A[i]

        if current > 0:
            if current > previous + 1: # breaks consecutiveness
                return previous + 1
            else:
                previous = current
        
        i += 1
    
    return max(previous+1, current+1)


print(smallest_missing_positive_integer(A))


def second_largest(A):
    m1, m2 = float('inf'), float('inf')
    for x in A:
        if x >= m1:
            m1, m2 = x, m1
        elif x > m2:
            m2 = x
    return m2



second_largest(A)

import heapq
def second_largest_2(numbers):
    return heapq.nsmallest(2, numbers)[-1]



second_largest_2(A)


def second_smallest(A):
    m1, m2 = float('inf'), float('inf')
    for x in A:
        if x <= m1:
            m1, m2 = x, m1
        elif x < m2:
            m2 = x
    return m2


s = set(A)
print (sorted(s)[1])

second_smallest(A)


def minpositive(A):
    b = set(A)
    ans = 1
    while ans in A:
       ans += 1
    return ans


print (minpositive(A))

A = [-1, -5, -3]

# +
from itertools import count, filterfalse 

def minpositive2(A):
    return(next(filterfalse(set(A).__contains__, count(1))))


# -

print (minpositive2(A))


#find the binary gap, max sequence of consecutive zeros surrounded by ones 
def max_gap(x):
    max_gap_length = 0
    current_gap_length = 0
    for i in range(x.bit_length()):
        if x & (1 << i):
            # Set, any gap is over.
            if current_gap_length > max_gap_length:
                max_gap_length = current_gap_length
            current_gap_length = 0
        else:
            # Not set, the gap widens.
            current_gap_length += 1
    # Gap might end at the end.
    if current_gap_length > max_gap_length:
        max_gap_length = current_gap_length
    return max_gap_length


#convert int to a binary, strip zeros from the right side, split a 1,
#find max in the list and return the length
def binary_gap(N):
    return len(max(format(N, 'b').strip('0').split('1')))


# %timeit binary_gap(529)

bin(529)

# %timeit max_gap(529)

#rotate an array, each element moves to the right by one, last element goes to beginning
x = np.arange(11)  #random.randn(3,27,1)

x


# %timeit print(np.roll(x, 3))

def rotater(l, n):
    return l[n:] + l[:n]


# %timeit print(rotater([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10], 3))

#find the unpaired value in an odd number of elements
def no_pair(y)


def no_pair(A):
    if len(A) == 1:
        return A[0]
    A = sorted(A)
    for i in range (0, len(A), 2):
        if i+1 == len(A):
            return A[i]
        if A[i] != A[i+1]:
            return A[i]


arr = [9,3,9,3,9,7,9,7,1]


def no_pair2(arr):
    result = 0
    for number in arr:
        result ^= number
    return result


no_pair2(arr)

no_pair(arr)


# +
#rotate array elementsarr2
# -

#count min number of fixed(y) jumps to >= D. 
#starting position is x
def badger(x, y, d):
    distance = y- x
    if distance % d == 0:
        return distance//d
    else:
        return distance//d +1


# %timeit badger(10, 88834999337775, 3.3)

def badger2():
    pass


#perm missing elements,if not a continous list will return highest missing value
def llama_milk(m):
    length = len(m)
    xor_sum = 0
    for index in range(0, length):
        xor_sum = xor_sum ^ m[index] ^ (index + 1)
    return xor_sum^(length +1)


m =[2,3,1,27]

llama_milk(m)

# #codility tape_equilibrium
# example from codility website
#
# >Array A = numbers on a tape, range(-1000, 1000)
# >Any integer P, such that 0 < P < N, N is an int range(2, 100,00)
# >splits this tape into two non-empty parts: 
# >A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ..., A[N − 1]
# >the difference is the absolute diff between the sum of the first part
# >and the sum of the second.
#

import numpy as np
#A5 = [3,1,2,4,3]
A5 = np.arange(1,66,1)
np.random.shuffle(A5)
A5


def tape_cutter(A5):
    a=A5 
    tablica=[]
    tablica_1=[]
    sum_a=0
    if len(a) == 2:
        return abs(a[0]-a[1])
    for x in a:
        sum_a  = sum_a + x
        tablica.append(sum_a)
    for i in range(len(tablica)-1):
        wynik=(sum_a-2*tablica[i])
        tablica_1.append(abs(wynik))
    tablica_1.sort()
    return tablica_1[0]


def tape_cutter2(A5):
    s = sum(A5)
    m = float('inf')
    left_sum = 0
    for i in A5[:-1]:
        left_sum += i
        m = min(abs(s - 2*left_sum), m)
    return m


# %time tape_cutter(A5)

# %time tape_cutter2(A5)

# ##Suduko converter
# Pass in a string of 81 numbers, using zeros for unknown values place holder.
#
#
#
# [stackoverflow_Suduko](https://stackoverflow.com/questions/201461/shortest-sudoku-solver-in-python-how-does-it-work/201771#201771)
#
# original source = http://norvig.com/sudoku.html
#
# https://towardsdatascience.com/peter-norvigs-sudoku-solver-25779bb349ce

# +
import sys

def same_row(i,j): return (i/9 == j/9)
def same_col(i,j): return (i-j) % 9 == 0
def same_block(i,j): return (i/27 == j/27 and i%9/3 == j%9/3)

def r(a):
    i = a.find('0')
    if i == -1:
        sys.exit(a)

    excluded_numbers = set()
    for j in range(81):
        if same_row(i,j) or same_col(i,j) or same_block(i,j):
            excluded_numbers.add(a[j])

    for m in '123456789':
        if m not in excluded_numbers:
            r(a[:i]+m+a[i+1:])

if __name__ == '__main__':
    if len(sys.argv) == 2 and len(sys.argv[1]) == 81:
        r(sys.argv[1])
    else:
        print ('Usage$ python sudoku.py puzzle')
        print ('  where the puzzle is an 81 character string')
        print ('  representing the puzzle read left-to-right,')
        print ('  top-to-bottom, and 0 is a blank')
# -

s1 = '070001500503007000014008003000000654000070000246000000700300280000600405005700030'


# %tb

# +
def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [a+b for a in A for b in B]

digits   = '123456789'
rows     = 'ABCDEFGHI'
cols     = digits
squares  = cross(rows, cols)
unitlist = ([cross(rows, c) for c in cols] +
            [cross(r, cols) for r in rows] +
            [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])
units = dict((s, [u for u in unitlist if s in u]) 
             for s in squares)
peers = dict((s, set(sum(units[s],[]))-set([s]))
             for s in squares)


# -

def test():
    "A set of unit tests."
    assert len(squares) == 81
    assert len(unitlist) == 27
    assert all(len(units[s]) == 3 for s in squares)
    assert all(len(peers[s]) == 20 for s in squares)
    assert units['C2'] == [['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'],
                           ['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'],
                           ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']]
    assert peers['C2'] == set(['A2', 'B2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
                               'C1', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
                               'A1', 'A3', 'B1', 'B3'])
    print('All tests pass.')


test()

print(len(unitlist))


# +
def parse_grid(grid):
    """Convert grid to a dict of possible values, {square: digits}, or
    return False if a contradiction is detected."""
    ## To start, every square can be any digit; then assign values from the grid.
    values = dict((s, digits) for s in squares)
    for s,d in grid_values(grid).items():
        if d in digits and not assign(values, s, d):
            return False ## (Fail if we can't assign d to square s.)
    return values

def grid_values(grid):
    "Convert grid into a dict of {square: char} with '0' or '.' for empties."
    chars = [c for c in grid if c in digits or c in '0.']
    assert len(chars) == 81
    return dict(zip(squares, chars))


# -

print(squares)


# +
def assign(values, s, d):
    """Eliminate all the other values (except d) from values[s] and propagate.
    Return values, except return False if a contradiction is detected."""
    other_values = values[s].replace(d, '')
    if all(eliminate(values, s, d2) for d2 in other_values):
        return values
    else:
        return False

def eliminate(values, s, d):
    """Eliminate d from values[s]; propagate when values or places <= 2.
    Return values, except return False if a contradiction is detected."""
    if d not in values[s]:
        return values ## Already eliminated
    values[s] = values[s].replace(d,'')
    ## (1) If a square s is reduced to one value d2, then eliminate d2 from the peers.
    if len(values[s]) == 0:
        return False ## Contradiction: removed last value
    elif len(values[s]) == 1:
        d2 = values[s]
        if not all(eliminate(values, s2, d2) for s2 in peers[s]):
            return False
    ## (2) If a unit u is reduced to only one place for a value d, then put it there.
    for u in units[s]:
        dplaces = [s for s in u if d in values[s]]
        if len(dplaces) == 0:
            return False ## Contradiction: no place for this value
        elif len(dplaces) == 1:
            # d can only be in one place in unit; assign it there
            if not assign(values, dplaces[0], d):
                return False
    return values


# -

def display(values):
    "Display these values as a 2-D grid."
    width = 1+max(len(values[s]) for s in squares)
    line = '+'.join(['-'*(width*3)]*3)
    for r in rows:
        print (''.join(values[r+c].center(width)+('|' if c in '36' else '')
                      for c in cols))
        if r in 'CF': print(line)
    print


grid1 = '003020600900305001001806400008102900700000008006708200002609500800203009005010300'


display(parse_grid(grid1))


# +
def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [a+b for a in A for b in B]

digits   = '123456789'
rows     = 'ABCDEFGHI'
cols     = digits
squares  = cross(rows, cols)
unitlist = ([cross(rows, c) for c in cols] +
            [cross(r, cols) for r in rows] +
            [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])
units = dict((s, [u for u in unitlist if s in u]) 
             for s in squares)
peers = dict((s, set(sum(units[s],[]))-set([s]))
             for s in squares)

def parse_grid(grid):
    """Convert grid to a dict of possible values, {square: digits}, or
    return False if a contradiction is detected."""
    ## To start, every square can be any digit; then assign values from the grid.
    values = dict((s, digits) for s in squares)
    for s,d in grid_values(grid).items():
        if d in digits and not assign(values, s, d):
            return False ## (Fail if we can't assign d to square s.)
    return values

def grid_values(grid):
    "Convert grid into a dict of {square: char} with '0' or '.' for empties."
    chars = [c for c in grid if c in digits or c in '0.']
    assert len(chars) == 81
    return dict(zip(squares, chars))

def assign(values, s, d):
    """Eliminate all the other values (except d) from values[s] and propagate.
    Return values, except return False if a contradiction is detected."""
    other_values = values[s].replace(d, '')
    if all(eliminate(values, s, d2) for d2 in other_values):
        return values
    else:
        return False

def eliminate(values, s, d):
    """Eliminate d from values[s]; propagate when values or places <= 2.
    Return values, except return False if a contradiction is detected."""
    if d not in values[s]:
        return values ## Already eliminated
    values[s] = values[s].replace(d,'')
    ## (1) If a square s is reduced to one value d2, then eliminate d2 from the peers.
    if len(values[s]) == 0:
        return False ## Contradiction: removed last value
    elif len(values[s]) == 1:
        d2 = values[s]
        if not all(eliminate(values, s2, d2) for s2 in peers[s]):
            return False
    ## (2) If a unit u is reduced to only one place for a value d, then put it there.
    for u in units[s]:
        dplaces = [s for s in u if d in values[s]]
        if len(dplaces) == 0:http://norvig.com/top95.txt
            return False ## Contradiction: no place for this value
        elif len(dplaces) == 1:
            # d can only be in one place in unit; assign it there
            if not assign(values, dplaces[0], d):
                return False
    return values

def solve(grid): return search(parse_grid(grid))

def search(values):
    "Using depth-first search and propagation, try all possible values."
    if values is False:
        return False ## Failed earlier
    if all(len(values[s]) == 1 for s in squares): 
        return values ## Solved!
    ## Chose the unfilled square s with the fewest possibilities
    n,s = min((len(values[s]), s) for s in squares if len(values[s]) > 1)
    return some(search(assign(values.copy(), s, d)) 
        for d in values[s])

def some(seq):
    "Return some element of seq that is true."
    for e in seq:
        if e: return e
    return False


# -

#permcheck practice example codility, solution by Sheng from codesays.com
#permutation is a seq from 1 to N, nothing repeated or missing
#return 0 if not a permutation
def permcheck(A):
    counter = [0]*len(A)
    limit = len(A)
    for element in A:
        if not 1 <= element <= limit:
            return 0
        else:
            if counter[element-1] != 0:
                return 0
            else:
                counter[element-1] = 1
    return 1


a2a = [4,1,3,2,5,9,9,6,7,8]

permcheck(a2a)

a3b = range(10,123,1)

print(a3b)


def frog1(X,A):

    covered = 0
    covered_a = [-1]*X

    for index,element in enumerate(A):
        if covered_a[element-1] == -1:

            covered_a[element-1] = element
            covered += 1
            if covered == X:
                return index
    return -1


A = [3, 3, 3, 3, 2, 1, 1, 4]

A = [1,3,1,4,2,3,5,4]

frog1(5, A)

B = [9, 4, 7, 3, 7, 2, 4, 4]

swap2(A, B, 8)


#codility practice example 4, counting
#given two arrays, can you swap elements to make the sums equal?
def counting(A, m):
    n = len(A)
    count = [0] * (m + 1)
    for k in range(n):
        count[A[k]] += 1
    return count
'''
#option 1, swap every pair of elements and then sum
def swap1(A, B, m):
    n = len(A)
    sum_a = sum(A)
    sum_b = sum(B)
    for i in range(n):
        for j in range(n):
            change = B[j] - A[i]
            sum_a += change
            sum_b -= change
            if sum_a == sum_b:
                return True
            sum_a -= change
            sum_b += change
    return False
'''
#faster to count the elements and diff the sums
def swap2(A, B, m):
    n = len(A)
    sum_a = sum(A)
    sum_b = sum(B)
    d = sum_b - sum_a
    if d % 2 == 1:
        return False
    d //= 2
    count = counting(A, m)
    for i in range(n):
        if 0 <= B[i]  - d and B[i] -d <= m and count [B[i]  - d] > 0:
            print('swap possible!') #return True
        print('No swap for you!!!') #return False


# +
#codility max counters practice example
#you have counters set to zero, increase by 1 or set to max
#calculate counter value after operations
def max_counter(N, A):
    counters = [0] * N
    max_value, threshold = 0, 0
    for a in A:
        index = a - 1
        if index == N:
            threshold = max_value
        else:
            counters[index] = max(threshold + 1, counters[index] + 1)
            max_value = max(max_value, counters[index])
    for index, counter in enumerate(counters):
        counters[index] = max(threshold, counter)
    return counters

#source = https://github.com/wouterken/codility-python/blob/master/codility-max-counters.py



# -

#should return 3 2 2 4 2
max_counter(5, [3,4,4,6,1,4,4])



StarcoderdataJupyterScriptsDedupFiltered