Skip to content

Commit

Permalink
Add Lecture 08 (+Code)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpconsuegra committed Mar 17, 2024
1 parent cb99f3d commit bf62f8e
Show file tree
Hide file tree
Showing 4 changed files with 272 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "src", "src\src.csproj", "{49B720A0-C2E9-4562-ADD2-6BC9C3D25704}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{49B720A0-C2E9-4562-ADD2-6BC9C3D25704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{49B720A0-C2E9-4562-ADD2-6BC9C3D25704}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49B720A0-C2E9-4562-ADD2-6BC9C3D25704}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49B720A0-C2E9-4562-ADD2-6BC9C3D25704}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
152 changes: 152 additions & 0 deletions conferences/2024/08-divide-and-conquer/code/recursion/src/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
namespace MatCom.Programming
{
class Program
{
static void Main()
{
int[] to_sort;
int[] numbers = new[] { 10, 9, -3, 8, 7, -1, 5, 4, 3, 2, 1 };

Console.WriteLine(Pow(2, 10));

to_sort = (int[])numbers.Clone();
MergeSort(to_sort);
Console.WriteLine("[{0}]", string.Join(", ", to_sort));

to_sort = (int[])numbers.Clone();
QuickSort(to_sort);
Console.WriteLine("[{0}]", string.Join(", ", to_sort));

Console.WriteLine(BinarySearch(to_sort, 4));
}


// Pow
static int Pow(int n, int p)
{
if (p == 0)
return 1;

int half = Pow(n, p / 2);
return half * half * (p % 2 == 0 ? 1 : n);
}


// BinarySearch
public static int BinarySearch(int[] array, int target)
{
return BinarySearch(array, target, 0, array.Length - 1);
}

private static int BinarySearch(int[] array, int target, int left, int right)
{
if (left > right)
return -1;

int mid = left + (right - left) / 2;

if (array[mid] == target)
return mid;
else if (array[mid] < target)
return BinarySearch(array, target, mid + 1, right);
else
return BinarySearch(array, target, left, mid - 1);
}

// MergeSort
static void MergeSort(int[] array)
{
MergeSort(array, 0, array.Length - 1, new int[array.Length]);
}

static void MergeSort(int[] array, int inicio, int fin, int[] aux)
{
if (inicio == fin)
return;

int medio = inicio + (fin - inicio) / 2;
MergeSort(array, inicio, medio, aux);
MergeSort(array, medio + 1, fin, aux);
Merge(array, aux, inicio, medio, fin);
}

static void Merge(int[] array, int[] aux, int inicioA, int finA, int finB)
{
int i = inicioA;
int j = finA + 1;
int pos = inicioA;

while (i <= finA && j <= finB)
{
if (array[i] <= array[j])
aux[pos++] = array[i++];
else
aux[pos++] = array[j++];
}
while (i <= finA)
{
aux[pos++] = array[i++];
}
while (j <= finB)
{
aux[pos++] = array[j++];
}
Array.Copy(aux, inicioA, array, inicioA, finB - inicioA + 1);
}

// QuickSort
static void QuickSort(int[] array)
{
QuickSort(array, 0, array.Length - 1);
}

static void QuickSort(int[] array, int inicio, int fin)
{
if (fin <= inicio)
return;

int pivotIndex = (inicio + fin) / 2;
pivotIndex = ArrangePivot(array, inicio, fin, pivotIndex);
QuickSort(array, inicio, pivotIndex - 1);
QuickSort(array, pivotIndex + 1, fin);
}

static int ArrangePivot(int[] array, int inicio, int fin, int pivotIndex)
{
int i = inicio;
int j = fin;

while (true)
{
if (array[i] <= array[pivotIndex] && i != pivotIndex)
i++;
if (array[j] >= array[pivotIndex] && j != pivotIndex)
j--;
if (i == j)
break;
if (array[i] >= array[pivotIndex] && array[j] <= array[pivotIndex])
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
if (i == pivotIndex)
{
pivotIndex = j;
i++;
}
else if (j == pivotIndex)
{
pivotIndex = i;
j--;
}
else
{
i++;
j--;
}
}
}
return i; // ~ RETURN J
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
88 changes: 88 additions & 0 deletions conferences/2024/08-divide-and-conquer/lecture-08.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Recursividad (Divide y Vencerás)

## Introducción

El enfoque de "divide y vencerás" es una técnica de resolución de problemas que se basa en dividir un problema en subproblemas más pequeños, resolver cada subproblema de manera recursiva y luego combinar las soluciones de los subproblemas para obtener la solución al problema original.

Por supuesto, todos los enfoques recursivos de una forma u otra siguen esa misma estructura;
la diferencia fundamental al aplicar "divide y vercerás" radica en que al dividir se crearán subproblemas con tamaño en ordenes de magnitud menores que la solución actual (o sea, en lugar de ser 1, 2, o N unidades más pequeño, cada subproblema será 2, 3, o M veces más pequeño).
Esta característica resultan en implementaciones que, generalmente, convergen a soluciones de forma más eficiente.

## Principios clave:

1. **Dividir**: Divide el problema en subproblemas más pequeños y manejables.
2. **Vencer**: Resuelve cada subproblema de manera recursiva.
3. **Combinar**: Combina las soluciones de los subproblemas para obtener la solución al problema original.

## Ejemplo de aplicación:

### 1. Búsqueda binaria:

La búsqueda binaria es un ejemplo clásico de "divide y vencerás".

```csharp
public static int BinarySearch(int[] array, int target)
{
return BinarySearch(array, target, 0, array.Length - 1);
}

private static int BinarySearch(int[] array, int target, int left, int right)
{
if (left > right)
return -1;

int mid = left + (right - left) / 2;

if (array[mid] == target)
return mid;
else if (array[mid] < target)
return BinarySearch(array, target, mid + 1, right);
else
return BinarySearch(array, target, left, mid - 1);
}
```

### 2. Merge Sort:

Merge Sort es un algoritmo de ordenamiento que sigue el principio de "divide y vencerás".

```csharp
static void MergeSort(int[] array)
{
MergeSort(array, 0, array.Length - 1, new int[array.Length]);
}

static void MergeSort(int[] array, int inicio, int fin, int[] aux)
{
if(inicio == fin)
return;

int medio = inicio + (fin - inicio) / 2;
MergeSort(array, inicio, medio, aux);
MergeSort(array, medio + 1, fin, aux);
Merge(array, aux, inicio, medio, fin);
}

static void Merge(int[] array, int[] aux, int inicioA, int finA, int finB)
{
int i = inicioA;
int j = finA + 1;
int pos = inicioA;

while(i <= finA && j <= finB) {
if(array[i] <= array[j])
aux[pos++] = array[i++];
else
aux[pos++] = array[j++];
}
while(i <= finA) {
aux[pos++] = array[i++];
}
while(j <= finB) {
aux[pos++] = array[j++];
}
Array.Copy(aux, inicioA, array, inicioA, finB - inicioA + 1);
}
```

Estos son solo dos ejemplos de cómo se puede aplicar el enfoque de "divide y vencerás" en la programación, pero este principio se puede utilizar para resolver una variedad de problemas de manera eficiente.

0 comments on commit bf62f8e

Please sign in to comment.