@icarusmx/creta 1.5.4 → 1.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/creta.js +44 -3
- package/lib/aws-guide-viewer.js +179 -0
- package/lib/builders/MenuBuilder.js +23 -4
- package/lib/executors/ExercisesExecutor.js +8 -0
- package/lib/exercises/array-object-manipulation.md +1281 -0
- package/lib/exercises/aws-billing-detective.md +588 -0
- package/lib/exercises/git-stash-workflow.md +426 -0
- package/lib/exercises/iterm2-pane-navigation.md +504 -0
- package/lib/exercises/railway-deployment.md +1185 -0
- package/lib/papers/bitcoin/bitcoin.md +92 -0
- package/lib/papers/mapreduce/mapreduce.md +476 -0
- package/lib/papers/spark/spark.md +49 -0
- package/lib/vim-setup-tutorial.js +367 -0
- package/package.json +5 -1
- package/ascii-logo.txt +0 -8
- package/codex-refactor.txt +0 -13
- package/docs/diagrams/README.md +0 -131
- package/docs/diagrams/architecture-overview.mmd +0 -71
- package/docs/diagrams/architecture.svg +0 -1
- package/docs/diagrams/ecosystem-integration.mmd +0 -49
- package/docs/diagrams/evolution-phases.mmd +0 -49
- package/docs/diagrams/output.svg +0 -1
- package/docs/diagrams/phase2-command-help-flow.mmd +0 -51
- package/docs/diagrams/user-journey.mmd +0 -78
- package/ejemplo.sh +0 -3
- package/refactor.txt +0 -581
- package/templates/sveltekit-portfolio/package.json +0 -20
- package/templates/sveltekit-portfolio/src/app.css +0 -51
- package/templates/sveltekit-portfolio/src/app.html +0 -12
- package/templates/sveltekit-portfolio/src/routes/+layout.svelte +0 -108
- package/templates/sveltekit-portfolio/src/routes/+page.svelte +0 -79
- package/templates/sveltekit-portfolio/static/favicon.png +0 -0
- package/templates/sveltekit-portfolio/svelte.config.js +0 -10
- package/templates/sveltekit-portfolio/vite.config.js +0 -10
- package/test/enunciados.test.js +0 -72
- package/test/sintaxis-menu.test.js +0 -45
- package/wea-fome-qlia.sh +0 -92
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Bitcoin: A Peer-to-Peer Electronic Cash System
|
|
2
|
+
**Satoshi Nakamoto (2008)**
|
|
3
|
+
|
|
4
|
+
<!--
|
|
5
|
+
Vim Tips Nivel 2:
|
|
6
|
+
- <leader>ff: Busca archivos en el proyecto (crear blockchain.js)
|
|
7
|
+
- gd: Go to definition (si usas LSP)
|
|
8
|
+
- <leader>ca: Code actions
|
|
9
|
+
- gcc: Comentar/descomentar línea
|
|
10
|
+
- gcap: Comentar párrafo
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 📚 Contexto: Crisis del 2008
|
|
16
|
+
|
|
17
|
+
**31 de Octubre 2008**: Un email anónimo llega a una lista de criptografía...
|
|
18
|
+
|
|
19
|
+
> "I've been working on a new electronic cash system that's fully
|
|
20
|
+
> peer-to-peer, with no trusted third party."
|
|
21
|
+
> — Satoshi Nakamoto
|
|
22
|
+
|
|
23
|
+
### El Mundo en 2008
|
|
24
|
+
|
|
25
|
+
- **Lehman Brothers colapsa** → crisis financiera global
|
|
26
|
+
- **Bancos rescatados** con dinero público
|
|
27
|
+
- **Desconfianza masiva** en instituciones centrales
|
|
28
|
+
- **Pregunta clave**: ¿Puede existir dinero sin bancos?
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🤔 El Problema del Doble Gasto
|
|
33
|
+
|
|
34
|
+
<!-- Usa } para saltar entre párrafos rápido -->
|
|
35
|
+
|
|
36
|
+
### Dinero Digital = Archivos
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
archivo_dinero.txt: "10 BTC"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Pero los archivos se pueden **copiar**:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cp archivo_dinero.txt copia1.txt
|
|
46
|
+
cp archivo_dinero.txt copia2.txt
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
¿Qué impide gastar el mismo dinero 2 veces?
|
|
50
|
+
|
|
51
|
+
### Solución Tradicional
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Banco Central verifica cada transacción
|
|
55
|
+
↓
|
|
56
|
+
❌ Punto único de falla
|
|
57
|
+
❌ Requiere confianza
|
|
58
|
+
❌ Puede censurar
|
|
59
|
+
❌ Puede imprimir dinero infinito
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### La Visión de Bitcoin
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
✅ Red peer-to-peer sin autoridad
|
|
66
|
+
✅ Historial público e inmutable
|
|
67
|
+
✅ Consenso descentralizado
|
|
68
|
+
✅ Nadie puede imprimir bitcoins
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 💡 Los 3 Pilares de Bitcoin
|
|
74
|
+
|
|
75
|
+
### 1. BLOCKCHAIN
|
|
76
|
+
Cadena de bloques enlazados criptográficamente
|
|
77
|
+
|
|
78
|
+
### 2. PROOF-OF-WORK
|
|
79
|
+
Minería costosa → atacar es más caro que participar
|
|
80
|
+
|
|
81
|
+
### 3. CONSENSO
|
|
82
|
+
La cadena más larga (más trabajo) gana
|
|
83
|
+
|
|
84
|
+
<!-- Ejercicio en blockchain.js próximamente... -->
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 🏆 Próximamente
|
|
89
|
+
|
|
90
|
+
Contenido completo de Bitcoin paper en desarrollo.
|
|
91
|
+
|
|
92
|
+
Por ahora, explora MapReduce y regresa después para blockchain!
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
# MapReduce: Simplified Data Processing on Large Clusters
|
|
2
|
+
**Jeffrey Dean y Sanjay Ghemawat, Google (2004)**
|
|
3
|
+
|
|
4
|
+
<!--
|
|
5
|
+
Vim Tips para este documento:
|
|
6
|
+
- zM: Cierra todos los folds (empieza aquí para ver solo títulos)
|
|
7
|
+
- za: Abre/cierra el fold donde está el cursor
|
|
8
|
+
- }: Salta al siguiente párrafo
|
|
9
|
+
- ]]: Salta a la siguiente sección
|
|
10
|
+
- <leader>e: Abre el file explorer (crear borrador.js para ejercicios)
|
|
11
|
+
- <leader>ff: Buscar archivos en el proyecto
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 📚 Cómo Google Se Convirtió en Google
|
|
17
|
+
|
|
18
|
+
### 1998: Dos Estudiantes en un Garage
|
|
19
|
+
|
|
20
|
+
Larry Page y Sergey Brin tienen una idea simple pero poderosa:
|
|
21
|
+
|
|
22
|
+
**"¿Y si rankeas páginas web como papers académicos?"**
|
|
23
|
+
|
|
24
|
+
→ Papers citados frecuentemente = importantes
|
|
25
|
+
→ Páginas enlazadas frecuentemente = relevantes
|
|
26
|
+
|
|
27
|
+
Nace **PageRank**. Google indexa la web y hace búsqueda **ultra rápida**.
|
|
28
|
+
|
|
29
|
+
### El Problema del Éxito (2000-2004)
|
|
30
|
+
|
|
31
|
+
Google crece explosivamente:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
1998: 26 millones de páginas indexadas
|
|
35
|
+
2000: 1 billón de páginas
|
|
36
|
+
2004: PETABYTES de datos
|
|
37
|
+
|
|
38
|
+
La web crece más rápido que el haardware
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### El Muro: Escalabilidad
|
|
42
|
+
|
|
43
|
+
**Tareas diarias en Google (2004)**:
|
|
44
|
+
|
|
45
|
+
1. **Crawling**: Descargar millones de páginas web/día
|
|
46
|
+
2. **Indexing**: Construir índice invertido (palabra → documentos)
|
|
47
|
+
3. **PageRank**: Calcular relevancia de billones de enlaces
|
|
48
|
+
4. **Log Analysis**: Procesar terabytes de clicks, búsquedas, ads
|
|
49
|
+
|
|
50
|
+
**Problema**:
|
|
51
|
+
- Una máquina → ❌ Imposible, tardaría meses
|
|
52
|
+
- Comprar supercomputadora → ❌ Demasiado caro
|
|
53
|
+
- Cluster de máquinas baratas → ✅ pero... ¿cómo programarlo?
|
|
54
|
+
|
|
55
|
+
### El Dilema del Programador
|
|
56
|
+
|
|
57
|
+
Cada ingeniero en Google escribía el mismo código una y otra vez:
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
// Split data across machines
|
|
61
|
+
// Handle network failures
|
|
62
|
+
// Re-run failed tasks
|
|
63
|
+
// Aggregate results
|
|
64
|
+
// Monitor progress
|
|
65
|
+
// ...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**El insight**: Estos problemas son INFRAESTRUCTURA, no lógica de negocio.
|
|
69
|
+
|
|
70
|
+
**La pregunta**: ¿Existe un patrón común que abstraiga la distribución?
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🤔 El Problema
|
|
75
|
+
|
|
76
|
+
Imagina tres tareas diferentes:
|
|
77
|
+
|
|
78
|
+
### 1. Word Count
|
|
79
|
+
Contar palabras en 1 millón de documentos
|
|
80
|
+
|
|
81
|
+
### 2. Log Analysis
|
|
82
|
+
Encontrar las URLs con más errores 404 en logs gigantes
|
|
83
|
+
|
|
84
|
+
### 3. Inverted Index
|
|
85
|
+
Construir un índice de búsqueda (palabra → documentos)
|
|
86
|
+
|
|
87
|
+
**¿Qué tienen en común?**
|
|
88
|
+
|
|
89
|
+
Todas siguen el mismo patrón:
|
|
90
|
+
1. Procesar cada elemento independientemente (paralelizable)
|
|
91
|
+
2. Agrupar resultados por alguna clave
|
|
92
|
+
3. Combinar/agregar valores para cada grupo
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 💡 El Insight de MapReduce
|
|
97
|
+
|
|
98
|
+
<!-- Vim tip: Usa 'za' para expandir esta sección -->
|
|
99
|
+
|
|
100
|
+
La mayoría de problemas de big data se pueden expresar en **2 funciones**:
|
|
101
|
+
|
|
102
|
+
### 1. MAP: Transforma
|
|
103
|
+
```
|
|
104
|
+
Input: (key1, value1)
|
|
105
|
+
Output: lista de (key2, value2)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Transforma cada elemento en pares clave-valor.
|
|
109
|
+
|
|
110
|
+
### 2. REDUCE: Agrega
|
|
111
|
+
```
|
|
112
|
+
Input: (key2, lista de values)
|
|
113
|
+
Output: (key2, value_final)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Combina todos los valores para cada clave.
|
|
117
|
+
|
|
118
|
+
### 3. SHUFFLE (automático)
|
|
119
|
+
El framework agrupa automáticamente todos los valores por clave.
|
|
120
|
+
|
|
121
|
+
**✨ Magia**: Google maneja distribución, fallas, y balanceo por ti.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 🗺️ La Función Map
|
|
126
|
+
|
|
127
|
+
<!--
|
|
128
|
+
Vim tip:
|
|
129
|
+
- yy: copiar línea completa
|
|
130
|
+
- p: pegar debajo
|
|
131
|
+
- ciw: cambiar palabra bajo cursor (útil para renombrar)
|
|
132
|
+
-->
|
|
133
|
+
|
|
134
|
+
Map transforma cada input independientemente:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Firma de Map
|
|
138
|
+
function map(key, value) {
|
|
139
|
+
// Procesa el input
|
|
140
|
+
// Emite cero o más pares (k2, v2)
|
|
141
|
+
return [[k2, v2], [k2, v2], ...]
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Ejemplo: Word Count
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
function map(documentId, content) {
|
|
149
|
+
const words = content.split(/\s+/)
|
|
150
|
+
const results = []
|
|
151
|
+
|
|
152
|
+
for (const word of words) {
|
|
153
|
+
results.push([word.toLowerCase(), 1])
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return results
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Input: (doc1, "MapReduce es genial")
|
|
160
|
+
// Output: [
|
|
161
|
+
// ["mapreduce", 1],
|
|
162
|
+
// ["es", 1],
|
|
163
|
+
// ["genial", 1]
|
|
164
|
+
// ]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Propiedad clave**: Cada documento se procesa **independientemente**.
|
|
168
|
+
→ Se puede ejecutar en N máquinas en paralelo.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 📦 La Función Reduce
|
|
173
|
+
|
|
174
|
+
<!-- Vim tip: Ctrl+d para scroll down rápido -->
|
|
175
|
+
|
|
176
|
+
Reduce combina todos los valores para una clave:
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// Firma de Reduce
|
|
180
|
+
function reduce(key, values) {
|
|
181
|
+
// Agrega/combina los valores
|
|
182
|
+
// Retorna resultado final
|
|
183
|
+
return finalValue
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Ejemplo: Sumar conteos
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
function reduce(word, counts) {
|
|
191
|
+
let sum = 0
|
|
192
|
+
|
|
193
|
+
for (const count of counts) {
|
|
194
|
+
sum += count
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return sum
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Input: ("mapreduce", [1, 1, 1, 1])
|
|
201
|
+
// Output: 4
|
|
202
|
+
|
|
203
|
+
// Input: ("genial", [1])
|
|
204
|
+
// Output: 1
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**El framework agrupa automáticamente**:
|
|
208
|
+
- "mapreduce" → [1, 1, 1, 1]
|
|
209
|
+
- "genial" → [1]
|
|
210
|
+
- "es" → [1, 1]
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 🔨 Ejercicio 1: Word Count Completo
|
|
215
|
+
|
|
216
|
+
<!--
|
|
217
|
+
LazyVim tips:
|
|
218
|
+
1. <leader>e: Abre neo-tree (file explorer)
|
|
219
|
+
2. Crea archivo: borrador.js (presiona 'a' en neo-tree)
|
|
220
|
+
3. Copia el código de abajo
|
|
221
|
+
4. <leader>`: Abre terminal flotante
|
|
222
|
+
5. node borrador.js para ejecutar
|
|
223
|
+
-->
|
|
224
|
+
|
|
225
|
+
### Paso 1: Copia este código a `borrador.js`
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
// Word Count con MapReduce
|
|
229
|
+
|
|
230
|
+
const documents = [
|
|
231
|
+
{ id: 'doc1', content: 'MapReduce es genial' },
|
|
232
|
+
{ id: 'doc2', content: 'MapReduce procesa big data' },
|
|
233
|
+
{ id: 'doc3', content: 'Big data es el futuro' }
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
// ==================== MAP ====================
|
|
237
|
+
function map(doc) {
|
|
238
|
+
const words = doc.content.toLowerCase().split(/\s+/)
|
|
239
|
+
return words.map(word => [word, 1])
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log('📍 FASE MAP:\n')
|
|
243
|
+
|
|
244
|
+
const mapResults = []
|
|
245
|
+
for (const doc of documents) {
|
|
246
|
+
const pairs = map(doc)
|
|
247
|
+
console.log(`${doc.id}: ${doc.content}`)
|
|
248
|
+
console.log(` →`, pairs)
|
|
249
|
+
console.log('')
|
|
250
|
+
|
|
251
|
+
mapResults.push(...pairs)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ==================== SHUFFLE ====================
|
|
255
|
+
console.log('🔀 FASE SHUFFLE (agrupación):\n')
|
|
256
|
+
|
|
257
|
+
const grouped = {}
|
|
258
|
+
for (const [word, count] of mapResults) {
|
|
259
|
+
if (!grouped[word]) {
|
|
260
|
+
grouped[word] = []
|
|
261
|
+
}
|
|
262
|
+
grouped[word].push(count)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
for (const [word, counts] of Object.entries(grouped)) {
|
|
266
|
+
console.log(`"${word}": [${counts.join(', ')}]`)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ==================== REDUCE ====================
|
|
270
|
+
console.log('\n📊 FASE REDUCE:\n')
|
|
271
|
+
|
|
272
|
+
function reduce(word, counts) {
|
|
273
|
+
return counts.reduce((a, b) => a + b, 0)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const results = {}
|
|
277
|
+
for (const [word, counts] of Object.entries(grouped)) {
|
|
278
|
+
results[word] = reduce(word, counts)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
console.log('✅ Resultado Final:\n')
|
|
282
|
+
const sorted = Object.entries(results).sort((a, b) => b[1] - a[1])
|
|
283
|
+
for (const [word, count] of sorted) {
|
|
284
|
+
console.log(` ${word}: ${count}`)
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Paso 2: Ejecuta y observa
|
|
289
|
+
|
|
290
|
+
Abre el terminal (<leader>\`) y corre:
|
|
291
|
+
```bash
|
|
292
|
+
node borrador.js
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Observa** las 3 fases:
|
|
296
|
+
1. MAP: Cada doc → pares (palabra, 1)
|
|
297
|
+
2. SHUFFLE: Agrupa por palabra
|
|
298
|
+
3. REDUCE: Suma conteos
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 🚀 Ejercicio 2: Log Analysis
|
|
303
|
+
|
|
304
|
+
Ahora tú implementas MapReduce desde cero.
|
|
305
|
+
|
|
306
|
+
### El Problema
|
|
307
|
+
|
|
308
|
+
Tienes logs de un servidor. Encuentra las URLs con más errores 404.
|
|
309
|
+
|
|
310
|
+
```javascript
|
|
311
|
+
const logs = [
|
|
312
|
+
'192.168.1.1 GET /home 200',
|
|
313
|
+
'192.168.1.2 GET /api/users 404',
|
|
314
|
+
'192.168.1.3 GET /home 200',
|
|
315
|
+
'192.168.1.1 GET /api/users 404',
|
|
316
|
+
'192.168.1.4 GET /about 200',
|
|
317
|
+
'192.168.1.2 GET /api/products 404',
|
|
318
|
+
'192.168.1.5 GET /api/users 404'
|
|
319
|
+
]
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Tu Tarea
|
|
323
|
+
|
|
324
|
+
<!-- Vim tip: Visual mode (V) + y para copiar bloque -->
|
|
325
|
+
|
|
326
|
+
1. **Map**: Si status es 404, emite (URL, 1)
|
|
327
|
+
2. **Shuffle**: Agrupa por URL (el framework lo hace)
|
|
328
|
+
3. **Reduce**: Suma los conteos
|
|
329
|
+
4. **Output**: Top 3 URLs con más 404s
|
|
330
|
+
|
|
331
|
+
### Código Base (complétalo)
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
const logs = [
|
|
335
|
+
'192.168.1.1 GET /home 200',
|
|
336
|
+
'192.168.1.2 GET /api/users 404',
|
|
337
|
+
'192.168.1.3 GET /home 200',
|
|
338
|
+
'192.168.1.1 GET /api/users 404',
|
|
339
|
+
'192.168.1.4 GET /about 200',
|
|
340
|
+
'192.168.1.2 GET /api/products 404',
|
|
341
|
+
'192.168.1.5 GET /api/users 404'
|
|
342
|
+
]
|
|
343
|
+
|
|
344
|
+
function map(log) {
|
|
345
|
+
const parts = log.split(' ')
|
|
346
|
+
const url = parts[2]
|
|
347
|
+
const status = parts[3]
|
|
348
|
+
|
|
349
|
+
// TODO: Si status === '404', retorna [[url, 1]]
|
|
350
|
+
// Sino, retorna []
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function reduce(url, counts) {
|
|
354
|
+
// TODO: Suma los conteos
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Ejecuta MapReduce aquí...
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Solución (no hagas trampa 😉)
|
|
361
|
+
|
|
362
|
+
<details>
|
|
363
|
+
<summary>Click para ver solución</summary>
|
|
364
|
+
|
|
365
|
+
```javascript
|
|
366
|
+
function map(log) {
|
|
367
|
+
const parts = log.split(' ')
|
|
368
|
+
const url = parts[2]
|
|
369
|
+
const status = parts[3]
|
|
370
|
+
|
|
371
|
+
if (status === '404') {
|
|
372
|
+
return [[url, 1]]
|
|
373
|
+
}
|
|
374
|
+
return []
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function reduce(url, counts) {
|
|
378
|
+
return counts.reduce((a, b) => a + b, 0)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Map phase
|
|
382
|
+
const mapResults = logs.flatMap(map)
|
|
383
|
+
|
|
384
|
+
// Shuffle phase
|
|
385
|
+
const grouped = {}
|
|
386
|
+
for (const [url, count] of mapResults) {
|
|
387
|
+
if (!grouped[url]) grouped[url] = []
|
|
388
|
+
grouped[url].push(count)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Reduce phase
|
|
392
|
+
const results = {}
|
|
393
|
+
for (const [url, counts] of Object.entries(grouped)) {
|
|
394
|
+
results[url] = reduce(url, counts)
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Top 3
|
|
398
|
+
const top3 = Object.entries(results)
|
|
399
|
+
.sort((a, b) => b[1] - a[1])
|
|
400
|
+
.slice(0, 3)
|
|
401
|
+
|
|
402
|
+
console.log('Top 3 URLs con más 404s:')
|
|
403
|
+
top3.forEach(([url, count]) => {
|
|
404
|
+
console.log(` ${url}: ${count} errores`)
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
// Output:
|
|
408
|
+
// /api/users: 3 errores
|
|
409
|
+
// /api/products: 1 errores
|
|
410
|
+
```
|
|
411
|
+
</details>
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## 🎯 Reflexión Final
|
|
416
|
+
|
|
417
|
+
### Lo que aprendiste
|
|
418
|
+
|
|
419
|
+
1. **MapReduce = 2 funciones simples**
|
|
420
|
+
- Map: transforma elementos independientemente
|
|
421
|
+
- Reduce: agrega valores por clave
|
|
422
|
+
|
|
423
|
+
2. **Paralelización automática**
|
|
424
|
+
- Map se ejecuta en N máquinas
|
|
425
|
+
- Reduce procesa grupos en paralelo
|
|
426
|
+
|
|
427
|
+
3. **Abstracción poderosa**
|
|
428
|
+
- Word count
|
|
429
|
+
- Log analysis
|
|
430
|
+
- Inverted index
|
|
431
|
+
- Todo sigue el mismo patrón
|
|
432
|
+
|
|
433
|
+
### Tecnologías basadas en MapReduce
|
|
434
|
+
|
|
435
|
+
```
|
|
436
|
+
📦 Hadoop → Implementación open-source de MapReduce
|
|
437
|
+
⚡ Spark → MapReduce en memoria (10-100x más rápido)
|
|
438
|
+
☁️ BigQuery → SQL sobre MapReduce (Google Cloud)
|
|
439
|
+
🌊 AWS EMR → MapReduce managed en AWS
|
|
440
|
+
🐘 Hive → SQL sobre Hadoop
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### El Paper Original
|
|
444
|
+
|
|
445
|
+
Si quieres leer el paper completo:
|
|
446
|
+
```
|
|
447
|
+
https://static.googleusercontent.com/media/research.google.com/en//archive/mapreduce-osdi04.pdf
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## 🏆 Completado
|
|
453
|
+
|
|
454
|
+
Has recreado uno de los papers más influyentes en la historia de la computación.
|
|
455
|
+
|
|
456
|
+
**Próximo paso**: Desbloquea **Bitcoin** completando 1 proyecto en Creta.
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
<!--
|
|
461
|
+
Vim tips que usaste hoy:
|
|
462
|
+
✅ zM - cerrar todos los folds
|
|
463
|
+
✅ za - toggle fold
|
|
464
|
+
✅ } - saltar párrafos
|
|
465
|
+
✅ ]] - saltar secciones
|
|
466
|
+
✅ <leader>e - file explorer
|
|
467
|
+
✅ <leader>` - terminal
|
|
468
|
+
✅ yy/p - copiar/pegar
|
|
469
|
+
✅ ciw - cambiar palabra
|
|
470
|
+
|
|
471
|
+
Próximos tips (Bitcoin paper):
|
|
472
|
+
- <leader>ff - fuzzy find files
|
|
473
|
+
- gd - go to definition
|
|
474
|
+
- <leader>ca - code actions
|
|
475
|
+
- gcc - comentar línea
|
|
476
|
+
-->
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Spark: Resilient Distributed Datasets
|
|
2
|
+
**Matei Zaharia et al., UC Berkeley (2010)**
|
|
3
|
+
|
|
4
|
+
<!--
|
|
5
|
+
Vim Tips Nivel 3:
|
|
6
|
+
- <leader>sg: Search with grep
|
|
7
|
+
- <leader>sr: Search and replace
|
|
8
|
+
- %s/foo/bar/g: Replace en todo el archivo
|
|
9
|
+
- :%norm A;: Agrega ; al final de cada línea
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 📚 Contexto: 6 Años Después de MapReduce
|
|
15
|
+
|
|
16
|
+
**2010**: Hadoop se volvió estándar... pero era **lento**.
|
|
17
|
+
|
|
18
|
+
### El Problema
|
|
19
|
+
|
|
20
|
+
Machine Learning requiere **muchas iteraciones**:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
Iteración 1: Leer disco → Map → Reduce → Escribir disco
|
|
24
|
+
Iteración 2: Leer disco → Map → Reduce → Escribir disco
|
|
25
|
+
...
|
|
26
|
+
Iteración 100: Leer disco → Map → Reduce → Escribir disco
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Disco es 100-1000x más lento que RAM** 🐌
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 💡 La Solución: In-Memory Computing
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Primera carga: Disco → RAM
|
|
37
|
+
Iteración 1-100: Todo en RAM ⚡
|
|
38
|
+
Final: RAM → Disco
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Resultado: 10-100x más rápido**
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 🏆 Próximamente
|
|
46
|
+
|
|
47
|
+
Contenido completo de Spark en desarrollo.
|
|
48
|
+
|
|
49
|
+
Completa MapReduce y Bitcoin primero!
|