quarta-feira, 27 de janeiro de 2021

Métodos de entrada Python para programação competitiva

Python é uma linguagem incrivelmente amigável com a única falha de ser lenta. Em comparação com C, C ++ e Java, é bem mais lento. Normalmente, em Java, o tempo fornecido é 2X e em Python, é 5X.
Para melhorar a velocidade de execução do código para problemas intensivos de entrada / saída, as linguagens têm vários procedimentos de entrada e saída.

Um Exemplo de Problema:

Considere a questão de encontrar a soma de N números inseridos pelo usuário. 
Entrada de um número com a quantidade de números. 
Insira os números separados por um único espaço em uma linha.

Exemplos: 

Entrada: 
5
1 2 3 4 5
Resultado:
15

Diferentes soluções para o problema acima em Python: 

Método normal Python: (Python 2.7) 

1. raw_input() recebe um argumento de prompt opcional. Ele também remove o caractere de nova linha final da string que retorna.
2. print é apenas um wrapper fino que formata as strings (espaço entre args e nova linha no final) e chama a função de gravação de um determinado objeto.

# método básico de entrada e saída
# N entradas
n = int(raw_input())

# entre com uma matriz
arr = [int(x) for x in raw_input().split()]

# inicializa variável
summation = 0

# calcula a soma
for x in arr:
    summation += x

# mostra a resposta
print(summation)

Um método um pouco mais rápido usando oa funções internas stdin, stdout: (Python 2.7)

1. sys.stdin por outro lado é um objeto de arquivo. É como criar qualquer outro objeto de arquivo que alguém possa criar para ler a entrada do arquivo. Nesse caso, o arquivo será o buffer de entrada padrão. 
2. stdout.write('D\n') é mais rápido que print('D')
3. Ainda mais rápido é escrever tudo de uma vez por stdout.write("".Join(list-comprehension)), mas isso torna o uso da memória dependente do tamanho da entrada.

# importa stdin stdout
from sys import stdin, stdout 

# suponha que uma função chamada main()
# e todas as operações sejam realizadas
def main():

    # entrada via readline
    n = stdin.readline()
 
    # método similar de entrada de array
    arr = [int(x) for x in stdin.readline().split()]

    # inicializa a variável
    summation = 0

    # calcula a soma
    for x in arr:
        summation += x

    # imprimir resposta por escrito
    # método write escreve apenas
    # operações de string
    # então precisamos converter qualquer
    # dados em string para entrada
    stdout.write(str(summation))

# chama o método principal
if __name__ == "__main__":
    main()

Diferença no tempo:

Resumo do tempo (100k linhas cada)
——————————–
Imprimir: 6.040s
Gravar no arquivo: 0.122s
Imprimir com saída padrão: 0.121s

Como vimos até agora, obter dados do sistema padrão e dar saída ao sistema padrão é sempre uma boa ideia para melhorar a eficiência do código, o que é sempre uma necessidade na programação competitiva. Mas espere! gostaria de escrever essas longas linhas sempre que precisar delas? Então, qual é a vantagem de usar Python.
Vamos discutir a solução para este problema. O que podemos fazer é criar funções separadas para pegar entradas de vários tipos e apenas chamá-las sempre que precisar.

Quando você deseja obter a entrada de números inteiros específicos fornecidos em uma única linha

Suponha que a entrada tenha o seguinte formato:

5 7 19 20

e queremos variáveis separadas para referenciá-los. o que queremos é:

a = 5
b = 7
c = 19
d = 20

então, podemos criar uma função chamada get_ints() da seguinte maneira:

import sys
def get_ints():
    return map(int, sys.stdin.readline().strip().split())
 
a, b, c, d = get_ints()

Agora você não precisa escrever esta linha novamente e novamente. Você apenas tem que chamar a função get_ints() para receber a entrada neste formulário. Na função get_ints, estamos usando a função map().

Quando você deseja obter a entrada de uma lista de inteiros fornecida em uma única linha

Suponha que a entrada tenha o seguinte formato

1 2 3 4 5 6 7 8

e queremos que uma única variável mantenha toda a lista de inteiros. O que queremos é:

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

Então, aqui vamos criar uma função chamada get_list() da seguinte maneira:

import sys
def get_ints():
    return list(map(int, sys.stdin.readline().strip().split()))
 
Arr = get_ints()

Agora você não precisa escrever esta linha novamente e novamente. Você apenas tem que chamar a função get_ints() para receber a entrada neste formulário.

Quando você deseja inserir uma string

Suponha que a entrada tenha o seguinte formato:

Acerov Lima é a melhor plataforma para praticar a codificação.

e queremos que uma única variável de referência mantenha esta string. O que queremos é:

string = "Acerov Lima é a melhor plataforma para praticar a codificação."

Então, aqui vamos criar uma função chamada get_string() da seguinte maneira:

import sys
def get_string():
    return sys.stdin.readline().strip()
 
string = get_string()

Agora você não precisa escrever esta linha novamente e novamente. Você apenas tem que chamar a função get_string() para receber a entrada neste formulário
Adicionando um pipe em buffer io: (Python 2.7) 
1. Simplesmente, Adicionando o código IO em buffer antes de seu código de envio para tornar a saída mais rápida. 
2. O benefício dos objetos io.BytesIO é que eles implementam uma interface comum (comumente conhecida como um objeto 'semelhante a um arquivo'). Os objetos BytesIO têm um ponteiro interno e para cada chamada para read(n) o ponteiro avança. 
3. O módulo atexit fornece uma interface simples para registrar funções a serem chamadas quando um programa fecha normalmente. O módulosys também fornece um gancho, sys.exitfunc, mas apenas uma função pode ser registrada lá. O registro atexit pode ser usado por vários módulos e bibliotecas simultaneamente.

# importar bibliotecas para manipulação de entrada / saída em nível genérico
import atexit, io, sys
 
# Uma implementação de fluxo usando um buffer de bytes na memória.
# Ele herda BufferedIOBase.
buffer = io.BytesIO()
sys.stdout = buffer
 
# print
@atexit.register
def write():
    sys.__stdout__.write(buffer.getvalue())
 
# método normal seguido de entrada N
n = int(raw_input())
 
# insira o array
arr = [int(x) for x in raw_input().split()]
 
summation = 0

for x in arr:
    summation += x

print(summation)

Ao lidar com uma grande quantidade de dados normalmente, o método normal falha ao executar dentro do limite de tempo. O Método 2 ajuda a manter uma grande quantidade de dados de E / S. O Método 3 é o mais rápido. Normalmente, o manuseio de arquivos de dados de entrada maiores que 2 ou 3 MBs é auxiliado pelos métodos 2 e 3.
Nota: Os códigos de menção acima estão em Python 2.7, para uso em versões Python 3.X. Simplesmente substitua raw_input() pela sintaxe input() do Python 3.X. O descanso deve funcionar bem.
Referências: 
1. Mais sobre a entrada em Python 2.7 
2. Saída via biblioteca sys e outros comandos.  
3. Entrada via biblioteca sys e outros comandos.  
4. Documentos do Módulo Python atexit.
Este artigo é uma contribuição de Shubham Saxena.

Artigo escrito por GeeksforGeeks e traduzido por Acervo Lima de Python Input Methods for Competitive Programming.

0 comentários:

Postar um comentário