I have a tree that looks like the following (a simple example, can be a variable size).
1 (root)
|---------------------------------|
1-1 1-2
|------------| |--------------|
1-1-1 1-1-2 1-2-1 1-2-2
I've written a Java class to generate this tree based on NumberOfSiblings (horizontal) and NumberOfChildren (vertical). I'm now looking to write a class that will generate the path of a given entry in the tree, for example:
Entry: 1-1-1
Path: /1/1-1/1-1-1
I believe that I need some sort of recursive method that will count the number of dashes and take off the last part of the entry (not always length() - 2 though as it could be 10-10-10).
This is the method that will generate the tree:
public static void generateCatalog(String parent, int siblings, int children, int level) {
for (int a = 1; a <= siblings; a++) {
String child = parent + "-" + a;
System.out.println(child);
if (level <= children) {
level++;
generateCatalog(child, siblings, children, level);
level--;
}
}
}
I've been trying something like this to generate the path but it does not work very well.
public static void getPath(String category, String path) {
System.out.println("Category: " + category);
System.out.println("Current path: " + path);
int numberOfDashes = category.length() - category.replace("-", "").length();
System.out.println("Number of dashes: " + numberOfDashes);
while (numberOfDashes > 1) {
path = category + "/" + category.substring(0, category.length() - 2);
getPath(category, path);
}
System.out.println("New path: " + path);
}
Could someone please tell me the best way to do this?
Instead of
path = category + "/" + category.substring(0, category.length() - 2);
Try
int endIndex = category.lastIndexOf("-");
if(endIndex != -1) {
path = category + "/" + category.subString(0, endIndex);
}
Not sure what you want to do if there aren't any dashes, but just stick that in an else block.
Related
I want to compute dragon curve till n = 10 in java with L system using recursion. For example,
Replace all F characters with F-H
Replace all H characters with F+H
dragon(0) = F-H (this is the input)
dragon(1) = F-H-F+H
dragon(2) = F-H-F+H-F-H+F+H
...
dragon(10) = ?
How can I accomplish the same in java using recursion? I'm only interested in knowing the recursive approach.
In recursive approach such "replace" problem statements usually can be implemented as recursive calls.
So let's create two functions - F() and H() each of them will return "F" or "H" when desired curve depth is reached, or F(...) + "-" + H(...) or F(...) + "+" + H(...) if further expansion is needed.
private String F(int depth) {
if (depth == 0) {
return "F";
} else {
return F(depth - 1) + "-" + H(depth - 1);
}
}
private String H(int depth) {
if (depth == 0) {
return "H";
} else {
return F(depth - 1) + "+" + H(depth - 1);
}
}
public String dragon(int depth) {
return F(depth + 1);
}
Try it online!
First off I know this probably isn't the most sophisticated way to do what I want, but its the way I thought of.
I am attempting to load in Soccer/Football data into an array list then create commands to let me analyze it.
Like if I want to know the last couple fo scores between two teams, or how many goals a team has scored in some seasons.
I have a file (6.txt) with my data delimited by ,
Ex. "12/8/17","Alaves","Las Palmas",2,0,'H',22,6,9,1
I have a contractor that takes in arguments
Then I have an array list for each team with their data
import java.util.ArrayList;
import java.util.Scanner;
import java.io.*;
public class games {
String hTeam;
String date;
String aTeam;
int totGoals;
int hGoals, aGoals, result, points, wins, draws, losses, hShots, aShots, hShotsTarget, aShotsTarget;
public games(String date, String hTeam, String aTeam, int hGoals, int aGoals, char result, int hShots, int aShots, int hShotsTarget, int aShotsTarget) {
this.hTeam = hTeam;
this.aTeam = aTeam;
this.hGoals = hGoals;
this.aGoals = aGoals;
this.result = result;
this.hShots = hShots;
this.aShots = aShots;
this.date = date;
}
public String toString() {
String temp = "";
String result = "";
if (this.result == 'H') {
result += "won against";
}
else if(this.result == 'A') {
result += "lost to";
}
else if (this.result == 'D') {
result += "drew with";
}
temp += "On " + date + " " + hTeam + " " + result + " " + aTeam + " " + hGoals + " to " + aGoals + "\n";
return temp;
}
public static void main(String[] args) {
ArrayList<games> Alaves = new ArrayList<games>();
Scanner s = new Scanner(new File("6.txt"));
while (s.hasNext()) {
Alaves.add(new games(s.nextLine()));
}
}
}
I want to be able to create an array list for each team with an associated file that will fill that list.
My end goal, is to be able to compare two teams using this data, which team is more likely to win, well lets check head to head matches and goals scored etc.
I am using javaparser to parse a Java file and I would like to find all occurrences of for loops (forEach & normal for loops). This is my approach so far, but it only finds some, not all occurrences.
public class AstElementTraverser extends VoidVisitorAdapter<File> {
#Override
public void visit(ForeachStmt n, File sourceFile) {
System.out.println("Found a foreach loop " + sourceFile.getAbsolutePath() + " # " + n.getBeginLine());
}
#Override
public void visit(ForStmt n, File sourceFile) {
System.out.println("Found a for loop " + sourceFile.getAbsolutePath() + " # " + n.getBeginLine());
}
}
For instance, it seems to work for this line:
for (final JavadocTagInfo tag : JavadocTagInfo.values()) {
... but not for this:
for (PropertyDescriptor<?> descriptor : propertyDescriptors) {
... nor this one:
for (int i = 1; i < typeCodes.length; i++) {
Is this a possible bug in javaparser, or am I just using it the wrong way?
I am having problems on my insert method. When I go to add a number that needs to be swapped, I get an index out of bounds exception. here: Collections.swap(table, table.get(parent), table.get(child)); This is how I am adding to the heap. tHeap.insert(14); Thanks for any help.
public class Heap {
private ArrayList<Integer> table;
public Heap() {
table = new ArrayList<Integer>();
}
public void insert(Integer toInsert) {
table.add(toInsert);
int child = table.size() - 1;
int parent = (child - 1) / 2;
//TextIO.putln("1 " + parent + " " + toInsert + " " + child);
while (parent >= 0 && table.get(parent) > table.get(child)) {
TextIO.putln("Swapping: " + parent + " Parent for Child: " + child);
Collections.swap(table, table.get(parent), table.get(child));
}
}
public void printTable() {
for (int i = 0; i < table.size(); i++) {
TextIO.putln("Index: " + i + " Data: " + table.get(i));
}
}
}
I think you mean Collections.swap(table, parent, child);? ArrayList.get will return the element at an index (Java ArrayList API) Collections.swap swaps the elements at an index (Java Collections API). You want to be passing in the indices, not the values at the indices. Also I think in your while loop you may want to be updating child and parent.
How can I get a class reference/TypeElement of a specific identifier at compile time in Java?
Say I have the following source file, and I want to get a reference to the Pixel class so I can get a list of its member fields.
package com.foo.bar;
class Test {
class Pixel {
int x,y,r,g,b;
}
Pixel saturate(Pixel p, int value) {...}
}
The Pixel class definition could be nested inside the Test class, or included from a different package where the source is not available.
I am using the javax.tools API to compile the source files, and I define visitor methods so I can view the arguments to each function. The arguments of a function can be iterated using VariableTree var : node.getParameters(), but the type information from var.getType() only triggers visitIdentifier for class names. This identifier is only the simple name Pixel, not the fully-qualified com.foo.bar.Pixel.
I need a way to reverse this identifier into either Pixel.class or into the TypeElement for the definition of the Pixel class, or into the fully-qualified com.foo.bar.Pixel string so I can then use a ClassLoader on it.
A crude way would be to record all class definitions and then try to do compile-time type lookup, but this wouldn't work for externally-defined classes.
As far as I remember var.getType().toString() returns you the fully qualified class name. Unfortunately I cannot check it right now, but try it yourself.
Yes, I know, it is a very bad style to use toString() for something except logging but it seems they have not given us other choice.
I ended up creating my own class lookup tool. For those that are interested, I'll include it here.
Call this with the path name of every source file to be included in the search:
public void populateClassDefinitions(String path) {
Iterable<? extends JavaFileObject> files = fileManager.getJavaFileObjects(path);
CompilationTask task =
compiler.getTask(null, fileManager, diagnosticsCollector, null, null, files);
final JavacTask javacTask = (JavacTask) task;
parseResult = null;
try {
parseResult = javacTask.parse();
} catch (IOException e) {
e.printStackTrace();
return;
}
for (CompilationUnitTree tree : parseResult) {
tree.accept(new TreeScanner<Void, Void>() {
#Override
public Void visitCompilationUnit(CompilationUnitTree node, Void p) {
currentPackage = "";
ExpressionTree packageName = node.getPackageName();
if (packageName != null) {
String packageNameString = String.valueOf(packageName);
if (packageNameString.length() > 0) {
currentPackage = packageNameString;
}
}
TreeScanner<Void, String> visitor = new TreeScanner<Void, String>() {
#Override
public Void visitClass(ClassTree node, String packagePrefix) {
if (classDefinitions.get(currentPackage) == null) {
classDefinitions.put(currentPackage, new HashMap<String, ClassTree>());
}
classDefinitions.get(currentPackage).put(packagePrefix + node.getSimpleName(), node);
return super.visitClass(node, packagePrefix + node.getSimpleName() + ".");
}
};
for (Tree decls : node.getTypeDecls()) {
decls.accept(visitor, "");
}
return super.visitCompilationUnit(node, p);
}
}, null);
}
}
Call this to search for classes.
/**
* Lookup the definition of a class.
*
* Lookup order: 1. Search in the current file: within the current class scope upwards to the
* root. 2. Search laterally across files with the same package value for implicitly included
* classes. 3. Check all import statements.
*
* #param pack
* Current package ex "edu.illinois.crhc"
* #param scope
* Current scope ex "Test.InnerClass"
* #param identifier
* The partial class name to search for
* #return ClassTree the definition of this class if found
*/
ClassLookup lookupClass(CompilationUnitTree packTree, String scope, String identifier) {
dumpClassTable();
String pack = packTree.getPackageName().toString();
System.out.println("Looking for class " + pack + " - " + scope + " - " + identifier);
// Search nested scope and within same package
HashMap<String, ClassTree> packClasses = classDefinitions.get(pack);
if (packClasses != null) {
String[] scopeWalk = scope.split("\\.");
for (int i = scopeWalk.length; i >= 0; i--) {
StringBuilder scopeTest = new StringBuilder();
for (int j = 0; j < i; j++) {
scopeTest.append(scopeWalk[j] + ".");
}
scopeTest.append(identifier);
System.out.println("Testing scope " + pack + " - " + scopeTest.toString());
if (packClasses.containsKey(scopeTest.toString())) {
return new ClassLookup(packClasses.get(scopeTest.toString()), pack.replace(".", "/")
+ "/" + scopeTest.toString().replace(".", "$"));
}
}
}
/*
* Check if fully-qualified identifier (foo.bar.Widget) is used. This needs to search all
* combinations of package and class nesting.
*/
StringBuilder packTest = new StringBuilder();
String[] qualifiedName = identifier.split("\\.");
for (int i = 0; i < qualifiedName.length - 1; i++) {
packTest.append(qualifiedName[i]);
if (i != qualifiedName.length - 2) {
packTest.append(".");
}
}
String clazz = qualifiedName[qualifiedName.length - 1];
System.out.println("Testing absolute identifier: " + packTest.toString() + " " + clazz);
if (classDefinitions.containsKey(packTest.toString())) {
HashMap<String, ClassTree> foundPack = classDefinitions.get(packTest.toString());
if (foundPack.containsKey(clazz)) {
return new ClassLookup(foundPack.get(clazz), packTest.toString().replace(".", "/") + "/"
+ clazz.replace(".", "$"));
}
}
/*
* Search import statements. Last identifier segment must be class name. Search all of the
* packages for the identifier by splitting off the class name. a.b.c.Tree Tree.Branch
* Tree.Branch.Leaf
*/
for (ImportTree imp : currentPackTree.getImports()) {
pack = imp.getQualifiedIdentifier().toString();
System.out.println(pack);
String[] importName = pack.split("\\.");
// Split off class name.
// TODO: (edge case) no package
StringBuilder importTest = new StringBuilder();
for (int i = 0; i < importName.length - 1; i++) {
importTest.append(importName[i]);
if (i != importName.length - 2) {
importTest.append(".");
}
}
// See if the last import segment is * or matches the first segment of the identifier.
System.out.println("Testing globally " + importTest.toString() + " - " + identifier);
if (classDefinitions.containsKey(importTest.toString())) {
HashMap<String, ClassTree> foundPack = classDefinitions.get(importTest.toString());
String[] identifierParts = identifier.split(".");
String importClass = importName[importName.length-1];
if (importClass.equals("*") || identifierParts[0].equals(importClass)) {
if (foundPack.containsKey(identifier)) {
return new ClassLookup(foundPack.get(identifier), importTest.toString().replace(".", "/")
+ "/" + identifier.replace(".", "$"));
}
}
}
}
return null;
}