Skip to content

Commit bfddce6

Browse files
committed
feat: add articles to hard challenges
1 parent 6d42ed3 commit bfddce6

File tree

10 files changed

+1240
-0
lines changed

10 files changed

+1240
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Challenge Description and Solution
2+
3+
## English Version
4+
5+
### Challenge Description
6+
Implement a solution for the travelling salesman problem using dynamic programming with bitmasking. This challenge requires optimizing the search in an exponential state space. Use object-oriented programming and follow the DRY principle.
7+
8+
### Code Explanation
9+
The `TravellingSalesman` class uses dynamic programming with bitmasking to solve the problem efficiently. It keeps track of visited cities using a bitmask and memoizes results to avoid redundant calculations.
10+
11+
The `tsp` method recursively explores all unvisited cities, calculating the minimum cost to complete the tour and return to the start.
12+
13+
### Relevant Code Snippet
14+
15+
```python
16+
from typing import List
17+
18+
class TravellingSalesman:
19+
def __init__(self, graph: List[List[int]]):
20+
self.graph = graph
21+
self.n = len(graph)
22+
self.ALL_VISITED = (1 << self.n) - 1
23+
self.memo = [[-1] * (1 << self.n) for _ in range(self.n)]
24+
25+
def tsp(self, pos: int, visited: int) -> int:
26+
if visited == self.ALL_VISITED:
27+
return self.graph[pos][0] # return to start
28+
29+
if self.memo[pos][visited] != -1:
30+
return self.memo[pos][visited]
31+
32+
ans = float('inf')
33+
for city in range(self.n):
34+
if (visited >> city) & 1 == 0:
35+
new_visited = visited | (1 << city)
36+
cost = self.graph[pos][city] + self.tsp(city, new_visited)
37+
ans = min(ans, cost)
38+
39+
self.memo[pos][visited] = ans
40+
return ans
41+
```
42+
43+
### Historical Context
44+
The travelling salesman problem (TSP) is a classic NP-hard problem in combinatorial optimization. Dynamic programming with bitmasking is a well-known approach to solve small instances efficiently by representing subsets of cities as bitmasks.
45+
46+
---
47+
48+
## Versión en Español
49+
50+
### Descripción del Reto
51+
Implementa una solución para el problema del viajante de comercio usando programación dinámica con bitmasking. Este reto requiere optimizar la búsqueda en un espacio de estados exponencial. Usa programación orientada a objetos y sigue el principio DRY.
52+
53+
### Explicación del Código
54+
La clase `TravellingSalesman` usa programación dinámica con bitmasking para resolver el problema eficientemente. Lleva un registro de las ciudades visitadas usando un bitmask y memoiza resultados para evitar cálculos redundantes.
55+
56+
El método `tsp` explora recursivamente todas las ciudades no visitadas, calculando el costo mínimo para completar el recorrido y regresar al inicio.
57+
58+
### Fragmento de Código Relevante
59+
60+
```python
61+
from typing import List
62+
63+
class TravellingSalesman:
64+
def __init__(self, graph: List[List[int]]):
65+
self.graph = graph
66+
self.n = len(graph)
67+
self.ALL_VISITED = (1 << self.n) - 1
68+
self.memo = [[-1] * (1 << self.n) for _ in range(self.n)]
69+
70+
def tsp(self, pos: int, visited: int) -> int:
71+
if visited == self.ALL_VISITED:
72+
return self.graph[pos][0] # regresar al inicio
73+
74+
if self.memo[pos][visited] != -1:
75+
return self.memo[pos][visited]
76+
77+
ans = float('inf')
78+
for city in range(self.n):
79+
if (visited >> city) & 1 == 0:
80+
new_visited = visited | (1 << city)
81+
cost = self.graph[pos][city] + self.tsp(city, new_visited)
82+
ans = min(ans, cost)
83+
84+
self.memo[pos][visited] = ans
85+
return ans
86+
```
87+
88+
### Contexto Histórico
89+
El problema del viajante de comercio (TSP) es un problema clásico NP-hard en optimización combinatoria. La programación dinámica con bitmasking es un enfoque conocido para resolver instancias pequeñas eficientemente representando subconjuntos de ciudades como bitmasks.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Challenge Description and Solution
2+
3+
## English Version
4+
5+
### Challenge Description
6+
Given a string and a dictionary, return all possible valid sentences that can be formed. This challenge requires recursion with memoization to avoid redundant solutions and explore multiple paths. Use object-oriented programming and follow the DRY principle.
7+
8+
### Code Explanation
9+
The `WordBreak` class uses recursion with memoization to find all valid sentences that can be formed from the input string using words from the dictionary.
10+
11+
Key points:
12+
- The `word_break` method recursively explores all substrings starting from the current index.
13+
- Memoization stores results for each start index to avoid redundant computations.
14+
- Sentences are constructed by concatenating valid words with results from recursive calls.
15+
16+
### Relevant Code Snippet
17+
18+
```python
19+
from typing import List, Set, Dict
20+
21+
class WordBreak:
22+
def __init__(self, s: str, word_dict: Set[str]):
23+
self.s = s
24+
self.word_dict = word_dict
25+
self.memo: Dict[int, List[str]] = {}
26+
27+
def word_break(self, start: int = 0) -> List[str]:
28+
if start == len(self.s):
29+
return [""]
30+
31+
if start in self.memo:
32+
return self.memo[start]
33+
34+
sentences = []
35+
for end in range(start + 1, len(self.s) + 1):
36+
word = self.s[start:end]
37+
if word in self.word_dict:
38+
for subsentence in self.word_break(end):
39+
sentence = word + (" " + subsentence if subsentence else "")
40+
sentences.append(sentence)
41+
42+
self.memo[start] = sentences
43+
return sentences
44+
```
45+
46+
### Historical Context
47+
The word break problem is a classic example of recursion with memoization, commonly used in natural language processing and text segmentation tasks. It efficiently explores multiple segmentation paths while avoiding redundant computations.
48+
49+
---
50+
51+
## Versión en Español
52+
53+
### Descripción del Reto
54+
Dada una cadena y un diccionario, devuelve todas las posibles oraciones válidas que se pueden formar. Este reto requiere recursión con memoización para evitar soluciones redundantes y explorar múltiples caminos. Usa programación orientada a objetos y sigue el principio DRY.
55+
56+
### Explicación del Código
57+
La clase `WordBreak` usa recursión con memoización para encontrar todas las oraciones válidas que se pueden formar a partir de la cadena de entrada usando palabras del diccionario.
58+
59+
Puntos clave:
60+
- El método `word_break` explora recursivamente todos los subcadenas desde el índice actual.
61+
- La memoización almacena resultados para cada índice de inicio para evitar cálculos redundantes.
62+
- Las oraciones se construyen concatenando palabras válidas con resultados de llamadas recursivas.
63+
64+
### Fragmento de Código Relevante
65+
66+
```python
67+
from typing import List, Set, Dict
68+
69+
class WordBreak:
70+
def __init__(self, s: str, word_dict: Set[str]):
71+
self.s = s
72+
self.word_dict = word_dict
73+
self.memo: Dict[int, List[str]] = {}
74+
75+
def word_break(self, start: int = 0) -> List[str]:
76+
if start == len(self.s):
77+
return [""]
78+
79+
if start in self.memo:
80+
return self.memo[start]
81+
82+
sentences = []
83+
for end in range(start + 1, len(self.s) + 1):
84+
word = self.s[start:end]
85+
if word in self.word_dict:
86+
for subsentence in self.word_break(end):
87+
sentence = word + (" " + subsentence if subsentence else "")
88+
sentences.append(sentence)
89+
90+
self.memo[start] = sentences
91+
return sentences
92+
```
93+
94+
### Contexto Histórico
95+
El problema de segmentación de palabras es un ejemplo clásico de recursión con memoización, comúnmente usado en procesamiento de lenguaje natural y tareas de segmentación de texto. Explora eficientemente múltiples caminos de segmentación evitando cálculos redundantes.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Challenge Description and Solution
2+
3+
## English Version
4+
5+
### Challenge Description
6+
Develop the Edmonds-Karp algorithm to calculate the maximum flow in a network. This challenge deepens advanced graph handling and data structures to improve efficiency. Use object-oriented programming and follow the DRY principle.
7+
8+
### Code Explanation
9+
The `EdmondsKarp` class implements the Edmonds-Karp algorithm using a residual graph and BFS to find augmenting paths. The `max_flow` method repeatedly finds paths from source to sink with available capacity, updates the residual graph, and accumulates the flow until no more augmenting paths exist.
10+
11+
### Relevant Code Snippet
12+
13+
```python
14+
from collections import deque
15+
from typing import List
16+
17+
class EdmondsKarp:
18+
def __init__(self, graph: List[List[int]]):
19+
self.graph = graph
20+
self.n = len(graph)
21+
self.residual_graph = [row[:] for row in graph]
22+
23+
def bfs(self, source: int, sink: int, parent: List[int]) -> bool:
24+
visited = [False] * self.n
25+
queue = deque([source])
26+
visited[source] = True
27+
28+
while queue:
29+
u = queue.popleft()
30+
for v, capacity in enumerate(self.residual_graph[u]):
31+
if not visited[v] and capacity > 0:
32+
queue.append(v)
33+
visited[v] = True
34+
parent[v] = u
35+
if v == sink:
36+
return True
37+
return False
38+
39+
def max_flow(self, source: int, sink: int) -> int:
40+
parent = [-1] * self.n
41+
max_flow = 0
42+
43+
while self.bfs(source, sink, parent):
44+
path_flow = float('inf')
45+
s = sink
46+
while s != source:
47+
path_flow = min(path_flow, self.residual_graph[parent[s]][s])
48+
s = parent[s]
49+
50+
max_flow += path_flow
51+
52+
v = sink
53+
while v != source:
54+
u = parent[v]
55+
self.residual_graph[u][v] -= path_flow
56+
self.residual_graph[v][u] += path_flow
57+
v = parent[v]
58+
59+
return max_flow
60+
```
61+
62+
### Historical Context
63+
The Edmonds-Karp algorithm is an implementation of the Ford-Fulkerson method for computing the maximum flow in a flow network. It uses BFS to find shortest augmenting paths, improving efficiency and guaranteeing polynomial time complexity.
64+
65+
---
66+
67+
## Versión en Español
68+
69+
### Descripción del Reto
70+
Desarrolla el algoritmo de Edmonds-Karp para calcular el flujo máximo en una red. Este reto profundiza en el manejo avanzado de grafos y estructuras de datos para mejorar la eficiencia. Usa programación orientada a objetos y sigue el principio DRY.
71+
72+
### Explicación del Código
73+
La clase `EdmondsKarp` implementa el algoritmo de Edmonds-Karp usando un grafo residual y BFS para encontrar caminos aumentantes. El método `max_flow` encuentra repetidamente caminos desde la fuente al sumidero con capacidad disponible, actualiza el grafo residual y acumula el flujo hasta que no existan más caminos aumentantes.
74+
75+
### Fragmento de Código Relevante
76+
77+
```python
78+
from collections import deque
79+
from typing import List
80+
81+
class EdmondsKarp:
82+
def __init__(self, graph: List[List[int]]):
83+
self.graph = graph
84+
self.n = len(graph)
85+
self.residual_graph = [row[:] for row in graph]
86+
87+
def bfs(self, source: int, sink: int, parent: List[int]) -> bool:
88+
visited = [False] * self.n
89+
queue = deque([source])
90+
visited[source] = True
91+
92+
while queue:
93+
u = queue.popleft()
94+
for v, capacity in enumerate(self.residual_graph[u]):
95+
if not visited[v] and capacity > 0:
96+
queue.append(v)
97+
visited[v] = True
98+
parent[v] = u
99+
if v == sink:
100+
return True
101+
return False
102+
103+
def max_flow(self, source: int, sink: int) -> int:
104+
parent = [-1] * self.n
105+
max_flow = 0
106+
107+
while self.bfs(source, sink, parent):
108+
path_flow = float('inf')
109+
s = sink
110+
while s != source:
111+
path_flow = min(path_flow, self.residual_graph[parent[s]][s])
112+
s = parent[s]
113+
114+
max_flow += path_flow
115+
116+
v = sink
117+
while v != source:
118+
u = parent[v]
119+
self.residual_graph[u][v] -= path_flow
120+
self.residual_graph[v][u] += path_flow
121+
v = parent[v]
122+
123+
return max_flow
124+
```
125+
126+
### Contexto Histórico
127+
El algoritmo de Edmonds-Karp es una implementación del método de Ford-Fulkerson para calcular el flujo máximo en una red de flujo. Usa BFS para encontrar los caminos aumentantes más cortos, mejorando la eficiencia y garantizando complejidad polinómica.

0 commit comments

Comments
 (0)