• Skip to main content
  • Skip to footer

Ghoper logic

Algoritmos y lógica con Golang

  • Fácil
  • Intermedio
  • Avanzado
  • Todos
  • GitHub

Factorial

Antes de ver el código, un pequeño baño de realidad: en el mundo real, calcular un factorial secuencialmente en un solo hilo es mucho más rápido, ya que el costo de crear goroutines y canales es mayor que el de hacer unas cuantas multiplicaciones. Sin embargo, como ejercicio pedagógico para entender la concurrencia en Go, es un ejemplo fantástico.

Aquí tienes cómo dividirías el trabajo matemático utilizando goroutines y sincronizando el resultado final a través de un canal.

Calculando un Factorial con Goroutines y Channels

Vamos a calcular el factorial de 10 ($10!$). Para hacerlo concurrente, dividiremos el trabajo en dos mitades:

  1. Una goroutine calculará la multiplicación del 1 al 5.
  2. Otra goroutine calculará la multiplicación del 6 al 10.
  3. El canal recibirá ambas partes y las multiplicará en la función principal.

Go

¿Por qué usamos channels aquí y cómo funcionan?

  • Comunicación sin compartir memoria: En lugar de crear una variable global total y usar un sync.Mutex para bloquearla y evitar condiciones de carrera (Race Conditions) cuando ambas goroutines intenten escribir en ella, los canales permiten que cada goroutine haga su trabajo aislada y simplemente “entregue” el paquete de vuelta.
  • Sincronización implícita: Las líneas part1 := <-ch y part2 := <-ch actúan como una barrera. El programa principal (main) se pausa automáticamente en ese punto exacto y no terminará hasta que ambas goroutines hayan terminado sus cálculos y enviado sus respuestas a través del canal.
Copy
package main

import (
	"fmt"
)

// partialFactorial calcula la multiplicación de un rango de números
// y envía el resultado al canal 'ch'.
func partialFactorial(start, end int64, ch chan<- int64) {
	var result int64 = 1
	for i := start; i <= end; i++ {
		result *= i
	}
	// Enviamos el resultado parcial al canal
	ch <- result
}

func main() {
	number := int64(10)
	mid := number / 2

	// Creamos un canal que transportará números int64.
	// Usamos un buffer de 2 porque esperamos dos resultados.
	ch := make(chan int64, 2)

	// Lanzamos la primera goroutine (calcula 1 * 2 * 3 * 4 * 5)
	go partialFactorial(1, mid, ch)

	// Lanzamos la segunda goroutine (calcula 6 * 7 * 8 * 9 * 10)
	go partialFactorial(mid+1, number, ch)

	// Sincronización:
	// La función main se bloqueará aquí hasta que el canal reciba datos.
	part1 := <-ch
	part2 := <-ch

	// Multiplicamos ambas partes para obtener el resultado final
	total := part1 * part2

	fmt.Printf("El factorial de %d es: %d\n", number, total)
}
Go

Algoritmo para el Cifrado Cesar en Go, común cuando inicias en criptografía y fácil de implementar, solo que en momentos de presión puedes llegar a hacer algo complicado cuando en realidad lo puedes resolver con un poco de aritmética (simple).

Copy
// Filtramos el slice sin crear copias extras
n := 0
for _, x := range slice {
    if keep(x) { // Condición para mantener el elemento
        slice[n] = x
        n++
    }
}
slice = slice[:n] // Ajustamos el tamaño final

Algoritmo para el Cifrado Cesar en Go, común cuando inicias en criptografía y fácil de implementar, solo que en momentos de presión puedes llegar a hacer algo complicado cuando en realidad lo puedes resolver con un poco de aritmética (simple).

Copy
package main

import "fmt"

type task struct {
	title       string
	descripcion string
	ok          bool
	createAt    int64
}

func main() {
	// 1. Datos de prueba
	tasks := []task{
		{title: "Aprender Go", ok: true},
		{title: "Ir al gym", ok: false},
		{title: "Mejorar Inglés", ok: true},
		{title: "Proyecto personal", ok: false},
	}

	fmt.Println("Antes:", len(tasks))

	// 2. EL ALGORITMO DE FILTRADO
	n := 0
	for i := range tasks {
		// "Si la tarea NO está lista (ok == false), la mantenemos"
		if !tasks[i].ok {
			tasks[n] = tasks[i]
			n++
		}
	}

	// 3. RE-SLICING: Ajustamos el tamaño al nuevo conteo
	tasks = tasks[:n]

	// 4. Resultado
	fmt.Println("Después:", len(tasks))
	for _, v := range tasks {
		fmt.Printf("- %s (Estado: %v)\n", v.title, v.ok)
	}

}
Copy

package main

import (
	"reflect"
	"testing"
)

func TestFilterTasksInPlace(t *testing.T) {
	// Definimos los casos de prueba (Table-driven tests)
	tests := []struct {
		name     string
		input    []task
		expected []task
	}{
		{
			name: "Filtrar algunas completadas",
			input: []task{
				{title: "T1", ok: true},
				{title: "T2", ok: false},
				{title: "T3", ok: true},
			},
			expected: []task{
				{title: "T2", ok: false},
			},
		},
		{
			name: "Todas completadas (debe quedar vacío)",
			input: []task{
				{title: "T1", ok: true},
				{title: "T2", ok: true},
			},
			expected: []task{},
		},
		{
			name: "Ninguna completada (debe quedar igual)",
			input: []task{
				{title: "T1", ok: false},
				{title: "T2", ok: false},
			},
			expected: []task{
				{title: "T1", ok: false},
				{title: "T2", ok: false},
			},
		},
		{
			name:     "Slice vacío",
			input:    []task{},
			expected: []task{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Ejecutamos tu algoritmo
			result := FilterTasksInPlace(tt.input)

			// Comparamos el resultado con lo esperado
			// reflect.DeepEqual es genial para comparar slices/structs
			if !reflect.DeepEqual(result, tt.expected) {
				t.Errorf("error en %s: esperado %v, obtenido %v", tt.name, tt.expected, result)
			}
		})
	}
}

Footer

Primeros con algoritmia

Factorial

Algoritmos por dificultad en Go

  • Fácil
  • Intermedio
  • Avanzado
  • Todos
  • GitHub

Cada sábado estudio y juego con un algoritmo, y se me ocurrió compartir las notas notas para me obligarme a escribir mejor y así  empece a escribir en 2021.

Ahora puedes resolverlos con IA, pero lo hago por curiosidad!

Algoritmos fáciles con Go

  • Factorial
  • Algoritmo de Floyd
  • In-Place
  • Amazon Interview | Asteroid Collision | Data Structures & Algorithms
  • Básicas
  • Más usadas
  • Complejas

Algoritmos intemedios con Go

  • Factorial
  • Algoritmo de Floyd

Algoritmos avanzados con Go

  • Factorial
  • Algoritmo de Floyd

Copyright © 2026 · Log in