Ayuda
NO SE COMO EMPEZAR
suponga que unos niños estaban jugando en una vieja fabrica y descubren un tunel oscuro y como cualquier persoona,
decidieron entrar a ver si tenia salida o no .
si el tunel tiene salida, entonces el primer niño en entrar sera ek primer niño en salir,
si no la tiene, entonces deberia dar la vuelta y el ultimo en entrar sera el primero en salir,
usted debera decidir si tiene o no salida
Realice un programa para que los niños entren uno a uno y despues salga uno a uno diciendo su nombre, considere que el tunel puede tener salida por el otro extremmo
- Inicie sesión o regístrese para enviar comentarios
Stack & Queue
Es un ejemplo de cola (queue, FIFO, First In First Out).
Es un ejemplo de pila (stack, LIFO, Last In First Out).
~~~
Comienza definiendo una clase
Comienza definiendo una clase que va a implementar lo que quieres:
private boolean hasExit;
public void add( String child ) {
...
}
public String remove() {
...
}
public static void main( String ... args ) {
Tunnel t = new Tunnel();
t.hasExit = false;
t.add("Hugo");
t.add("Paco");
t.add("Luis");
System.out.println(t.remove());
System.out.println(t.remove());
}
}
Y luego continúa implementando esos dos métodos.
En el método remove tienes que ver si el tunel tiene salida; si tiene, sacas el primero que entró ( como en una Cola como dice jpaul ) y si no tiene sacas el último que entró (Pila como dice jpaul)
Para almacenar a los niños usa un arreglo o una lista ( java.util.List )
Intenta avanzar con eso y si tienes dudas vuelve a preguntar.
si no me equivoco Y si lo hago que alguien me lo diga por favor
debería hacer que al momento de decirle al programa que niño entra primero le asigne un ID ya sea con un HashMap y algún tipo de
if
que verifique si el boolean de si el tunel tiene salida sea verdadero o falsoy que imprima en pantalla el orden de los niños en cada caso.
mejor ignoren mi comentario
no se como borrarlo
Usa LinkedList
Si te permiten usar cualquier colección y no tienes que hacer tu propia implementacion yo usaria LinkedList ya que esta implementa las interfaces List y Deque entre otras, con la segunda te permite ir obteniendo y sacando los datos de la colección de ambos lados (actuando como Double End Queue):
Un pequeño ejemplo: aqui.
Para referencia tambien puedes ver estas ligas:
Aqui definen que es un Deque
Aquí mencionan algo más sobre Deque
y tambien checa Deque y LinkedList, es la documentación oficial.
Un simple arreglo, un indice
Un simple arreglo, un indice y un if es lo único que le hace falta al código que puse. Usar otra estructura de datos en este momento parecería "overkill" pero igual al parecer (como en muchas otras ocasiones) es autor del post jamás regresará a ver si alguien respondió su pregunta.
Fecha de entrega Vencida
Es que la fecha de entrega de la tarea ya termino, y el camarada esta frito, pero lo que no sabes es que debería venir a checar las respuestas, nunca se sabe tal vez pueda venir en el Examen Extraordinario o en el Adicional jajajaja
Pues convirtámoslo en kata /
Pues convirtámoslo en kata / showdown ... quien empieza?
Ok va
Algo aprenderé, en un rato libre hice el código, se que pueden meter lambdas y otros conceptos ademas de refactorizar varias cosas ahi lo dejo:
private String[] line;
private final boolean hasExit;
Tunel(boolean hasExit) {
this.hasExit = hasExit;
line = new String[3];
}
public void add(String child) {
int index = findPlace();
if (index == -1){
String[] temp = line;
line = new String[temp.length + 1];
System.arraycopy(temp, 0, line, 0, temp.length);
line[line.length - 1] = child;
} else{
line[index] = child;
}
}
public String remove() {
String result = null;
if (!isEmpty()){
if (hasExit){
result = line[0];
for (int i = 0; i < line.length - 1; i++){
line[i] = line[i + 1];
line[i + 1] = null;
}
} else{
result = line[line.length - 1];
for (int i = line.length - 1; i >= 1; i--){
line[i] = line[i - 1];
line[i - 1] = null;
}
}
}
return result;
}
public static void main(String[] args) {
Tunel tunel = new Tunel(false);
tunel.add("Hugo");
tunel.add("Paco");
tunel.add("Luis");
tunel.add("Cynthia");
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
}
public int findPlace() {
int index = -1;
for (int i = 0; i < line.length; i++){
if (line[i] == null){
index = i;
break;
}
}
return index;
}
public boolean isEmpty() {
boolean result = true;
for (String tmp : line){
result = (tmp != null) ? false : result;
if (!result){
break;
}
}
return result;
}
public void print() {
for (String tmp : line){
if (tmp != null){
System.out.print(tmp + " ");
}
}
System.out.println();
}
}
La otra opción
Bueno la otra era usar un tipo de Deque como LinkedList o ArrayDeque:;
public class TunelDeque {
private final ArrayDeque <String> line;
private final boolean hasExit;
TunelDeque(boolean hasExit) {
this.hasExit = hasExit;
line = new ArrayDeque <String>(3);
}
public static void main(String[] args) {
TunelDeque tunel = new TunelDeque(false);
tunel.add("Hugo");
tunel.add("Paco");
tunel.add("Luis");
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
System.out.println("Remove: " + tunel.remove());
tunel.print();
}
public String remove() {
String name = (hasExit) ? line.pollFirst() : line.pollLast();
return name;
}
public void add(String child) {
line.addFirst(child);
}
public void print() {
System.out.println(line);
}
}
Estructura de datos
Seguramente, como Josué ya mencionó, se trata de alguna tarea de estructura de datos. Aunque en Java se tiene un conjunto de clases e interfaces conocido como The Collections Framework, considero que es importante conocer los fundamentos detras de cada estructura de datos para utilizar esas clases e interfaces de una manera óptima.
Utilizando la plantilla de Oscar, el siguiente código incluye una implementación —muy rudimentaria— de una lista doblemente ligada/enlazada (aquí hay una imagen), que intenta resolver el problema planteado por el OP:
class Node<T> {
T payload;
Node<T> next;
Node<T> prev;
public Node(T payload) {
this.payload = java.util.Objects.requireNonNull(payload);
}
}
class Tunnel<T> {
boolean hasExit;
Node<T> head;
Node<T> tail;
public void add(T t) {
Node<T> node = new Node<>(t);
if (head == null) {
head = node;
} else {
tail.next = node;
node.prev = tail;
}
tail = node;
}
public T remove() {
if (head == null) {
return null;
}
if (hasExit) {
Node<T> temp = head;
if (head.next == null) {
tail = null;
} else {
head.next.prev = null;
}
head = head.next;
return temp.payload;
} else {
Node<T> temp = tail;
if (head.next == null) {
head = null;
} else {
tail.prev.next = null;
}
tail = tail.prev;
return temp.payload;
}
}
}
Tunnel<String> t = new Tunnel<>();
t.hasExit = true;
t.add("Hugo");
t.add("Paco");
t.add("Luis");
System.out.println(t.remove());
System.out.println(t.remove());
t.hasExit = false;
System.out.println("¡Sin salida!");
t.add("Juan");
t.add("Olga");
t.add("Ciro");
for(String child; (child = t.remove()) != null;) {
System.out.println(child);
}
}
Ver demo en línea.
~~~
El tipo de dato debe de ser:
Respecto a: http://www.javamexico.org/foros/comunidad/ayuda_4#comment-27952 El tipo de dato debe de ser:
Daque<String>
en vez deArrayDeque <String>
( La interfaz y sin espacio en el generic) y si lo vas a hacer final puedes inicializarlo de una vez.ArrayTunnel
Primero defino la interfaz que representa un túnel al que se le pueden meter y sacar cosas. No porque lo necesite, simplemente para seguir la convención del paquete java.util
public void add(E child);
public E remove();
}
Y luego lo implemento con un arreglo. Siguiendo el ejemplo de ArrayList, se puede implementar un ArrayTunnel que crezca y crezca.
Como siempre intenté hacerlo muy sencillo y termino algo que si bien no es nada complicado, tampoco es oneliner.
class ArrayTunnel<E> implements Tunnel<E> {
private Object[] tube;
private final boolean hasExit;
private int i; // index to the last element;
public ArrayTunnel(boolean hasExit) {
this.tube = new Object[10];
this.hasExit = hasExit;
}
@SuppressWarnings("unchecked")
public void add( E child ) {
if( i == tube.length ) { // allocate more space
E[] newData = (E[]) new Object[tube.length+10];
System.arraycopy(tube, 0, newData, 0, tube.length);
tube = newData;
}
tube[i++] = child;
}
@SuppressWarnings("unchecked")
public E remove() {
--i;// we are going to have one less
E value = (E) tube[ hasExit ? 0 : i ];
if (hasExit) { // shift elements by one
System.arraycopy(tube, 1, tube, 0, tube.length-1);
}
return value; // profit
}
}
Y probando.
class Main {
public static void main( String ... args ) {
Tunnel<String> t = new ArrayTunnel<>(false);
t.add("Hugo");
t.add("Paco");
t.add("Luis");
out.println(t.remove());
out.println(t.remove());
out.println("Adding more kids");
t.add("Oscar");
out.println(t.remove());
out.println(t.remove());
}
}
$java Main
Luis
Paco
Adding more kids
Oscar
Hugo
Lo interesante es que no sabía como funcionaba ArrayList y ahora sé que al quitar un elemento de enfrente se recorren todos los elementos copiandolo al mismo arreglo.
También ignoraba como crear un arreglo cuando se usaban generics, el secreto está en hacer el cast:
E[] existente = (E[]) nuevo;
y ponerle la anotación@SuppressWarnings
; ¡que cosas! pero así lo implementajava.util.ArrayList
Algún día le pondremos votos
Algún día le pondremos votos a este sitio, por lo pronto +1 por a SrCid y a jpaul por sus impl :)
Ceylon
Chale, pues ya ni pensaba pelar esto pero bueno, no quiero perder la oportunidad de mostrar la alternativa en Ceylon. Sin utilizar módulos adicionales, la hice así:
variable [String*] chavos = [];
shared void add(String chavo)
=> chavos = chavos.withLeading(chavo);
shared String? remove() {
if (nonempty kids=chavos) {
String? chavo;
if (salida) {
chavo = chavos[kids.lastIndex];
chavos = chavos.initial(kids.lastIndex);
} else {
chavo = chavos.first;
chavos = chavos[1...];
}
return chavo;
}
return null;
}
}
Y su comprobación:
value fifo = Tunel(true);
value lifo = Tunel(false);
value data = ["Uno", "Dos", "Tres"];
for (s in data) {
fifo.add(s);
lifo.add(s);
}
for (s in data) {
assert(exists e=fifo.remove(), e==s);
}
for (s in data.reversed) {
assert(exists e=lifo.remove(), e==s);
}
}
Curioso
Algo que noté implementando esto, es que se puede hacer una implementación más corta si la condición de tener salida o no, se revisa al meter elementos a la colección, en vez de a la hora de sacarlos:
variable [String*] chavos = [];
shared void add(String chavo)
=> chavos = salida then chavos.withTrailing(chavo) else chavos.withLeading(chavo);
shared String? remove() {
String? chavo = chavos.first;
chavos = chavos[1...];
return chavo;
}
}
Pero, aunque parezca no haber diferencia y sólo ser una optimización, la diferencia realmente es importante por no seguir la especificación: Qué pasa si hacemos que el atributo salida sea variable? Es decir, llenar la colección, y luego poder tapar y destapar la salida conforme se van sacando elementos... la segunda implementación no funciona con esa nueva funcionalidad, mientras que la primera funcionaría sin problemas.
Jaja cierto, la mayoría de
Jaja cierto, la mayoría de las veces la estructura de datos no va a cambiar su comportamiento al vuelo.
Como se llama el tipo de dato
String*
?Alguna vez se desharán de los modificadores "shared", "variable" etc. :)
tipos
Los tipos secuenciales son parte de los tipos de colección:
{T*}
es un iterable (secuencia tardía) con cero o más T{T+}
es un iterable con uno o más T[T*]
es una secuencia con cero o más T. También se puede escribirT[]
[T+]
es una secuencia con uno o más T[T*]
es de tipoSequential
, que puede tener dos subtipos:Empty
, oSequence
. Empty ps es una secuencia vacía, de hecho su argumento de tipo esNothing
. Sequence es el[T+]
, es una secuencia que no está vacía, tiene al menos un elemento siempre. El operadornonempty
te sirve para refinar un [T*] a [T+].Ahora, si usas
T*
solito en una lista de parámetros, es un parámetro variádico (como cuando en Java le pones tres puntos). Y si tienes un valor secuencial, lo puedes desplegar (spread) anteponiéndole un asterisco. Incluso con tuplas lo puedes hacer. Si tienes una tupla tipo[String,Integer,Float]
y un método que recibe exactamente esos tres tipos de parámetros, puedes pasarla directo:value tupla = ["1", 2, 3.0];
f(*tupla);
//Lo anterior es azúcar para esto:
f(tupla[0], tupla[1], tupla[2]);
No, no vamos a deshacernos de shared ni variable. Entiendan que shared no es lo mismo que public, y que favorecemos la inmutabilidad, por lo que si quieres que algo sea mutable, tienes que teclear la palabrota variable.
Oigan ...
Oigan, Oscar y Enrique ¡Sólo estaba siendo retórico! Recuerdo haber visto en algún lado algo como
t.hasExit = false;
(silbidos en el aire) :-Pjejej
sí jpaul, tu Túnel se puede configurar al vuelo, ponerle o quitarle salida. Y está bien hecho porque esa configuración afecta el método para sacar algo de la colección, no para meter algo.
Que bonitos... haciendo la
Que bonitos... haciendo la tarea de los demás!!
kata / showdown!
kata / showdown!
@nopalin El post ya tenía una
@nopalin El post ya tenía una semana sin respuestas... y pues ya.