encontrar el inicio de un ciclo en una lista enlazada.
La imagen que subiste anteriormente es precisamente el ejemplo visual que utiliza el autor para explicar el Algoritmo de Floyd (también conocido como el algoritmo de “la liebre y la tortuga”).
// 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 finalAlgoritmo 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).
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)
}
}graph TD
%% --- ESTILOS ---
%% Definimos colores claros y bordes definidos para máxima claridad
classDef inicioEnd fill:#f9f,stroke:#333,stroke-width:2px,rx:15,ry:15,color:black;
classDef proceso fill:#e3f2fd,stroke:#1565c0,stroke-width:1px,color:black;
classDef decision fill:#fffde7,stroke:#fbc02d,stroke-width:1px,color:black;
classDef datos fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px,color:black;
%% --- NODOS PRINCIPALES ---
Start((Inicio)):::inicioEnd
%% Fase 1: Inicialización
InitN[n := 0<br/>Indice de escritura]:::proceso
%% Fase 2: Bucle
ForLoop{"¿Hay más<br/>elementos x en<br/>slice?"}:::decision
%% Fase 3: Condición
IfKeep{"¿keep(x)?<br/>(Condición<br/>cumplida)"}:::decision
%% Fase 4: Acciones dentro del IF
AssignX["slice[n] = x<br/>(Se guarda x en<br/>posición válida)"]:::proceso
IncN[n++<br/>(Avanzar indice<br/>de escritura)]:::proceso
%% Fase 5: Finalización
Reslice["slice = slice[:n]<br/>(Ajuste final del tamaño)"]:::proceso
End((Fin)):::inicioEnd
%% --- CONEXIONES (FLUJO) ---
Start --> InitN
InitN --> ForLoop
%% Flujo dentro del bucle
ForLoop -- "Sí" --> IfKeep
%% Flujo si la condición keep(x) es verdadera
IfKeep -- "Sí (True)" --> AssignX
AssignX --> IncN
IncN --> ForLoop %% Vuelve al inicio del bucle
%% Flujo si la condición keep(x) es falsa
IfKeep -- "No (False)" --> ForLoop %% Salta la asignación y vuelve al bucle
%% Salida del bucle y finalización
ForLoop -- "No (Fin)" --> Reslice
Reslice --> End