7 problemas clássicos de lógica resolvidos em Go
golang

7 problemas clássicos de lógica resolvidos em Go

Fala, dev! Pronto para embarcar em mais uma jornada pela programação? Hoje vamos explorar juntos problemas clássicos de lógica e como solucioná-los com Golang (Go). Go é uma linguagem poderosa, eficiente e perfeita para sistemas que exigem alta performance. Além disso, é muito divertida para praticar e aprimorar suas habilidades de lógica!
Então, se ajeite na cadeira, pegue o café e bora para mais uma missão!

Por que a lógica é tão importante?

A lógica de programação é como o motor por trás do código. Ela não apenas te ajuda a resolver problemas, mas também permite que você pense de forma estruturada e eficiente. E adivinha? A prática com problemas clássicos é uma das melhores formas de melhorar suas habilidades!
Golang é uma linguagem que se destaca por sua simplicidade e eficiência, sendo perfeita para quem quer aprender e aplicar conceitos de forma clara e direta. Vamos começar com conceitos essenciais de Go, que você usará para resolver nossos desafios.
🚀
Quer entender mais sobre as vantagens de programar em Go? Dê o play no vídeo abaixo e descubra por que essa linguagem tem se tornado uma das queridinhas do mercado:
Video preview

Conceitos essenciais em Go

Antes de mergulharmos nos problemas, vale revisar alguns pilares da linguagem que facilitarão sua jornada:
  • Controle de fluxo: if/else, switch, for.
  • Estruturas de dados: arrays, slices e maps.
  • Funções: como definir e usar funções, incluindo as anônimas.
  • Concorrência: Goroutines para tarefas simultâneas.
Esses conceitos são como ferramentas que você usará para montar as soluções dos problemas. Agora, vamos começar com exemplos práticos para aquecer os motores!
Quer entender um pouco mais sobre essa linguagem poderosa e explorar cada um desses conceitos com mais profundidade? Confira alguns artigos que preparamos especialmente para você:

Problemas clássicos de lógica e suas soluções

1. Calculadora básica

Começando pelo básico, uma calculadora é um ótimo ponto de partida para quem está começando a codar. Vamos implementar as operações básicas: soma, subtração, multiplicação e divisão.
package main import ( "fmt" ) func main() { var num1, num2 float64 var operador string fmt.Print("Digite o primeiro número: ") fmt.Scanln(&num1) fmt.Print("Digite o operador (+, -, *, /): ") fmt.Scanln(&operador) fmt.Print("Digite o segundo número: ") fmt.Scanln(&num2) var resultado float64 switch operador { case "+": resultado = num1 + num2 case "-": resultado = num1 - num2 case "*": resultado = num1 * num2 case "/": resultado = num1 / num2 default: fmt.Println("Operador inválido!") return } fmt.Printf("Resultado: %.2f\n", resultado) }
Esse código é simples e direto. Começamos pedindo ao usuário para digitar dois números e um operador matemático (+, -, *, /). Utilizamos fmt.Scanln para capturar as entradas do usuário. Em seguida, usamos um switch para determinar qual operação deve ser realizada com base no operador fornecido. Por fim, calculamos o resultado e o exibimos formatado com duas casas decimais. Essa implementação é uma ótima forma de praticar entradas do usuário e controle de fluxo em Go.
Teste agora este código diretamente no OneCompiler e explore como ele funciona! Você pode modificar os valores e operadores no próprio código para ver diferentes resultados. Clique aqui!

2. Fatorial de um número

O cálculo do fatorial é um clássico e ajuda a entender recursão. Vamos ver como implementá-lo:
package main import "fmt" func fatorial(n int) int { if n == 0 { return 1 } return n * fatorial(n-1) } func main() { fmt.Print("Digite um número: ") var numero int fmt.Scan(&numero) fmt.Printf("Fatorial de %d é %d\n", numero, fatorial(numero)) }
Aqui, implementamos o cálculo do fatorial de um número usando recursão. A função fatorial(n int) int chama a si mesma, multiplicando o número atual n pelo fatorial de n-1. Quando n chega a zero, retornamos 1, que é o caso base da recursão. Essa é a essência da recursão: funções que se chamam até atingirem uma condição de parada. Essa abordagem é poderosa para resolver problemas que podem ser divididos em subproblemas menores semelhantes.,
Quer experimentar esse código? Você pode alterar o valor da variável numero para entender como o fatorial é calculado. Clique aqui!

3. Sequência de Fibonacci

A sequência de Fibonacci é um dos exercícios mais clássicos e úteis para praticar lógica de programação. Ela aparece em diversos contextos, como na natureza e na ciência da computação, sendo um ótimo exercício para desenvolver tanto o uso de loops quanto de recursão.
3.1 Implementando Fibonacci com recursão
Aqui está a implementação básica da sequência de Fibonacci usando recursão.
package main import "fmt" func fibonacci(n int) int { if n <= 1 { return n } return fibonacci(n-1) + fibonacci(n-2) } func main() { fmt.Print("Digite o número de termos da sequência: ") var termos int fmt.Scan(&termos) fmt.Println("Sequência de Fibonacci:") for i := 0; i < termos; i++ { fmt.Printf("%d ", fibonacci(i)) } fmt.Println() }
Neste exemplo, calculamos a sequência de Fibonacci usando recursão. A função fibonacci(n int) int retorna n se n for 0 ou 1. Caso contrário, ela retorna a soma das duas chamadas anteriores: fibonacci(n-1) + fibonacci(n-2). Embora essa implementação seja elegante e reflita a definição matemática da sequência, ela pode ser ineficiente para valores grandes de n, pois realiza muitas chamadas recursivas redundantes.
Teste este código clicando aqui. Modifique o valor de termos para gerar diferentes sequências de Fibonacci e veja como a função otimizada melhora a performance.

3.2 Otimizando Fibonacci com loop

A recursão é interessante para entender o conceito, mas para grandes valores, ela pode consumir muitos recursos. Uma versão mais eficiente é a que utiliza loops para evitar chamadas repetidas e otimizar o tempo de execução.
package main import "fmt" func fibonacciOtimizado(termos int) { a, b := 0, 1 fmt.Printf("%d %d ", a, b) for i := 2; i < termos; i++ { a, b = b, a+b fmt.Printf("%d ", b) } fmt.Println() } func main() { fmt.Print("Digite o número de termos: ") var termos int fmt.Scan(&termos) fibonacciOtimizado(termos) }
Para melhorar a eficiência, reescrevemos o cálculo da sequência de Fibonacci usando um loop. Inicializamos os dois primeiros termos da sequência e, em seguida, iteramos para calcular os próximos termos, atualizando os valores a cada iteração. Essa abordagem iterativa é muito mais eficiente, pois elimina as chamadas recursivas redundantes, tornando o algoritmo mais rápido e adequado para valores maiores de n.
Experimente este código agora clicando aqui! Modifique o valor de termos para gerar diferentes sequências de Fibonacci e veja como a função otimizada melhora a performance.

4. Verificar palíndromo

Um palíndromo é uma palavra ou frase que é a mesma lida de trás para frente. Veja como verificar se uma string é um palíndromo em Go.
package main import ( "fmt" "strings" ) func ePalindromo(texto string) bool { texto = strings.ToLower(strings.ReplaceAll(texto, " ", "")) invertido := "" for _, char := range texto { invertido = string(char) + invertido } return texto == invertido } func main() { var palavra string fmt.Print("Digite uma palavra ou frase: ") fmt.Scanln(&palavra) if ePalindromo(palavra) { fmt.Println("É um palíndromo!") } else { fmt.Println("Não é um palíndromo.") } }
Neste código, verificamos se uma palavra ou frase é um palíndromo. Primeiro, normalizamos o texto, convertendo-o para minúsculas e removendo espaços em branco, usando strings.ToLower e strings.ReplaceAll. Depois, invertimos a string percorrendo cada caractere e construindo uma nova string invertida. Comparando a string original com a invertida, determinamos se é um palíndromo. Essa técnica é útil para diversas aplicações, como validação de entradas e processamento de linguagem natural.
Prepare-se para testar este código incrível clicando aqui. Veja a magia dos palíndromos em ação e experimente modificar a frase para testar outras combinações.

5. Máximo divisor comum (MDC)

Vamos usar o algoritmo de Euclides para calcular o máximo divisor comum (MDC) de dois números.
package main import ( "fmt" ) func calcularMDC(a, b int) int { for b != 0 { a, b = b, a%b } return a } func main() { var num1, num2 int fmt.Print("Digite o primeiro número: ") fmt.Scanln(&num1) fmt.Print("Digite o segundo número: ") fmt.Scanln(&num2) mdc := calcularMDC(num1, num2) fmt.Printf("MDC de %d e %d é %d\n", num1, num2, mdc) }
Implementamos o cálculo do MDC usando o algoritmo de Euclides, que é simples e eficiente. O algoritmo funciona substituindo o par de números (a, b) pelo par (b, a%b) repetidamente, até que b seja zero. Quando isso acontece, o valor de a é o MDC. Essa implementação ilustra como conceitos matemáticos clássicos podem ser facilmente traduzidos em código Go.
Agora é sua vez! Execute este código clicando aqui e veja o poder do algoritmo de Euclides em ação!

6. Ordenação de números (bubble sort)

O bubble sort é um algoritmo simples de ordenação que compara pares adjacentes e os troca se estiverem na ordem errada.
package main import ( "fmt" ) func bubbleSort(array []int) { n := len(array) for i := 0; i < n-1; i++ { for j := 0; j < n-i-1; j++ { if array[j] > array[j+1] { // Troca os elementos array[j], array[j+1] = array[j+1], array[j] } } } } func main() { numeros := []int{29, 10, 14, 37, 13} bubbleSort(numeros) fmt.Println("Array ordenado com Bubble Sort:") for _, num := range numeros { fmt.Printf("%d ", num) } fmt.Println() }
Aqui, utilizamos o algoritmo bubble sort para ordenar um array de números. O algoritmo funciona comparando pares adjacentes de elementos e trocando-os se estiverem na ordem errada. Isso é feito repetidamente em múltiplas passagens pelo array, até que todos os elementos estejam ordenados. Embora não seja o método mais eficiente para grandes conjuntos de dados, o bubble sort é fácil de entender e implementar, sendo ideal para fins didáticos.
Vamos lá! Teste este código clicando aqui e veja a magia do bubble sort em ação! Substitua os números do array por outros e descubra como a ordenação funciona. Desafie-se a entender cada etapa e crie seus próprios exemplos! Divirta-se explorando!

7. Ordenação de números (quick sort)

O quick sort é um algoritmo eficiente que utiliza a estratégia de dividir e conquistar.
package main import ( "fmt" ) func quickSort(array []int, inicio, fim int) { if inicio < fim { indicePivo := particionar(array, inicio, fim) quickSort(array, inicio, indicePivo-1) quickSort(array, indicePivo+1, fim) } } func particionar(array []int, inicio, fim int) int { pivo := array[fim] indiceMenor := inicio for j := inicio; j < fim; j++ { if array[j] <= pivo { array[indiceMenor], array[j] = array[j], array[indiceMenor] indiceMenor++ } } array[indiceMenor], array[fim] = array[fim], array[indiceMenor] return indiceMenor } func main() { numeros := []int{33, 15, 10, 7, 40, 22} quickSort(numeros, 0, len(numeros)-1) fmt.Println("Array ordenado com Quick Sort:") for _, num := range numeros { fmt.Printf("%d ", num) } fmt.Println() }
Neste exemplo, implementamos o quick sort, um algoritmo de ordenação mais eficiente que usa a estratégia de dividir e conquistar. Escolhemos um elemento como pivô (neste caso, o último elemento do array) e reorganizamos os outros elementos em torno dele, de forma que os menores fiquem à esquerda e os maiores à direita. Em seguida, aplicamos recursivamente o mesmo processo às sublistas resultantes. O quick sort é muito eficiente para grandes volumes de dados e é amplamente utilizado em aplicações reais.
É hora de ver o poder do quick sort em ação! Experimente este código clicando aqui e veja como essa técnica rápida e elegante organiza os números. Troque os valores no array para testar diferentes cenários e se surpreenda com a eficiência deste algoritmo clássico. Bora codar?

Dicas para resolver problemas de lógica em Go

  • Decomponha o problema: quebre em partes menores e resolva passo a passo.
  • Use ferramentas de depuração: Go possui excelentes ferramentas para depurar e testar seu código.
  • Escreva testes: utilize o pacote testing para criar testes unitários.
  • Explore as bibliotecas padrão: Essa linguagem possui uma rica biblioteca padrão que pode simplificar muitas tarefas.
  • Aprenda sobre concorrência: aproveite goroutines e channels para escrever código eficiente.
  • Participe de comunidades: troque ideias e aprenda com outros devs.

Junte-se à comunidade Rocketseat!

Na Rocketseat, acreditamos que aprender em conjunto torna a jornada mais envolvente e eficaz. Nossa comunidade é formada por milhares de desenvolvedores como você, prontos para compartilhar conhecimentos, tirar dúvidas e comemorar cada conquista. E o melhor: aqui, você nunca estará sozinho! Precisa de ajuda com um bug complicado ou quer celebrar uma vitória com quem realmente entende? A Rocketseat é o lugar perfeito para isso.

Conclusão

Se você chegou até aqui, parabéns! Você mandou muito bem explorando alguns dos problemas clássicos de lógica em Go e como abordá-los. Essa jornada foi intensa, mas saiba que você apenas arranhou a superfície do vasto universo da programação!
Quer continuar evoluindo e mergulhar ainda mais fundo? Embarque no foguete da Rocketseat! Nossa formação em Go é o combustível que você precisa para decolar na carreira, aprendendo na prática com projetos profissionais e construindo um portfólio capaz de impressionar qualquer recrutador.
Você vai desenvolver habilidades reais ao lidar com desafios do dia a dia, aplicando novas tecnologias em projetos que simulam situações reais do mercado. E o melhor: todo o processo é acompanhado por um suporte personalizado.

O que mais você encontra na formação em Go?

  • Suporte ao aluno: tenha ajuda com a IA da Rocketseat e atendimento direto da equipe de sucesso do aluno para tirar dúvidas e receber suporte personalizado.
  • Tutorias individuais: agende conversas individuais com a equipe para falar sobre seus estudos ou carreira.
  • Bate-papos em grupo: participe semanalmente de bate-papos sobre carreira e estudos, trocando experiências e fazendo networking com outros alunos.
  • Café com os instrutores: encontros semanais ao vivo com especialistas do mercado para discutir tópicos relevantes sobre carreira e tecnologia.
  • Talent space: uma semana cheia de eventos focados na sua carreira, com empresas parceiras compartilhando dicas e oportunidades de vagas.
  • Mentoria de carreira: uma jornada completa de cinco encontros para desenvolver habilidades essenciais, como autoconhecimento, networking, LinkedIn e muito mais.
E sabe quem estará ao seu lado nessa jornada? Pedro Henrique Pessoa, um desenvolvedor experiente e apaixonado por tecnologia. Pedro já criou e manteve produtos digitais utilizados por mais de 500 milhões de pessoas, processando mais de 1 bilhão de requisições mensais. Especialista em Go, ele também é contribuidor de projetos open source e compartilha insights valiosos no seu canal no YouTube.

Aprenda programação do zero e DE GRAÇA

No Discover você vai descomplicar a programação, aprender a criar seu primeiro site com a mão na massa e iniciar sua transição de carreira.

COMECE A ESTUDAR AGORA