#!/usr/bin/env python
# coding: utf-8

# refer to https://machinelearningmastery.com/multivariate-time-series-forecasting-lstms-keras/
#
# to tune parameters
# refer to http://yangguang2009.github.io/2017/01/08/deeplearning/grid-search-hyperparameters-for-deep-learning/

# In[1]:

from __future__ import print_function

import json
import numpy as np
import os
import pandas as pd
import urllib
import math

from sklearn.model_selection import GridSearchCV
from keras.wrappers.scikit_learn import KerasClassifier

from hyperopt import Trials, STATUS_OK, tpe
from hyperas import optim
from hyperas.distributions import choice, uniform

# connect to poloniex's API
url = 'https://poloniex.com/public?command=returnChartData&currencyPair=USDT_BTC&start=1546300800&end=9999999999&period=300&resolution=auto'

# parse json returned from the API to Pandas DF
openUrl = urllib.request.urlopen(url)
r = openUrl.read()
openUrl.close()
d = json.loads(r.decode())
df = pd.DataFrame(d)

original_columns=[u'date', u'close',  u'high', u'low', u'open', u'volume']
new_columns = ['Timestamp','Close','High','Low','Open','Volume']
df = df.loc[:,original_columns]
df.columns = new_columns
df.to_csv('bitcoin201901to201905.csv',index=None)

# In[2]:

df = df.set_index('Timestamp')
df.head()

# In[3]:

from math import sqrt
from numpy import concatenate
from matplotlib import pyplot
from pandas import read_csv
from pandas import DataFrame
from pandas import concat
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM

import seaborn as sns
import numpy as np

# convert series to supervised learning
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
	n_vars = 1 if type(data) is list else data.shape[1]
	df = DataFrame(data)
	cols, names = list(), list()
	# input sequence (t-n, ... t-1)
	for i in range(n_in, 0, -1):
		cols.append(df.shift(i))
		names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
	# forecast sequence (t, t+1, ... t+n)
	for i in range(0, n_out):
		cols.append(df.shift(-i))
		if i == 0:
			names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
		else:
			names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
	# put it all together
	agg = concat(cols, axis=1)
	agg.columns = names
	# drop rows with NaN values
	if dropnan:
		agg.dropna(inplace=True)
	return agg

# In[4]:

pyplot.plot(df['Close'].values, label='price')
pyplot.legend()
pyplot.show()

# In[5]:

sns.heatmap(df.corr(), annot=True, cmap='RdYlGn', linewidths=0.1, vmin=0)

# In[6]:

# load dataset
#dataset = read_csv('update_20190301_bitbank_f.csv', header=0, index_col=0)
#values = dataset.values

#dataset.head()

values = df['Close'].values
values = values.reshape(-1, 1)
print(values)

# In[7]:

# ensure all data is float
values = values.astype('float32')
# normalize features
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
# frame as supervised learning
reframed = series_to_supervised(scaled, 1, 1)

#test =  series_to_supervised(values, 1, 1)
#print(test.head())
#print(test.shape)

# In[8]:

print(values.shape)
print(reframed.shape)
print('---------')
#print(reframed.columes)

# split into train and test sets
values = reframed.values
print(values.shape)

n_train_rate = 0.7
n_train = values.shape[0] * n_train_rate
n_train = math.floor(n_train)
print(n_train)

train = values[:n_train, :]
test = values[n_train:, :]

# split into input and outputs
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
# reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)

# In[9]:

import math

# drop columns we don't want to predict
# 只留下 close 列
#reframed.drop(reframed.columns[[6, 7, 8, 10, 11]], axis=1, inplace=True)
#print(reframed.head())

# split into train and test sets
values = reframed.values
print(values.shape)

n_train_rate = 0.7
n_train = values.shape[0] * n_train_rate
n_train = math.floor(n_train)
print(n_train)

train = values[:n_train, :]
test = values[n_train:, :]

# split into input and outputs
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
# reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)

# In[10]:

#!pip install tqdm --upgrade
#!pip install hyperopt --upgrade
#!pip install hyperas --upgrade
type(train_X)

# In[16]:

def data():
    global train_X, test_X, train_y, test_y
    return train_X, test_X, train_y, test_y

# design network
def model(train_X, train_Y, test_X, test_Y):
    model = Sequential()
    model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    model.add(Dense(1))
    model.compile(loss='mae', optimizer='adam')
    history = model.fit(train_X, train_y, epochs={{choice([10, 25, 50])}}, batch_size={{choice([8, 16, 32,50])}}, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    score, acc = model.evaluate(test_X, test_y, verbose=0)
    print('Test accuracy:', acc)
    return {'loss': -acc, 'status': STATUS_OK, 'model': model}

best_run, best_model = optim.minimize(model=model,
                                          data=data,
                                          algo=tpe.suggest,
                                          max_evals=10,
                                          trials=Trials(),
                                          notebook_name='LSTMsinKeras-VirtualCurrency-Simple')
print("Evalutation of best performing model:")
print(best_model.evaluate(test_X, test_y))

# In[ ]:

# plot history
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()

# In[ ]:

# make a prediction
yhat = model.predict(test_X)
print('yhat.shape', yhat.shape, yhat[0:5, :])
test_X_reshape = test_X.reshape((test_X.shape[0], test_X.shape[2]))
print(test_X_reshape.shape, test_X_reshape[0:5, -7:])

# invert scaling for forecast
inv_yhat = concatenate((yhat, test_X_reshape[:, 1:]), axis=1)
inv_yhat = scaler.inverse_transform(inv_yhat)
print('inv_yhat.shape', inv_yhat.shape, inv_yhat[0:5, :])

inv_yhat = inv_yhat[:,0]
# invert scaling for actual
test_y = test_y.reshape((len(test_y), 1))
inv_y = concatenate((test_y, test_X_reshape[:, 1:]), axis=1)
inv_y = scaler.inverse_transform(inv_y)
inv_y = inv_y[:,0]
# calculate RMSE
# 因为inv_y 预测是下一时刻的值，所以需要把 inv_yhat 往后 shift 一个时刻
rmse = sqrt(mean_squared_error(inv_y[:-1], inv_yhat[1:]))
print('Test RMSE: %.3f' % rmse)

# In[ ]:

print(test_X.shape)
#print(range(test_X.shape))

#pyplot.plot( inv_y[-100:-1], label='predict')
#pyplot.plot( inv_yhat[-99:], label='actual')
pyplot.plot( inv_y, label='predict')
pyplot.plot( inv_yhat, label='actual')
pyplot.legend()
pyplot.show()

#涨跌的判准率

#获取预测跟实际对应元素值，是否大于0
a = np.diff(inv_y) > 0
b = np.diff(inv_yhat) > 0

#比较相同值的个数
print(sum(a ==b)/a.shape[0])

# In[14]:

x = 6
def func():
    global x
    print(x)
    return x
func()

# In[ ]:


class Item:
    def __init__(self, name, price,
                 quantity=0):  # this method is like constructor in java.this method is executed automatically when an instance is created
        # by making quantity = 0 that means giving a default value when u don't the value currently
        # so if quantity is not passed then it will assume qunatity as 0 by default and show no error

        print(f"Instance is created : {name}")
        self.name = name  # here an attribute is created by passing argument value while creating an instance by using init() method
        self.price = price  # dynamicly allocating the attributes
        self.quantity = quantity

    # instead of passing separate variables to this function we can use self.attributes as it is already initialize
    # since we are passing self so it will also pass attributes connected to it
    def calculate_total_price(self):
        return self.price * self.quantity

'''instead of hardcoding attributes to avoid it
   __init__(self) function is used'''
item1 = Item("Phone", 55900, 5)

print(item1.name, item1.price, item1.quantity)
print("Total price:", item1.calculate_total_price())

item2 = Item("Laptop", 129900, 3)
print(item2.name, item2.price, item2.quantity)
print("Total price:", item2.calculate_total_price())

# this is an attribute for this instance only item2 and other instances will not have this attribute
item2.has_numpad = False
# what if it would have been easier instead of declaring instances like above
# an instance can be created only by passing those attributes values


from PRISMRenderingShaders.CustomShader import CustomShader

"""PlaneIntersectingShader Class containing the code for the Plane intersecting shader.

:param CustomShader:  Parent class containing the function to access the parameters of the shader.
:type CustomShader: class.
"""
class PlaneIntersectingShader(CustomShader):

  shaderfParams = { 'relativePosition' : { 'displayName' : 'Relative Position', 'min' : 0.0, 'max' : 1.0, 'defaultValue' : 1.0 }}
  shader4fParams = {'entry': {'displayName': 'Entry', 'defaultValue': {'x': 0.0, 'y': 0.0, 'z': 0.0, 'w': 0.0}}, \
                    'target': {'displayName': 'Target', 'defaultValue': {'x': 0.0, 'y': 0.0, 'z': 0.0, 'w': 0.0}}}

  shaderbParams = { 'plane' : { 'displayName' : 'Third Plane', 'defaultValue' : 0, 'optionalWidgets' : []}}

  def __init__(self, shaderPropertyNode, volumeNode = None):
    CustomShader.__init__(self,shaderPropertyNode)

  @classmethod
  def GetBasicDescription(cls):
    """Function to get a basic description of the current shader.

    :return: Description of the current shader.
    :rtype: str
    """
    return 'Allows to visualize the anatomy along the approach plane for surgery'

  @classmethod
  def GetDisplayName(cls):
    return 'Plane intersecting'

  def setupShader(self):
    super(PlaneIntersectingShader,self).setupShader()
    replacement = """
      vec4 texCoordRAS = in_volumeMatrix[0] * in_textureDatasetMatrix[0]  * vec4(g_dataPos, 1.);
      vec3 dirVect = normalize(entry.xyz - target.xyz);

      bool skipAlongAxis = dot(texCoordRAS.xyz - entry.xyz, dirVect) + length(entry.xyz - target.xyz) * relativePosition > 0;

      vec3 vPlaneN = cross(vec3(0.0,0.0,1.0), dirVect);
      float dirCoord = dot(texCoordRAS.xyz - entry.xyz, vPlaneN);
      float dirCam = dot(in_cameraPos - entry.xyz, vPlaneN);
      bool skipVertical = dirCoord * dirCam > 0.0;

      vec3 hPlaneN = cross(vPlaneN, dirVect);
      dirCoord = dot(texCoordRAS.xyz - entry.xyz, hPlaneN);
      dirCam = dot(in_cameraPos - entry.xyz, hPlaneN);
      bool skipHorizontal = dirCoord * dirCam > 0.0;

      if (plane == 1)
        g_skip = skipAlongAxis && skipVertical && skipHorizontal;
      else
        g_skip = skipAlongAxis && skipVertical;

    """
    self.shaderProperty.AddFragmentShaderReplacement("//VTK::Cropping::Impl", True, replacement, False)
    #shaderreplacement


# USAGE
# python align_faces.py --shape-predictor shape_predictor_68_face_landmarks.dat --image images/example_01.jpg

# import the necessary packages
from imutils.face_utils import FaceAligner
from imutils.face_utils import rect_to_bb
import argparse
import imutils
import dlib
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
	help="path to facial landmark predictor")
ap.add_argument("-i", "--image", required=True,
	help="path to input image")
args = vars(ap.parse_args())

# initialize dlib's face detector (HOG-based) and then create
# the facial landmark predictor and the face aligner
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
# 0.25 is the desired zoom 0.25 is the default
fa = FaceAligner(predictor, desiredLeftEye=(0.25, 0.25),desiredFaceWidth=112)

# load the input image, resize it, and convert it to grayscale
image = cv2.imread(args["image"])
image = imutils.resize(image, width=800)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
rects = detector(gray, 2)

# loop over the face detections
# rect contains the bounding boxes
for rect in rects:
	# extract the ROI of the *original* face, then align the face
	# using facial landmarks
	(x, y, w, h) = rect_to_bb(rect)
	faceAligned = fa.align(image, gray, rect)
	#faceAligned = cv2.resize(faceAligned, (224, 224))
	import uuid
	f = str(uuid.uuid4())
	# write resulting image
	cv2.imwrite("/home/monete/monete@gmail.com/studying/IA/thesis/deeplearning/dataset/fer2013/output/7-surprise/" + f + ".png", faceAligned)

	# display the output images
	#cv2.imshow("Aligned", faceAligned)
	#cv2.waitKey(0)


import os
import tempfile
import pytest
import warnings
import numpy as np
import onnxruntime as ort
import torch
from torch import nn as nn
from typing import Optional, Union, Tuple, List
import transformer_engine.pytorch as te
from transformer_engine.common import recipe
import transformer_engine_extensions as tex
from transformer_engine.pytorch.cpp_extensions import gemm, fp8_gemm, gelu, cast_to_fp8, cast_from_fp8
from transformer_engine.pytorch.module.base import get_workspace
import transformer_engine.pytorch.cpp_extensions as texcpp
import transformer_engine.pytorch.softmax as softmax_defs
from transformer_engine.pytorch.utils import get_default_init_method
from transformer_engine.pytorch.export import is_in_onnx_export_mode
from transformer_engine.pytorch.fp8 import FP8GlobalStateManager

# Global test configuration knobs.

# Enable this to serialize test inputs and outputs to file (as a Polygraphy RunResults instance).
SAVE_TEST_IO = bool(int(os.getenv("NVTE_ONNX_EXPORT_SAVE_TEST_IO", "0")))

if SAVE_TEST_IO:
    from polygraphy.json import save_json
    from polygraphy.comparator import RunResults

# The directory where generated ONNX test models are stored.
NVTE_TEST_ARTIFACTS_DIR = os.environ.get('NVTE_TEST_ARTIFACTS_DIR')
NVTE_TEST_ARTIFACTS_DIR = NVTE_TEST_ARTIFACTS_DIR or os.path.join(tempfile.gettempdir(), "./gen_onnx_models")

# The directory where this file is stored.
TESTS_DIR = os.path.dirname(os.path.abspath(__file__))

# ScaledUpperTriangMaskedSoftmax is exported via ONNX::Trilu which was introduced in opset 14.
TRILU_OPSET = 14
# Opset used in the ONNX files generated by the tests.
OPSET = 17
assert OPSET >= TRILU_OPSET

# Shared library implementing custom FP8 Q/DQ operators for ONNX Runtime (ORT).
ORT_CUSTOM_OPS_LIB = os.path.join(TESTS_DIR, "./libcustom_ort_fp8_qdq_ops.so")

fp8_available, reason_for_no_fp8 = FP8GlobalStateManager.is_fp8_available()
skip_FP8 = pytest.mark.skipif(not fp8_available, reason=reason_for_no_fp8)

supported_activations = ["gelu", "relu", "reglu", "geglu", "swiglu"]

all_normalizations = ["LayerNorm", "RMSNorm"]

@pytest.fixture()
def seed_default_rng():
    """Reseed the PRNG for test reproducibility"""
    torch.random.seed()

@pytest.fixture()
def set_max_seq_len(max_seq_len=128):
    """Set the maximum sequence length that can be used for attention masking"""
    os.environ["NVTE_ONNX_KVCACHE_MAX_SEQ_LEN"] = f"{max_seq_len}"

def create_fp8_recipe():
    return recipe.DelayedScaling(margin=0, interval=1, fp8_format=recipe.Format.E4M3)

def do_export(
    model: torch.nn.Module,
    inp: torch.Tensor,
    fname: str,
    use_fp8: bool=True,
    opset: int=OPSET,
    input_names: List[str]=None,
    output_names: List[str]=None,
    dynamic_axes: List[str]=None
):
    """Export to ONNX"""
    fp8_recipe = create_fp8_recipe()
    input_names = input_names or ["input"]
    output_names = output_names or ["output"]

    with torch.inference_mode(), te.fp8_autocast(enabled=use_fp8, fp8_recipe=fp8_recipe), warnings.catch_warnings():
        warnings.filterwarnings(
            action='ignore',
            category=torch.jit.TracerWarning,
            module=r'.*'
        )

        model.cuda().eval()
        os.makedirs(NVTE_TEST_ARTIFACTS_DIR, exist_ok=True)
        fname = os.path.join(NVTE_TEST_ARTIFACTS_DIR, fname)

        inps = inp if isinstance(inp, list) or isinstance(inp, tuple) else (inp,)
        assert len(inps) == len(input_names)
        inds_to_del = [i for i in range(len(inps)) if inps[i] is None]
        input_names = [input_names[i] for i in range(len(inps)) if i not in inds_to_del]

        with te.onnx_export(True):
            torch.onnx.export(
                model,
                inps,
                fname,
                verbose=True,
                dynamic_axes=dynamic_axes,
                opset_version=opset,
                input_names=input_names,
                output_names=output_names,
                do_constant_folding=True,
                operator_export_type=torch.onnx.OperatorExportTypes.ONNX_FALLTHROUGH)

def to_numpy(tensor):
    if isinstance(tensor, torch.Tensor):
        if tensor.dtype == torch.bfloat16:
            tensor = tensor.type(torch.float32)
        tensor = tensor.detach().cpu().numpy()
    return tensor

def set_layer_scale(module: torch.nn.Module, scale: float, num_gemms: int):
    """Initialize the FP8 quantization scales in module"""
    NB_SCALES_PER_GEMM = 3  # One scale per: input, weights, and output GEMM tensors.
    nb_total_scales = num_gemms * NB_SCALES_PER_GEMM
    module.fp8_init(num_gemms)
    module.fp8_meta["scaling_fwd"].scale = torch.ones(
        nb_total_scales, dtype=torch.float32, device="cuda") / scale
    module.fp8_meta["scaling_fwd"].scale_inv = torch.ones(
        nb_total_scales, dtype=torch.float32, device="cuda") * scale

def te_infer(model: torch.nn.Module, inps: Union[Tuple[torch.tensor], torch.tensor], is_fp8: bool):
    """Transformer Engine forward propagation."""
    fp8_recipe = create_fp8_recipe()
    with torch.inference_mode(), te.fp8_autocast(enabled=is_fp8, fp8_recipe=fp8_recipe), warnings.catch_warnings():
        te_outputs = model(*inps if isinstance(inps, tuple) else (inps,))
        if not isinstance(te_outputs, tuple):
            te_outputs = (te_outputs,)
        return te_outputs

def compare_outputs(onnx_outputs, te_outputs, atol, rtol, max_errors_printed, allow_cnt_errors, fname):
    """ Compare ORT and TE outputs."""
    assert len(onnx_outputs) == len(te_outputs)
    # Compare ORT and PyTorch outputs.
    for onnx_output, te_output in zip(onnx_outputs, te_outputs):
        # np.isclose: abs(a - b) <= (atol + rtol * abs(b))
        te_output = to_numpy(te_output)
        onnx_output = to_numpy(onnx_output)
        ac = ~np.isclose(onnx_output, te_output, atol=atol, rtol=rtol)
        mismatches = ac.nonzero()
        mismatched_ids = [loc for loc in zip(*mismatches)]
        if mismatched_ids:
            # Log some information in case of error.
            print("*" * 100)
            nb_errors = len(mismatched_ids)
            nb_vals = min(nb_errors, max_errors_printed)
            print(f"Detected {nb_errors} diverging values (output shape={onnx_output.shape})")
            print(f"Showing first {nb_vals} errors (ONNX -- TE):")
            abs_err = np.abs(onnx_output - te_output)
            errors = abs_err[mismatches]
            for loc in mismatched_ids[:nb_vals]:
                ref = te_output[loc]
                print(f"{onnx_output[loc]} -- {te_output[loc]} err={abs_err[loc]} > {atol + rtol * abs(ref)}")
            print(f"Max error: {np.max(errors)}")
            if nb_errors > allow_cnt_errors:
                raise ValueError(f"Output validation of {fname} failed with {nb_errors} errors")

def serialize_inputs_outputs(
    fname: str,
    inputs: Union[Tuple[torch.Tensor], torch.Tensor],
    te_outputs: List[torch.Tensor],
    input_names: Optional[List[str]] = None,
    output_names: Optional[List[str]] = None,
):
    if not SAVE_TEST_IO:
        return

    fname = os.path.join(NVTE_TEST_ARTIFACTS_DIR, fname)

    input_names = input_names or ["input"]
    output_names = output_names or ["output"]
    inputs = inputs if isinstance(inputs, list) or isinstance(inputs, tuple) else (inputs,)
    named_inputs = zip(input_names, inputs)
    input_data = [{k: v.cpu() for k, v in named_inputs if v is not None}]
    json_fname = fname[:-len(".onnx")] + "_inputs.json"
    save_json(input_data, json_fname, description="custom input data")

    json_fname = fname[:-len(".onnx")] + "_output.json"
    named_outputs = zip(output_names, te_outputs)
    output_data = {k: v.detach().cpu() for k, v in named_outputs if v is not None}
    custom_outputs = RunResults()
    custom_outputs.add([output_data], runner_name="custom_runner")
    custom_outputs.save(json_fname)

def validate_result(
    fname: str,
    inps: Union[Tuple[torch.Tensor], torch.Tensor],
    model: torch.nn.Module,
    atol: float=1.e-8, # np.isclose default atol
    rtol: float=1.e-5, # np.isclose default rtol
    max_errors_printed: int=10,
    is_fp8: bool=False,
    allow_cnt_errors: int=0,
    input_names: List[str]=None,
    output_names: List[str]=None,
    te_outputs: List[torch.Tensor]=None,
):
    """Compare the outputs of a Transformer Engine (TE) module vs the outputs of its ONNX
    representation using ONNX Runtime (ORT) and ensure they are close.

    The purpose of the output comparison is to validate that TE models are converted to
    their correct ONNX representation by testing that TE and ORT outputs match within some
    small threshold (allowing for finite precision errors).

    Argument `allow_cnt_errors` reduces test failure noise due to spurious errors by ignoring,
    a very small number (0-3) of outliers. This is fine to do because these outliers are due to
    small kernel implementation differences between TE and ORT and do not imply an incorrect ONNX
    representation (the tests assume both ORT or TE kernels are correct).

    Argument `te_outputs` can be used to provide pre-computed TE outputs.
    """

    def create_ort_session(fname: str, is_fp8: bool):
        def load_custom_ops(session_opts: ort.SessionOptions):
            """For FP8 validation with ORT we need to load our custom FP8 Q/DQ extension."""
            if not os.path.exists(ORT_CUSTOM_OPS_LIB):
                raise FileNotFoundError(f"Unable to find {ORT_CUSTOM_OPS_LIB}")
            session_opts.register_custom_ops_library(ORT_CUSTOM_OPS_LIB)
            print("registered custom FP8 Q/DQ ops!")

        """Create an ONNX Runtime session for validation."""
        kwargs = {"providers": ['CUDAExecutionProvider', 'CPUExecutionProvider']}
        if is_fp8:
            sess_options = ort.SessionOptions()
            load_custom_ops(sess_options)
            kwargs["sess_options"] = sess_options

        s = ort.InferenceSession(fname, **kwargs)
        return s

    def create_ort_input_dict(session, inputs):
        inputs = inputs if isinstance(inputs, list) or isinstance(inputs, tuple) else (inputs,)
        input_names = [x.name for x in session.get_inputs()]
        inps = [to_numpy(x) for x in inputs if x is not None]
        inp_dict = dict(zip(input_names, inps))
        return inp_dict

    input_names = input_names or ["input"]
    output_names = output_names or ["output"]

    # Run ORT session and TE model.
    fname = os.path.join(NVTE_TEST_ARTIFACTS_DIR, fname)
    if not te_outputs:
        te_outputs = te_infer(model, inps, is_fp8)
    ort_s = create_ort_session(fname, is_fp8)
    input_feed = create_ort_input_dict(ort_s, inps)
    onnx_outputs = ort_s.run(None, input_feed=input_feed)
    compare_outputs(onnx_outputs, te_outputs, atol, rtol, max_errors_printed, allow_cnt_errors, fname)

def create_meta(scale_factor: float, size: int=1):
    meta = tex.FP8TensorMeta()
    meta.amax_history = torch.zeros(1, size, dtype=torch.float32, device="cuda")
    meta.scale_inv = torch.ones(size, dtype=torch.float32, device="cuda") / scale_factor
    meta.scale = torch.ones(size, dtype=torch.float32, device="cuda") * scale_factor
    return meta

def dtype2str(dtype: torch.dtype, fake_bf16_io=False):
    if fake_bf16_io:
        assert dtype == torch.bfloat16
        return "_fake_bf16"
    return {
        torch.float32: "_fp32",
        torch.float16: "_fp16",
        torch.bfloat16: "_bf16",
    }[dtype]

def as_te_type(dtype: torch.dtype):
    return {
        torch.float32: tex.DType.kFloat32,
        torch.float16: tex.DType.kFloat16,
        torch.bfloat16: tex.DType.kBFloat16,
    }[dtype]

def get_attn_mask_str(use_mask, attn_mask_type):
    # See FusedScaleMaskSoftmax::forward_fused_softmax for logic behind names.
    if attn_mask_type is None:
        return "_mask" if use_mask else "_no-mask"
    attn_mask_str = "_arbitrary-no-mask"
    attn_mask_str = "_causal-mask" if attn_mask_type == "causal" else attn_mask_str
    attn_mask_str = "_arbitrary-mask" if use_mask and attn_mask_type == "arbitrary" else attn_mask_str
    return attn_mask_str

"""
Tests cases begin here.
"""

@skip_FP8
@pytest.mark.parametrize("scale_factor", [1, 224])
@pytest.mark.parametrize(
    "precision,             atol", [
    [torch.float32,         1e-7],
    [torch.float16,         1e-7],
    [torch.bfloat16,        5e-3],
    ["fake-torch.bfloat16", 5e-3],
])
def test_export_cast_ops(seed_default_rng, scale_factor: float, atol: float, precision: torch.dtype):
    fake_bf16_io = precision == "fake-torch.bfloat16"
    # reset precision to torch.bfloat16 after capturing fake BF16 mode
    precision = torch.bfloat16 if precision == "fake-torch.bfloat16" else precision

    class TestFP8_QDQ(nn.Module):
        def __init__(self, fake_bf16_io):
            super().__init__()
            self.fp8_tensor = 0
            self.meta = create_meta(scale_factor)
            self.highprec_type = as_te_type(precision)
            self.fp8_type = tex.DType.kFloat8E4M3
            self.fake_bf16_io = fake_bf16_io

        def forward(self, inp):
            ret = cast_to_fp8(
                inp,
                self.meta,
                self.fp8_tensor,
                self.fp8_type)

            ret = cast_from_fp8(
                ret,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                self.highprec_type)
            if self.fake_bf16_io:
                ret = ret.type(torch.float32)
            return ret

    # Set dimensions (these are arbitrary).
    in_features = 64
    hidden_size = 256
    inp = torch.randn(hidden_size, in_features, device="cuda",
        dtype=torch.float if fake_bf16_io else precision)
    high_prec_str = dtype2str(precision, fake_bf16_io=fake_bf16_io)
    fname = f"te.cast_fp8_{scale_factor}{high_prec_str}.onnx"
    model = TestFP8_QDQ(fake_bf16_io)

    do_export(model, inp, fname)
    te_outputs = te_infer(model, inp, is_fp8=True)
    serialize_inputs_outputs(fname, inp, te_outputs)
    if fake_bf16_io or precision != torch.bfloat16:
        validate_result(fname, inp, model, atol=atol, is_fp8=True, te_outputs=te_outputs)

@skip_FP8
@pytest.mark.parametrize("scale_factor", [448])
@pytest.mark.parametrize(
    "precision,             atol", [
    [torch.float32,         1e-5],
    [torch.float16,         1e-5],
    [torch.bfloat16,        5e-3],
    ["fake-torch.bfloat16", 5e-3]
])
def test_export_gelu_fp8(scale_factor: float, precision: torch.dtype, atol: float):
    fake_bf16_io = precision == "fake-torch.bfloat16"
    # reset precision to torch.bfloat16 after capturing fake BF16 mode
    precision = torch.bfloat16 if precision == "fake-torch.bfloat16" else precision

    class TestFP8_Gelu(nn.Module):
        def __init__(self, fake_bf16_io):
            super().__init__()
            self.fp8_tensor = 0
            self.meta = create_meta(scale_factor)
            self.highprec_type = as_te_type(precision)
            self.fp8_type = tex.DType.kFloat8E4M3
            self.fake_bf16_io = fake_bf16_io

        def forward(self, inp):
            ret = gelu(
                inp,
                self.meta,
                self.fp8_tensor,
                self.fp8_type)
            ret = cast_from_fp8(
                ret,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                self.highprec_type)
            if self.fake_bf16_io:
                ret = ret.type(torch.float32)
            return ret

    # Set dimensions (these are arbitrary).
    in_features = 64
    hidden_size = 256
    inp = torch.randn(hidden_size, in_features, device="cuda",
        dtype=torch.float if fake_bf16_io else precision)
    high_prec_str = dtype2str(precision, fake_bf16_io=fake_bf16_io)
    fname = f"te.gelu_fp8_{scale_factor}{high_prec_str}.onnx"
    model = TestFP8_Gelu(fake_bf16_io)
    do_export(model, inp, fname)
    te_outputs = te_infer(model, inp, is_fp8=True)
    serialize_inputs_outputs(fname, inp, te_outputs)
    if fake_bf16_io or precision != torch.bfloat16:
        validate_result(fname, inp, model, rtol=0, atol=atol, is_fp8=True, allow_cnt_errors=2, te_outputs=te_outputs)

@pytest.mark.parametrize("scale_factors",
    [(224, 224,),
])
@pytest.mark.parametrize(
    "precision,             use_fp8, use_bias, use_gelu", [
    (torch.float32,         False,   False,    False),
    (torch.float16,         False,   False,    False),
    (torch.bfloat16,        False,   False,    False),
    (torch.float32,         False,   True,     False),
    (torch.float16,         False,   True,     False),
    (torch.bfloat16,        False,   True,     False),
    (torch.float32,         False,   True,     True),
    (torch.float16,         False,   True,     True),
    (torch.bfloat16,        False,   True,     True),

    # For FP8 GEMM GeLU is not used.
    (torch.float32,         True,    False,    False),
    (torch.float16,         True,    False,    False),
    (torch.bfloat16,        True,    False,    False),
    # When enabling bias we must use float16 or bfloat16 (because of kernel limitations)
    (torch.float16,         True,    True,     False),
    (torch.bfloat16,        True,    True,     False),
])
def test_export_gemm(
    seed_default_rng,
    precision, # Precision of inputs, weights, output and bias
    use_fp8,
    use_bias,
    use_gelu,
    scale_factors
):
    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    class TestFP8_GEMM(nn.Module):
        def __init__(self, precision, use_bias, gelu, scale_factors):
            super().__init__()
            self.use_bias = use_bias
            self.gelu = gelu
            self.precision = precision

            self.fp8_tensor_inp = tex.FP8FwdTensors.GEMM1_INPUT
            self.fp8_tensor_weight = tex.FP8FwdTensors.GEMM1_WEIGHT
            nb_inp_scales, nb_weight_scales = 1, out_features
            act_scale_factor, weight_scale_factor = scale_factors
            self.meta_inp = create_meta(act_scale_factor, nb_inp_scales)
            self.meta_weight = create_meta(weight_scale_factor, nb_weight_scales)

            bias_size = nb_weight_scales
            self.bias = torch.randn(bias_size, dtype=precision, device="cuda")
            self.gelu_input = torch.randn(hidden_size, out_features, dtype=precision, device="cuda")

            self.inp_type = tex.DType.kFloat8E4M3
            self.weights_type = tex.DType.kFloat8E4M3
            self.outp_type = precision

        def forward(self, inp, weight):
            inp_fp8 = cast_to_fp8(
                inp,
                self.meta_inp,
                self.fp8_tensor_inp,
                self.inp_type)

            weight_fp8 = cast_to_fp8(
                weight,
                self.meta_weight,
                self.fp8_tensor_weight,
                self.weights_type)

            ret, _ = fp8_gemm(
                weight_fp8,
                self.meta_weight.scale_inv,
                self.fp8_tensor_weight,
                self.inp_type,
                inp_fp8,
                self.meta_inp.scale_inv,
                self.fp8_tensor_inp,
                self.weights_type,
                self.outp_type,
                get_workspace(),
                bias=self.bias,
                use_bias=self.use_bias,
                use_split_accumulator=False)
            return ret

    class Test_GEMM(nn.Module):
        def __init__(self, precision, use_bias=False, gelu=False):
            super().__init__()
            self.use_bias = use_bias
            self.gelu = gelu
            self.precision = precision
            bias_size = out_features
            self.bias = torch.randn(bias_size, dtype=precision, device="cuda")
            self.gelu_input = torch.randn(hidden_size, out_features, dtype=precision, device="cuda")

        def forward(self, inp, weight):
            outp_type = self.precision

            # note: due to logic in lines 104:116 and L129 in cpp_extensions.py
            # it appears either bias OR gelu can be activated, not both
            ret, _, _ = gemm(
                weight,
                inp,
                outp_type,
                get_workspace(),

                # test bias
                bias=self.bias,
                use_bias=self.use_bias,

                # test gelu
                gelu=self.gelu,
                gelu_input=self.gelu_input,
                grad=False, # only True for backward pass
                accumulate=False,
            )
            return ret

    # If gelu is applied then bias must be added, as defined by TE kernel.
    if use_gelu: assert use_bias
    # Set dimensions (these are arbitrary).
    out_features = 128
    hidden_size = 256
    in_features = 64
    inp = torch.randn(hidden_size, in_features, device="cuda", dtype=precision)
    weight = torch.randn(out_features, in_features, device="cuda", dtype=precision)
    fp8_str = "_fp8" if use_fp8 else ""
    bias_str = "_bias" if use_bias else ""
    gelu_str = "_gelu" if use_gelu else ""
    high_prec_str = dtype2str(precision)
    fname = f"te.gemm{fp8_str}{bias_str}{gelu_str}{high_prec_str}.onnx"
    input_names = ['input', 'weight']
    if use_fp8:
        model = TestFP8_GEMM(precision, use_bias, use_gelu, scale_factors)
        do_export(model, (inp, weight), fname, use_fp8, input_names=input_names)
        te_outputs = te_infer(model, (inp, weight), is_fp8=use_fp8)
        serialize_inputs_outputs(fname, (inp, weight), te_outputs, input_names=input_names)
        if precision != torch.bfloat16:
            validate_result(fname, (inp, weight), model, rtol=1e-2, atol=2e-2,
                is_fp8=True, input_names=input_names, te_outputs=te_outputs)
    else:
        model = Test_GEMM(precision, use_bias, use_gelu)
        do_export(model, (inp, weight), fname, use_fp8, input_names=input_names)
        te_outputs = te_infer(model, (inp, weight), is_fp8=use_fp8)
        serialize_inputs_outputs(fname, (inp, weight), te_outputs, input_names=input_names)
        if precision != torch.bfloat16:
            validate_result(fname, (inp, weight), model, rtol=1e-2, atol=2e-2,
                input_names=input_names, te_outputs=te_outputs)

@pytest.mark.parametrize("scale_factor", [448, 112])
@pytest.mark.parametrize("zero_centered_gamma", [False, True])
@pytest.mark.parametrize(
    "use_fp8, precision,             atol", [
    [False,   torch.float32,         1e-7],
    [False,   torch.float16,         1e-7],
    [False,   torch.bfloat16,        1e-7],
    [False,   "fake-torch.bfloat16", 1e-7],
    [True,    torch.float32,         1e-7],
    [True,    torch.float16,         1e-7],
    [True,    torch.bfloat16,        1e-2],
    [True,    "fake-torch.bfloat16", 1e-2]
])
def test_export_layernorm(
    seed_default_rng,
    use_fp8: bool,
    scale_factor: float,
    precision: torch.dtype,
    zero_centered_gamma: bool,
    atol: float
):
    fake_bf16_io = precision == "fake-torch.bfloat16"
    # reset precision to torch.bfloat16 after capturing fake BF16 mode
    precision = torch.bfloat16 if precision == "fake-torch.bfloat16" else precision

    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    # Set dimensions (these are arbitrary).
    inp_shape = [64, 32]

    class Test_Layernorm(nn.Module):
        def __init__(self) -> None:
            super().__init__()
            eps = 1e-6 # An arbitrary small value
            dtype = torch.float if fake_bf16_io else precision
            self.ln = te.LayerNorm(inp_shape[1], eps, params_dtype=dtype,
                zero_centered_gamma=False).eval().cuda()

        def forward(self, inp):
            ret = self.ln(inp)
            return ret

    class TestFP8_Layernorm(nn.Module):
        def __init__(self) -> None:
            super().__init__()
            normalized_shape = torch.Size(inp.shape[1:])
            self.weight = torch.randn(*normalized_shape, device="cuda",
                dtype=torch.float32 if fake_bf16_io else precision)
            self.bias = torch.zeros(*normalized_shape, device="cuda",
                dtype=torch.float32 if fake_bf16_io else precision)
            self.eps = 1e-6 # An arbitrary small value

            self.fp8_tensor = tex.FP8FwdTensors.GEMM1_INPUT
            self.meta = create_meta(scale_factor)
            self.fp8_type = tex.DType.kFloat8E4M3

        def forward(self, inp):
            ret = texcpp.layernorm_fwd_fp8_inf(
                inp,
                self.weight,
                self.bias,
                self.eps,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                zero_centered_gamma)

            ret = cast_from_fp8(
                ret,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                as_te_type(precision))
            if fake_bf16_io:
                ret = ret.type(torch.float32)
            return ret

    inp = torch.randn(*inp_shape, device="cuda", dtype=torch.float32 if fake_bf16_io else precision)
    model = TestFP8_Layernorm() if use_fp8 else Test_Layernorm()
    high_prec_str = dtype2str(precision, fake_bf16_io=fake_bf16_io)
    fp8_str = f"_fp8-{scale_factor}" if use_fp8 else ""
    fname = f"te.layernorm{fp8_str}{high_prec_str}.onnx"
    do_export(model, inp, fname, use_fp8=use_fp8)
    te_outputs = te_infer(model, inp, is_fp8=use_fp8)
    serialize_inputs_outputs(fname, inp, te_outputs)
    if fake_bf16_io or precision != torch.bfloat16:
        validate_result(
            fname, inp, model, atol=atol, is_fp8=use_fp8, allow_cnt_errors=3, te_outputs=te_outputs)

@pytest.mark.parametrize("scale_factor", [448, 112])
@pytest.mark.parametrize(
    "use_fp8, precision,             atol", [
    [False,   torch.float32,         1e-7],
    [False,   torch.float16,         1e-7],
    [False,   torch.bfloat16,        1e-7],
    [False,   "fake-torch.bfloat16", 1e-7],
    [True,    torch.float32,         1e-7],
    [True,    torch.float16,         1e-7],
    [True,    torch.bfloat16,        1e-2],
    [True,    "fake-torch.bfloat16", 1e-2]
])
def test_export_rmsnorm(
    seed_default_rng,
    use_fp8: bool,
    scale_factor: float,
    precision: torch.dtype,
    atol: float
):
    fake_bf16_io = precision == "fake-torch.bfloat16"
    # reset precision to torch.bfloat16 after capturing fake BF16 mode
    precision = torch.bfloat16 if precision == "fake-torch.bfloat16" else precision

    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    # Set dimensions (these are arbitrary).
    inp_shape = [64, 32]

    class Test_RMSnorm(nn.Module):
        def __init__(self) -> None:
            super().__init__()
            eps = 1e-6 # An arbitrary small value
            dtype = torch.float if fake_bf16_io else precision
            self.ln = te.RMSNorm(inp_shape[1], eps, params_dtype=dtype).eval().cuda()

        def forward(self, inp):
            ret = self.ln(inp)
            return ret

    class TestFP8_RMSnorm(nn.Module):
        def __init__(self) -> None:
            super().__init__()
            normalized_shape = torch.Size(inp.shape[1:])
            self.weight = torch.randn(*normalized_shape, device="cuda",
                dtype=torch.float32 if fake_bf16_io else precision)
            self.eps = 1e-6 # An arbitrary small value

            self.fp8_tensor = tex.FP8FwdTensors.GEMM1_INPUT
            self.meta = create_meta(scale_factor)
            self.fp8_type = tex.DType.kFloat8E4M3

        def forward(self, inp):
            ret = texcpp.rmsnorm_fwd_fp8_inf(
                inp,
                self.weight,
                self.eps,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                False)

            ret = cast_from_fp8(
                ret,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                as_te_type(precision))
            if fake_bf16_io:
                ret = ret.type(torch.float32)
            return ret

    inp = torch.randn(*inp_shape, device="cuda", dtype=torch.float32 if fake_bf16_io else precision)
    model = TestFP8_RMSnorm() if use_fp8 else Test_RMSnorm()
    high_prec_str = dtype2str(precision, fake_bf16_io=fake_bf16_io)
    fp8_str = f"_fp8-{scale_factor}" if use_fp8 else ""
    fname = f"te.layernorm{fp8_str}{high_prec_str}.onnx"
    do_export(model, inp, fname, use_fp8=use_fp8)
    te_outputs = te_infer(model, inp, is_fp8=use_fp8)
    serialize_inputs_outputs(fname, inp, te_outputs)
    if fake_bf16_io or precision != torch.bfloat16:
        validate_result(
            fname, inp, model, atol=atol, is_fp8=use_fp8, allow_cnt_errors=3, te_outputs=te_outputs)

@pytest.mark.parametrize("scale_factor", [1])
@pytest.mark.parametrize("use_fp8", [False, True])
# Returning the bias is a TE fusion optimization we don't care about.
@pytest.mark.parametrize("return_bias", [False])
@pytest.mark.parametrize(
    "precision,      use_bias",[
    (torch.float32,  False),
    (torch.float32,  True),
    (torch.float16,  False),
    (torch.float16,  True),
    # Todo: cannot configure BF16 when bias is disabled (ORT issue?)
    (torch.bfloat16, False),
    # Todo: cannot configure BF16 when bias is enabled (ORT issue?)
    (torch.bfloat16, True),
])
def test_export_linear(
    seed_default_rng,
    scale_factor: float,
    use_fp8: bool,
    use_bias: bool,
    return_bias: bool,
    precision: torch.dtype
):
    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    # Set dimensions (these are arbitrary).
    in_features = 64
    out_features = 256
    hidden_size = 256

    class Test_Linear(nn.Module):
        def __init__(self,
                in_features,
                out_features,
                use_bias,
                return_bias,
                precision
            ):
            super().__init__()
            self.linear = te.Linear(
                in_features,
                out_features,
                bias=use_bias,
                return_bias=return_bias,
                params_dtype=precision
            )

        def forward(self, inp):
            ret = self.linear(inp)
            return ret

    inp = torch.randn(hidden_size, in_features, device="cuda", dtype=precision)
    fp8_str = "_fp8" if use_fp8 else ""
    bias_str = "_bias" if use_bias else ""
    high_prec_str = dtype2str(precision)
    fname = f"te.linear{fp8_str}{bias_str}{high_prec_str}.onnx"
    with te.fp8_autocast(enabled=use_fp8):
        model = Test_Linear(
            in_features,
            out_features,
            use_bias,
            return_bias,
            precision
        ).to(device='cuda')
        if use_fp8:
            set_layer_scale(model.linear, scale_factor, num_gemms=1)
        do_export(model, inp, fname, use_fp8)
        te_outputs = te_infer(model, inp, is_fp8=use_fp8)
        serialize_inputs_outputs(fname, inp, te_outputs)

        if precision in (torch.bfloat16, ):
            return
        if not use_fp8:
            validate_result(fname, inp, model, atol=1e-3, te_outputs=te_outputs)
        else:
            validate_result(fname, inp, model, atol=1e-3, is_fp8=use_fp8, te_outputs=te_outputs)

@pytest.mark.parametrize("scale_factor", [112])
@pytest.mark.parametrize("use_fp8", [False, True])
# Returning the bias is a TE fusion optimization we don't care about.
@pytest.mark.parametrize("return_bias", [False])
@pytest.mark.parametrize("return_layernorm_output", [False])
@pytest.mark.parametrize(
    "precision,      use_bias",[
    (torch.float32,  False),
    (torch.float32,  True),
    (torch.float16,  True),
    (torch.float16,  False),
    (torch.bfloat16, True),
    (torch.bfloat16, False),
])
@pytest.mark.parametrize("zero_centered_gamma", [False, True])
@pytest.mark.parametrize("normalization", all_normalizations)
def test_export_layernorm_linear(
    seed_default_rng,
    scale_factor: float,
    use_fp8: bool,
    use_bias: bool,
    return_bias: bool,
    return_layernorm_output: bool,
    precision: torch.dtype,
    zero_centered_gamma: bool,
    normalization: str,
):
    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    if normalization == "RMSNorm" and zero_centered_gamma:
        pytest.skip("RMSNorm does not support zero_centered_gamma yet!")

    # Set dimensions (these are arbitrary).
    in_features = 64
    out_features = 256
    hidden_size = 256

    inp = torch.randn(in_features, out_features, device="cuda", dtype=precision)
    fp8_str = "_fp8" if use_fp8 else ""
    bias_str = "_bias" if use_bias else ""
    high_prec_str = dtype2str(precision)
    fname = f"te.layernorm_linear{fp8_str}{bias_str}{high_prec_str}.onnx"

    with te.fp8_autocast(enabled=use_fp8):
        model = te.LayerNormLinear(
            hidden_size,
            3 * hidden_size,
            bias=use_bias,
            return_bias=return_bias,
            return_layernorm_output=return_layernorm_output,
            params_dtype=precision,
            zero_centered_gamma=zero_centered_gamma,
            normalization=normalization,
        ).to(device='cuda')
        if use_fp8:
            set_layer_scale(model, scale_factor, num_gemms=1)
        do_export(model, inp, fname, use_fp8)
        te_outputs = te_infer(model, inp, is_fp8=use_fp8)
        serialize_inputs_outputs(fname, inp, te_outputs)
        if precision in (torch.bfloat16, ):
            return
        if not use_fp8:
            validate_result(fname, inp, model, atol=1e-3, te_outputs=te_outputs)
        elif precision != torch.bfloat16:
            validate_result(fname, inp, model, atol=1e-6, is_fp8=use_fp8, te_outputs=te_outputs)

@pytest.mark.parametrize("scale_factor", [112])
@pytest.mark.parametrize("use_fp8", [False, True])
# Returning the bias is a TE fusion optimization we don't care about.
@pytest.mark.parametrize("return_bias", [False])
@pytest.mark.parametrize("return_layernorm_output", [False])
@pytest.mark.parametrize(
    "precision,      use_bias",[
    (torch.float32,  False),
    (torch.float32,  True),
    (torch.float16,  True),
    (torch.float16,  False),
    (torch.bfloat16, True),
    (torch.bfloat16, False),
])
@pytest.mark.parametrize("zero_centered_gamma", [False, True])
@pytest.mark.parametrize("activation", supported_activations)
@pytest.mark.parametrize("normalization", all_normalizations)
def test_export_layernorm_mlp(
    seed_default_rng,
    scale_factor: float,
    use_fp8: bool,
    use_bias: bool,
    return_bias: bool,
    return_layernorm_output: bool,
    precision: torch.dtype,
    zero_centered_gamma: bool,
    activation: str,
    normalization: str,
):
    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    if normalization == "RMSNorm" and zero_centered_gamma:
        pytest.skip("RMSNorm does not support zero_centered_gamma yet!")

    # Set dimensions (these are arbitrary).
    in_features = 64
    out_features = 256
    hidden_size = 256
    ffn_hidden_size = 256

    inp = torch.randn(in_features, out_features, device="cuda", dtype=precision)
    fp8_str = "_fp8" if use_fp8 else ""
    bias_str = "_bias" if use_bias else ""
    high_prec_str = dtype2str(precision)
    fname = f"te.layernorm_mlp{fp8_str}{bias_str}{high_prec_str}_{activation}.onnx"
    with te.fp8_autocast(enabled=use_fp8):
        model = te.LayerNormMLP(
            hidden_size,
            ffn_hidden_size,
            bias=use_bias,
            return_bias=return_bias,
            return_layernorm_output=return_layernorm_output,
            params_dtype=precision,
            zero_centered_gamma=zero_centered_gamma,
            activation=activation,
            normalization=normalization,
        ).to(device='cuda')
        if use_fp8:
            set_layer_scale(model, scale_factor, num_gemms=2)
        do_export(model, inp, fname, use_fp8)
        te_outputs = te_infer(model, inp, is_fp8=use_fp8)
        serialize_inputs_outputs(fname, inp, te_outputs)
        if precision in (torch.bfloat16, ):
            return
        atol = 1e-6 if use_fp8 else (5e-1 if activation=="swiglu" else 1e-3)
        validate_result(fname, inp, model, atol=atol, is_fp8=use_fp8, te_outputs=te_outputs)

@skip_FP8
@pytest.mark.parametrize(
    "precision,      use_mask, attn_mask_type", [
    (torch.float32,  True,     "arbitrary"), # calls forward_torch_softmax (apply user mask)
    (torch.float32,  False,    "no_mask"),   # calls forward_torch_softmax (apply no mask)
    (torch.float16,  False,    "causal"),    # calls forward_torch_softmax (apply dynamic onnx mask)
    (torch.float16,  True,     "arbitrary"), # calls forward_torch_softmax (apply user mask)
    (torch.float16,  False,    "no_mask"),   # calls forward_torch_softmax (apply no mask)
    (torch.bfloat16, False,    "causal"),    # calls forward_torch_softmax (apply dynamic onnx mask)
    (torch.bfloat16, True,     "arbitrary"), # calls forward_torch_softmax (apply user mask)
    (torch.bfloat16, False,    "no_mask"),   # calls forward_torch_softmax (apply no mask)
])
def test_export_core_attention(
    seed_default_rng,
    set_max_seq_len,
    precision: torch.dtype,
    use_mask: bool,
    attn_mask_type: str,
):
    # Set dimensions (these are arbitrary).
    seq_len, batch_size, num_attention_heads, kv_channels = (64, 4, 1, 64)
    qkv_size = (seq_len, batch_size, num_attention_heads, kv_channels)
    qkv_format = "sbhd"

    query_layer = torch.randn(qkv_size, dtype=precision, device="cuda")
    key_layer = torch.randn(qkv_size, dtype=precision, device="cuda")
    value_layer = torch.randn(qkv_size, dtype=precision, device="cuda")
    input_names = ["query", "key", "value", "attention_mask"]
    attention_mask = None
    if use_mask:
        # Generate a random mask with 50% probability for 0 or 1.
        probs = 0.5 * torch.ones(batch_size, 1, 1, seq_len, device="cuda", dtype=precision)
        attention_mask = torch.bernoulli(probs).to("cuda", dtype=torch.bool)
    inp = (query_layer, key_layer, value_layer, attention_mask)

    mask_str = get_attn_mask_str(use_mask, attn_mask_type)
    high_prec_str = dtype2str(precision)
    fname = f"te.core_attention{mask_str}{high_prec_str}.onnx"

    model = te.attention.DotProductAttention(
        num_attention_heads=num_attention_heads,
        kv_channels=kv_channels,
        attention_dropout=0.5,
        qkv_format=qkv_format,
        attn_mask_type=attn_mask_type,
    ).to(device='cuda')
    do_export(model,
            inp,
            fname,
            input_names=input_names,
            use_fp8=True)
    te_outputs = te_infer(model, inp, is_fp8=True)
    serialize_inputs_outputs(fname, inp, te_outputs, input_names=input_names)
    if precision in (torch.bfloat16, ):
        return
    validate_result(fname, inp, model, is_fp8=True, atol=1e-2, input_names=input_names, te_outputs=te_outputs)

test_configs_multihead_attention = [
    #"use_mask, attn_mask_type"
    (False,    "no_mask"),   # calls ScaledSoftmax
    (True,     "arbitrary"), # calls ScaledMaskedSoftmax
]
test_configs_attention_type = [
    #"input_layernorm, attention_type, fuse_qkv_params"
    (True,             "self",         True),
    (False,            "self",         True),
    (True,             "self",         False),
    (False,            "self",         False),
    (True,             "cross",        True),
    (False,            "cross",        True),
    (True,             "cross",        False),
    (False,            "cross",        False),
]
@pytest.mark.parametrize("use_fp8", [False, True])
@pytest.mark.parametrize("use_mask, attn_mask_type", test_configs_multihead_attention)
@pytest.mark.parametrize("precision", [torch.float32, torch.float16, torch.bfloat16])
@pytest.mark.parametrize("return_layernorm_output", [False])
@pytest.mark.parametrize("input_layernorm, attention_type, fuse_qkv_params", test_configs_attention_type)
def test_export_multihead_attention(
    seed_default_rng,
    set_max_seq_len,
    use_fp8: bool,
    use_mask: bool,
    attn_mask_type: str,
    precision: torch.dtype,
    return_layernorm_output: bool,
    input_layernorm: bool,
    attention_type: str,
    fuse_qkv_params: bool
):
    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    hidden_size = 256
    sequence_length = 128
    batch_size = 4
    num_attention_heads = 32
    kv_channels = 8
    attention_dropout = 0.1
    layernorm_epsilon = 1e-5
    init_method = output_layer_init_method = get_default_init_method()
    attention_args = (
        hidden_size,
        num_attention_heads,
        kv_channels,
        attention_dropout,
        layernorm_epsilon,
        init_method,
        output_layer_init_method,
    )

    hidden_states_context = torch.randn(sequence_length, batch_size, hidden_size, dtype=precision, device="cuda")
    attention_mask = None
    if use_mask and attn_mask_type != "causal":
        # Generate a random mask with 50% probability for 0 or 1.
        probs = 0.5 * torch.ones(batch_size, 1, sequence_length, sequence_length, device="cuda", dtype=precision)
        attention_mask = torch.bernoulli(probs).to("cuda", dtype=torch.bool)

    encoder_output = None

    if attention_type == "cross":
        encoder_output = torch.randn(sequence_length, batch_size, hidden_size, dtype=precision, device="cuda")

    fp8_str = "_fp8" if use_fp8 else ""
    dtype_str = dtype2str(precision)
    attn_type_str = "_self-attention" if attention_type == "self" else "_cross-attention"
    fuse_qkv_str = "_fused-qkv" if fuse_qkv_params else ""
    attn_mask_str = get_attn_mask_str(use_mask, attn_mask_type)
    input_ln_str = "_input-ln" if input_layernorm else ""
    fname = f"te.multihead_attention{fp8_str}{attn_mask_str}{attn_type_str}{input_ln_str}{fuse_qkv_str}{dtype_str}.onnx"

    model = te.MultiheadAttention(
        *attention_args,
        attn_mask_type=attn_mask_type,
        params_dtype=precision,
        return_layernorm_output=return_layernorm_output,
        input_layernorm=input_layernorm,
        attention_type=attention_type,
        fuse_qkv_params=fuse_qkv_params,
        return_bias=True,
    ).to(device='cuda')

    inp_context = (hidden_states_context, attention_mask, encoder_output)
    input_names = ["hidden_states", "attention_mask", "encoder_output"]
    output_names=["attention_output", "attention_bias"]
    do_export(model, inp_context, fname, use_fp8, input_names=input_names, output_names=output_names,
        dynamic_axes={"hidden_states": {0: "seq", 1:"bs"},
                      "attention_output": {0: "seq", 1:"bs"}})
    te_outputs = te_infer(model, inp_context, is_fp8=use_fp8)
    serialize_inputs_outputs(fname, inp_context, te_outputs, input_names=input_names, output_names=output_names)
    if precision in (torch.bfloat16, ):
        return

    if not use_fp8:
        validate_result(fname, inp_context, model, atol=1e-3, input_names=input_names,
            output_names=output_names, te_outputs=te_outputs)
    else:
        validate_result(fname, inp_context, model, atol=1e-2, is_fp8=use_fp8,
            input_names=input_names, output_names=output_names, allow_cnt_errors=3,
            te_outputs=te_outputs)

    # In GPT generative phase (inference) the input sequence is smaller than the maximum
    # allowed sequence length and we want to test this condition.
    # Pretend that we're in generative phase when it makes sense (causal mask and self-attention).
    is_generative_phase = (attn_mask_type == "causal" and attention_type == "self")
    if is_generative_phase:
        seq_len_offset = 8
        hidden_states_generative = torch.randn(sequence_length-seq_len_offset, batch_size, hidden_size, dtype=precision, device="cuda")
        inp_generative = (hidden_states_generative, attention_mask, encoder_output)
        if not use_fp8:
            validate_result(fname, inp_generative, model, atol=1e-3, input_names=input_names, output_names=output_names)
        else:
            validate_result(fname, inp_generative, model, atol=1e-2, is_fp8=use_fp8,
                input_names=input_names, output_names=output_names, allow_cnt_errors=3)

@pytest.mark.parametrize("use_fp8", [False, True])
@pytest.mark.parametrize("use_mask, attn_mask_type", test_configs_multihead_attention)
@pytest.mark.parametrize("output_layernorm", [
    #True, # TO DO: handle this
    False
])
@pytest.mark.parametrize("precision", [torch.float32, torch.float16, torch.bfloat16])
@pytest.mark.parametrize("fuse_qkv_params", [False, True])
@pytest.mark.parametrize("zero_centered_gamma", [False, True])
@pytest.mark.parametrize("activation", supported_activations)
def test_export_transformer_layer(
    seed_default_rng,
    set_max_seq_len,
    use_fp8: bool,
    use_mask: bool,
    attn_mask_type: str,
    output_layernorm: bool,
    precision: torch.dtype,
    fuse_qkv_params: bool,
    zero_centered_gamma: bool,
    activation: str,
):
    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    # Layer configuration
    hidden_size = 64
    sequence_length = 128
    batch_size = 1
    ffn_hidden_size = 256
    num_attention_heads = 4

    input_tensor = torch.rand(sequence_length, batch_size, hidden_size, dtype=precision, device="cuda")
    input_names = ["input", "attention_mask"]
    attention_mask = None
    if use_mask and attn_mask_type != "causal":
        # Generate a random mask with 50% probability for 0 or 1.
        probs = 0.5 * torch.ones(batch_size, 1, sequence_length, sequence_length, device="cuda", dtype=precision)
        attention_mask = torch.bernoulli(probs).to("cuda", dtype=torch.bool)
    inp = (input_tensor, attention_mask)

    fp8_str = "_fp8" if use_fp8 else ""
    fuse_qkv_params_str = "_fused-qkv" if fuse_qkv_params else ""
    high_prec_str = dtype2str(precision)
    attn_mask_str = get_attn_mask_str(use_mask, attn_mask_type)
    fname = f"te.transformer_layer{fp8_str}{attn_mask_str}{fuse_qkv_params_str}{high_prec_str}_{activation}.onnx"

    model = te.TransformerLayer(
        hidden_size,
        ffn_hidden_size,
        num_attention_heads,
        self_attn_mask_type=attn_mask_type,
        output_layernorm=output_layernorm,
        params_dtype=precision,
        fuse_qkv_params=fuse_qkv_params,
        zero_centered_gamma=zero_centered_gamma,
        activation=activation).to(device='cuda')
    do_export(model, inp, fname, use_fp8, input_names=input_names)
    te_outputs = te_infer(model, inp, is_fp8=use_fp8)
    serialize_inputs_outputs(fname, inp, te_outputs, input_names=input_names)
    if precision in (torch.bfloat16, ):
        return
    atol = 5e-1 if use_fp8 else (5e-1 if activation=="swiglu" else 1e-3)
    validate_result(fname, inp, model, atol=atol, is_fp8=use_fp8, input_names=input_names, te_outputs=te_outputs)

@pytest.mark.parametrize("use_fp8", [True])
@pytest.mark.parametrize("ln_scale_factor", [448*2])
@pytest.mark.parametrize("gemm_scale_factors", [(224, 224,),])
@pytest.mark.parametrize("precision", [torch.float32, torch.float16, torch.bfloat16])
@pytest.mark.parametrize("zero_centered_gamma", [False, True])
def test_export_gemm_layernorm(
    seed_default_rng,
    use_fp8: bool,
    ln_scale_factor: float,
    gemm_scale_factors: Tuple[float, float],
    precision: torch.dtype,
    zero_centered_gamma: bool
):
    """This is a regression test for testing that all LN inputs have the same type.

    The test sets up GEMM with FP32 output which feeds into an LN that is configured
    with FP16 or BF16 weights and bias.
    """

    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)
    class TestFP8_GemmLayernorm(nn.Module):
        def __init__(self) -> None:
            super().__init__()
            normalized_shape = torch.Size(inp.shape[1:])
            self.weight = torch.randn(*normalized_shape, dtype=precision, device="cuda")
            self.bias = torch.zeros(*normalized_shape, dtype=precision, device="cuda")
            self.eps = 1e-6 # An arbitrary small value

            self.fp8_tensor = tex.FP8FwdTensors.GEMM1_INPUT
            self.meta = create_meta(ln_scale_factor)
            self.fp8_type = tex.DType.kFloat8E4M3
            self.gemm = TestFP8_GEMM(
                precision, use_bias=False, gelu=False, scale_factors=gemm_scale_factors)

        def forward(self, inp, weight):
            x = self.gemm(inp, weight)
            x = texcpp.layernorm_fwd_fp8_inf(
                x,
                self.weight,
                self.bias,
                self.eps,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                zero_centered_gamma)

            x = cast_from_fp8(
                x,
                self.meta,
                self.fp8_tensor,
                self.fp8_type,
                tex.DType.kFloat32 if precision == torch.float32 else tex.DType.kFloat16)
            return x

    out_features = 128
    hidden_size = 128
    in_features = 128
    class TestFP8_GEMM(nn.Module):
        def __init__(self, precision, use_bias, gelu, scale_factors):
            super().__init__()
            self.use_bias = use_bias
            self.gelu = gelu
            self.precision = precision

            self.fp8_tensor_inp = tex.FP8FwdTensors.GEMM1_INPUT
            self.fp8_tensor_weight = tex.FP8FwdTensors.GEMM1_WEIGHT
            nb_inp_scales, nb_weight_scales = 1, out_features
            act_scale_factor, weight_scale_factor = scale_factors
            self.meta_inp = create_meta(act_scale_factor, nb_inp_scales)
            self.meta_weight = create_meta(weight_scale_factor, nb_weight_scales)

            bias_size = nb_weight_scales
            self.bias = torch.randn(bias_size, dtype=precision, device="cuda")
            self.gelu_input = torch.randn(hidden_size, out_features, dtype=precision, device="cuda")

            self.inp_type = tex.DType.kFloat8E4M3
            self.weights_type = tex.DType.kFloat8E4M3
            self.outp_type = precision

        def forward(self, inp, weight):
            inp_fp8 = cast_to_fp8(
                inp,
                self.meta_inp,
                self.fp8_tensor_inp,
                self.inp_type)

            weight_fp8 = cast_to_fp8(
                weight,
                self.meta_weight,
                self.fp8_tensor_weight,
                self.weights_type)

            ret, _ = fp8_gemm(
                weight_fp8,
                self.meta_weight.scale_inv,
                self.fp8_tensor_weight,
                self.inp_type,
                inp_fp8,
                self.meta_inp.scale_inv,
                self.fp8_tensor_inp,
                self.weights_type,
                self.outp_type,
                get_workspace(),
                bias=self.bias,
                use_bias=self.use_bias,
                use_split_accumulator=False)
            return ret

    inp = torch.randn(hidden_size, in_features, dtype=precision, device="cuda")
    weight = torch.randn(out_features, in_features, dtype=precision, device="cuda")
    model = TestFP8_GemmLayernorm()
    high_prec_str = dtype2str(precision)
    fp8_str = f"_fp8" if use_fp8 else ""
    fname = f"te.gemm_layernorm{fp8_str}{high_prec_str}.onnx"
    input_names = ['input', 'weight']
    do_export(model, (inp, weight), fname, use_fp8=use_fp8, input_names=input_names)
    te_outputs = te_infer(model, (inp, weight), is_fp8=use_fp8)
    serialize_inputs_outputs(fname, (inp, weight), te_outputs, input_names=input_names)
    if precision not in (torch.bfloat16, ):
        validate_result(
            fname, (inp, weight), model, atol=5e-2, is_fp8=use_fp8, allow_cnt_errors=2,
            input_names=input_names, te_outputs=te_outputs)

@skip_FP8
@pytest.mark.parametrize("use_fp8", [True, False])
@pytest.mark.parametrize("precision", [torch.float16, torch.bfloat16])
@pytest.mark.parametrize("zero_centered_gamma", [True])
def test_export_gpt_generation(
    seed_default_rng,
    set_max_seq_len,
    use_fp8: bool,
    precision: torch.dtype,
    zero_centered_gamma: bool,
):
    """Test that the ONNX model can correctly handle inputs with different shapes and that
    the attention mask it adjusted on-the-fly to different sequence lengths.
    """

    # Skip FP8 tests on non-hopper devices
    if use_fp8 and not fp8_available:
        pytest.skip(reason_for_no_fp8)

    # Layer configuration
    hidden_size = 64
    sequence_length = 128
    batch_size = 1
    ffn_hidden_size = 256
    num_attention_heads = 4
    attention_mask = None
    use_mask = True
    attn_mask_type = "causal"
    fuse_qkv_params = True
    output_layernorm = False

    fp8_str = "_fp8" if use_fp8 else ""
    fuse_qkv_params_str = "_fused-qkv" if fuse_qkv_params else ""
    high_prec_str = dtype2str(precision)
    attn_mask_str = get_attn_mask_str(use_mask, attn_mask_type)
    fname = f"te.transformer_layer_generative{fp8_str}{attn_mask_str}{fuse_qkv_params_str}{high_prec_str}.onnx"

    model = te.TransformerLayer(
        hidden_size,
        ffn_hidden_size,
        num_attention_heads,
        self_attn_mask_type=attn_mask_type,
        output_layernorm=output_layernorm,
        params_dtype=precision,
        fuse_qkv_params=fuse_qkv_params,
        zero_centered_gamma=zero_centered_gamma).to(device='cuda')

    # "Context phase": use full input sequence length
    input_names = ["input"]
    output_names = ["output"]
    input_tensor = torch.rand(sequence_length, batch_size, hidden_size, dtype=precision, device="cuda")
    inp = (input_tensor,)
    do_export(model, inp, fname, use_fp8,
        input_names=input_names, output_names=output_names,
        dynamic_axes={"input": {0: "seq", 1:"bs"},
                      "output": {0: "seq", 1:"bs"}, })
    te_outputs = te_infer(model, inp, is_fp8=use_fp8)
    serialize_inputs_outputs(fname, inp, te_outputs, input_names=input_names, output_names=output_names)
    if precision not in (torch.bfloat16, ):
        validate_result(fname, inp, model, atol=6e-3, is_fp8=use_fp8, input_names=input_names,
            te_outputs=te_outputs)

    # "Generative phase": use a single input (sequence len=1). For FP8 we need to pad the sequence to mult of 8.
    sequence_length = 1 if not use_fp8 else 8
    input_tensor = torch.rand(sequence_length, batch_size, hidden_size, dtype=precision, device="cuda")
    inp = (input_tensor, attention_mask)
    te_outputs = te_infer(model, inp, is_fp8=use_fp8)
    serialize_inputs_outputs(fname, inp, te_outputs, input_names=input_names)
    if precision not in (torch.bfloat16, ):
        validate_result(fname, inp, model, atol=6e-3, is_fp8=use_fp8, input_names=input_names,
            te_outputs=te_outputs)

@pytest.mark.parametrize("enabled", [True, False])
def test_export_ctx_manager(enabled):
    assert is_in_onnx_export_mode() == False
    with te.onnx_export(enabled):
        assert is_in_onnx_export_mode() == enabled
    assert is_in_onnx_export_mode() == False


while 1:
    try:
        numbers = input()
        data = [int(i) for i in input().split()]

        #create variable
        max_by_far = data[0]
        min_by_far = data[0]
        max_location = 0
        min_location = 0
        current_index = 1
        # now data is a map object , but also iterable
        for i in data[1:]:
            #check max
            if i == max_by_far:
                #if equal , don't need to change max_location
                pass
            elif i > max_by_far:
                max_by_far = i
                max_location = current_index
            #check min
            if i == min_by_far:
                # if equal , change the min_location since it's near the end
                min_location = current_index
            elif i < min_by_far:
                min_by_far = i
                min_location = current_index

            current_index += 1

        max_move = max_location
        #min location is index , so it's actual place is index +1
        min_move = len(data) - (min_location+1)
        if max_location > min_location:
            # because they cross each other
            answer = (max_move + min_move) - 1
            print(answer)
            # print('type 1')
            # print("max_info :",max_by_far,max_location,max_move)
            # print('min_info :',min_by_far,min_location,min_move)
        else:
            answer = max_move + min_move
            print(answer)
            # print('type 2')
            # print("max_info :",max_by_far,max_location,max_move)
            # print('min_info :',min_by_far,min_location,min_move)
    except:
        break


#!/usr/bin/env python3

import tkinter as tk

root = tk.Tk()
root.geometry("400x480")
root.resizable(width=False, height=False)
root.title("Calculator")

def btn1():
	val1 = valVar.get()+'1'
	notOk = True
	while notOk:
		if val1[0] == '0' and val1[1] == '.':
			notOk = False
		elif val1[0] == '0' and val1[1] != '.':
			val1 = val1[1:]
		elif val1[0] != '0':
			notOk = False
	valVar.set(val1)

def btn2():
	val2 = valVar.get()+'2'
	notOk = True
	while notOk:
		if val2[0] == '0' and val2[1] == '.':
			notOk = False
		elif val2[0] == '0' and val2[1] != '.':
			val2 = val2[1:]
		elif val2[0] != '0':
			notOk = False
	valVar.set(val2)

def btn3():
	val3 = valVar.get()+'3'
	notOk = True
	while notOk:
		if val3[0] == '0' and val3[1] == '.':
			notOk = False
		elif val3[0] == '0' and val3[1] != '.':
			val3 = val3[1:]
		elif val3[0] != '0':
			notOk = False
	valVar.set(val3)

def btn4():
	val4 = valVar.get()+'4'
	notOk = True
	while notOk:
		if val4[0] == '0' and val4[1] == '.':
			notOk = False
		elif val4[0] == '0' and val4[1] != '.':
			val4 = val4[1:]
		elif val4[0] != '0':
			notOk = False
	valVar.set(val4)

def btn5():
	val5 = valVar.get()+'5'
	notOk = True
	while notOk:
		if val5[0] == '0' and val5[1] == '.':
			notOk = False
		elif val5[0] == '0' and val5[1] != '.':
			val5 = val5[1:]
		elif val5[0] != '0':
			notOk = False
	valVar.set(val5)

def btn6():
	val6 = valVar.get()+'6'
	notOk = True
	while notOk:
		if val6[0] == '0' and val6[1] == '.':
			notOk = False
		elif val6[0] == '0' and val6[1] != '.':
			val6 = val6[1:]
		elif val6[0] != '0':
			notOk = False
	valVar.set(val6)

def btn7():
	val7 = valVar.get()+'7'
	notOk = True
	while notOk:
		if val7[0] == '0' and val7[1] == '.':
			notOk = False
		elif val7[0] == '0' and val7[1] != '.':
			val7 = val7[1:]
		elif val7[0] != '0':
			notOk = False
	valVar.set(val7)

def btn8():
	val8 = valVar.get()+'8'
	notOk = True
	while notOk:
		if val8[0] == '0' and val8[1] == '.':
			notOk = False
		elif val8[0] == '0' and val8[1] != '.':
			val8 = val8[1:]
		elif val8[0] != '0':
			notOk = False
	valVar.set(val8)

def btn9():
	val9 = valVar.get()+'9'
	notOk = True
	while notOk:
		if val9[0] == '0' and val9[1] == '.':
			notOk = False
		elif val9[0] == '0' and val9[1] != '.':
			val9 = val9[1:]
		elif val9[0] != '0':
			notOk = False
	valVar.set(val9)

def btn0():
	val0 = valVar.get()+'0'
	if val0[0] == '0' and val0[1] == '0':
		val0 = val0[1:]
	valVar.set(val0)

def reset():
	valVar.set("0")

valVar = tk.StringVar(root)
valVar.set("0")

# Results display Frame
display_lbl_frame = tk.LabelFrame(root)
display_lbl_frame.grid(row=0,column=0,columnspan=2,padx=10, pady=5)

display_label = tk.Entry(display_lbl_frame,font=('10'), textvariable=valVar,highlightthickness=5,bd=5,width=35, justify="right")
display_label.pack()

# Numbers Frame
nums_frame = tk.LabelFrame(root)
nums_frame.grid(row=1,column=0,sticky='N',padx=5,pady=5)

# Math Symbols Frame
math_sym_frame = tk.LabelFrame(root,pady=3)
math_sym_frame.grid(row=1,column=1,columnspan=1,sticky='N',padx=5,pady=5)

# 1,2,3
b1 = tk.Button(nums_frame, text='1',font=(12),padx=25,pady=25, command=btn1)
b1.grid(row=0,column=0,pady=2,padx=2)

b2 = tk.Button(nums_frame, text='2',font=(12),padx=25,pady=25, command=btn2)
b2.grid(row=0,column=1,pady=2,padx=2)

b3 = tk.Button(nums_frame, text='3',font=(12),padx=25,pady=25, command=btn3)
b3.grid(row=0,column=2,pady=2,padx=2)

# 4,5,6
b4 = tk.Button(nums_frame, text='4',font=(12),padx=25,pady=25, command=btn4)
b4.grid(row=1,column=0,pady=2,padx=2)

b5 = tk.Button(nums_frame, text='5',font=(12),padx=25,pady=25, command=btn5)
b5.grid(row=1,column=1,pady=2,padx=2)

b6 = tk.Button(nums_frame, text='6',font=(12),padx=25,pady=25, command=btn6)
b6.grid(row=1,column=2,pady=2,padx=2)

# 7,8,9
b7 = tk.Button(nums_frame, text='7',font=(12),padx=25,pady=25, command=btn7)
b7.grid(row=2,column=0,pady=2,padx=2)

b8 = tk.Button(nums_frame, text='8',font=(12),padx=25,pady=25, command=btn8)
b8.grid(row=2,column=1,pady=2,padx=2)

b9 = tk.Button(nums_frame, text='9',font=(12),padx=25,pady=25, command=btn9)
b9.grid(row=2,column=2,pady=2,padx=2)

# 0
b0 = tk.Button(nums_frame, text='0',font=(12),padx=96,pady=23, command=btn0)
b0.grid(row=3,column=0,columnspan=3,pady=2,padx=2)

def addition():
	addVar = valVar.get()+'+'
	valVar.set(addVar)

def subtraction():
	subVar = valVar.get()+'-'
	valVar.set(subVar)

def multiplication():
	multVar = valVar.get()+'*'
	valVar.set(multVar)

def division():
	divVar = valVar.get()+'/'
	valVar.set(divVar)

def dot():
	dotVar = valVar.get()
	dotVar += '.'
	valVar.set(dotVar)

def open_bracket():
	openBracketVar = valVar.get()
	operations = ['+','-','*','/']
	for operation_char in operations:
		if  openBracketVar[-1] == operation_char:
			openBracketVar += '('
		elif openBracketVar[-1] == '(':
			openBracketVar += '('
			break
		elif openBracketVar[-1].isnumeric():
			openBracketVar += '*('
			break
	valVar.set(openBracketVar)

def close_bracket():
	closeBracketVar = valVar.get() + ')'
	valVar.set(closeBracketVar)

def equals():
	eqVar = eval(valVar.get())
	valVar.set(eqVar)

def removeChar():
	removeVar = valVar.get()
	removeVar = removeVar[:-1]
	if len(removeVar) == 0:
		removeVar = '0'
	valVar.set(removeVar)

# Symbols Buttons
additionBtn = tk.Button(math_sym_frame, text = "+",font=(12),padx=25,pady=25, command=addition)
additionBtn.grid(row=0,column=0,padx=2,pady=2)

subtractionBtn = tk.Button(math_sym_frame, text = "-",font=('TkDefaultFont',12,'bold'),padx=25,pady=25, command=subtraction)
subtractionBtn.grid(row=0,column=1,padx=2,pady=2)

multiplicationBtn = tk.Button(math_sym_frame, text = "x",font=(12),padx=25,pady=25, command=multiplication)
multiplicationBtn.grid(row=1,column=0,padx=2,pady=2)

divisionBtn = tk.Button(math_sym_frame, text = ":",font=(12),padx=25,pady=25, command=division)
divisionBtn.grid(row=1,column=1,padx=2,pady=2)

open_bracketBtn = tk.Button(math_sym_frame, text= "(",font=(12), padx=25, pady=25, command=open_bracket)
open_bracketBtn.grid(row=2,column=0)

close_bracketBtn = tk.Button(math_sym_frame, text= ")",font=(12), padx=25, pady=25, command=close_bracket)
close_bracketBtn.grid(row=2,column=1)

dotBtn = tk.Button(math_sym_frame, text= ".",font=('TkDefaultFont',12,'bold'), padx=24, pady=22, command=dot)
dotBtn.grid(row=3,column=0,sticky='N',padx=2,pady=2)

delBtn = tk.Button(math_sym_frame, text= "<-",font=("TkDefaultFont",12,'bold'),padx=17,pady=22,command=removeChar)
delBtn.grid(row=3,column=1,sticky='N',padx=2,pady=2)

# Equal Frame
equalFrame = tk.LabelFrame(root)
equalFrame.grid(row=2,column=1,sticky='N')

equalsBtn = tk.Button(equalFrame, text = "=",font=("TkDefaultFont",12,'bold'), padx=58, pady=27, command=equals)
equalsBtn.grid(row=4,column=0,columnspan=2,padx=2,pady=2)

# Exit & Reset Frame
exit_frame = tk.LabelFrame(root)
exit_frame.grid(row=2)

resetBtn = tk.Button(exit_frame, text="Reset",bd=3,font=(12),padx=20,pady=25,command=reset)
resetBtn.grid(row=2,column=0,sticky='N',padx=8,pady=2)

exitBtn = tk.Button(exit_frame, text="Exit",font=(12),bd=3,padx=20,pady=25,command=root.destroy)
exitBtn.grid(row=2,column=1,sticky='N',padx=8,pady=2)

root.mainloop()


"""AD&D Second Edition Combat Simulator"""

# Always prefer setuptools over distutils
from setuptools import setup, find_packages
from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='adnd2e-combat-simulator',
    version='1.0.2',

    description='A tool to simulate combat in AD&D 2nd Edition',
    long_description=long_description,
    url='https://github.com/gene1wood/adnd2e-combat-simulator',
    author='Gene Wood',
    author_email='gene_wood@cementhorizon.com',
    license='GPL-3.0',
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: End Users/Desktop',
        'Topic :: Games/Entertainment :: Role-Playing',
        'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.7',
    ],
    keywords='ad&d d&d adnd dnd combat',
    packages=find_packages(exclude=['contrib', 'docs', 'tests']),
    install_requires=['PyYAML', 'dice', 'colorama'],
    package_data={
        'adnd2e_combat_simulator': ['combatants.example.yaml'],
    },
    entry_points={
        'console_scripts': [
            'battle=adnd2e_combat_simulator:main',
        ],
    },
)


quiz = {
    "stimulus":"Answer the following algebra questions:",
    "stem":"If x = 8, then what is the value of 4(x+3)?",
    "choices":["1.35","2.36","3.40","4.44"],
    "right choice": 4,
}
while True:
    print(quiz["stimulus"])
    print(quiz["stem"])
    print(*quiz["choices"],sep='\n')
    answer = input("Your choice: ")
    if answer.isdigit():
        answer = int(answer)
        if answer == quiz["right choice"]:
            print("Bingo")
            break
        else :
            print(":(((")


from collections import deque
import sys

dx = [1,-1,0,0]
dy = [0,0,-1,1]

def iswall(x,y):
    if x<0 or y<0 :
        return False
    if x >= n or y >= m :
        return False
    if matrix[x][y] == 0 : # 방문한 경우
        return False
    return True # 그 외의 경우

def bfs(x,y):
    queue = deque()
    print(queue)
    queue.append((x, y))
    print(queue)
# queue = deque((x,y)) # 시작 지점을 넣는다.
    while queue:
        x,y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if iswall(nx,ny) and matrix[nx][ny]==1:
                matrix[nx][ny] = matrix[x][y]+1
                queue.append((nx,ny))
    return matrix[n-1][m-1]

n,m = map(int,input().split())
matrix = [[1, 1, 0], [0, 1, 0], [0, 1, 1]]
print(bfs(0,0))

파이썬 알고리즘 인터뷰/미로탈출.py


class Classy:
    def __init__(self):
        pass

    def minSlidingWindow(self,s,t):
        '''

        :param s:
        :param t:
        :return:
            Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

            Example:

            Input: S = "ADOBECODEBANC", T = "ABC"
            Output: "BANC"
        '''

        i = 0
        final_count = len(s)
        final_string = ""
        temp = len(t)
        t_ls = list(t)
        while i+len(t) < len(s):
            temp_string = s[i:i+temp]
            temp_ls = list(temp_string)
            flag = False
            for each in t_ls:
                if each not in temp_ls:
                    temp+=1
                    flag = True
                    break
            if not flag:
                temp_ln = len(temp_string)
                if final_count>temp_ln:
                    final_count = temp_ln
                    final_string = temp_string
                i+=1
        return final_count,final_string

S = "ADOBECODEBANC"
T = "ABC"

S1 ="a"
T1 = "b"

obj = Classy()
print (obj.minSlidingWindow (S1, T1))


#!/usr/bin/env python
import rospy
from std_msgs.msg import String
from move_base_msgs.msg import MoveBaseGoal
from move_base_msgs.msg import MoveBaseAction
import re
from Command import Command
from Queue import Queue
import actionlib
from tf import transformations
from geometry_msgs.msg import Quaternion
from sound_play.libsoundplay import SoundClient
import genpy

class CommandScheduler:
    """
    Scheduler class for the multi-step speech processing
    """

    def __init__(self):
        rospy.init_node('command_scheduler', anonymous=True)

        self.rate = rospy.Rate(10)  # 10hz

        self.command_listener = rospy.Subscriber('/autospeech/run', String, self.received_command)

        self.typeSwitch = {
            'go': self.navigate,
            'turn': self.turn,
            'say': self.say
        }

        self.queue = Queue()
        self.sound_client = SoundClient()

        while not rospy.is_shutdown():
            if self.queue.not_empty:
                current = self.queue.get()

                if current.get_data_type() == SoundClient:
                    rospy.loginfo("Saying " + current.get_data())
                    self.sound_client.say(current.get_data())
                    rospy.sleep(2)
                else:
                    ac = actionlib.SimpleActionClient(current.get_path(), current.get_data_type())
                    ac.wait_for_server()

                    ac.send_goal_and_wait(current.get_data())

        rospy.spin()

    def received_command(self, data):
        split = re.split('///', data.data)
        command = self.typeSwitch[split[0]](split[1])
        self.queue.put(command)

    @staticmethod
    def navigate(location):
        goal = MoveBaseGoal()
        goal.target_pose.header.stamp = genpy.Time()
        goal.target_pose.header.frame_id = "/base_link"

        dirs = {
            'forward': 1.0,
            'backward': -1.0
        }

        goal.target_pose.pose.position.x = dirs[location]
        goal.target_pose.pose.orientation.w = 1.0

        return Command('/move_base', MoveBaseAction, goal)

    @staticmethod
    def say(string):
        return Command('', SoundClient, string)

    @staticmethod
    def turn(direction):

        goal = MoveBaseGoal()
        goal.target_pose.header.stamp = genpy.Time()
        goal.target_pose.header.frame_id = "/base_link"

        dirs = {
            'left': 90,
            'right': -90
        }

        quaternion = transformations.quaternion_from_euler(0, 0, dirs[direction])

        goal.target_pose.pose.orientation.x = quaternion[0]
        goal.target_pose.pose.orientation.y = quaternion[1]
        goal.target_pose.pose.orientation.z = quaternion[2]
        goal.target_pose.pose.orientation.w = quaternion[3]

        return Command('/move_base', MoveBaseAction, goal)

if __name__ == '__main__':
    try:
        CommandScheduler()
    except rospy.ROSInterruptException:
        pass


import pickle
import random

def main():
    ## Analyze a bridge hand.
    bridgeHand = getHandOfCards(13)
    displayBridgeHand(bridgeHand)
    analyzeBridgeHand(bridgeHand)

def getHandOfCards(numberOfCards):
    deckOfCards = pickle.load(open("deckOfCardsList.dat", 'rb'))
    return random.sample(deckOfCards, numberOfCards)

def displayBridgeHand(bridgeHand):
    print(", ".join(bridgeHand))

def analyzeBridgeHand(bridgeHand):
   suits = {x[-1] for x in bridgeHand}
   d = {suit:0 for suit in suits}  # distribution of cards into suits
   for card in bridgeHand:
       d[card[-1]] += 1
   t = tuple(d.items())
   tSorted = sorted(t)
   tSorted = sorted(t, key=lambda x: x[1], reverse=True)
   for k in tSorted:
       print("Number of", k[0], "is", k[1])

main()


#
# @lc app=leetcode.cn id=189 lang=python3
#
# [189] 旋转数组
#

# @lc code=start
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        def swap(l, r):
            while l < r:
                nums[l], nums[r] = nums[r], nums[l]
                l += 1
                r -= 1
        k %= len(nums)
        swap(0, len(nums) - k - 1)
        swap(len(nums) - k, len(nums) - 1)
        swap(0, len(nums) - 1)

# @lc code=end


import math

def fun(a, first, last, key):
    if first > last:
        return -1
    else:
        mid = math.floor((first+last)/2)
        if key == a[mid]:
            return mid
        elif key < a[mid]:
            return fun(a, first, mid-1, key)
        else:
            return fun(a, mid+1, last, key)

ls = [2, 5, 7, 10, 12, "apple"]

size = 6
print(fun(ls, 0, size-1, 10))
# can't do this kind of type
#print("apple"< 7)
# can't do this kind of type either
#size = "Hello!"
print(size)

print("Python doesn't need any type infront of parameters of the functions")
print("\nso cool")


import random

def rand_white():
    num = random.randrange(0,3)
    if num == 0:
        return " "
    elif num == 1:
        return "\t"
    else:
        return "\n"

amounts = 5
fil = "duplicate.txt"
dup = True
d_number = 19

if dup:
    amounts -= 2

lista = []
for i in range(amounts):
        num = random.randrange(1, 10001)
        lista.append(num)

inx1 = random.randrange(0, len(lista))
if inx1 != len(lista) - 1:
        lista.insert(inx1, d_number)
else:
        lista.append(d_number)

inx2 = random.randrange(0, len(lista))
if inx2 != len(lista) - 1:
        lista.insert(inx2, d_number)
else:
        lista.append(d_number)

lista = map(str, lista)
with open(fil, "w") as f:
    for i in lista:
        f.write(i)
        for k in range(10):
            f.write(rand_white())
    f.write("\n")


import torch
from torch import nn
from fuxictr.pytorch.models import MultiTaskModel
from fuxictr.pytorch.layers import FeatureEmbedding, MLP_Block

class SharedBottom(MultiTaskModel):
    def __init__(self,
                 feature_map,
                 model_id="SharedBottom",
                 gpu=-1,
                 task=["binary_classification"],
                 num_tasks=1,
                 loss_weight='EQ',
                 learning_rate=1e-3,
                 embedding_dim=10,
                 bottom_hidden_units=[64, 64, 64],
                 tower_hidden_units=[64, ],
                 hidden_activations="ReLU",
                 net_dropout=0,
                 batch_norm=False,
                 embedding_regularizer=None,
                 net_regularizer=None,
                 **kwargs):
        super(SharedBottom, self).__init__(feature_map,
                                           task=task,
                                           loss_weight=loss_weight,
                                           num_tasks=num_tasks,
                                           model_id=model_id,
                                           gpu=gpu,
                                           embedding_regularizer=embedding_regularizer,
                                           net_regularizer=net_regularizer,
                                           **kwargs)
        self.embedding_layer = FeatureEmbedding(feature_map, embedding_dim)
        self.bottom = MLP_Block(input_dim=embedding_dim * feature_map.num_fields,
                                hidden_units=bottom_hidden_units,
                                hidden_activations=hidden_activations,
                                output_activation=None,
                                dropout_rates=net_dropout,
                                batch_norm=batch_norm)
        self.tower = nn.ModuleList([MLP_Block(input_dim=bottom_hidden_units[-1],
                                              output_dim=1,
                                              hidden_units=tower_hidden_units,
                                              hidden_activations=hidden_activations,
                                              output_activation=None,
                                              dropout_rates=net_dropout,
                                              batch_norm=batch_norm)
                                    for _ in range(num_tasks)])
        self.compile(kwargs["optimizer"], kwargs["loss"], learning_rate)
        self.reset_parameters()
        self.model_to_device()

    def forward(self, inputs):
        X = self.get_inputs(inputs)
        feature_emb = self.embedding_layer(X)
        bottom_output = self.bottom(feature_emb.flatten(start_dim=1)) # (?, bottom_hidden_units[-1])
        tower_output = [self.tower[i](bottom_output) for i in range(self.num_tasks)]
        y_pred = [self.output_activation[i](tower_output[i]) for i in range(self.num_tasks)]
        return_dict = {}
        labels = self.feature_map.labels
        for i in range(self.num_tasks):
            return_dict["{}_pred".format(labels[i])] = y_pred[i]
        return return_dict


#!/bin/python

import collections
import os
import re
import subprocess
import time

GHOSTLY_PATH = '/usr/bin/ghostly'

ALLIE_DBG = '../target/debug/allie'

# Old versions
ALLIE_1_1 = './bin/allie_v1.1'
ALLIE_1_0 = './bin/allie_v1.0'
ALLIE_0_9 = './bin/allie_v0.9'
ALLIE_0_8 = './bin/allie_v0.8'
ALLIE_0_7 = './bin/allie_v0.7'
ALLIE_0_6 = './bin/allie_v0.6'
ALLIE_0_5 = './bin/allie_v0.5'
ALLIE_0_4 = './bin/allie_v0.4'
ALLIE_0_3 = './bin/allie_v0.3'
ALLIE_0_2 = './bin/allie_v0.2'
ALLIE_0_1 = './bin/allie_v0.1'

RESULT_RE = re.compile(r'^name:(?P<name>[^;]+);wins:(?P<wins>\d+);score:(?P<score>\d+)$')

ROUNDS = 25

Score = collections.namedtuple('Score', ['wins', 'score'])

def parse_result(server_output):
    ret = {}

    for result in server_output.decode("utf-8").split('\n'):
        match = RESULT_RE.match(result)
        if match is not None:
            ret[match.group('name')] = Score(int(match.group('wins')), int(match.group('score')))

    return ret

def benchmark():
    # Start the server
    server = subprocess.Popen([GHOSTLY_PATH
                            #    , '--headless'
                               , '--start-at', '2'
                               , '--tickless'
                               , '--rounds', str(ROUNDS)]
                              , stdout=subprocess.PIPE
                              , stderr=subprocess.PIPE)
    time.sleep(1)

    # Start the bots, ignoring any output
    devnull = open(os.devnull, 'w')
    subprocess.Popen([ALLIE_1_0], stdout=devnull, stderr=devnull)
    subprocess.Popen([ALLIE_1_1])

    # Wait here until the match is finished
    out, _ = server.communicate()

    # Parse the result
    results = parse_result(out)
    total_wins = sum(t.wins for t in results.values())
    total_score = sum(t.score for t in results.values())

    # Print the result
    for name, result in results.items():
        print(name + ":")
        print('\tWins: {}/{} {:.2f}%'
              .format(result.wins
                      , total_wins
                      , result.wins / total_wins * 100 if total_wins > 0 else 0))
        print('\tScore: {}/{} {:.2f}%'
              .format(result.score
                      , total_score
                      , result.score / total_score * 100 if total_score > 0 else 0))

if __name__ == '__main__':
    benchmark()


#!/usr/local/bin/python3
import socket
import struct
import crcmod
#from  dataservice.datawave_produce.waveproduce import sin_wave,triangle_wave
import random

def crccreate(b,length):
    crc16_func = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF, rev=True, xorOut=0x0000)
    return crc16_func(b[0:length])
def crccheckhole(b,length):
    crc16_func = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF, rev=True, xorOut=0x0000)

    return hex(crc16_func(b[0:length]))==bytesToHex(b[length],b[length+1])
def crccheck(b,length):
    print('传过来的b，和lenght',b,'   ',length)
    crc16_func = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF, rev=True, xorOut=0x0000)
    return crc16_func(b[0:length]) == bytesToInt(b[length], b[length + 1])

def get_send_msgflowbytes(slave,func,register,length,data):
    if length!=4:
        pass
    else:
        # print('data',data)
        a = struct.pack('!bbbbf', slave, func, register, length, data)
        # print(len(a))
        b=struct.pack('H',crccreate(a[0:8], length=8))
        a=a + b
        # print(a)
    return a

if __name__=='__main__':

    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建套接字
    tcp_server_socket.bind(('127.0.0.1',5000))#绑定本机地址和接收端口
    tcp_server_socket.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,True)
    print('Waiting connecting')
    # tcp_server_socket.listen(1)#监听（）内为最大监听值
    # client_socket,client_addr= tcp_server_socket.accept()#建立连接（accept（无参数）
    # print('Someone has connected to this sever')

    #xsin,ysin=sin_wave(0,100,1,2,2)
    #xtri,ytri=triangle_wave(0,100,1,2,2)
    #ysin=ysin-0.5
    #ytri=10*ytri
    data=0.0

    #sinindex=0;
    #triindex=0;
    while True:
        tim
        # b =client_socket.recv(10)
        # print('receiving msg:',b)
        # if b[1]==0x03:
        #     print('we are receiving setting command',b)
        #     # client_socket.send(b)
        # elif b[2]==0x01: #正弦波产生函数
        #     slave,func,register,length=struct.unpack('!bbbb',b[0:4]) #解析传过来的二进制字节流
            #sinindex +=1
        data=random.uniform(10,11)
        print(data)
            # #此处的数据包格式由epics 的protocol文件所确定
            # msg = get_send_msgflowbytes(slave, func, register, length, data)  #构建符合要求的数据包格式
            # print('sending msg:',msg)
            # print(b)
            # client_socket.send(msg)
            #if sinindex==99:
            #    sinindex=0


import machine

# Sensor is completly unreliable for me and showing extremely different values in same condition when trying to get the max and min values

class MoistureSensor:
    """A class that can read set pins for a moisture sensor installed on Lopy4"""
    max_moisture_sensor_value = 1000 # From multiple manual callibration test in glas of water, the average value
    min_moisture_sensor_value = 4095 # From manual calibration in complety dry in air, average value
    range_sensor_value = min_moisture_sensor_value - max_moisture_sensor_value

    def __init__(self):
        """Default constructor"""
        adc = machine.ADC()
        adc.vref(1100)
        self.pin16 = adc.channel(pin='P16',attn=machine.ADC.ATTN_11DB)

    def get_value_in_procent(self):
        """Get the value in procent depending of the fixed max and min moisture values"""
        value = self.pin16.value()

        if value < self.max_moisture_sensor_value: return 1
        if value > self.min_moisture_sensor_value: return 0

        valueOverMax = value - self.max_moisture_sensor_value

        return round(1 - (valueOverMax / self.range_sensor_value), 2)


pixel_data = open("D8-input.txt").read().strip()

width = 25
height = 6
row_length = width * height

layers = [[] for i in range(len(pixel_data) // row_length)]
print("Number of layers: ", len(layers))

for l in range(len(layers) ):
    for pos in range(row_length):
        layers[l].append(pixel_data[l * row_length + pos])

counts = list()
for list in layers:
    ones, twos, zeros = [0,0,0]

    for raw in list:
        val = int(raw)
        if val == 0:
            zeros += 1
        elif val == 1:
            ones += 1
        elif val == 2:
            twos += 1

    counts.append((zeros, ones, twos))

least_zeros = None
zeros_count = None
for layer in counts:
    if (layer[0] + layer[1] + layer[2]) != 150:
        print(layer, "is not 150 in size")
    if zeros_count == None or layer[0] < zeros_count:
        least_zeros = layer
        zeros_count = layer[0]

print('The digit count for layer with least amount of zeros (0, 1, 2): ', least_zeros)
print('Count of ones multiplied with count of twos: ', least_zeros[1] * least_zeros[2])

# Task 2
print('Rendering image:\n')
image = [[2] * width for i in range(height)]
for h in range(height):
    for w in range(width):
        if image[h][w] == 2:
            layer_pos = h * width + w
            for layer in layers:
                char = int(layer[layer_pos])
                if char != 2:
                    image[h][w] = char
                    break

for row in image:
    for pos in row:
        char = ' '
        if pos == 1:
            char = '#'
        print(char, end='')
    print()