import random
import time
import sys

def printf(format, *args):  sys.stdout.write(format % args)

M = 4
N = 6

# Define array with M rows and N columns
# filled with 0.
arr =  [[34]*N for i in range(M)]
print(arr)
print()

# Print the array neatly in a rectangular shape
# It happens quite often that seeing what is in the array
# helps in the debugging process.
def prt( arr ):
    for i in range( len(arr) ):
        print( arr[i] )
    print()

# print with equal cell length
def prt2( arr, cellLen ):
    formatStr = "%"+str( cellLen )+"d"
    print( "Format string is:", '"'+formatStr+'"' )
    for i in range( len(arr) ):
        for j in range( len(arr[i]) ):
            #print("%5d" % (arr[i][j]), end="")
            print( formatStr % (arr[i][j]), end="" )
        print() # new line
    print()

# fill the array with some random values
def rndFill( arr, minVal, maxVal, aSeed ):
    random.seed(aSeed)
    for i in range( len(arr) ):
        for j in range( len(arr[i]) ):
            arr[i][j] = random.randint(minVal, maxVal)
        # the following is also possible (less efficient, why?)
        # arr[i] = [random.randint(minVal, maxVal) for j in range( len(arr[i]) )]

# fill the array with some constant
def arrFill( arr, value ):
    for i in range( len(arr) ):
        for j in range( len(arr[i]) ):
            arr[i][j] = value
        # the following is also possible
        # arr[i] = [value] * len(arr[i])


# fill the array in a chessboard-like way with two values
def chessFill( arr, value1, value2 ):
    for i in range( len(arr) ):
        for j in range( len(arr[i]) ):
            if (i+j) % 2 == 0:
                arr[i][j] = value1
            else:
                arr[i][j] = value2

# fill the array of size MxN with values 1,2,3, ..., M*N
# in random order
def rndFillPermute( arr ):
    M = len(arr)
    N = len(arr[0])
    aux = list( range(1, M*N+1) )
    print( aux )
    random.shuffle( aux )
    print( aux )
    for i in range( M ):
        arr[i] = aux[i*N : i*N+N]
    print()

# find max and min
def minmax( arr ):
    aMin = min(arr[0])
    aMax = max(arr[0])
    for i in range( 1, len(arr) ):
        aMin = min( aMin, min(arr[i]) )
        aMax = max( aMax, max(arr[i]) )
    return aMin, aMax

# Decide if values in the array are mutually different
def areAllDifferent( arr ):
    all = []
    for i in range(len(arr)):
        all.extend( arr[i] )
    all.sort()
    for i in range( len(all)-1 ):
        if( all[i] == all[i+1] ):
            return False
    return True

# Solution of Exercise 2 below
def mx2( a, b, size):
    mx = [ [a] * size for i in range(size)]
    for i in range( size ):
        for j in range( size ):
            if i + j >= size:
                mx[i][j] = b
    prt( mx )

# Auxilliary procedure which helps
# in solution of Exercise 3 below
def square( mx, size, x, val ):
    for j in range (x, size-x-1 +1):
        mx[x][j] = val = val
        mx[size-x-1][j] = val
        mx[j][x] = val = val
        mx[j][size-x-1] = val

def mx3( size, a, b):
    mx = [ [a] * size for i in range(size)]
    for i in range( 1, (size // 2) +1, 2 ):
        square(mx, size, i, b)
    prt( mx )




prt(arr)
prt2( arr, 4 )
print( arr )
rndFill( arr, 10, 20, 542012001 )
#print(arr)
prt(arr)
#print( sum(arr) ) # does not work
print( minmax(arr) )

rndFill( arr, 10, 10000, 12323091 )
prt2( arr, 5 )
print( minmax(arr) )

arrFill( arr, 23 )
prt2( arr, 4 )

chessFill( arr, 11, 88 )
prt2( arr, 3 )

rndFill( arr, 10, 10000, 14323091 )
prt2( arr, 6 )
print( areAllDifferent(arr) )


M = 8
N = 8
arr =  [[0]*N for i in range(M)]

print( "----------- chess fill -------------")
chessFill( arr, 11, 44 )
prt2( arr, 3 )
print( areAllDifferent(arr) )

rndFillPermute( arr )
prt2( arr, 4 )

mx2(11,88, 7)
mx3( 10, 11, 88)

# Exercises:

# Exercise 1
# fill the array with two values, a and b,
# b is only on the main diagonal
# b a a a a a a
# a b a a a a a
# a a b a a a a
# a a a b a a a
# a a a a b a a
# a a a a a b a
# a a a a a a b

# Exercise 2
# fill the array with two values, a and b,
# b is everywhere below the secondary diagonal
# a a a a a a a
# a a a a a a b
# a a a a a b b
# a a a a b b b
# a a a b b b b
# a a b b b b b
# a b b b b b b

# Exercise 3
# fill the array with two values, a and b,
# in the following concentric way,
# the stripes are 1 unit wide
# a a a a a a a
# a b b b b b a
# a b a a a b a
# a b a b a b a
# a b a a a b a
# a b b b b b a
# a a a a a a a


