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

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Stack & Queue

si el tunel tiene salida, entonces el primer niño en entrar sera ek primer niño en salir,

     Es un ejemplo de cola (queue, FIFO, First In First Out).

si no la tiene, entonces deberia dar la vuelta y el ultimo en entrar sera el primero en salir,

     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:

class Tunnel {
    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.

Imagen de Rafael Carrillo

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 falso

y que imprima en pantalla el orden de los niños en cada caso.

Imagen de Rafael Carrillo

mejor ignoren mi comentario

no se como borrarlo

Imagen de Cid

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.

Imagen de chicowed

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?

Imagen de Cid

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:

public class Tunel {

        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();
        }
}

Imagen de Cid

La otra opción

Bueno la otra era usar un tipo de Deque como LinkedList o ArrayDeque:;

import java.util.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:

public static void main(String[] args) {
    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 de ArrayDeque <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

interface Tunnel<E> {
    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.

import static java.lang.System.out;

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.

// Test it
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 implementa java.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 :)

Imagen de ezamudio

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í:

class Tunel(Boolean salida) {
  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:

shared void testTunnel() {
  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);
  }
}
Imagen de ezamudio

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:

class Tunel2(Boolean salida) {
  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. :)

Imagen de ezamudio

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 escribir T[]
  • [T+] es una secuencia con uno o más T
  • [T*] es de tipo Sequential, que puede tener dos subtipos: Empty, o Sequence. Empty ps es una secuencia vacía, de hecho su argumento de tipo es Nothing. Sequence es el [T+], es una secuencia que no está vacía, tiene al menos un elemento siempre. El operador nonempty 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:

    void f(String s, Integer i, Float f) {}
    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) :-P

Imagen de ezamudio

jejej

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.

Imagen de Nopalin

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.