2012-11-19 4 views
3

Ma méthode ne peut pas passer le test unitaire. Je l'ai regardé pendant 5 heures en vain. Quelqu'un pourrait-il m'aider à voir ce qui ne va pas? PS: la méthode getAllRelations() dans mon code ci-dessous consiste à séparer les entrées formatées en listes de tableaux de ArrayList de chaînes, par exemple, si j'ai une entrée formatée comme ceci (je l'ai utilisée dans mon cas de test qui ne pouvait pas t pass)Arbre généalogique ancêtre trouver algorithme

String format = "John Doe , Mary Smith" + "\n" + "Brian William , John Doe" + "\n" + "Brian William ,Robert Andrew" + "\n" + "Mary Smith , Max Jackson"; 

Dans chaque ligne, la première personne est le parent de la deuxième personne. La méthode getAllRelations() divisera ces chaînes formatées en listes arithmétiques que chaque liste contient uniquement les deux chaînes de noms (sans espace après ou avant les noms) dans chaque ligne en tant qu'éléments. par exemple arraylist1 sera une liste contenant "John" et "Mary Smith".

Voici mes méthodes que je ne pouvais pas comprendre ce qui ne va pas, je veux utiliser cette méthode pour vérifier si deux personnes partagent le même ancêtre.

private boolean hasSameAncestor(String person1, String person2){ 
    ArrayList<ArrayList<String>> allRelations = allRelations(); 
    int i = 0; 
    int j = 0; 
    String name1 = person1; 
    String name2 = person2; 
    String parent1; 
    String parent2; 
    for(i = 0, parent1 = ""; i < allRelations.size(); i++){ 
     if(name1.equals(allRelations.get(i).get(1))){ 
      parent1 = allRelations.get(i).get(0); 
      for(j = 0, name2 = person2, parent2 = ""; j < allRelations.size(); j++){ 
       if(name2.equals(allRelations.get(j).get(1))){ 
        parent2 = allRelations.get(j).get(0); 
        if(parent2.equals(parent1)){ 
         return true; 
        } 
        else{ 
         name2 = parent2; 
         j = 0; 
        } 
       } 
      } 
      name1 = parent1; 
      i = 0; 
     } 
    } 
    return false; 
} 

Mon test qui ne peut pas passer est comme ça.

@Test 
    public void testHasSameAncestor() 
    FamilyTree familyTree4 = new FamilyTree("John Doe , Mary Smith" + "\n" + "Brian William , John Doe" + "\n" + "Brian William ,Robert Andrew" + "\n" + "Mary Smith , Max Jackson"); 
    assertEquals(true, format.hasSameAncestor("Max Jackson", "Robert Andrew")); 
} 

Je ne peux pas comprendre ce qui ne va pas avec ma fonction, quelqu'un pourrait-il me aider? Merci beaucoup.

code qui pourrait coller à éclipser pour le débogage aide

package test; 

import java.util.ArrayList; 
import java.util.Arrays; 


public class Test1 { 

    String test; 

    public Test1(String test){ 
     this.test = test; 
    } 


    private ArrayList<String> lineRelations(){ 
     int i; 
     ArrayList<String> lineRelations = new ArrayList<String>(); 
     String[] lines = test.split("\n"); 
     for(i = 0; i < lines.length; i++){ 
      lineRelations.add(lines[i]); 
     } 
     return lineRelations; 
    } 

    private ArrayList<ArrayList<String>> allRelations(){ 
     int i; 
     ArrayList<ArrayList<String>> allRelations = new ArrayList<ArrayList<String>>(); 
     ArrayList<String> lineRelations = lineRelations(); 
     for(i = 0; i < lineRelations.size(); i++){ 
      ArrayList<String> eachLine = new ArrayList<String>(Arrays.asList(lineRelations.get(i).split("\\s*,\\s*"))); 
      allRelations.add(eachLine); 
     } 
     return allRelations; 
    } 

    public boolean hasSameAncestor(String person1, String person2){ 
     ArrayList<ArrayList<String>> allRelations = allRelations(); 
     int i = 0; 
     int j = 0; 
     String name1 = person1; 
     String name2 = person2; 
     String parent1; 
     String parent2; 
     for(i = 0, parent1 = ""; i < allRelations.size(); i++){ 
      if(name1.equals(allRelations.get(i).get(1))){ 
       parent1 = allRelations.get(i).get(0); 
       for(j = 0, name2 = person2, parent2 = ""; j < allRelations.size(); j++){ 
        if(name2.equals(allRelations.get(j).get(1))){ 
         parent2 = allRelations.get(j).get(0); 
         if(parent2.equals(parent1)){ 
          return true; 
         } 
         else{ 
          name2 = parent2; 
          j = 0; 
         } 
        } 
       } 
       name1 = parent1; 
       i = 0; 
      } 
     } 
     return false; 
    } 
} 

cas de test

package test; 
import static org.junit.Assert.*; 
import test.Test1; 

import org.junit.Test; 


public class Test1Test { 

    @Test 
    public void testHasSameAncestor(){ 
     Test1 test1 = new Test1("John Doe , Mary Smith" + "\n" + "Brian William , John Doe" + "\n" + "Brian William ,Robert Andrew" + "\n" + "Mary Smith , Max Jackson"); 
     assertEquals(true, test1.hasSameAncestor("Max Jackson", "Robert Andrew")); 
    } 
} 
+0

Qu'est-ce qui ne va pas? Avez-vous réussi à l'exécuter? Avez-vous eu une erreur? Mettez quelques debug stmts et voir la sortie – mtk

+0

pourquoi êtes-vous si fâché ... Je veux juste obtenir de l'aide .. Je l'ai couru. Et le test unitaire m'a indiqué que le résultat réel est faux plutôt qu'escompté vrai ... le débogage ne montre rien de significatif pour moi cependant ... donc je ne peux pas comprendre pourquoi – user1835156

+0

Donnez la méthode allRelations() ou un exemple de données qui retournent AllRelations() Peut-être que la méthode allRelations() a des bugs? –

Répondre

1

D'abord, les structures de données que vous utilisez sont horribles pour ce genre d'application. Au lieu de tout emballer dans une chaîne et ensuite diviser la chaîne autour et la traiter dans une boucle doublée-for, vous devez construire une structure de données réelle pour votre arbre généalogique.

En informatique, les arbres sont le type de structure que vous souhaitez utiliser pour cette tâche. Un arbre a deux objets différents types:

1) A Node, which has two children, that are also Nodes. 
2) A Leaf, which has no children. 

Vous pouvez modéliser votre arbre généalogique à l'aide des nœuds, puis appliquez l'un des nombreux algorithmes d'arbres qui sont connus. (Une question similaire pour cela est Intersection of 2 binary search trees)

Pour être plus précis: Chaque personne dans votre modèle aurait deux autres personnes définies comme leurs parents. Une feuille est une personne qui n'a pas de parents (connus). Vous pouvez ensuite exécuter un algorithme qui calcule l'intersection de deux arbres binaires. Si l'intersection est vide, ils n'ont pas d'ancêtre commun.

+0

le format d'entrée est donné par mon professeur ... Je ne veux vraiment pas les emballer dans une telle chaîne ... mais .. devoirs .. – user1835156

+0

Vous pourriez utiliser la chaîne d'entrée pour construire votre structure de données une fois, je ne pense pas que votre professeur va se plaindre de cela (sinon je remettrais en question la compétence de ce type). – Sebastian

1

Vos boucles internes commencent toujours par 1.

Marque i = 1, j = -1 au lieu de 0 dans les boucles résoudrai. "Max Jackson" et "Robert Andrew" ont des ancêtres différents.

+0

ancêtre ne signifie pas seulement parent ... il peut être grand-parent ou plus – user1835156

+0

oui, maintenant je sais ce qui ne va pas, merci! – user1835156

1

"John Doe" et "Robert Andrew" partagent les mêmes ancêtres. Remplacez votre condition comme indiqué ci-dessous et vérifiez

assertEquals(false, format.hasSameAncestor("Max Jackson", "Robert Andrew")); 
assertEquals(true, format.hasSameAncestor("John Doe", "Robert Andrew")); 
+0

ancêtre ne signifie pas seulement parent ... il peut être grand-parent ou plus – user1835156

2

d'abord trouver l'ancêtre de base de deux personnes et de les comparer.

S'il vous plaît vérifier :)

public boolean hasSameAncestor(String person1, String person2) { 
     ArrayList<ArrayList<String>> allRelations = allRelations(); 
     int i = 0; 
     String name1 = person1; 
     String name2 = person2; 
     String parent1; 
     String parent2; 

     //Find first person's ancestor 
     for (i = 0, parent1 = ""; i < allRelations.size(); i++) { 
      if (name1.equals(allRelations.get(i).get(1))) { 
       parent1 = allRelations.get(i).get(0); 
       name1 = parent1; 
       i = -1; // because i will increase before start new loop 
      } 
     } 

     //Find second person's ancestor 
     for (i = 0, parent2 = ""; i < allRelations.size(); i++) { 
      if (name2.equals(allRelations.get(i).get(1))) { 
       parent2 = allRelations.get(i).get(0); 
       name2 = parent2; 
       i = -1; 
      } 
     } 
     System.out.println(parent1); 
     System.out.println(parent2); 
     if (parent1.equals(parent2)) { 
      return true; 
     } 
     return false; 
    } 

Meilleurs voeux.

+0

Excellent! Merci beaucoup. Tu résous ma question. :) – user1835156

+0

Si vous avez trouvé la solution utile, vous devez accepter la réponse :) –

1

vos relations vont de droite à gauche, non? Donc Max est apparenté à Marie et Marie à John. Robert est seulement lié à Brian. Il n'est pas du bon côté. Mais vous voulez aussi vérifier l'autre direction (?), Donc Brian est aussi lié à John et ils ont tous les deux le même ancêtre. Mais c'est très inhabituel.

Cocher cette solution en utilisant un hashmap et recherche récursive avec les relations de gauche (clé) à droite (valeur):

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.HashMap; 

public class Test { 

    private String test; 
    private HashMap<String, String> allRelations; 
    private ArrayList<String> ancestors; 
    public Test(String test){ 
     this.test = test; 
     allRelations = allRelations(); 
     ancestors= new ArrayList<String>(); 
    } 

    private ArrayList<String> lineRelations(){ 
     int i; 
     ArrayList<String> lineRelations = new ArrayList<String>(); 
     String[] lines = test.split("\n"); 
     for(i = 0; i < lines.length; i++){ 
      lineRelations.add(lines[i]); 
     } 
     return lineRelations; 
    } 

    private HashMap<String, String> allRelations(){ 
     int i; 
     HashMap<String, String> allRelations = new HashMap<String, String>(); 
     ArrayList<String> lineRelations = lineRelations(); 
     for(i = 0; i < lineRelations.size(); i++){ 
      allRelations.put(Arrays.asList(lineRelations.get(i).split("\\s*,\\s*")).get(0), Arrays.asList(lineRelations.get(i).split("\\s*,\\s*")).get(1));      
     } 
     return allRelations; 
    } 

    public boolean hasSameAncestor(String person1, String person2){ 
     if (allRelations.containsKey(person1)){ 
      if (ancestors.contains(allRelations.get(person1))){            
       if (allRelations.containsKey(person2)){ 
        if (ancestors.contains(allRelations.get(person2))){ 
         return true; 
        } else if (allRelations.containsKey(allRelations.get(person2))){ 
         return hasSameAncestor(person1, allRelations.get(person2)); 
        } else { 
         return false; 
        } 
       } else { 
        return false; 
       } 
      } else { 
       ancestors.add(allRelations.get(person1)); 
       if (allRelations.containsKey(allRelations.get(person1))){ 
        return hasSameAncestor(allRelations.get(person1), person2); 
       } else if (allRelations.containsKey(person2)) { 
        return hasSameAncestor(person1,allRelations.get(person2)); 
       } else { 
        return false; 
       } 
      } 
     } else { 
      return false; 
     }  
    } 
} 

Cela retourne vrai pour

Test test1 = new Test("a1 , b1" + "\n" + "b1 , c1" + "\n" + "a2 , b2" + "\n" + "b2 , c1" + "\n" + "a3 , c3"); 
System.out.println(test1.hasSameAncestor("a1", "a2")); 

et faux pour

System.out.println(test1.hasSameAncestor("a1", "a3")); 

concerne

+0

une bonne solution. Merci beaucoup. – user1835156

Questions connexes