Problema Java ricorsione e controllo

di il
5 risposte

Problema Java ricorsione e controllo

Ciao ho un problema su un esercizio che richiede di aggiungere degli argomenti ad un capitolo usando il metodo addTopic(Topic); tale metodo aggiunge un dato argomento al capitolo e, ricorsivamente, tutti i sotto-argomenti. Per esempio, se Class è un sotto-argomento di Java, e Abstract Class è un sotto-argomento di Class, aggiungere l’argomento Java significa aggiungere anche Class e Abstract Class, di conseguenza fatto cio il metodo getTopics() restituisce tutti gli argomenti inseriti con addTopic(), senza ripetizioni e ordinati alfabeticamente.

Scusate sono nuovo spero che la formattazione del codice sia corretta, sennò mi scuso a prioiri, comunque questo pezzo di codice non mi ritorna tutti i sotto-argomenti.

package it.polito.oop.books;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;

import static java.util.stream.Collectors.*;

import java.util.ArrayList;

public class TheoryChapter {
	
	private String title;
	private int numPages;
	private String text;
	List<Topic> topics = new LinkedList<>();

    public TheoryChapter(String title, int numPages, String text) {
		// TODO Auto-generated constructor stub
    	this.title = title;
    	this.numPages = numPages;
    	this.text = text;
	}

	public String getText() {
		return text;
	}

    public void setText(String newText) {
    	this.text = newText;
    }


	public List<Topic> getTopics() {
		List<Topic> elements = new ArrayList<>();
		elements = Stream.concat(topics.stream(), topics.stream().flatMap(f->f.subTopics.stream())).distinct().sorted().collect(toList()); 
	    return elements;
	}

    public String getTitle() {
        return title;
    }

    public void setTitle(String newTitle) {
    	this.title = newTitle;
    }

    public int getNumPages() {
        return numPages;
    }
    
    public void setNumPages(int newPages) {
    	this.numPages = newPages;
    }
    
    public void addTopic(Topic topic) {
    	topics.add(topic);
    }
}
Mentre il metodo di controllo deve restituire true se tutti gli argomenti specificati in tutti i capitoli di esercizi sono contenuti in almeno un capitolo di teoria. La classe degli esercizi è simile a quella di teoria. Il problema che il metodo di controllo si trova in un altra classe.


package it.polito.oop.books;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static java.util.stream.Collectors.*;
import static java.util.Comparator.*;
import java.util.ArrayList;

public class Book {
	
	private Map<String,Topic> topics = new HashMap<>();
	private Map<String,Question> questions = new HashMap<>();
	private Map<String,TheoryChapter> theoryChapters = new HashMap<>();
	private Map<String,ExerciseChapter> exerciseChapters = new HashMap<>();
	private Map<String,Assignment> assignements = new HashMap<>();

    /**
	 * Creates a new topic, if it does not exist yet, or returns a reference to the
	 * corresponding topic.
	 * 
	 * @param keyword the unique keyword of the topic
	 * @return the {@link Topic} associated to the keyword
	 * @throws BookException
	 */
	public Topic getTopic(String keyword) throws BookException {
		if(keyword==null || keyword=="") {
			throw new BookException();
		}
		if(!topics.containsKey(keyword)) {
			Topic t = new Topic(keyword);
			topics.put(keyword, t);
			return t;
		} else {
			return topics.get(keyword);
		}
	}

	public Question createQuestion(String question, Topic mainTopic) {
		Question q = new Question(question,mainTopic);
		questions.put(question, q);
        return q;
	}

	public TheoryChapter createTheoryChapter(String title, int numPages, String text) {
		TheoryChapter tc = new TheoryChapter(title,numPages,text);
		theoryChapters.put(title, tc);
        return tc;
	}

	public ExerciseChapter createExerciseChapter(String title, int numPages) {
		ExerciseChapter ec = new ExerciseChapter(title,numPages);
		exerciseChapters.put(title, ec);
        return ec;
	}
	
	public List<Topic> getAllTopics() {
        return topics.values().stream().distinct().sorted().collect(toList());
	}

	public boolean checkTopics() {
		return false;
	}

Scusate se posto doppio problema ma sono bloccato con questi due metodi.

5 Risposte

  • Re: Problema Java ricorsione e controllo

    Rawven ha scritto:


    Ciao ho un problema su un esercizio che richiede di aggiungere degli argomenti ad un capitolo usando il metodo addTopic(Topic); tale metodo aggiunge un dato argomento al capitolo e, ricorsivamente, tutti i sotto-argomenti. Per esempio, se Class è un sotto-argomento di Java, e Abstract Class è un sotto-argomento di Class, aggiungere l’argomento Java significa aggiungere anche Class e Abstract Class, di conseguenza fatto cio il metodo getTopics() restituisce tutti gli argomenti inseriti con addTopic(), senza ripetizioni e ordinati alfabeticamente.
    Precisiamo innanzitutto una cosa: quel addTopic(Topic) in TheoryChapter non ha nulla di sbagliato. E' l'aggiunta di un elemento in una lista del tipo di quel elemento. Quindi assolutamente ok.

    Mostra come è la classe Topic. Perché è lì il punto! Se (come immagino) Topic contiene una lista di Topic, allora strutturalmente con gli oggetti Topic crei un "albero". Ciascun Topic ha una lista di Topic in cui ciascuno ha a sua volta altri Topic. Quindi di fatto sarebbe un albero, punto.

    La questione è che il flatMap in getTopics() "appiattisce" solo un livello. Quindi dovrebbe essere subTopics (tra l'altro è un campo accessibile ... non è molto buono) a fornire una lista di tutti i sotto-topic. Quindi è in Topic che ci dovrebbe essere la ricorsione.

    Se facessi anche le cose bene/meglio quel Stream.concat sarebbe pure evitabile.

    Quindi mostra Topic. Così verifichiamo anche un'altra questione: il distinct() presuppone di poter distinguere gli elementi e quindi bisogna vedere come hai definito la uguaglianza tra Topic.

    Rawven ha scritto:


    Mentre il metodo di controllo deve restituire true se tutti gli argomenti specificati in tutti i capitoli di esercizi sono contenuti in almeno un capitolo di teoria. La classe degli esercizi è simile a quella di teoria. Il problema che il metodo di controllo si trova in un altra classe.
    Qui non mi è molto chiaro .. spiega meglio.


    P.S. keyword=="" è inappropriato!!
  • Re: Problema Java ricorsione e controllo

    Questa è la classe Topic
    [code]
    
    package it.polito.oop.books;
    
    import java.util.List;
    
    import static java.util.stream.Collectors.*;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    
    public class Topic implements Comparable<Topic> {
    	
    	private String id;
    	HashSet<Topic> subTopics;
    	List<Question> questions = new LinkedList<>();
    	
    	public Topic(String id) {
    		this.id = id;
    		subTopics = new HashSet<>();
    	}
    
    	public String getKeyword() {
            return id;
    	}
    	
    	@Override
    	public String toString() {
    	    return getKeyword();
    	}
    
    	public boolean addSubTopic(Topic topic) {
    		if(subTopics.contains(topic)) {
    			return false;
    		}
    		subTopics.add(topic);
            return true;
    	}
    
    	/*
    	 * Returns a sorted list of subtopics. Topics in the list *MAY* be modified without
    	 * affecting any of the Book topic.
    	 */
    	public List<Topic> getSubTopics() {
            return subTopics.stream().sorted().collect(toList());
    	}
    	
    	@Override
    	public boolean equals(Object o) {
    		if(o==null) return false;
    		if(! (o instanceof Topic) ) return false;
    		
    		return this.id.equals(((Topic)o).id);
    	}
    	
    	@Override
    	public int hashCode() {  // this is required for HashSet
    		return id.hashCode();
    	}
    
    	@Override
    	public int compareTo(Topic o) { // this is required for TreeSet
    		return this.id.compareTo(o.id);
    	}
    	
    	public void addQuestion(Question q) {
    		questions.add(q);
    	}
    	
    }
    
    
    [/code]
  • Re: Problema Java ricorsione e controllo

    Rawven ha scritto:


    Questa è la classe Topic
    Ok, "quasi" come immaginavo. Hai messo un HashSet<Topic> ma il risultato è lo stesso che dicevo prima: con più oggetti Topic puoi creare un "albero" di topic.

    Innanzitutto abituati a mettere sempre i campi come "private" (salvo casi davvero particolari). Inoltre il campo id mettilo anche come "final" perché questo dà la identità dei Topic e NON deve quindi cambiare successivamente.

    Riguardo la questione di avere uno Stream per scorrere l'albero, io ti suggerirei questo:
    public class Topic implements Comparable<Topic> {
        // .....
        
        public Stream<Topic> getAllTopics() {
            // completa tu ......
        }
    
        // .....
    }
    Dove getAllTopics() restituisce uno Stream di tutti i sotto-topic, compreso sé stesso. Qui il concat() può di nuovo essere utile ma viene più semplice di quanto puoi pensare.

    A quel punto in getTopics() di TheoryChapter diventa davvero banale fare un flatMap di tutta la lista!
  • Re: Problema Java ricorsione e controllo

    Ok inteso questo è il pezzo di codice che ho scritto ma nello stream tu dici di stampare tutti i sotto argomenti compreso se stesso e li non capisco. Partendo dall'argomento java li stampo tutto ricorsivamente e quindi ho inteso l'albero ma è l'elemento iniziale che non capisco, scusami ho scritto un pò confusionario.

    Scusa ti riposto, l'ho riscritto cosi, mi stampa tutto tranne l'argomento iniziale che è java
    
    
    public class Topic implements Comparable<Topic> {
    	
    	private final String id;
    	private List<Topic> subTopics = new LinkedList<>();
    	private List<Question> questions = new LinkedList<>();
    	
    	public Topic(String id) {
    		this.id = id;
    	}
    
    	public String getKeyword() {
            return id;
    	}
    	
    	public Stream<Topic> getAllTopics() {
    		Stream<Topic> res = Stream.concat(subTopics.stream(), subTopics.stream().flatMap(f->f.subTopics.stream()));
    		return res;
    	}
    
    // risultato corretto
            // Java Fundamentals: [Abstract classes, Classes, Functional Interfaces,
            // Generics, Inheritance, Interfaces, Java, Lambda expressions]
    // quello che viene a me
    Java Fundamentals: [Abstract classes, Classes, Generics, Inheritance, Interfaces, Lambda expressions]
    
  • Re: Problema Java ricorsione e controllo

    Grazie mille andbin problema risolto, è riuscito!!

    Per quanto riguarda l'altro problema si tratta di: Il metodo checkTopics restituisce true se tutti gli argomenti specificati in tutti i capitoli di esercizi sono contenuti in almeno un capitolo di teoria.

    Le classi esercizi e teoria sono:
    
    
    package it.polito.oop.books;
    
    import java.util.LinkedList;
    import java.util.List;
    import java.util.stream.Stream;
    
    import static java.util.stream.Collectors.*;
    
    public class TheoryChapter {
    	
    	private String title;
    	private int numPages;
    	private String text;
    	private List<Topic> topics = new LinkedList<>();
    
        public TheoryChapter(String title, int numPages, String text) {
    		// TODO Auto-generated constructor stub
        	this.title = title;
        	this.numPages = numPages;
        	this.text = text;
    	}
    
    	public String getText() {
    		return text;
    	}
    
        public void setText(String newText) {
        	this.text = newText;
        }
    
    
    	public List<Topic> getTopics() {
    		List<Topic> res = Stream.concat(topics.stream(), topics.stream().flatMap(f->f.getAllTopics())).distinct().sorted().collect(toList());
    		return res;
    	}
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String newTitle) {
        	this.title = newTitle;
        }
    
        public int getNumPages() {
            return numPages;
        }
        
        public void setNumPages(int newPages) {
        	this.numPages = newPages;
        }
        
        public void addTopic(Topic topic) {
        	topics.add(topic);
        }
        
        public List<Topic> getMainTopics() {
        	return topics;
        }
    }
    
    
    
    
    package it.polito.oop.books;
    
    import java.util.LinkedList;
    import java.util.List;
    
    import static java.util.stream.Collectors.*;
    
    public class ExerciseChapter {
    	
    	private String title;
    	private int numPages;
    	List<Question> questions = new LinkedList<>();
    	List<Assignment> assignments = new LinkedList<>();
    
        public ExerciseChapter(String title, int numPages) {
    		// TODO Auto-generated constructor stub
        	this.title = title;
        	this.numPages = numPages;
    	}
    
    
    	public List<Topic> getTopics() {
            return questions.stream().map(Question::getMainTopic).distinct().sorted().collect(toList());
    	};
    	
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String newTitle) {
        	this.title = newTitle;
        }
    
        public int getNumPages() {
            return numPages;
        }
        
        public void setNumPages(int newPages) {
        	this.numPages = newPages;
        }    
    
    	public void addQuestion(Question question) {
    		questions.add(question);
    	}
    	
    	public void addAssignment(Assignment assignment) {
    		// TODO Auto-generated method stub
    		assignments.add(assignment);
    	}
    }
    
    
    Il metodo di controllo si trova nella classe Book che ti ho postato sopra, il mio problema si tratta di fare il confronto tra gli argomenti (topic) di esercizi contenuti in almeno uno di teoria, ma il metodo non ha nessun argomento.

    Mi scuso se sono invasivo nel qual caso riuscissi ad aiutarmi te ne sarei duplicemente grato altrimenti nessun problema già quello di prima è stata una tortura .

    Buona giornata!!
Devi accedere o registrarti per scrivere nel forum
5 risposte