Академический Документы
Профессиональный Документы
Культура Документы
Un disco de mayor tamao no puede descansar sobre uno ms pequeo que l mismo.
3.
[fuente Wikipedia]
Torres de Hani
En este artculo sobre ocio se detectaron los siguientes problemas:
Torres de Hani.
1 Descripcin
2 Historia
3 Resolucin
o
3.3 Iterativa
4 Variantes
5 Vase tambin
6 Notas y referencias
7 Enlaces externos
Descripcin[editar]
El juego, en su forma ms tradicional, consiste en tres varillas verticales. En una de las varillas
se apila un nmero indeterminado de discos (elaborados de madera) que determinar la
complejidad de la solucin, por regla general se consideran ocho discos. Los discos se apilan
sobre una varilla en tamao decreciente. No hay dos discos iguales, y todos ellos estn
apilados de mayor a menor radio en una de las varillas, quedando las otras dos varillas
vacantes. El juego consiste en pasar todos los discos de la varilla ocupada (es decir la que
posee la torre) a una de las otras varillas vacantes. Para realizar este objetivo, es necesario
seguir tres simples reglas:
1. Slo se puede mover un disco cada vez.
2. Un disco de mayor tamao no puede descansar sobre uno ms pequeo que l
mismo.
Historia[editar]
Se cuenta que en un templo de Benars (Uttar Pradesh, India) se encontraba una cpula que
sealaba el centro del mundo. All estaba una bandeja sobre la que existan tres agujas de
diamante. En una maana lluviosa, un rey mand a poner 64 discos de oro ordenados por
tamao: el mayor, en la base de la bandeja, y el menor, arriba de todos los discos. Tras su
colocacin, los sacerdotes del templo intentaron mover los discos entre las agujas, segn las
leyes que se les haban entregado: El sacerdote de turno no debe mover ms de un disco a
la vez, y no puede situar ningn disco encima de otro de menor dimetro. Hoy no existe tal
templo, pero el juego an perdura en el tiempo.
Otra leyenda cuenta que Dios, al crear el mundo, coloc tres varillas de diamante con 64
discos en la primera. Tambin cre unmonasterio con monjes, quienes tenan la tarea de
resolver esta Torre de Hani divina. El da que estos monjes consiguieran terminar el juego, el
mundo acabara. No obstante, esta leyenda result ser un invento publicitario del creador del
juego, el matemtico duard Lucas. (En aquella poca, era muy comn encontrar
matemticos ganndose la vida de forma itinerante con juegos de su invencin, de la misma
forma que los juglares lo hacan con su msica. No obstante, la falacia result ser tan efectista
y tan bonita que ha perdurado hasta nuestros das. Adems, invita a realizarse la pregunta:
Si la leyenda fuera cierta, cundo sera el fin del mundo?.) La mnima cantidad de
movimientos para resolver este problema es de 264 1; si los monjes hicieran un movimiento
por segundo, sin equivocarse, los 64 discos estaran en la tercera varilla en algo menos de
585 mil millones de aos. (Como comparacin para ver la magnitud de esta cifra,
la Tierra tiene unos 5 mil millones de aos, y el Universo, unos 14 mil millones de aos de
antigedad, solo una pequea fraccin de esa cifra.)
Resolucin[editar]
La solucin del problema de las Torres de Hani es muy fcil de hallar, aunque el nmero de
pasos para resolver el problema crece exponencialmente conforme aumenta el nmero de
discos.
Solucin simple[editar]
Una forma de resolver el problema se fundamenta en el disco ms pequeo, el de ms arriba
en la varilla de origen. El movimiento inicial de este es hacia la varilla auxiliar. El disco n.o 2 se
debe mover, por regla, a la varilla destino. Luego, el disco n.o 1 se mueve tambin a la
varilla destino para que quede sobre el disco n.o 2. A continuacin, se mueve el disco que
sigue de la varilla origen, en este caso el disco n.o 3, y se coloca en la varilla auxiliar.
Finalmente, el disco n.o 1 regresa de la varilla destino a la origen (sin pasar por la auxiliar), y
as sucesivamente. Es decir, el truco est en el disco ms pequeo.
Mediante recursividad[editar]
Este problema se suele plantear a menudo en programacin, especialmente para explicar
la recursividad. Si numeramos los discos desde 1 hasta n, si llamamos origen a la primera pila
de discos, destino a la tercera y auxiliar a la intermedia, y si a la funcin la
denominramos hanoi, con origen, auxiliar y destino como parmetros, el algoritmo de la
funcin sera el siguiente:
Entrada: Tres pilas de nmeros origen, auxiliar, destino, con la pila origen ordenada
Salida: La pila destino
1. si origen
entonces
1. mover el disco 1 de pila origen a la pila destino (insertarlo arriba de la pila destino)
2. terminar
2. si no
1. hanoi(
,origen,destino, auxiliar)
Iterativa[editar]
Otra manera de resolver el problema, sin utilizar la recursividad, se basa en el hecho de que
para obtener la solucin ms corta, es necesario mover el disco ms pequeo en todos los
pasos impares, mientras que en los pasos pares slo existe un movimiento posible que no lo
incluye. El problema se reduce a decidir en cada paso impar a cul de las dos pilas posibles
se desplazar el disco pequeo. El algoritmo en cuestin depende del nmero de discos del
problema:
Variantes[editar]
Henry Dudeney en su libro The Canterbury Puzzles (1907) propuso una variante
(llamada Problema del almojarife o The reve's puzzle) que usa cuatro agujas en
lugar de tres.2 En 1939, J. S. Frame y B. M. Stewart propusieron en forma
independiente un algoritmo que resuelve el problema, dado un parmetro i:
1. Trasladar recursivamente una pila de n i discos, desde la aguja inicial a otra
auxiliar, usando las cuatro agujas en el proceso.
2. Trasladar los i discos ms grandes, desde la aguja inicial hacia la aguja final,
usando el algoritmo estndar para tres agujas e ignorando la cuarta.
3. Recursivamente trasladar los n i discos ms pequeos, desde la aguja
auxiliar hacia la aguja final, usando las cuatro agujas en el proceso.
Y demostraron que, si n es igual al nmero triangular tk, la eleccin ptima para i es
justamente k, y si tk 1 < n < tk, tanto k 1 como k lo son. Ntese que se est hablando
del valor ptimo para este algoritmo particular; encontrar el nmero mnimo de
movimientos en el caso general es, todava, una cuestin abierta. Sin embargo,
para n menor o igual a 30 discos se ha verificado que el algoritmo de Frame-Stewart
es, efectivamente, ptimo
Una lista es una estructura de datos que nos permite agrupar elementos de una
manera organizada. Las listas al igual que los algoritmos son importantsimas en la
computacin y crticas en muchos programas informticos.
Las listas estn compuestas por nodos, estos nodos tienen un dato o valor y un puntero
a otro(s) nodo(s).
Existen varios tipos de listas: Simplemente enlazada, doblemente enlazada, circular
simplemente enlazada, circular doblemente enlazada.
Vamos a revisar las listas enlazadas simples, por ser el punto de partida y
fundamentales para poder entender las otras.
Una lista enlazada tiene un conjunto de nodos, los cuales almacenan 2 tipos de
informacin: El dato que contienen y un puntero al siguiente nodo en la lista. El ltimo
nodo de la lista tiene como siguiente nodo el valor NULL. Entonces las listas enlazadas
simples solo pueden ser recorridas en una direccin, apuntando al nodo siguiente, mas
no a un nodo anterior.
Aqu una ejemplo de un lista enlazada simple.
1
2
3
4
5
6
7
En cristiano:
55-> 60-> 31-> 5-> 4-> 51-> 9-> 27-> 68-> 62-> NULL
Internamente:
Nodo-> Dato: 55
Nodo-> Dato: 60
Nodo-> Dato: 31
Nodo-> Dato: 5
Direcion:
Direcion:
Direcion:
Direcion:
0x3d2c00
0x3d2c80
0x3d2c90
0x3d2ca0
Siguiente:
Siguiente:
Siguiente:
Siguiente:
0x3d2c80
0x3d2c90
0x3d2ca0
0x3d2cb0
8
9
10
11
12
13
14
Nodo->
Nodo->
Nodo->
Nodo->
Nodo->
Nodo->
Dato:
Dato:
Dato:
Dato:
Dato:
Dato:
4
51
9
27
68
62
Direcion:
Direcion:
Direcion:
Direcion:
Direcion:
Direcion:
0x3d2cb0
0x3d2cc0
0x3d3ab8
0x3d3ac8
0x3d3ad8
0x3d3ae8
Siguiente:
Siguiente:
Siguiente:
Siguiente:
Siguiente:
Siguiente:
0x3d2cc0
0x3d3ab8
0x3d3ac8
0x3d3ad8
0x3d3ae8
0
Imprimir la lista
Buscar un elemento
Podrn ver la variable *temp en casi todos los mtodos , este es el puntero de tipo
Nodo que me va a permitir moverme a travs de la lista y que inicialmente es igual a la
cabeza (head). Mientras exista algo en la lista, voy avanzado el puntero para que
apunte al siguiente. Esto se consigue en casi todos los casos con un while.
1
2
3
while (temp) {
temp = temp->next;
}
Otra operacin comn en los mtodos es preguntar si inicialmente la lista est vaca,
es decir, si la cabeza no contiene algo o es igual a Null.
1
2
3
if (!m_head) {
...
}
Apliqu mis limitados conocimientos de templates para tener una lista genrica y as
pueda funcionar con varios tipos de datos y de verdad funciona.
Ah la definicin e implementacin de la clase, lista, clase nodo y el main para ver el
funcionamiento. Cualquier crtica, sugerencia o comentarios son bienvenidos siempre.
node.h
#ifndef NODE_H
1
#define NODE_H
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
template <class T>
class Node
{
public:
Node();
Node(T);
~Node();
Node *next;
T data;
};
void delete_all();
void print();
#endif // NODE_H
24
node.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "node.h"
// Constructor por defecto
template<typename T>
Node<T>::Node()
{
data = NULL;
next = NULL;
}
// Constructor por parmetro
template<typename T>
Node<T>::Node(T data_)
{
data = data_;
next = NULL;
}
// Eliminar todos los Nodos
template<typename T>
void Node<T>::delete_all()
{
if (next)
next->delete_all();
delete this;
}
// Imprimir un Nodo
template<typename T>
void Node<T>::print()
{
//cout << "Node-> " << "Dato: " << dato << " Direcion: " << this << " Siguiente:
next << endl;
cout << data << "-> ";
}
template<typename T>
Node<T>::~Node() {}
list.h
#ifndef LIST_H
1
#define LIST_H
2
3
4
5
6
#include
#include
#include
#include
<fstream>
<iostream>
<string>
<stdlib.h>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "node.h"
#include "node.cpp"
using namespace std;
template <class T>
class List
{
public:
List();
~List();
void
void
void
void
void
void
void
void
void
void
void
void
void
void
void
void
add_head(T);
add_end(T);
add_sort(T);
concat(List);
del_all();
del_by_data(T);
del_by_position(int);
fill_by_user(int);
fill_random(int);
intersection(List);
invert();
load_file(string);
print();
save_file(string);
search(T);
sort();
private:
Node<T> *m_head;
int m_num_nodes;
};
#endif // LIST_H
list.cpp
#include "list.h"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
m_head = NULL;
}
// Insertar al inicio
template<typename T>
void List<T>::add_head(T data_)
{
Node<T> *new_node = new Node<T> (data_);
Node<T> *temp = m_head;
if (!m_head) {
m_head = new_node;
} else {
new_node->next = m_head;
m_head = new_node;
while (temp) {
temp = temp->next;
}
}
m_num_nodes++;
// Insertar al final
template<typename T>
void List<T>::add_end(T data_)
{
Node<T> *new_node = new Node<T> (data_);
Node<T> *temp = m_head;
if (!m_head) {
m_head = new_node;
} else {
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new_node;
}
m_num_nodes++;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
}
}
m_num_nodes++;
while (temp2) {
add_end(temp2->data);
temp2 = temp2->next;
}
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
if (cont == 0) {
cout << "No existe el dato " << endl;
}
}
// Eliminar por posicin del nodo
template<typename T>
void List<T>::del_by_position(int pos)
{
Node<T> *temp = m_head;
Node<T> *temp1 = temp->next;
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
T temp;
for (int i = 0; i < size; i++) {
for (int j = i-1; j>= 0 && a[j+1] < a[j]; j--) {
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
// Lleno los vectores v1 y v2 con los datas de la lista original y segunda list
respectivamente
int i = 0;
while (temp) {
v1[i] = temp->data;
temp = temp->next;
i++;
}
int j = 0;
while (temp2) {
v2[j] = temp2->data;
temp2 = temp2->next;
j++;
}
// Ordeno los vectores
insert_sort(v1, m_num_nodes);
insert_sort(v2, num_nodes_2);
// ndice del 1er vector (v1)
int v1_i = 0;
// ndice del 2do vector (v2)
int v2_i = 0;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// Invertir la lista
template<typename T>
void List<T>::invert()
{
Node<T> *prev = NULL;
Node<T> *next = NULL;
Node<T> *temp = m_head;
while (temp) {
next = temp->next;
temp->next = prev;
prev = temp;
temp = next;
}
m_head = prev;
}
// Cargar una lista desde un archivo
template<typename T>
void List<T>::load_file(string file)
{
T line;
ifstream in;
in.open(file.c_str());
if (!in.is_open()) {
cout << "No se puede abrir el archivo: " << file << endl << endl;
} else {
while (in >> line) {
add_end(line);
}
}
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
in.close();
}
// Imprimir la Lista
template<typename T>
void List<T>::print()
{
Node<T> *temp = m_head;
if (!m_head) {
cout << "La Lista est vaca " << endl;
} else {
while (temp) {
temp->print();
if (!temp->next) cout << "NULL";
temp = temp->next;
}
}
cout << endl << endl;
}
// Buscar el dato de un nodo
template<typename T>
void List<T>::search(T data_)
{
Node<T> *temp = m_head;
int cont = 1;
int cont2 = 0;
while (temp) {
if (temp->data == data_) {
cout << "El dato se encuentra en la posicin: " << cont << endl;
cont2++;
}
temp = temp->next;
cont++;
}
if (cont2 == 0) {
cout << "No existe el dato " << endl;
}
cout << endl << endl;
}
// Ordenar de manera ascendente
template<typename T>
void List<T>::sort()
{
T temp_data;
Node<T> *aux_node = m_head;
Node<T> *temp = aux_node;
while (aux_node) {
temp = aux_node;
while (temp->next) {
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
temp = temp->next;
aux_node = aux_node->next;
}
// Guardar una lista en un archivo
template<typename T>
void List<T>::save_file(string file)
{
Node<T> *temp = m_head;
ofstream out;
out.open(file.c_str());
if (!out.is_open()) {
cout << "No se puede guardar el archivo " << endl;
} else {
while (temp) {
out << temp->data;
out << " ";
temp = temp->next;
}
}
out.close();
}
template<typename T>
List<T>::~List() {}
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
main.cpp
#include <iostream>
1
2
3
4
5
6
7
8
9
#include "list.h"
#include "list.cpp"
using namespace std;
int main()
{
List<int> list_1;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
List<int> list_2;
int ele;
int dim;
int pos;
string file_with_list;
cout << "Ingresa la dimensin de la lista: " << endl;
cin >> dim;
list_1.fill_random(dim);
cout << "Lista A al inicio " << endl;
list_1.print();
cout << "Agrega un elemento por la cabeza: " << endl;
cin >> ele;
list_1.add_head(ele);
list_1.print();
cout << "Lista invertida: " << endl;
list_1.invert();
list_1.print();
cout << "Lista ordenada: " << endl;
list_1.sort();
list_1.print();
cout << "Agrega un elemento. Ser insertado ordenadamente: " << endl;
cin >> ele;
list_1.add_sort(ele);
list_1.print();
cout << "Busca un elemento: " << endl;
cin >> ele;
list_1.search(ele);
cout << "Elimina un elemento por dato: " << endl;
cin >> ele;
list_1.del_by_data(ele);
list_1.print();
cout << "Elimina un elemento por posicin: " << endl;
cin >> pos;
list_1.del_by_position(pos);
list_1.print();
cout << "Cargar una lista desde archivo - Ingresa el nombre(Ex: list.txt): " <<
endl;
// El archivo debe estar en el mismo directorio que este programa
cin >> file_with_list;
list_2.load_file(file_with_list);
cout << "Lista B: " << endl;
list_2.print();
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
return 0;