• Nenhum resultado encontrado

Técnicas de resolução da situação de Time Limit Exceeded de questões da maratona de programação

N/A
N/A
Protected

Academic year: 2023

Share "Técnicas de resolução da situação de Time Limit Exceeded de questões da maratona de programação"

Copied!
61
0
0

Texto

(1)

CURSO SUPERIOR DE SISTEMAS DE INFORMAÇÃO

BRENDON MAURO

TÉCNICAS DE RESOLUÇÃO DA SITUAÇÃO DE TIME LIMIT EXCEEDED DE QUESTÕES DA MARATONA DE PROGRAMAÇÃO

Serra 2022

(2)

TÉCNICAS DE RESOLUÇÃO DA SITUAÇÃO DE TIME LIMIT EXCEEDED DE QUESTÕES DA MARATONA DE PROGRAMAÇÃO

Trabalho de Conclusão de Curso apresentado à Coordenadoria do Curso de Sistemas de Informação do Instituto Federal do Espírito Santo, Campus Serra, como requisito parcial para a obtenção do título de Bacharel em Sistemas de Informação.

orientadora: Prof.a Dr.a Karin Satie Komati co-orientador: Prof. Dr. Jefferson Oliveira Andrade

Serra 2022

(3)

Bibliotecária Rogeria Gomes Belchior - CRB6/ES 417

M457t 2022

Mauro, Brendon

Técnicas de resolução da situação de Time Limit Exceeded de questões da maratona de programação / Brendon Mauro. - 2022.

59 f.; il.; 30 cm

Orientadora: Prof.ª. Dra. Karin Satie Komati.

Coorientador: Prof. Dr. Jefferson Oliveira Andrade.

Monografia (graduação) - Instituto Federal do Espírito Santo, Coordenadoria de Informática, Curso de Bacharelado em Sistemas de Informação, 2022.

1. Programação (Computadores). 2. Algoritmos de computador.

3. Raciocínio. 4. Solução de problemas. I. Komati, Karin Satie. II.

Andrade, Jefferson Oliveira. III. Instituto Federal do Espírito Santo.

IV. Título.

CDD 005.1

(4)

TÉCNICAS DE RESOLUÇÃO DA SITUAÇÃO DE TIME LIMIT EXCEEDED DE QUESTÕES DA MARATONA DE PROGRAMAÇÃO

Trabalho de Conclusão de Curso apresentado como parte das atividades para obtenção do título de Bacharel em Sistemas de Informação, do curso de Bacharelado em Sistemas de Informação do Instituto Federal do Espírito Santo.

Aprovado em 01 de dezembro de 2022.

COMISSÃO EXAMINADORA

_________________________________________________

Profª Drª Karin Satie Komati (orientadora) Instituto Federal do Espírito Santo - Campus Serra

__________________________________________________

Prof. Dr. Jefferson Oliveira Andrade (coorientador) Instituto Federal do Espírito Santo - Campus Serra

___________________________________________________

Prof. Dr. Flávio Severiano Lamas de Souza Instituto Federal do Espírito Santo - Campus Serra

__________________________________________________

Prof. Dr. Leandro Colombi Resendo

Instituto Federal do Espírito Santo - Campus Serra

(5)

SISTEMA INTEGRADO DE PATRIMÔNIO, ADMINISTRAÇÃO E CONTRATOS

Emitido em 01/12/2022

FOLHA DE APROVAÇÃO-TCC Nº 7/2022 - SER-DPPGE (11.02.32.11) NÃO PROTOCOLADO)

(Nº do Protocolo:

(Assinado digitalmente em 01/12/2022 16:57 ) FLAVIO SEVERIANO LAMAS DE SOUZA

PROFESSOR DO ENSINO BASICO TECNICO E TECNOLOGICO SER-CGEN (11.02.32.01.08.02)

Matrícula: 1586353

(Assinado digitalmente em 12/12/2022 11:08 ) JEFFERSON OLIVEIRA ANDRADE

PROFESSOR DO ENSINO BASICO TECNICO E TECNOLOGICO SER-CCSI (11.02.32.01.08.02.04)

Matrícula: 1208144

(Assinado digitalmente em 01/12/2022 16:08 ) KARIN SATIE KOMATI

PROFESSOR DO ENSINO BASICO TECNICO E TECNOLOGICO SER-DPPGE (11.02.32.11)

Matrícula: 2324453

(Assinado digitalmente em 01/12/2022 16:48 ) LEANDRO COLOMBI RESENDO

COORDENADOR DE CURSO - TITULAR CMPCA (11.02.32.01.07.08)

Matrícula: 1687072

Para verificar a autenticidade deste documento entre em https://sipac.ifes.edu.br/documentos/ informando seu número: , ano: 7 2022, tipo: FOLHA DE APROVAÇÃO-TCC, data de emissão: 01/12/2022 e o código de

verificação: 8dbd7d1b42

(6)

A minha família Aos meus professores

A todos funcionários que mantém a universidade pública Aos meus orientadores

Aos meus colegas

À todos aqueles que me acompanharam nessa jornada

(7)

Agradeço a minha mãe, Cláudia Alves dos Santos, que foi a pessoa que mais acreditou no meu potencial, e nunca hesitou sobre minha capacidade mesmo quando eu me desacreditei.

Agradeço a minha família, que tiveram que se adequar a minha nova rotina e me deram recursos, e todo apoio necessário para continuar no curso.

Agradeço aos meus professores, que são inspiração quanto ao aprimorado grau de conhecimento e são exemplos de pessoas clementes e que fazem a diferença na sociedade. Além disso, incentivam os alunos a buscar seu potencial e concedem todo apoio necessário para os alunos manterem no curso.

Agradeço a todos os funcionários que permitem que a Universidade Pública aconteça de fato, e ofereça oportunidades para que estudantes possam realizar seus sonhos.

Agradeço aos meus orientadores, Karin Satie Komati e Jefferson Oliveira Andrade, pelo carinho, pela inspiração e o incentivo grandioso que recebi deles, e por propiciar todo suporte necessário para concluir este trabalho.

Por fim, agradeço a todos os colegas que estiveram comigo durante essa jornada no curso, pois com a parceria dos mesmos conseguimos fazer dessa jornada um pouco mais leve e confortável.

(8)

(DIJKSTRA, 1970)

(9)

A programação é a essência da computação. Um dos eventos que tem como cerne este conceito é a Maratona de Programação. O estudante de computação que participa do evento põe em prática importantes conceitos da computação, além de aguçar sua criatividade na resolução de problemas, e a capacidade de resolvê-los sob pressão. O objetivo não é apenas solucionar o problema, mas também solucionar de forma que passe na bateria de testes no tempo limite estabelecido. Quando o tempo limite é ultrapassado o juiz online responde TLE (Time Limit Exceeded). Este trabalho tem como objetivo apresentar soluções para evitar TLE. Problemas de nível fácil geralmente não requerem uma técnica avançada para que a solução passe na bateria de testes abaixo do tempo limite, porém problemas de nível médio e difícil, requer uma atenção na escolha do algoritmo a ser utilizado. Para testar as soluções apresentadas foi utilizado o beecrowd, um online judge, que é um site que possui os problemas de maratonas de programação anteriores e é possível submeter código/solução e verificar se a solução está correta ou não. Assim, é possível se estudar técnicas para evitar TLE, e uma melhor capacidade em pensar soluções rápidas e eficientes diante de desafios em programação.

Palavras-chave: técnicas de programação. otimização de código. raciocínio lógico.

(10)

Programming is the essence of computing. One competition with this concept as its core is the Programming Marathon. The computing student who participates in the event puts into practice important computing concepts, sharpening their creativity in problem-solving, and the ability to solve them under pressure. The goal is not only to solve the problem but also to solve it in a way that passes the battery of tests within the established time limit.

When the time limit is exceeded the online judge responds TLE (Time Limit Exceeded).

This work aims to present solutions to avoid TLE. Easy-level problems generally do not require an advanced technique for the answer to pass the battery of tests under the time limit, but medium and hard-level problems require attention in choosing the algorithm to be used. To test the presented solutions, beecrowd was used, an online judge, which is a site that has the problems of previous programming marathons and it is possible to submit code/solution and verify if the answer is correct or not. Thus, it is possible to study techniques to avoid TLE, and a better ability to think of fast and efficient solutions in the face of programming challenges.

Keywords: programming techniques. code optimization. logical reasoning.

(11)

Figura 1 – Exemplo de placar com os nomes das equipes e os balões ganhos.

Resultados da Maratona 2010 na UFPel. . . 14

Figura 2 – Foto tirada durante a Maratona de Programação 2015, fase local, no campus Serra do Ifes. . . 14

Figura 3 – Tela principal do BOCA . . . 20

Figura 4 – Tela “Problems” do BOCA . . . 21

Figura 5 – Tela “Runs” do BOCA . . . 21

Figura 6 – Tela “Runs” do BOCA, para submissão . . . 21

Figura 7 – Tela “Score” do BOCA . . . 22

Figura 8 – Tela inicial do beecrowd . . . 23

Figura 9 – Categoria de problemas do beecrowd . . . 24

Figura 10 – Tela com o enunciado do problema “Hello World” . . . 24

Figura 11 – Tela exemplo com um resultado de submissão . . . 25

Figura 12 – Exemplos de entrada e saída do Problema Divisores. . . 28

Figura 13 – Exemplos de entrada e saída do Problema Isósceles. . . 32

Figura 14 – Exemplos de entrada e saída do Problema Espiral. . . 35

Figura 15 – Exemplos de entrada e saída do Problema do Imposto Real. . . 42

Figura 16 – Grafo da entrada 1 do enunciado. . . 42

Figura 17 – Exemplo de grafo e matriz de distância associada. . . 44

Figura 18 – Exemplos de entrada e saída do Problema Remendo. . . 49

(12)

Quadro 1 – Enunciado do problema Divisores. . . 28

Quadro 2 – Solução 1 do problema Divisores. . . 29

Quadro 3 – Resposta do URI da solução 1 do problema Divisores. . . 29

Quadro 4 – Solução 2 do problema Divisores. . . 30

Quadro 5 – Resposta do URI da Solução 2 do problema Divisores. . . 30

Quadro 6 – Enunciado do problema 2243 – Isósceles. . . 31

Quadro 7 – Solução 1 do problema do Isósceles. . . 32

Quadro 8 – Resposta do URI da solução 1 do problema Isósceles. . . 33

Quadro 9 – Solução 2 do problema do Isósceles. . . 34

Quadro 10 – Resposta do URI da Solução 2 do problema Isósceles. . . 34

Quadro 11 – Enunciado do problema Espiral. . . 35

Quadro 12 – Solução 1 do problema Espiral. . . 37

Quadro 13 – Resposta do URI da solução 1 do problema Espiral. . . 38

Quadro 14 – Solução 2 do problema Espiral. . . 40

Quadro 15 – Resposta do URI da solução 2 do problema Espiral. . . 40

Quadro 16 – Enunciado do problema do Imposto Real - Parte I. . . 41

Quadro 17 – Enunciado do problema do Imposto Real - Parte II. . . 42

Quadro 18 – Solução 1 do problema Imposto Real - Parte II. . . 45

Quadro 19 – Solução 1 do problema Imposto Real - Parte I. . . 46

Quadro 20 – Resposta do URI da Solução 1 do problema Imposto Real. . . 46

Quadro 21 – Solução 2 do problema Imposto Real - Parte II. . . 47

Quadro 22 – Solução 2 do problema Imposto Real - Parte I. . . 47

Quadro 23 – Resposta do URI da Solução 2 do problema Imposto Real. . . 48

Quadro 24 – Enunciado do problema Remendo - Parte I. . . 48

Quadro 25 – Enunciado do problema Remendo - Parte II. . . 49

Quadro 26 – Solução 1 do problema Remendo - Parte I. . . 50

Quadro 27 – Solução 1 do problema Remendo - Parte II. . . 51

Quadro 28 – Resposta do URI da Solução 1 do problema Remendo. . . 52

Quadro 29 – Solução 2 do problema Remendo - Parte I. . . 53

Quadro 30 – Solução 2 do problema Remendo - Parte II. . . 54

Quadro 31 – Resposta do URI da Solução 2 do problema Remendo. . . 54

(13)

1 INTRODUÇÃO . . . . 12

1.1 OBJETIVOS . . . 16

1.1.1 Objetivo Geral . . . 16

1.1.2 Objetivos Específicos . . . 16

1.2 ESTRUTURA DO TEXTO . . . 16

2 REFERENCIAL TEÓRICO . . . . 17

2.1 SISTEMAS DE JUÍZES ONLINE . . . 19

2.1.1 BOCA . . . 19

2.1.2 beecrowd . . . 22

2.2 TRABALHOS CORRELATOS . . . 25

3 QUESTÕES DA MARATONA DE PROGRAMAÇÃO . . . . . 27

3.1 PROBLEMA DIVISORES . . . 27

3.1.1 Solução 1 . . . 28

3.1.2 Solução 2 . . . 29

3.2 PROBLEMA ISÓSCELES . . . 30

3.2.1 Solução 1 . . . 32

3.2.2 Solução 2 . . . 33

3.3 PROBLEMA ESPIRAL . . . 34

3.3.1 Solução 1 . . . 36

3.3.2 Solução 2 . . . 38

3.4 PROBLEMA IMPOSTO REAL . . . 41

3.4.1 Solução 1 . . . 44

3.4.2 Solução 2 . . . 46

3.5 PROBLEMA REMENDO . . . 48

3.5.1 Solução 1 . . . 49

3.5.2 Solução 2 . . . 52

4 CONSIDERAÇÕES FINAIS . . . . 55

4.1 TRABALHOS FUTUROS . . . 55

REFERÊNCIAS . . . . 57

(14)

1 INTRODUÇÃO

O uso da computação é cada vez mais comum em diversas áreas, pois é uma ferramenta que visa otimizar os processos de informação, independentemente para qual especificidade este processo é utilizado. Usar processos computacionais é sempre vantajoso, e pode ser um diferencial para o profissional. De acordo com o documento da Sociedade Brasileira de Computação (SBC) “Manifesto da SBC pela Inserção de Computação na Educação Básica” (SBC, 2018):

Computação é uma ciência que estuda formas de representação da informação e o processo de resolução de problemas em si, incluindo tanto o desenvolvimento de técnicas de construção de soluções quanto o de máquinas capazes de executar essas soluções. Essas técnicas desenvolvem não somente a capacidade de construir modelos abstratos (de informação e processos) e sistematizar a solução de problemas, mas também as habilidades de argumentação, análise crítica e trabalho cooperativo. Por isso, Computação é usada nas outras ciências, na Matemática, Física, Biologia, Línguas, História, Economia, Artes, etc. A área da Computação provê habilidades, conhecimento, ferramentas e máquinas para tornar as pessoas mais capazes de criar e inovar em todas as áreas. (SBC, 2018).

Programação é a essência da computação (OLIVEIRA; PEREIRA, 2019). O estudante da área da computação quando programa, aplica os conceitos sobre gerenciamento de memória, escalonamento, processos, lógica matemática, matemática discreta, linguagem binária, entre outros tantos conceitos apresentados em qualquer curso da área da computação.

Infelizmente, de acordo com Gonçalves et al. (2013), o alto nível de abstração exigido em disciplinas relacionadas a programação causa desmotivação nos alunos, fator preponderante para altas taxas de reprovações e desistências. O estudo de Brito et al. (2019) indica que a programação competitiva pode ser uma ferramenta de apoio ao ensino de algoritmos e estrutura de dados para alunos de computação. A programação competitiva é um esporte mental, em que os participantes programam soluções de acordo com as especificações fornecidas de alguns problemas.

Existem várias competições de programação para incentivar a programação (FORTUNA, 2014), elas variam no estilo e regras, mas em todas é necessário programar. A principal competição para alunos do ensino médio e primeiro ano do ensino superior é a “International Olympiad in Informatics”1 (IOI), que é uma competição internacional e individual. O Brasil leva para a competição uma equipe de 4 alunos selecionados na OBI (Olimpíada Brasileira de Informática2). A OBI é uma competição nacional, organizada pelo Instituto de Computação da UNICAMP e é realizada nos moldes da IOI. Já para o ensino superior e o primeiro ano da pós-graduação, a principal competição internacional é a “International

1 https://ioinformatics.org/

2 https://olimpiada.ic.unicamp.br/

(15)

Collegiate Programming Contest”3 (ICPC). Para participar é necessário ser campeão ou vice na Maratona de Programação4. A Maratona de Programação é uma competição nacional, organizada pela SBC e é realizada nos moldes da ICPC.

O ICPC tem sede na Baylor University5. De 1977 até 2017, a ICPC era organizada pela ACM e muitas vezes referenciada como ACM-ICPC. Nos primeiros anos da competição, entre 1977 e 1989, apenas times dos Estados Unidos da América foram os vencedores das finais mundiais. Entre o ano 2000 e 2021, apenas equipes da Rússia (15 vezes), China (4 vezes) e Polônia (2 vezes) venceram as finais mundiais do ICPC. Alguns ex-finalistas do ICPC alcançaram posições de reconhecimento, incluindo Adam D’Angelo, ex-CTO do Facebook e fundador do Quora, Nikolai Durov, cofundador do Telegram Messenger, Matei Zaharia, criador do Apache Spark, Tony Hsieh, CEO da Zappos e Craig Silverstein, o primeiro funcionário do Google.

O evento da Maratona de Programação nacional é dividido em duas fases, sendo a 1ª fase em nível regional, e a 2ª fase é a nacional, ou final, com todos os times classificados na fase regional (SBC, 2021). A participação é em equipe, composta por três alunos que dividem um único computador. A prova da maratona tem de 9 a 13 questões, pois varia conforme o ano da competição. Cada questão é associada à um balão de uma determinada cor, e quando a equipe resolve uma questão, recebe um balão daquela cor. A Figura 1 apresenta um exemplo do placar (dashboard) da competição. São apresentados os resultados de 11 equipes (numeradas de 1 a 11), cada um com o usuário de acesso ao sistema (User), o nome da equipe (Name), as questões (identificadas por letras do alfabeto, no exemplo há 11 questões deA à K), e o total. A coluna Total tem duas informações, a quantidade de questões resolvidas e o tempo total entre parênteses, que é a somatória de todos os tempos das questões resolvidas. Ganha a equipe que tiver resolvido a maior quantidade de questões e no menor tempo. A Figura 2 é uma foto da competição regional de 2015 realizada no Ifes, em que é possível ver alguns balões distribuídos para as equipes.

As competições usam um sistema chamado de online judges ou online contests ou juízes online (RAUCCI, 2021). Nestes sistemas, é possível submeter soluções para um determinado problema, que compila o código fonte submetido e o executa em uma bateria de testes, que é um conjunto extenso de entrada-saída do problema. Em geral, estes sistemas possuem compiladores para diferentes linguagens de programação, como por exemplo, o GCC, o python, o python3, openjdkm dentre outros. Além disso, avalia o uso de recursos e o tempo de execução dos testes. O ICPC não possui um sistema único e padrão e, a cada ano, um sistema diferente foi usado na competição. No ano de 2021, foi usado o DOMjudge programming contest control system version 8.0 (DOMJUDGE, 2021),

3 https://icpc.global/

4 http://maratona.sbc.org.br/

5 https://isc.baylor.edu/

(16)

Figura 1 – Exemplo de placar com os nomes das equipes e os balões ganhos. Resultados da Maratona 2010 na UFPel.

Fonte: UFPel (2021)

Figura 2 – Foto tirada durante a Maratona de Programação 2015, fase local, no campus Serra do Ifes.

Fonte: Foto tirada pela organização da Maratona.

em 2000 foi usado o UVa Online Judge6. Já a Maratona de Programação tem usado o sistema BOCA, no últimos anos.

Para se preparar e treinar para as competições, há vários sistemas online disponíveis além

6 http://uva.onlinejudge.org/

(17)

dos já citados, tais como Kattis7, Codeforces8, Topcoder9, CodeChef10, URI Online Judge

11, dentre outras. No dia 24 de outubro de 2021, o URI Online Judge entrou em uma nova fase e foi renomeado para beecrowd12, que é o sistema usado neste trabalho. Neste sistema, cada solução é compilada e submetida à uma bateria de testes, desconhecida aos competidores, e pode gerar as seguintes mensagens:

1. Compilation Error: erro de compilação;

2. Runtime Error: erro de execução;

3. Wrong Answer: caso encontrado algum resultado de um teste que é diferente do esperado;

4. Output Format Error ou Presentation Error: indica que a saída do seu programa não segue a especificação exigida na folha de questões, apesar do resultado estar correto;

5. Time-limit Exceeded – TLE: a execução do seu programa excedeu o tempo permitido definido pelos juízes;

6. Resources Exceeded – RE: excesso do uso de memória, ou de processamento, ou quando ocorre alguma exceção não tratado no código para algum teste específico e;

7. YES ouAccepted: seu programa foi aceito, e você receberá um balão da cor correspondente ao problema.

Para cada questão é fornecido um enunciado e um conjunto de exemplos de entrada-saída, em geral, dois ou três exemplos. Uma situação comum é quando os competidores acham que sua solução está correta, pois resolve os casos exemplos da questão, mas recebem respostas de que a solução não atende (erros de 1 a 4). Mesmo que uma solução forneça resultados corretos para toda a bateria de testes, é possível receber como resposta um TLE (erro 5) ou RE (erro 6). No caso do TLE, ao executar a bateria de testes, que o usuário do sistema de juiz online não tem conhecimento, o tempo limite é excedido em algum caso de testes da bateria. Para resolver um problema sem TLE, é necessário compreender fatores que impactam no tempo de execução do algoritmo.

A proposta deste trabalho é apresentar duas soluções para 5 (cinco) problemas, ambas as soluções estão corretas, mas uma delas apresenta um TLE como resposta do beecrowd e uma segunda variação que além de estar correta algoritmicamente, é executada dentro do

7 https://open.kattis.com

8 http://codeforces.com/

9 http://www.topcoder.com/

10 http://www.codechef.com/

11 https://www.urionlinejudge.com.br/

12 www.beecrowd.com.br

(18)

tempo limite de processamento. Ambas as soluções serão detalhadas e comparadas. A definição do tempo limite é pré-definido pelo sistema.

1.1 OBJETIVOS 1.1.1 Objetivo Geral

Comparar duas soluções algorítmicas de questões da Maratona de Programação com relação à restrição de tempo limite de processamento.

1.1.2 Objetivos Específicos

Para se alcançar o objetivo geral, os seguintes objetivos específicos serão realizados:

• Selecionar problemas de maratonas abrangendo diferentes categorias.

• Programar soluções que resolvam o problema, mas que apresentaram respostas TLE do online judge.

• Pesquisar as melhores técnicas para a categoria do problema proposto.

• Programar soluções que resolvam o problema e recebe a resposta de resolvido do online judge.

• Coletar os dados referentes as submissões como tempo de processamento, memória utilizada da resposta do online judge.

1.2 ESTRUTURA DO TEXTO

No Capítulo 2, detalha-se a fundamentação teórica, abordando informações gerais sobre a Maratona de Programação e trabalhos correlatos. O Capítulo 3 apresenta os enunciados dos problemas, e duas soluções para cada problema, uma com resposta TLE e outra com resposta aceita pelo sistema. No Capítulo 4, tem-se as considerações finais sobre o estudo e trabalhos futuros.

(19)

2 REFERENCIAL TEÓRICO

A maratona de programação é um evento da SBC que ocorre anualmente, desde 1996, destinado a alunos de graduação da área de computação, embora não exista impedimento da participação de alunos de outros cursos. Neste capítulo são descritas as regras gerais de forma resumida, mais detalhes no site da Maratona13.

Atualmente, a maratona tem duas fases: a primeira fase e a final brasileira. A primeira fase é eliminatória e desde a situação de pandemia do COVID-19, a primeira fase tem sido online. Em 2021, houve uma sede virtual em cada estado e no distrito federal e cada instituição se inscreveu na sede de seu estado. A alocação de vagas na final brasileira são de três tipos:

• regra 1: 15 (quinze) vagas serão atribuídas aos times com melhor desempenho por todas as sedes. Uma sede se qualifica para vagas deste tipo se tiver times de pelo menos 2 escolas.

• regra 2: cerca de 65% das vagas serão distribuídas entre as sedes de acordo com o número de escolas participantes naquela sede através da fórmula:

NúmerodeVagas = arredonda(VagasRegra2 * NumerodeEscolasnaSede / TotaldeEscolas).

Uma sede se qualifica para vagas deste tipo se tiver pelo menos 10 times de 5 escolas.

• regra 3: cerca de 10% das vagas serão atribuídas entre as sedes pelo Comitê Diretor da Maratona de Programação sob forma de incentivo ao crescimento de sedes ainda não contempladas, ou por outros critérios que serão divulgados na ocasião da definição dos times participantes da final.

As sedes que não atingirem o limiar (10 times e 5 escolas) para fins de distribuição das vagas pela regra 2 são agrupadas:

• em uma supersede estadual, que junta as sedes do mesmo estado que não atingiram o limiar.

• se ainda não atingirem o mínimo (pelo item anterior), são agrupadas em uma supersede regional, que junta as supersedes estaduais da mesma região, que ainda não atingiram o limite.

• se ainda assim não atingem o mínimo (pelo item anterior), são agrupadas em uma supersede nacional.

13 http://maratona.sbc.org.br/

(20)

Estas supersedes receberão vagas na final brasileira utilizando a fórmula descrita na regra 2, sendo que cada sede de uma supersede pode classificar apenas um time pela regra 2.

Um time só se qualifica para passar à final brasileira caso tenha resolvido pelo menos três problemas na prova da primeira fase. Se o time for campeão de sua sede pode se classificar com dois problemas. Além disso, uma mesma escola pode ter no máximo dois times na final brasileira.

A Maratona oferece medalhas aos dez primeiros colocados na fase final da competição:

ouro para os três primeiros; prata para o quarto, quinto e sexto; e bronze para o sétimo a décimo lugares. Além disso, o time campeão recebe uma cópia do troféu “Maratona de Programação”. O time campeão da Maratona de Programação garante vaga na final mundial do concurso de programação do ICPC. Caso o Brasil receba outras vagas nesta final, estas serão ocupadas pelos primeiros colocados da final brasileira, respeitado o limite de vagas por escola, conforme regra da regional latino-americana do ICPC.

Os times são formados por um coach e três alunos regularmente matriculados desta instituição e, no máximo, um reserva. Uma mesma instituição pode ter vários times participantes da primeira fase do concurso. Todos os times de uma instituição devem disputar a primeira fase em uma mesma sede. No ano de 2019, mais de 50 mil estudantes de mais de 3.000 escolas de mais de 100 países competiram em regionais em todo o planeta, e apenas 135 (cerca de 1%) participaram da final mundial que foi em Moscou, Rússia. Nove times brasileiros, dos quase de 800 participantes, estiveram presentes nas finais mundiais.

Quando era na modalidade presencial, no dia da competição, o evento inicia com a chegada dos times e a entrega dos materiais por volta das 8h às 10h. Depois, há a sessão de aquecimento (warm up), que vai até 12h, e o horário do almoço é das 12h às 14h. Logo após o almoço, inicia a competição oficial, a duração da competição é de 5 horas, geralmente iniciando às 14 horas e encerrando às 19 horas. Na competição, é importante que cada equipe tenha exatamente 3 (três) participantes, caso contrário a equipe é desclassificada.

Depois de iniciado o concurso não há possibilidade de substituições no time. Durante a competição era permitida a pesquisa em material impresso que o time poderia levar (livros, listagens, manuais).

O melhor desempenho na competição é a maior quantidade de soluções que respondem corretamente à bateria de testes, de acordo com os limites de recursos e tempo. Caso tenha empate pela quantidade de questões resolvidas, o desempate é obtido através do tempo de resolução, contado da seguinte forma para cada problema resolvido: o número de minutos desde o início da competição mais 20 vezes o número de submissões erradas.

Na versão 2021 da Maratona, foi fornecido um documento com informações gerais do uso do sistema, comandos de compilação , questões específicas de cada linguagem, limites

(21)

de memória, limites de tamanho de arquivo de código e limites de tempo. A Tabela 1 é a imagem da tabela fornecida sobre limite de tempo, que é diferente para cada questão (linha) e para cada linguagem (coluna). Observa-se que o limite de tempo em C/C++ é menor ou igual que nas outras linguagens, como no problema N, em que o tempo é de 0,7 segundos e em Java/Kotlin é de 7 segundos, ou como problema I, que em C/C++ é de 0,1 s e em Python é de 6 s. O tempo limite em Python é, em sua maioria, menor ou igual ao tempo de Java/Kotlin, mas há exceções como nos problemas I e M.

Tabela 1 – Limites de tempo em segundos.

Fonte: <http://maratona.sbc.org.br/primeira-fase/info_maratona.pdf>

2.1 SISTEMAS DE JUÍZES ONLINE

Numa competição de programação, a correção dos programas enviados pelos times para o sistema de juiz online e o resultado é fornecido logo em seguida. Assim, o time tem a possibilidade de consertar a solução e entregá-la novamente, ainda durante o tempo de prova, mas sem saber especificadamente o que estava errado na questão. Há vários sistemas de ambientes de competição, nesta seção são fornecidos mais detalhes de dois sistemas brasileiros, o sistema BOCA, por ser o sistema usado na Maratona de Programação, e o beecrowd, que é a ferramenta usada neste trabalho.

2.1.1 BOCA

BOCA14,15 (BOCA Online Contest Administrator) é o sistema utilizado na maratona de programação SBC. O sistema BOCA é uma ferramenta brasileira, de autoria de Cassio Polpo de Campos (Utrecht) que foi o responsável pelos sistemas de 2002 a 2018 (CAMPOS;

FERREIRA, 2004; CAMPOS; FERREIRA; ANIDO, 2010). Na competição de 2020

14 http://www.ime.usp.br/ cassio/boca

15 https://github.com/maratona-linux/maratona-linux

(22)

foi utilizado a distribuição Ubuntu GNU/Linux 20.04 LTS amd64, com os seguintes compiladores:

• . C - gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1 20.04)

• . C++ - gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1 20.04)

• . Python 3 - Python 3.8.5

• . Java - openjdk-11

• . Kotlin - Kotlin version 1.4

O sistema foi desenvolvido em PHP e a interação dos times com o sistema é feita usando-se um navegador (SILVA; CAMPOS, 2021). Para armazenamento dos dados e controle de concorrência foi usado o banco de dados relacional PostgreSQL1, e o servidor de paginas é o Apache2. Quanto à questão de segurança, as transferências de dados são feitas através do protocolo de paginas HTTPS, as demais são feitas entre bancos de dados PostgreSQL, via conexões seguras com autenticação e SSL. Além disso, usa-se um firewall, para bloqueio de conexões indesejadas.

Quanto ao uso, após o login no sistema, o usuário é redirecionado para a página principal do BOCA (Figura 3). A quantidade de balões apresentados depende da configuração feita no servidor para o usuário em questão. Na barra de menu, há as opções: Problems, Runs,Score,Tasks,Backups,OptionseLogout. São apresentadas as telas principais, as três primeiras do menu. Na tela Problems(Figura 4) se encontram todas as questões disponíveis. Para cada questão, há o nome (Name), a cor do balão associado, um aliás básico (Basename), um aliás mais descritivo (Fullname) e o nome do arquivo de código já submetido (Descfile).

Figura 3 – Tela principal do BOCA

Fonte: PETEngComp-UFES (2021)

A tela Runs é apresentada em duas figuras, a Figura 5 apresenta a parte inicial e a Figura 6 a parte final da tela. Na aba Runsse encontram todas as questões já enviados pelo usuário, com a identificação da questão (Problem), bem como a situação de cada envio (Answer), a linguagem do código submetido (Language), o nome do arquivo do código

1 https://www.postgresql.org/

2 https://www.apache.org/

(23)

Figura 4 – Tela “Problems” do BOCA

Fonte: PETEngComp-UFES (2021)

Figura 5 – Tela “Runs” do BOCA

Fonte: PETEngComp-UFES (2021)

Figura 6 – Tela “Runs” do BOCA, para submissão

Fonte: PETEngComp-UFES (2021)

(File) e o tempo que o BOCA executou a bateria de testes com o código enviado (Time).

Na parte final da tela, são apresentados os campos de submissão, em que o usuário deve escolher a questão (o nome da questão, em Problem) , a linguagem (Language) e o código fonte (Source Code). Clicando no botão Send, a solução é enviada ao sistema para avaliação. Na aba Score (Figura 7) é possível ver quais questões foram submetidas

(24)

com o resultado, bem como quantas tentativas foram feitas.

Figura 7 – Tela “Score” do BOCA

Fonte: PETEngComp-UFES (2021)

2.1.2 beecrowd

O sistema beecrowd (anteriormente chamado de URI online judge) é um projeto que foi desenvolvido na URI (Universidade Regional Integrada), Campus de Erechim, que teve início em 2011 (BEZ; FERREIRA; TONIN, 2013; BEZ; TONIN, 2014; BEZ; TONIN;

RODEGHERI, 2014; SELIVON; BEZERRA; TONIN, 2015). Todas as questões são disponibilizadas em português, inglês e espanhol. O sistema apresenta 3 ambientes diferentes: o site principal para acesso pelos estudantes, um ambiente para uso exclusivo para professores e o fórum. Nesta subseção, é descrito o ambiente voltado aos alunos.

No URI é possível visualizar os problemas mesmo não possua uma conta ativa, porém é necessário criar uma conta para submeter os códigos. Pode ser criada conta associada a contas externas, como contas Google, Facebook ou Twitter. A Figura 8 apresenta a tela inicial dosite, na parte superior há opções via botões: LOGIN, REGISTRAR, FÓRUM, CONTESTS, PROBLEMAS, RANKS, PROFESSORES (em vermelho) e CORPORAÇÕES (em azul); na parte inferior central os campos para login; nas laterais da parte inferior,

algumas das opções existentes no menu de botões.

Ao selecionar a opção PROBLEMAS, é apresentada a tela da Figura 9, com 9 categorias:

Iniciante, Ad-hoc, String, Estruturas e Bibliotecas, Matemática, Paradigmas, Grafos, Geometria Computacional e SQL. As opções LISTAR TODOS é para listar todos os problemas independente de qualquer tipo de classificação ou filtro, a opção AUTORES lista os problemas agrupados por seu autor e a opção ORIGENS, apresenta os problemas por competição ou evento em que foi originalmente apresentado. Os problemas das maratonas estão nas categorias de 2 a 8, pois nenhum dos problemas da maratona é classificado como iniciante, dado que são problemas básicos para quem está iniciando na programação. A categoria SQL se trata de problemas que envolvem consulta de banco de dados, e não é uma linguagem incluída na maratona de programação.

(25)

Figura 8 – Tela inicial do beecrowd

Fonte: Retirado de <https://www.beecrowd.com.br/>

Após entrar na categoria, o usuário pode escolher um problema. Como exemplo, selecionamos a categoria Iniciante e escolhemos o problema “Hello World”, a tela da Figura 10 é apresentada. A tela é dividida em duas partes, a parte esquerda contém o enunciado e na parte direita, a parte de submissão de código. No canto superior esquerdo do enunciado podemos ver qual é a categoria do problema, e ao lado qual é o nível do problema. Logo abaixo do título podemos ver o limite de tempo (Timelimit), o número é referente a quantidade de segundos que o código deve passar na bateria de testes. No lado direito podemos escolher qual linguagem será feita a solução, e abaixo nosource codeserá colocado o código a ser submetido. Para submeter o código é só clicar no botão enviar. Note que no campo “Problema” temos o número do problema, que é o identificador do problema no sistema. É através desse número que é possível encontrá-lo através dos buscadores, isso é interessante se a sua conta já tiver um grande número de submissões e você deseja filtrar as submissões de um problema específico.

Feita a submissão do código, é exibida a tela com as informações da submissão (Figura 11).

Ao lado da palava “SUBMISSÃO”, em negrito, temos o identificador da submissão. Logo abaixo, temos o identificador do problema com identificador e nome (PROBLEMA), a

(26)

Figura 9 – Categoria de problemas do beecrowd

Fonte: Retirado de <https://www.beecrowd.com.br/>

Figura 10 – Tela com o enunciado do problema “Hello World”

Fonte: Retirado de <https://www.beecrowd.com.br/>

resposta do judge (RESPOSTA) juntamente com a porcentagem referente a quantidade de testes da bateria de testes em que foi testado, entre parênteses, seguido da linguagem (LINGUAGEM), o tempo que demorou a executar o código (TEMPO), o tamanho do código fonte em bytes (TAMANHO), a quantidade de memória RAM utilizada (MEMÓRIA) e, a data e horário da submissão (SUBMISSÃO). Na parte inferior, é apresentado o código fonte da submissão. Caso queira ajustar o código para um novo envio, basta clicar no botão “EDITAR E ENVIAR” (indicado pela seta vermelha na parte superior à direita da

(27)

tela).

Figura 11 – Tela exemplo com um resultado de submissão

Fonte: Retirado de <https://www.beecrowd.com.br/>

2.2 TRABALHOS CORRELATOS

O trabalho de Piekarski et al. (2015) descreve sobre o relato de uma experiência de um projeto de extensão utilizando a metodologia da maratona de programação, e tem como objetivo geral oferecer oportunidades extracurriculares de treinamento em programação de computadores aos alunos do bacharelado em Ciência da Computação e demais acadêmicos interessados. Sendo eles, estudantes da Universidade Estadual do Centro-Oeste (UNICENTRO), que já tem um histórico de estimular os seus alunos a participarem de maratonas, oferecendo a inscrição e o transporte dos times selecionados.

A metodologia das maratonas de programação possui três características distintas que são aplicadas de forma complementar: cooperativa, competitiva e baseada em problemas.

O aprendizado cooperativo é constituído por técnicas de ensino em que os estudantes trabalham em atividades de aprendizado em pequenos grupos e recebem gratificações e reconhecimento baseado no desempenho do grupo (SLAVIN, 1980). O aprendizado baseado em competição é uma metodologia onde o aprendizado é ativado por meio da competição, mas o resultado do aprendizado é independente do resultado da competição (classificação obtida pelo estudante) (BURGUILLO, 2010). O aprendizado baseado em

(28)

problemas resulta do processo de trabalhar através da compreensão ou resolução de um problema; o ponto de partida para o aprendizado é o problema (ATTLE; BAKER, 2007).

Ainda no trabalho de Piekarski et al. (2015) foi desenvolvido atividades para alcançar o objetivo proposto: encontros ordinários para a discussão e resoluções dos problemas, competições simuladas, seleção dos times para competir na Primeira Fase da Maratona de programação, e preparação dos times selecionadas. As competições simuladas seguem o mesmo modelo das maratonas, utilizando o sistema BOCA. Outra atividade do projeto, para alunos do primeiro semestre da disciplina introdutória de programação de computadores, é a “Gincana de Programação”. Esta atividade propicia uma abordagem diferente para testar o conhecimento dos alunos e estimula a participação futura em outras atividades do projeto.

As atividades do projeto permitiu: despertar nos alunos o interesse pelos problemas das competições de programação, desenvolver/incrementar o conhecimento dos participantes em linguagens de programação e suas bibliotecas, estimular a resoluções problemas computacionais, estimula o trabalho em equipe e incentivar a participação nas Maratonas de Programação.

O trabalho de Brito et al. (2019) propõe uma metodologia de aprendizagem baseada na metodologia de programação competitiva como ferramenta de apoio ao processo de ensino-aprendizagem. Essa metodologia é definida com base nos conceitos de maratona de programação, gamificação e da utilização de uma plataforma online que permita acesso a problemas, submissão de soluções e correção automática das soluções submetidas. Os participantes dessa pesquisa foram alunos dos primeiros períodos do curso de Ciência da Computação que ainda estejam cursando uma das disciplinas de algoritmos ou estruturas de dados que aderiram voluntariamente ao projeto.

As atividades para alcançar o objetivo do trabalho são: aulas expositivas e desafios presenciais, metas e ranking semanais, ranking final e recompensas. Para a avaliar a metodologia de ensino, os dados de 73 alunos foram divididos em dois grupos: experimental e controle. O resultado foi que 60% aderiram ao programa proposto, representando o grupo experimental, e 40% não aderiram ao programam representando o grupo de controle.

Foi utilizado para avaliação: o desempenho nas disciplinas de algoritmos e estruturas de dados, histórico completo das disciplinas cursadas e questionários de opinião.

(29)

3 QUESTÕES DA MARATONA DE PROGRAMAÇÃO

Neste capítulo são apresentados 5 problemas da Maratona de Programação. Para cada problema temos: o enunciado, exemplos de entradas e saídas, limite de tempo permitido, as soluções desenvolvidas, sendo uma solução tendo como resposta TLE e outra comoAccepted.

Em ambas as soluções, segue explicação da(s) técnica(s) de programação utilizada(s).

Todos os problemas foram resolvidos utilizando a linguagem de programação C.

O motivo da escolha destes 5 problemas teve origem pessoal. O aluno participou de 5 maratonas de programação, e cada problema tem um histórico dos desafios experienciado.

Infelizmente, o aluno ao resolver estes problemas, no dia oficial da competição, não obteve resposta Accepted do juiz online. Entretanto, o desafio de resolver estes problemas se manteve, o que gerou um interesse por técnicas avançadas de programação que gerem soluções sem TLE.

Na solução com resposta TLE, serão explorados partes do código para entender como a solução resolve o problema. Na solução com resposta Accepted, será explorado como é possível identificar as técnicas que serão utilizadas e como essas técnicas otimizam a solução, e evitam o TLE. Essas técnicas podem ser estudadas através de livros específicos (HALIM; HALIM, 2013; AREFIN, 2006).

Com as informações das submissões das soluções deste trabalho, é possível ser feita uma análise de processamento e memória, explorando matematicamente como as técnicas de programação utilizadas reduzem a complexidade do algoritmo.

3.1 PROBLEMA DIVISORES

Este problema foi apresentado na Maratona de Programação da SBC 2017, comTimelimit de 1, isto é, deve executar a bateria de testes em 1 segundo. O enunciado foi dado pelo Quadro 1, os exemplos de entrada e saída pelo Figura 12.

No primeiro exemplo, é possível verificar que a saída satisfaz a todas as situações indicadas no enunciado. O número 4 (A) é divisível por 2, 12 (B) não é um divisor de 4, 8 (C) é um múltiplo de 4 e 2 (D) não é múltiplo de 4. E no caso, é o menor múltiplo de 2 em que as condições são satisfeitas. O número 2 não poderia ser solução, pois a última condição seria falsa, de que 2 (D) não é múltiplo de 2. Da mesma forma, para o segundo exemplo de entrada e saída.

(30)

Quadro 1 – Enunciado do problema Divisores.

Pense um número positivo n. Agora me diga um divisorA de n. Agora me dê um outro número B que não seja divisor de n. Agora um múltiplo C. E um não múltiplo D. O número que você pensou é...

Parece um truque de mágica, mas é matemática! Será que, conhecendo os númerosA, B, C e D, você consegue descobrir qual era o número originaln? Note que pode existir mais de uma solução!

Neste problema, dados os valores deA, B, C eD, você deve escrever um programa que determine qual o menor númeron que pode ter sido pensado ou concluir que não existe um valor possível.

Entrada: a entrada consiste de uma única linha que contém quatro números inteiros A, B,C, e D, como descrito acima (1A, B, C, D ≤109).

Saída: seu programa deve produzir uma única linha. Caso exista pelo menos um número n para os quais A, B,C e D façam sentido, a linha deve conter o menor n possível. Caso contrário, a linha deve conter −1.

Fonte: Retirado de <https://www.beecrowd.com.br/>

Figura 12 – Exemplos de entrada e saída do Problema Divisores.

Fonte: Retirado de <https://www.beecrowd.com.br/>

3.1.1 Solução 1

A princípio não é possível encontrar uma fórmula para resolver o problema, então a primeira solução é explorar todas as possibilidades, na força bruta, como no loop da linha 7 do Quadro 2.

O espaço de busca da resposta pode variar de A (um divisor de n) ao valor de C (um mútiplo de n). Para que não faça a verificação dos possíveis números, acrescentando somente de 1 em 1, podemos adicionar de A em A (linha 13), uma vez o número tem que ser divisor de A. Nesta solução, de forma simples, apenas é feita a verificação de qual número atende as regras descritas no enunciado dados os valores de A, B, C e D (linha 8 e linha 9). Caso as condições sejam satisfeitas, imprime-se a variável num (linha 10) e finaliza-se o programa (linha 11). Caso não se encontre o valor, então o valor -1 é apresentado (linha 15).

(31)

Quadro 2 – Solução 1 do problema Divisores.

1 # i n c l u d e < s t d i o . h >

2 int m a i n (int argc , c h a r ** a r g v ) { 3 int A , B , C , D , num ;

4 s c a n f (" % d ␣ % d ␣ % d ␣ % d ", & A , & B , & C , & D ) ; 5

6 num = A ;

7 w h i l e ( num <= C ) {

8 if( num % A == 0 && num % B != 0 &&

9 C % num == 0 && D % num != 0 ) {

10 p r i n t f (" % d \ n ", num ) ;

11 r e t u r n 0;

12 }

13 num += A ;

14 }

15 p r i n t f (" % d \ n ", -1) ; 16 r e t u r n 0;

17 }

Fonte: Elaborado pelo autor (2022).

Quadro 3 – Resposta do URI da solução 1 do problema Divisores.

INFORMAÇOES DA SUBMISSÂO PROBLEMA: 2238 - Divisores RESPOSTA: Time limit exceeded

LINGUAGEM: C (gcc 4.8.5, -O2 -lm) [+0s]

TEMPO: 1.000s

TAMANHO: 329 Bytes MEMÓRIA: -

SUBMISSÃO: 28/07/2021 22:44:37

Fonte: Elaborado pelo autor (2022).

O resultado é apresentado no Quadro 3, em que a resposta foi TLE.

3.1.2 Solução 2

A Solução 2 é apresentada no Quadro 4. A diferença de código entre a Solução e a Solução 2 são as linhas 6 e 7 da Solução 2. Esta diferença significa tratar os casos mais básicos de validação de dados de entrada:

A é igual a B: o valor dado de um divisor de n também não é divisor de n. Como esta possibilidade é impossível, logo, a resposta é -1, e evita-se a avaliação do loop.

C é igual a D: da mesma forma que na questão anterior, é impossível que um número seja múltiplo (C) e não múltiplo (D) ao mesmo tempo.

A é diferente de 0: é impossível a divisão por zero.

(32)

Apenas com a validação de dados de entrada, foi possível evitar o TLE, e o tempo de execução foi de aproximadamente 0 (zero). A estratégia é evitar que os casos, que podem ser validados na entrada como impossíveis de ter um número que satisfaça as condições, não entrem no loop para testar as condições. Se um exemplo de entrada onde A é igual a 1 eC é igual a 109, teremos neste caso de teste 109 iterações, pois como não é um caso que possui um número válido para as condições, será testado todas as possibilidades que são esperadas no loop.

Quadro 4 – Solução 2 do problema Divisores.

1 # i n c l u d e < s t d i o . h >

2 int m a i n (int argc , c h a r ** a r g v ) { 3 int A , B , C , D , num ;

4 s c a n f (" % d ␣ % d ␣ % d ␣ % d ", & A , & B , & C , & D ) ; 5

6 if ( A == B || C == D || C % A != 0)

7 p r i n t f (" % d \ n ", -1) ;

8 e l s e{

9 num = A ;

10 w h i l e ( num <= C ) {

11 if ( num % A == 0 && num % B != 0 &&

12 C % num == 0 && d % num != 0 ) {

13 p r i n t f (" % d \ n ", num ) ;

14 r e t u r n 0;

15 }

16 num += A ;

17 }

18 p r i n t f (" % d \ n ", -1) ;

19 }

20 r e t u r n 0;

21 }

Fonte: Elaborado pelo autor (2022).

Quadro 5 – Resposta do URI da Solução 2 do problema Divisores.

INFORMAÇOES DA SUBMISSÂO PROBLEMA: 2238 - Divisores RESPOSTA: Accepted

LINGUAGEM: C (gcc 4.8.5, -O2 -lm) [+0s]

TEMPO: 0.000s

TAMANHO: 411 Bytes MEMÓRIA: -

SUBMISSÃO: 13/09/2021 15:12:45

Fonte: Elaborado pelo autor (2022).

3.2 PROBLEMA ISÓSCELES

Este problema foi apresentado na Maratona de Programação 2016, com Timelimit de 1, isto é, deve executar a bateria de testes em 1 segundo. O enunciado é apresentado no Quadro 6 e os exemplos de entrada e saída na Figura 13.

(33)

No primeiro exemplo de entrada, temos exatamente as 16 primeiras colunas (das 30) da primeira figura do enunciado. Vemos que a saída de exemplo é a altura 6, isso pode ser justificado com um triangulo isósceles que começa na posição 1 com altura 1 e atinge 6 na posição 6, e termina com a altura 1 na posição 11, e também é possível obter um triângulo isósceles de altura 6 entre as posições 3 e 13. No segundo exemplo de entrada, vemos que não é possível formar um triângulo maior que a altura 1, pois apenas as laterais são maiores do que 1.

Quadro 6 – Enunciado do problema 2243 – Isósceles.

Os irmãos Sérgio e Luiz estavam brincando com cubinhos de madeira e queriam construir um muro, que acabou ficando incompleto, com as colunas tendo diferentes alturas, como nessa figura.

Eles decidiram agora que a brincadeira seria retirar cubinhos, sempre de cima para baixo nas colunas, de maneira que no final restasse apenas um triângulo isósceles de cubinhos.

Eles podem apenas retirar cubinhos do muro, sem recolocar em outra coluna, e os triângulos têm que ser completos. A figura abaixo ilustra os cinco primeiros triângulos isósceles de cubinhos, do tipo que eles querem, com alturas 1, 2, 3, 4 e 5 respectivamente.

Dada a sequência de alturas das colunas do muro, seu programa deve ajudar Sérgio e Luiz a descobrir qual é a altura máxima que o triângulo poderia ter ao final. No muro da primeira figura, com 30 colunas de cubinhos, o triângulo mais alto possível teria altura igual a sete.

Entrada: a primeira linha da entrada contém um inteiroN, 1≤N ≤50000, representando o número de colunas do muro. A segunda linha contém N inteiros Ai, 1≤AiN, para 1≤iN, indicando as alturas de cada coluna.

Saída: seu programa deve produzir uma única linha com um inteiro H, representando a altura máxima que um triângulo poderia ter ao final.

Fonte: Retirado de <https://www.beecrowd.com.br/>

(34)

Figura 13 – Exemplos de entrada e saída do Problema Isósceles.

Fonte: Retirado de <https://www.beecrowd.com.br/>

3.2.1 Solução 1

Um código de solução possível é apresentado no Quadro 7.

Quadro 7 – Solução 1 do problema do Isósceles.

1 # i n c l u d e < s t d i o . h >

2 # i n c l u d e < s t d l i b . h >

3 int m a i n (int argc , c h a r ** a r g v ) {

4 int n , * a , d , i , j , k = 2 , m a i o r = 1;

5 s c a n f (" % d ", & n ) ;

6 a = m a l l o c (s i z e o f(int) * n ) ;

7 for( i = 0; i < n ; i ++) s c a n f (" % d ", & a [ i ]) ; 8

9 for( i = 1; i < n - 1; i ++ , k ++) { 10 if( a [ i ] < k ) k = a [ i ];

11 d = k + 1;

12 w h i l e( - - d > 1) {

13 j = i ;

14 int e = d ;

15 w h i l e(++ j < n && - - e > 1)

16 if ( a [ j ] < e ) b r e a k;

17 if( e == 1 && k > m a i o r && k > i ) m a i o r = k ;

18 }

19 }

20 p r i n t f (" % d \ n ", m a i o r ) ; 21 r e t u r n 0;

22 }

Fonte: Elaborado pelo autor (2022).

O resultado da solução é armazenado pela variável maior, que inicia com 1. As linhas de 5 à 7 processam a entrada de dados. No linha 5 é feita a leitura da variável n, que representa a quantidade de colunas do muro. Na linha 6 é feita a alocação de um vetor de inteiros de nome a, do tamanho de n. Em seguida, na linha 7 é feita a leitura da segunda linha de entrada, preenchendo o vetor a.

Nesta solução, há 3 comandos de repetição aninhados (linha 9, linha 12 e linha 15). Na linha 9, o loop tem como objetivo percorrer cada coluna do muro. No primeiro loop, é importante notar o uso da variávelk, que armazena a maior altura possível do triângulo. A variável é incrementada a cada repetição, inicia com tamanho 1. Porém temos a verificação na linha 10, para verificar se a altura contida na variável k é compatível com a altura da

(35)

coluna. Caso a altura da coluna não seja compatível com o valor da variávelk, a variávelk recebe o valor da altura desta coluna (linha 10), pois é a maior altura possível de triângulo isósceles naquela coluna.

A variável auxiliar d recebe a altura k (linha 11), para validar se é possível fazer a outra metade do triângulo, a metade que desce o muro e é por isso que o seu valor é decrementado em 1 no loop da linha 12. Em cada passo, portanto devemos verificar se as próximas colunas terão altura suficiente para a altura d. O valor de d é armazenado na variável auxiliar e (linha 14), que será testado de acordo com as alturas das próximas colunas através do loop da linha 15. Caso não seja possível formar um triângulo, a repetição é interrompida (linha 16). Na linha 17 é verificado se as condições de formação de um triângulo foram satisfeitas (e com o valor de 1) e se houve alteração no valor do maior triângulo encontrado, assim a variável maioré atualizada.

Quadro 8 – Resposta do URI da solução 1 do problema Isósceles.

INFORMAÇÕES DA SUBMISSÃO PROBLEMA: 2243 - Isósceles RESPOSTA: Time limit exceeded

LINGUAGEM: C (gcc 4.8.5, -O2 -lm) [+0s]

TEMPO: 1.000s

TAMANHO: 511 Bytes MEMÓRIA: -

SUBMISSÃO: 28/07/2021 22:28:26

Fonte: Elaborado pelo autor (2022).

O resultado da execução da Solução 1 é apresentado no Quadro 8, em que se tem o TLE como resposta. Usando a análise rápida, consideramos que a solução apresentada é O(n3), pois a solução possui 3 loops aninhados com proporções similares de iterações. Na linha 12 o valor de dé decrementado até o número 1, edé obtido a partir de kque é incrementado no loop principal a medida que percorre as colunas.

3.2.2 Solução 2

Na Solução 2, a estratégia utilizada para resolver o problema do para não obter TLE, foi fazer uma análise para identificar quais pontos estão causando gargalos, em outras palavras, diminuindo a complexidade do algoritmo. Modificar algum dos loops aninhados para diminuir o número de iterações será vantajoso. A diferença entre a Solução 1 e Solução 2 (Quadro 9) se encontra entre as linhas 12 à 16, principalmente na condição do loop da linha 12. Na Solução 1, sempre é verificado se a parte à direita do triângulo é formado, mas na Solução 2, essa verificação só será feita se d for maior que a maior altura vigente (da variável maior), isso evita que seja feita verificações desnecessárias, uma vez que o objetivo é encontrar o maior triângulo e não verificar se cada posição forma um triângulo.

(36)

Quadro 9 – Solução 2 do problema do Isósceles.

1 # i n c l u d e < s t d i o . h >

2 # i n c l u d e < s t d l i b . h >

3 int m a i n (int argc , c h a r ** a r g v ) {

4 int n , * a , d , i , j , k = 2 , m a i o r = 1;

5 s c a n f (" % d ", & n ) ;

6 a = m a l l o c (s i z e o f(int) * n ) ;

7 for( i = 0; i < n ; i ++) s c a n f (" % d ", & a [ i ]) ; 8

9 for( i = 1; i < n - 1; i ++ , k ++) { 10 if( a [ i ] < k ) k = a [ i ];

11 d = k + 1;

12 w h i l e( - - d > m a i o r ) {

13 j = i ;

14 w h i l e(++ j < n && - - d > 1)

15 if ( a [ j ] < d ) b r e a k;

16 if( d == 1) m a i o r = k ;

17 }

18 }

19 p r i n t f (" % d \ n ", m a i o r ) ; 20 r e t u r n 0;

21 }

Fonte: Elaborado pelo autor (2022).

Quadro 10 – Resposta do URI da Solução 2 do problema Isósceles.

INFORMAÇOES DA SUBMISSÂO PROBLEMA: 2243 - Isósceles RESPOSTA: Accepted

LINGUAGEM: C (gcc 4.8.5, -O2 -lm) [+0s]

TEMPO: 0.088s

TAMANHO: 478 Bytes MEMÓRIA: -

SUBMISSÃO: 13/09/2021 13:29:25

Fonte: Elaborado pelo autor (2022).

O resultado da execução da Solução 2 é apresentado no Quadro 10, em que a resposta foi aceita com um tempo de 0,0088s, menor que o 1s definido no enunciado do problema.

Usando a análise rápida, a solução apresentada é, em média O(n2). Pois apesar de ter 3 loops aninhados como na solução 1, na linha 12 a variável d só decrementará até o valor da variável maior, e outro detalhe sobre a variável dé que ela é decrementada no loop da linha 14, ao contrário da solução 1 onde é utilizado uma variável auxiliar nomeada como e para recebe o valor de d, e d não é decrementado.

3.3 PROBLEMA ESPIRAL

Este problema foi apresentado na Maratona de Programação da SBC 2017, comTimelimit de 1 segundo. O enunciado é apresentado no Quadro 11 e os exemplos de entrada e saída na Figura 14.

(37)

Quadro 11 – Enunciado do problema Espiral.

Dado um tabuleiro de dimensõesN ×N, gostaríamos de colocar feijões, um grão em cada quadrado, seguindo uma espiral como mostrado na figura. Começando do canto superior esquerdo, com coordenadas (1, 1), e depois indo para a direita enquanto possível, depois para baixo enquanto possível, depois para esquerda enquanto possível e depois para cima enquanto possível. Repetimos esse padrão, direita-baixo-esquerda-cima, até que B grãos de feijão sejam colocados no tabuleiro. O problema é: dados N e B, em que coordenadas será colocado o último grão de feijão? Na figura, paraN = 8 e B = 53, o último grão foi colocado no quadrado de coordenadas (4, 6).

Entrada: a entrada contém apenas uma linha com dois inteiros,N eB, onde 1N ≤230 e 1≤BN2 .

Saída: seu programa deve produzir uma única linha com dois inteirosLeC representando as coordenadas do último grão de feijão.

Fonte: Retirado de <https://www.beecrowd.com.br/>

Figura 14 – Exemplos de entrada e saída do Problema Espiral.

Fonte: Retirado de <https://www.beecrowd.com.br/>

No primeiro exemplo de entrada, temos como entrada 8 53, sendo 8 a largura e altura do quadrado, e 53 a quantidade de feijões, que é exatamente o exemplo dado no enunciado.

A soma da quantidade de feijões foi dado por: 8 (primeira linha) +7 (última coluna) +7 (última linha) + 6 (primeira coluna) + 6 (segunda linha) + 5 (penúltima coluna) + 5 (penúltima linha) + 4 (segunda coluna) + 4 (terceira linha) + 1 (que termina a quantidade

de feijões).

(38)

No segundo exemplo de entrada, temos como entrada "1073741824 e 1152921504603393520", note que 1073741824 é o mesmo que 230 e que 1152921504603393520 é o mesmo que 10737418242, que é justamente as maiores entradas permitidas para N e B. Neste exemplo, podemos testar se o algoritmo passará na bateria de testes sem extrapolar o tempo limite.

3.3.1 Solução 1

A Solução 1 á apresentada no Quadro 12. Na Solução 1, usamos a ideia de somar as partes para “percorrer a espiral”. Considerando o exemplo do tabuleiro 8×8 do enunciado, preenchemos com 8 feijões a primeira fileira na parte superior da esquerda para a direita, e com 7 feijões preenche de cima para a baixo, e com mais 7 feijões preenche da esquerda para direita, e por fim temos 6 feijões para preencher de baixo para cima, e com mais 1 feijão chegamos a posição (2, 2). Somando os feijões temos um total de 29, e se fazemos o mesmo mecanismo para chegar a posição (3, 3), temos um total de 49 feijões. Removendo o primeiro feijão conseguimos chegar em um padrão, da posição (1, 1) para a posição (2, 2) adicionamos 28 feijões, e da posição (2, 2) para a posição (3, 3) adicionamos mais 20 feijões.

O valor 28 é o mesmo que 7 multiplicado por 4, e 20 é o mesmo que 5 multiplicado por 4.

Para chegar na posição (4, 4), basta adicionar mais 12 feijões, o que seria 3 multiplicado por 4.

Dessa forma, passar de uma posição (A, A) para (A+1, A+1), é um “pulo”. Para esse mecanismo de pulo temos uma fórmula específica, inicialmente sempre contamos 1 feijão, para a primeira posição. Se quisermos adicionar o primeiro pulo, pegamos o tamanho do tabuleiro N e o primeiro pulo será (N−1)∗4. Para os próximos pulos, a cada pulo subtrai-se N de 2.

No código, as entradas são lidas na linha 5, sendo a variável n representando o tamanho do tabuleiro e a variável b, a quantidade de feijões. O resultado são as variáveis y e x, representando a linha e coluna da posição do último feijão.

Na linha 6, as variáveis passam por um decréscimo de 1, pois o primeiro pulo se dá por N−1 e desconta-se o feijão da posição (1,1). Oloop da linha 8 avalia se é possível se fazer um pulo completo (volta completa), caso seja possível, a quantidade de feijões diminui de 4 vezes o valor de n, n é decrementado de 2 e xé incrementado de 1. Após o loop,y recebe o mesmo valor de x. Passando da posição (x, x) para (x+1, x+1). No exemplo do enunciado, ao final do loop, a variável n com o valor 3 (igual ay) e b com o valor 4 (53-7*4-5*3).

Entre as linhas 15 a 40, é verificado em qual das 4 partes do caminho termina a quantidade de feijões. A primeira condição (linha 15 a 21) verifica se o movimento à direita é completo, se for, então x é incrementado de n e b é decrementado de n. Se não for possível, x recebe a quantidade de feijões que ainda resta, e o resultado é impresso. No exemplo do

Referências

Documentos relacionados

Nessa situação temos claramente a relação de tecnovívio apresentado por Dubatti (2012) operando, visto que nessa experiência ambos os atores tra- çam um diálogo que não se dá

xii) número de alunos matriculados classificados de acordo com a renda per capita familiar. b) encaminhem à Setec/MEC, até o dia 31 de janeiro de cada exercício, para a alimentação de

Atualmente os currículos em ensino de ciências sinalizam que os conteúdos difundidos em sala de aula devem proporcionar ao educando o desenvolvimento de competências e habilidades

Local de realização da avaliação: Centro de Aperfeiçoamento dos Profissionais da Educação - EAPE , endereço : SGAS 907 - Brasília/DF. Estamos à disposição

No entanto, não podemos deixar de comentar, como foi anteriormente abor- dado, que em relação aos Festivais de Viña del Mar e Mérida dos anos 1960, os Encontros ocorridos na

Os candidatos reclassificados deverão cumprir os mesmos procedimentos estabelecidos nos subitens 5.1.1, 5.1.1.1, e 5.1.2 deste Edital, no período de 15 e 16 de junho de 2021,

8- Bruno não percebeu (verbo perceber, no Pretérito Perfeito do Indicativo) o que ela queria (verbo querer, no Pretérito Imperfeito do Indicativo) dizer e, por isso, fez

- Se o estagiário, ou alguém com contacto direto, tiver sintomas sugestivos de infeção respiratória (febre, tosse, expetoração e/ou falta de ar) NÃO DEVE frequentar