<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: André Ulle</title>
    <description>The latest articles on DEV Community by André Ulle (@ulleandre).</description>
    <link>https://dev.to/ulleandre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1164331%2F36e3d390-6731-4cac-bbab-98e501501534.png</url>
      <title>DEV Community: André Ulle</title>
      <link>https://dev.to/ulleandre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ulleandre"/>
    <language>en</language>
    <item>
      <title>Entendendo Algoritmos - Cap.5 Quicksort em Clojure</title>
      <dc:creator>André Ulle</dc:creator>
      <pubDate>Mon, 16 Oct 2023 02:08:36 +0000</pubDate>
      <link>https://dev.to/ulleandre/entendendo-algoritmos-cap5-quicksort-em-clojure-2jl8</link>
      <guid>https://dev.to/ulleandre/entendendo-algoritmos-cap5-quicksort-em-clojure-2jl8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este mês estou participando do clube de leitura #devslendo &lt;a href="https://twitter.com/loremimpsu/status/1707020185515773989"&gt;(Mais informações aqui)&lt;/a&gt; em que o livro escolhido é o &lt;a href="https://www.amazon.com.br/Entendendo-Algoritmos-ilustrado-programadores-curiosos-ebook/dp/B07B61HC3L"&gt;Entendendo Algoritmos&lt;/a&gt;. No capítulo 5, é apresentado o Quicksort. Assim como no outro artigo, não irei explicar o conceito, pois o livro já o faz muito bem. A ideia aqui não é ser mais um resumo, mas sim mostrar como implementar na prática usando Clojure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Quicksort
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;O quicksort é um algoritmo de ordenação. Este algoritmo é muito mais rápido do que a ordenação por seleção e é muito utilizado na prática. por exemplo, a biblioteca-padrão da linguagem C tem uma função chamada qsort, que é uma implementação do quicksort. O algoritmo quicksort também utiliza a estratégia DC (Dividir e Conquistar). &lt;br&gt;
Aditya Y. Bhargava&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Além do livro, sugiro também esse &lt;a href="https://www.youtube.com/watch?v=wx5juM9bbFo"&gt;vídeo&lt;/a&gt; para quem gostaria de entender mais sobre o quicksort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando Quicksort com clojure
&lt;/h2&gt;

&lt;p&gt;Vou dar uma breve introdução sobre o que é o quicksort. Basicamente, temos um vetor, e para ordená-lo, escolheremos um pivô. O pivô servirá de base para nossa comparação. Após a primeira iteração com esse vetor, teremos todos os valores menores que o pivô ao lado esquerdo e todos os maiores ou iguais ao lado direito. Para isso, dado o seguinte vetor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[3 4 5 2 1 6 7 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos escolher o primeiro elemento como nosso pivô. Seguindo a regra acima, teríamos o seguinte resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;esquerda [2 1]
pivô 3
direita [4 5 6 7 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"E repetiremos a execução para cada subgrupo, selecionando um novo pivô nesse subgrupo (esquerda e direita). Sei que essa explicação é bem breve e sucinta, por isso recomendo esse &lt;a href="https://www.youtube.com/watch?v=wx5juM9bbFo"&gt;vídeo&lt;/a&gt; para que você entenda bem o conceito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quicksort no Clojure
&lt;/h2&gt;

&lt;p&gt;O Clojure é uma linguagem funcional que tem como um de seus princípios a imutabilidade, isso significa que um valor não sofre alterações ao longo da execução. Isso garante a confiabilidade nos dados e evita side-effects inesperados. Temos que levar isso em conta ao implementar o algoritmo de Quicksort.&lt;br&gt;
Iremos utilizar a recursividade, para trabalhar os subgrupos, até que todo o vetor esteja devidamente ordenado. Irei explicar cada passo da função.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Função
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(ns entendendo-algoritmos-clojure.recursion.quicksort)

(defn execute
  [values]
  (let [pivot (last values)
        remaining-values (butlast values)
        left (filter #(&amp;lt; % pivot) remaining-values)
        right (filter #(&amp;gt;= % pivot) remaining-values)]
    (flatten (concat (if (&amp;gt; (count left) 1) (execute left) left)
                     [pivot]
                     (if (&amp;gt; (count right) 1) (execute right) right)))))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Caso queira testar a função acima, basta acessar o &lt;a href="https://replit.com/"&gt;replit.com&lt;/a&gt;, criar um novo repl do tipo Clojure, colar a função acima e, logo na linha debaixo, adicionar uma chamada como por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(execute [4 5 2 3 7 8 1])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado deverá ser o vetor ordenado &lt;code&gt;[1 2 3 4 5 7 8]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;O nome da função é execute, pois o namespace já contem o contexto de quicksort: &lt;code&gt;(ns entendendo-algoritmos-clojure.recursion.quicksort)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo a função
&lt;/h2&gt;

&lt;p&gt;A primeira coisa sobre nossa função é que recebemos o parâmetro &lt;code&gt;values&lt;/code&gt;, que irá representar nosso vetor na função. Logo em seguida, temos a seção &lt;code&gt;(let [])&lt;/code&gt; onde definimos alguns símbolos para organizar nosso código. O &lt;code&gt;let&lt;/code&gt; funciona da seguinte forma, dentro de colchetes temos nossos símbolos, seguindo a seguinte lógica:"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(let [simbolo valor
      simbolo-2 valor-2])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde simbolo passa a representar o valor que está logo a sua direita, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(let [filme "O auto da compadecia"])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para utilizar os símbolos, precisamos estar dentro do escopo do &lt;code&gt;let&lt;/code&gt;, portanto, antes de fechar seu parênteses. Entenda por símbolo o que, em outras linguagens, chamamos de propriedade, variável ou &lt;strong&gt;constante&lt;/strong&gt;, o que nesse caso faz mais sentido, uma vez que seu valor nunca muda. Nesse caso, se quisermos imprimir o valor, faríamos da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(let [filme "O alto da compadecia"]
(print filme))
; Imprime no console: O auto da compadecia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note que antes de fechar o parênteses do &lt;code&gt;let&lt;/code&gt;, chamamos a instrução &lt;code&gt;(println simbolo)&lt;/code&gt;. Isso acontece porque os símbolos criados no let só existem dentro do seu escopo.&lt;/p&gt;

&lt;p&gt;Ok, agora que você entende um pouco mais sobre o escopo e como o let funciona para criar nossos símbolos locais. Vamos entender o que cada símbolo representa.&lt;br&gt;
Começando pelo nosso &lt;code&gt;pivot&lt;/code&gt;. Iremos utilizar a função &lt;code&gt;last&lt;/code&gt; que retorna o último item do nosso array. Ele seria o equivalente a &lt;code&gt;values[values.length - 1]&lt;/code&gt;, como é visto na maioria das linguagens.&lt;/p&gt;

&lt;p&gt;Em seguida, para não repetirmos o próprio item na lista, iremos criar uma nova lista, descartando o pivot, para isso, utilizaremos a função &lt;code&gt;butlast&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para o símbolo &lt;code&gt;left&lt;/code&gt;, filtramos a lista com os valores menores que o &lt;code&gt;pivot&lt;/code&gt;, e em &lt;code&gt;right&lt;/code&gt; os valores maiores ou iguais ao &lt;code&gt;pivot&lt;/code&gt;, utilizando a função &lt;code&gt;filter&lt;/code&gt;, que possui dois parâmetros: o predicado e uma lista. O predicado é simplesmente uma condição para filtrar nossa lista, trazendo apenas os itens desejados. No caso de &lt;code&gt;left&lt;/code&gt;, queremos todos os itens menores que o &lt;code&gt;pivot&lt;/code&gt;, então usamos &lt;code&gt;(&amp;lt; % pivot)&lt;/code&gt;, onde &lt;code&gt;%&lt;/code&gt; representa cada um dos elementos de &lt;code&gt;values&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(filter #(&amp;lt; % pivot) remaining-values)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OBS: No Clojure, sempre começamos a comparação com o operador, então em vez de &lt;code&gt;% &amp;lt; pivot&lt;/code&gt;, escrevemos &lt;code&gt;&amp;lt; % pivot&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Caso base
&lt;/h2&gt;

&lt;p&gt;Se não sabe o que é um caso base na recursividade sugiro a leitura desse &lt;a href="https://carlacastanho.github.io/Material-de-APC/aulas/aula14.html"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O nosso caso base acontece quando o vetor (left ou right) possui apenas um elemento, nesse caso ao invés de chamarmos a função recursivamente, iremos apenas retornar o próprio vetor.&lt;br&gt;
&lt;code&gt;(if (&amp;gt; (count right) 1) (execute right) right)&lt;/code&gt;&lt;br&gt;
Se você não está acostumado com a sintaxe Clojure, saiba que o &lt;code&gt;if&lt;/code&gt; também é uma função e, nesse caso, ela espera três parâmetros:&lt;br&gt;
&lt;code&gt;(if predicate value-when-true value-when-false)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Então, para a nossa função, se o número de itens for maior que um, ela irá chamar novamente a função &lt;code&gt;execute&lt;/code&gt; para aquele &lt;strong&gt;subvetor&lt;/strong&gt;, caso contrário, retornará o próprio subvetor. Note que fizemos o mesmo para &lt;em&gt;left&lt;/em&gt; e &lt;em&gt;right&lt;/em&gt;, então seguem o mesmo princípio.&lt;/p&gt;

&lt;p&gt;Nesse momento vamos então concatenar &lt;code&gt;left + [pivot] + right&lt;/code&gt;. Então, uma certeza que temos é que nossa função sempre terá um pivô no meio da concatenação, e consequentemente, tudo que está à esquerda é menor que ele e tudo à direita é maior.&lt;/p&gt;

&lt;p&gt;Simplificando o &lt;code&gt;concat&lt;/code&gt; sem o if teriamos a seguinte concatenação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(concat left [pivot] right)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Substituindo os símbolos por valores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(concat [3 2 1] [4] [5 6 8 7])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso tem como resultado:&lt;br&gt;
&lt;code&gt;[3 2 1 4 5 6 8 7]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;E por fim, como a recursão poderá retornar listas dentro de listas, temos o &lt;code&gt;flaten&lt;/code&gt; que faz o achatamento dos dados.&lt;br&gt;
Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(flaten [2 [2 3 [4]] [5 6] 8])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retorna o dado achatado:&lt;br&gt;
&lt;code&gt;[2 2 3 4 5 6 8]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como a função se resolve
&lt;/h2&gt;

&lt;p&gt;Na imagem a seguir, ilustrei o que acontece em cada iteração da função execute e como os blocos da concatenação são organizados naquele momento. Portanto, sempre teremos três blocos na seguinte sequência: &lt;code&gt;left, pivot e right&lt;/code&gt;.&lt;br&gt;
O item que será o nosso pivô naquela interação está destacado em vermelho.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wctCo3eI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/as1h5ca3a2bns64w0nda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wctCo3eI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/as1h5ca3a2bns64w0nda.png" alt="Image description" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ficamos por aqui
&lt;/h2&gt;

&lt;p&gt;Espero que o exemplo tenha te ajudado a visualizar o quicksort na prática dentro do paradigma funcional.&lt;/p&gt;

&lt;p&gt;Agradeço a todos que chegaram até aqui e peço, por favor, que me ajudem com seu feedback. Comentem se os exemplos foram claros ou se sentiram falta de algum ponto que não abordei. Ficarei feliz em ajudá-los!&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>quicksort</category>
      <category>algorithms</category>
      <category>lisp</category>
    </item>
    <item>
      <title>Entendendo Algoritmos - CAP 2. Como usar arrays e listas encadeadas na prática</title>
      <dc:creator>André Ulle</dc:creator>
      <pubDate>Tue, 10 Oct 2023 01:23:17 +0000</pubDate>
      <link>https://dev.to/ulleandre/entendendo-algoritmos-cap-2-como-usar-arrays-e-listas-encadeadas-na-pratica-2n94</link>
      <guid>https://dev.to/ulleandre/entendendo-algoritmos-cap-2-como-usar-arrays-e-listas-encadeadas-na-pratica-2n94</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este mês estou participando do clube de leitura #devslendo &lt;a href="https://twitter.com/loremimpsu/status/1707020185515773989"&gt;(Mais informações aqui)&lt;/a&gt; em que o livro escolhido é o &lt;a href="https://www.amazon.com.br/Entendendo-Algoritmos-ilustrado-programadores-curiosos-ebook/dp/B07B61HC3L"&gt;Entendendo Algoritmos&lt;/a&gt;. No capítulo 2, são apresentados o array e a lista encadeada. O capítulo por si só é muito claro e direto. O objetivo deste post é trazer exemplos de implementações práticas em diferentes linguagens.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para testar os exemplos aqui apresentados você pode utilizar o site &lt;a href="https://replit.com/"&gt;replit&lt;/a&gt;. Basta criar um novo REPL selecionando a linguagem desejada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um pouquinho sobre Array
&lt;/h2&gt;

&lt;p&gt;Não tenho a intenção de falar muito sobre o &lt;code&gt;array&lt;/code&gt;. Acredito que ele seja mais familiar para a maioria das pessoas, e a implementação é introduzida nos primeiros passos de várias linguagens. No entanto, se é novidade para você, aqui vai um exemplo de array em C:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include&amp;lt;stdio.h&amp;gt;
#include&amp;lt;conio.h&amp;gt;
int main(void)
{
  float notas[5] = {7, 8, 9.5, 9.9, 5.2};
  // declarando e inicializando o vetor notas

  printf("Exibindo os Valores do Vetor \n\n");
  printf("notas[0] = %.1f\n", notas[0]); // imprime 7
  printf("notas[1] = %.1f\n", notas[1]); // imprime 8
  printf("notas[2] = %.1f\n", notas[2]); // imprime 9.5
  printf("notas[3] = %.1f\n", notas[3]); // imprime 9.9
  printf("notas[4] = %.1f\n", notas[4]); // imprime 5.2

  getch();
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos pensar no vetor (também conhecido como array) como uma variável com páginas, onde sempre começamos da página 0 e podemos ir até o número de páginas que determinamos quando o declaramos. Essa é uma restrição importante sobre o array; na maioria das linguagens, você precisa definir o tamanho dele assim que o declara. No caso acima, se tentássemos atribuir ou imprimir um valor para a posição 5, que corresponderia à sexta nota, receberíamos uma exceção de índice fora dos limites do vetor, pois nesse caso o limite é a posição 4. Essa exceção em inglês é comumente traduzida como: &lt;code&gt;index out of bounds exception&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listas Encadeadas
&lt;/h2&gt;

&lt;p&gt;Vou tentar ser o mais sucinto possível, sem deixar de abordar detalhes importantes para que possamos compreender a implementação das listas encadeadas em cada um dos exemplos. &lt;/p&gt;

&lt;p&gt;Em todos os exemplos utilizarei o mesmo conceito de caixas, onde, ao abrirmos essa caixa, iremos validar se existe uma chave através do atributo &lt;code&gt;temChave&lt;/code&gt;. Enquanto não encontramos, continuaremos abrindo as próximas caixas, ou, até não houver mais caixas.&lt;/p&gt;

&lt;p&gt;Decidi escrever o nome das variáveis e os comentários em português para que os exemplos fossem mais acessíveis. Além disso, utilizei um laço de repetição para não dar &lt;em&gt;spoilers&lt;/em&gt; sobre o Capítulo 3 do livro, que trata de recursividade.&lt;/p&gt;

&lt;p&gt;Começando pelo exemplo que acredito ser o mais simples, utilizando POO, através de uma Classe que possui a si mesma como um dos tipos de atributo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo em POO utilizando JAVA
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Estrutura das caixas
class Caixa {
  boolean temChave;
  Caixa proximaCaixa;
}

class Main {
  public static void main(String[] args) {
    //Criando as Caixas
    Caixa primeiraCaixa = new Caixa();
    primeiraCaixa.temChave = false;
    Caixa segundaCaixa = new Caixa();
    segundaCaixa.temChave = false;
    Caixa terceiraCaixa = new Caixa();
    terceiraCaixa.temChave = true;
    Caixa quartaCaixa = new Caixa();
    quartaCaixa.temChave = false;

    // Criando lista encadeada
    primeiraCaixa.proximaCaixa = segundaCaixa;
    segundaCaixa.proximaCaixa = terceiraCaixa;
    terceiraCaixa.proximaCaixa = quartaCaixa;

    Caixa caixaAberta = primeiraCaixa;

    //inicializamos com 1 porque começamos com a primeira caixa aberta
    int contador = 1;

    // Abrindo as caixas enquanto houver não encontrar a chave, ou até acabarem as caixas
    while(!caixaAberta.temChave &amp;amp;&amp;amp; caixaAberta != null){
      contador++; // contador = contador + 1;
      caixaAberta = caixaAberta.proximaCaixa;
    }

    System.out.println(contador);
  } 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O retorno do código acima será 3, porque mesmo que exista uma caixa dentro da terceira, ela tem a chave, portanto, cumpre a nossa condição.&lt;/p&gt;

&lt;p&gt;A magia acontece no trecho &lt;code&gt;caixaAberta = caixaAberta.proximaCaixa;&lt;/code&gt;. Onde a caixaAberta passa a ser a próxima caixa, que por sua vez, possui uma próxima caixa, e por aí vai.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo em POO utilizando Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Caixa:
    def __init__(self, tem_chave, proxima_caixa=None):
        self.tem_chave = tem_chave
        self.proxima_caixa = proxima_caixa

# Criando as Caixas
primeira_caixa = Caixa(False)
segunda_caixa = Caixa(False)
terceira_caixa = Caixa(True)
quarta_caixa = Caixa(True)

# Criando lista encadeada
primeira_caixa.proxima_caixa = segunda_caixa
segunda_caixa.proxima_caixa = terceira_caixa
terceira_caixa.proxima_caixa = quarta_caixa

caixa_aberta = primeira_caixa

# Inicializamos com 1 porque começamos com a primeira caixa aberta
contador = 1

# Abrindo as caixas enquanto houver não encontrar a chave, ou até acabarem as caixas
while caixa_aberta is not None and not caixa_aberta.tem_chave:
    contador += 1
    caixa_aberta = caixa_aberta.proxima_caixa

print(contador)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O exemplo é muito parecido, mudando levemente a sintaxe utilizada. Nesse momento, vamos apenas contemplar a diferença na limpeza e elegância do Python sem &lt;code&gt;{}();&lt;/code&gt;. Eu gosto hihi&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo em Programação Estruturada utilizando C
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;

// Definição da estrutura Caixa
typedef struct Caixa {
    bool temChave;
    struct Caixa* proximaCaixa;
} Caixa;

int main() {
    // Criando as Caixas
    Caixa caixas[4];
    //Inicializando cada caixa com a referência da próxima "&amp;amp; "
    caixas[0] = (Caixa){false, &amp;amp;caixas[1]};
    caixas[1] = (Caixa){false, &amp;amp;caixas[2]};
    caixas[2] = (Caixa){true, &amp;amp;caixas[3]};
    caixas[3] = (Caixa){true, NULL};

    Caixa* caixaAberta = &amp;amp;caixas[0];

    // Inicializamos com 1 porque começamos com a primeira caixa aberta
    int contador = 1;

    // Abrindo as caixas enquanto houver não encontrar a chave, ou até acabarem as caixas
    while (caixaAberta != NULL &amp;amp;&amp;amp; !caixaAberta-&amp;gt;temChave) {
        contador++; 
        caixaAberta = caixaAberta-&amp;gt;proximaCaixa;
    }

    printf("%d\n", contador);

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;Deixei o exemplo ligeiramente diferente. Note que dessa vez estou utilizando uma &lt;code&gt;struct&lt;/code&gt; em C no lugar da classe, e as Caixas são representadas por um vetor de 4 posições. Ao contrário do que fiz no Java, inicializo as caixas já com a referência da próxima. Isso é possível porque utilizamos ponteiros e guardamos o endereço de memória daquela variável ao invés do valor. Para não me estender muito nesse universo, irei deixar esse &lt;a href="https://www.ime.usp.br/~pf/algoritmos/aulas/pont.html"&gt;link&lt;/a&gt;, para que você possa conhecer mais sobre ponteiros.&lt;br&gt;
O Vetor nesse caso é apenas para simplificar os nomes das caixas, ao invés de primeiraCaixa, segundaCaixa e etc, utilizei um vetor com caixa[1], caixa[2], caixa[n]...&lt;br&gt;
Apesar disso, continuo usando a referência dentro de cada caixa, para chegar na caixa seguinte, através do &lt;code&gt;caixaAberta = caixaAberta-&amp;gt;proximaCaixa;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Porém o resultado permanece 3, pois a execução é a mesma da anterior.&lt;/p&gt;
&lt;h2&gt;
  
  
  Exemplo em Programação Funcional utilizando Clojure
&lt;/h2&gt;

&lt;p&gt;Deixei o meu preferido para o final. Não se assuste e nem se frustre por não entender esse código logo de cara.&lt;br&gt;
Existem várias particularidades no dialeto LISP, que são diferentes das linguagens baseadas em C, como C#, Java, JavaScript e até mesmo Python.&lt;br&gt;
Você também estranhará o uso de hífen, ponto de interrogação e dois pontos, mas isso é comum nas convenções do Clojure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; criando um mapa chave e valor para cada caixa
(def quarta-caixa {:tem-chave? false
                  :proxima-caixa nil});

(def terceira-caixa {:tem-chave? true
                  :proxima-caixa quarta-caixa});

(def segunda-caixa {:tem-chave? false
                  :proxima-caixa terceira-caixa});

(def primeira-caixa {:tem-chave? false
                    :proxima-caixa segunda-caixa});

; função que abre as caixas
(defn abrir-caixa 
  [caixa contador]
  ; Se tem chave imprime o contador, senão abre a próxima caixa e incrementa 1 ao contador
  (if (:tem-chave? caixa)
    (print contador)
    (recur (:proxima-caixa caixa) (inc contador))))

; incializa a operação pela primeira caixa
(abrir-caixa primeira-caixa 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse exemplo não tive como fugir da recursividade, uma vez que o Clojure é principalmente baseado em funções.&lt;/p&gt;

&lt;p&gt;Clojure é uma linguagem interpretada que executa suas aplicações com base na JVM (máquina virtual Java). Portanto, não podemos utilizar um símbolo que ainda não foi criado. Por isso, comecei pelas caixas internas para referenciá-las na caixa anterior.&lt;br&gt;
Sim, os comentários de uma linha utilizam o caractere &lt;code&gt;;&lt;/code&gt; hihi.&lt;/p&gt;

&lt;p&gt;Mesmo não entendendo completamente, nada te impede de abrir o &lt;a href="https://replit.com/"&gt;replit&lt;/a&gt; e fazer alterações no código acima para ver o que acontece hihi&lt;/p&gt;

&lt;h2&gt;
  
  
  Ficamos por aqui
&lt;/h2&gt;

&lt;p&gt;Espero que os exemplos possam ter te ajudado a visualizar um pouco as listas na prática. Apesar dos exemplos em C e Clojure, acredito que compreender bem o primeiro exemplo em Java ou Python já é mais do que suficiente para entender como as listas encadeadas funcionam e como manipulá-las.&lt;/p&gt;

&lt;p&gt;Agradeço a todos que chegaram até aqui e peço, por favor, que me ajudem com seu feedback. Comentem se os exemplos foram claros ou se sentiram falta de algum ponto que não abordei. Ficarei feliz em ajudá-los!&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>java</category>
      <category>python</category>
      <category>clojure</category>
    </item>
    <item>
      <title>Software design - Você entendeu o problema?</title>
      <dc:creator>André Ulle</dc:creator>
      <pubDate>Thu, 05 Oct 2023 17:18:23 +0000</pubDate>
      <link>https://dev.to/ulleandre/voce-entendeu-o-problema-j09</link>
      <guid>https://dev.to/ulleandre/voce-entendeu-o-problema-j09</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Esse é o primeiro artigo que escrevo sobre Discovery Técnico e minha ideia é abordar todas as etapas de forma detalhada e com exemplos práticos. Começaremos desde o entendimento inicial do problema até os entregáveis de arquitetura.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Acredito que, para a grande maioria das pessoas, quando começamos a ter contato com uma nova requisição, seja para a manutenção de algo ou para a implementação de algo novo, começamos simultaneamente a escrever mentalmente o código e o design da solução para aquele problema que ainda estamos conhecendo. Isso é natural, queremos resolver, e queremos resolver rapidamente, pois o backlog está suspirando em nosso cangote, e o prazo apertado ativa esse nosso instinto de sobrevivência, onde resolver logo é o melhor caminho. Porém, esse estado de alerta pode ser traiçoeiro, e você pode se fechar para entender o problema de fato. No meio do caminho, você pode ter o viés de uma solução pronta em sua cabeça. Conforme o problema vai tornando a sua solução inviável, existe o risco de você se apegar tanto a ela, e se deixar levar pela frustração. No pior dos casos, você pode manter a solução que veio precocemente, recorrendo a adaptações ou até abrindo mão de alguma regra ou outra, pois o foco aqui já não está mais no problema, ele se perdeu. Esqueça o código por enquanto; no primeiro momento, não existe algoritmo, não existe linguagem. Seu foco deve ser principalmente entender o problema e, para isso, o separaremos em dois pontos: dados e regras.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dados e Regras
&lt;/h2&gt;

&lt;p&gt;Eu desenvolvi essa forma de organizar as coisas na minha mente, e se por acaso a adotei de algum lugar, juro que foi de forma inconsciente hehe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dados
&lt;/h3&gt;

&lt;p&gt;Vamos lá. Primeiro, falando sobre os Dados, eu os vejo como a matéria-prima que teremos que manipular. Neste momento, é importante compreender a natureza do dado (Oxi?), ou seja, o que quero dizer é que precisamos primeiro entender quais são os dados que serão inseridos na nossa aplicação, o que são, de onde vêm, do que se alimentam e como sobrevivem. O Dado pode ser mais livre e flexível, como uma String, ou pode seguir um padrão mais rígido, como uma lista enumerada com itens específicos.&lt;/p&gt;

&lt;p&gt;Neste estágio inicial, gosto de criar um dicionário de dados, onde os organizo por tipo e pela semântica que possuem, além de verificar se são obrigatórios ou se têm algum tipo de restrição, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;------  Pedido de Reparo ---------
|   Descrição.       |     Tipo.             |   Exemplo.   |   
| Relato             |   Texto               | "PC morreu"  |  
| Severidade         |   Inteiro             | 5            | 
| Status             |   Lista de Status     | "Cancelado"  | 
| Valor              |   Decimal             | 2,000.00     | 
| Data de Criação    |   Date                | 1993-08-26.  |
| Categoria          |   Lista de Categorias | "Informática"|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que estamos utilizando tipos primitivos para &lt;code&gt;Relato&lt;/code&gt;, &lt;code&gt;Severidade&lt;/code&gt;, &lt;code&gt;Valor&lt;/code&gt; e &lt;code&gt;Data de Criação&lt;/code&gt;. No entanto, para &lt;code&gt;Categoria&lt;/code&gt; e &lt;code&gt;Status&lt;/code&gt;, utilizaremos uma lista. Isso já me implica na necessidade de levantar as possibilidades dessa lista. Neste momento, vou apresentar apenas o exemplo para a categoria. Seguiríamos a mesma lógica para Status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;------ Categorias -----
|   Descrição    |     Tipo     |   Exemplo  
| Nome           |   Texto      | Informática 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;------ Categorias Existentes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Informática
- Escritório
- Eletrodomésticos
- Outros
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Entender os dados te guiará para compreender o domínio de negócio. Saber como esses dados estão interconectados proporcionará uma noção inicial de como organizar esses domínios na sua abstração. Os dados vão nos guiar aos domínios de negócio, e estes, por sua vez, vão influenciar a arquitetura e o design. Portanto seja mais que um amigo, seja &lt;em&gt;friend&lt;/em&gt; dos dados e os conheça bem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Regras
&lt;/h3&gt;

&lt;p&gt;Legal. Agora que tenho os dados organizados e uma compreensão inicial de como estão estruturados, é crucial aprender como esses dados se transformarão em regras. É neste momento que o dado ganha vida, quando eu oriento os fluxos dentro do sistema e capacito o sistema para a tomada de decisão. Escrever regras claras e precisas ajudará a eliminar possíveis ruídos de comunicação entre mim e a pessoa que fez a requisição (PM/PO/SM/BA e tantas outras siglas que representam nossos demandantes).&lt;/p&gt;

&lt;p&gt;Mas como poderei avaliar se a minha regra está bem escrita? Evite descrever regras abstratas ou que exijam conhecimento prévio do negócio. Por exemplo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1 - Cancelar casos antigos&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O que define se um caso é antigo? Como posso tomar essa decisão com base nos dados disponíveis? &lt;br&gt;
Que tal a seguinte regra:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1 - Quando a data de criação do chamado for superior a dois dias da data atual, alterar o status do report para "Cancelado"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A regra proposta parece bem clara e precisa. Ela estabelece que, se a data de criação do chamado for superior a dois dias em relação à data atual, o status do Chamado deve ser alterado para "Cancelado". Isso proporciona uma orientação direta e mensurável para a ação a ser tomada.&lt;/p&gt;

&lt;p&gt;Outro ponto importante é saber qual é o gatilho do fluxo em que implementaremos a regra. Em que momento na linha do tempo do nosso sistema isso vai acontecer? Deixar a regra solta, por mais bem escrita que esteja, não é suficiente. É necessário investigar as expectativas em relação a isso, talvez o stakeholder ainda não saiba que uma rotina precisa ser implementada. Nesse caso, poderíamos atualizar a regra:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ponto de disparo: Execução de rotina de revisão dos chamados&lt;br&gt;
&lt;strong&gt;Dado&lt;/strong&gt; que existam chamados cadastrados&lt;br&gt;
1 - &lt;strong&gt;Quando&lt;/strong&gt; a data de criação do chamado for superior a dois dias da data atual, &lt;strong&gt;então&lt;/strong&gt; alterar o status do report para "Cancelado"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inseri um &lt;a href="https://cucumber.io/docs/gherkin/reference/"&gt;Gherkin&lt;/a&gt; subliminar na regra acima. No entanto, o que é crucial aqui é deixarmos claro o evento que irá disparar nossa regra. É quando esse dado deixa o seu ninho confortável no disco rígido para ser arranhado pelas garras das nossas regras. Posteriormente, podemos entrar em detalhes técnicos, como se essa rotina é um Job no CTRL-M (Socorro DEUS), uma Lambda na AWS, um cronjob, entre outras opções. Neste momento, o essencial é que você vai tornar evidente para todos que as coisas não acontecem magicamente, e ninguém irá te reportar um BUG dizendo que o status não foi atualizado às 6 horas da manhã, quando na verdade essa rotina é executada às 7.&lt;/p&gt;

&lt;p&gt;Menos importante do que decidir se utilizaremos um loop FOR, um operador ternário ou cinquenta estruturas IF aninhadas que se amontoam num monte horrendo fedendo à manutenção e à complexidade, é garantir, neste momento, que o comportamento esperado esteja baseado nos dados corretos e nos momentos certos.&lt;/p&gt;

&lt;p&gt;Em resumo, uma boa regra possui clareza quanto aos dados de entrada, quando ela deve acontecer, o comportamento desejado e quais dados ele influencia na saída.&lt;/p&gt;

&lt;p&gt;Depois de tudo, retornamos à reflexão "Entendi o Problema?". Talvez, ao longo dessa jornada, você perceba que o problema não está claro, nem mesmo para os Stakeholders. Isso será útil para eliminar os ruídos de comunicação ou para elucidar detalhes importantes de negócio que estão subentendidos por alguma pessoa ou área. Também te ajudará a antecipar possíveis blocks relacionados a falta de insumos de negócio.&lt;/p&gt;

&lt;p&gt;A próxima pergunta é: "Apenas você entendeu o problema?"&lt;/p&gt;

&lt;p&gt;Mas isso fica para uma próxima leitura. Agradeço a quem chegou até aqui e peço que, por favor, me ajude com seu feedback. Isso me permitirá saber se conteúdos como este podem auxiliar as pessoas nessa aventura que é o Desenvolvimento e a Arquitetura de Software.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>discovery</category>
      <category>softwareengineering</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
