Is there a way to "extract" individual strings from an ArrayList?
I have stored strings in an ArrayList and want to print them to the console.
I know that I can use a for-loop but it isn't quite that simple. I'm trying to create a column based print and I use a method (Created by "CandiedOrange" here on stack overflow) that takes strings separated by commas as input.
What it basically does is; It creates column spacing based on the length of strings in each column. (All credit to "CandiedOrange")
List<List<String>> lines = new ArrayList<>();
List<Integer> maxLengths = new ArrayList<>();
int numColumns = -1;
public Columns addLine(String... line) {
if (numColumns == -1){
numColumns = line.length;
for(int i = 0; i < numColumns; i++) {
maxLengths.add(0);
}
}
if (numColumns != line.length) {
throw new IllegalArgumentException();
}
for(int i = 0; i < numColumns; i++) {
maxLengths.set( i, Math.max( maxLengths.get(i), line[i].length() ) );
}
lines.add( Arrays.asList(line) );
return this;
}
The number of columns I want to print is unknown during compile time because the user enters the number of columns 1-5 during run time. So I figured I could use ArrayLists for the rows and use the addLine() method with each of the arraylists for the rows.
If there Is a better way of solving this, I'd be more than happy to know.
EDIT:
From the start:
I'm creating a Yahtzee game with 1-5 players. Each Player is defined by instances of the class "Player"
public class Player {
private String name;
private int ones;
private int twos;
private int threes;
private int fours;
private int fives;
private int sixes;
private int threeofakind;
private int fourofakind;
private int fullhouse;
private int smallstraight;
private int largestraight;
private int chance;
private int yahtzee;
private int totalscore;
public int getOnes() {
return ones;
}
public void setOnes(int ones) {
this.ones = ones;
}
public int getTwos() {
return twos;
}
public void setTwos(int twos) {
this.twos = twos;
}
public int getThrees() {
return threes;
}
public void setThrees(int threes) {
this.threes = threes;
}
public int getFours() {
return fours;
}
public void setFours(int fours) {
this.fours = fours;
}
public int getFives() {
return fives;
}
public void setFives(int fives) {
this.fives = fives;
}
public int getSixes() {
return sixes;
}
public void setSixes(int sixes) {
this.sixes = sixes;
}
public int getThreeofakind() {
return threeofakind;
}
public void setThreeofakind(int threeofakind) {
this.threeofakind = threeofakind;
}
public int getFourofakind() {
return fourofakind;
}
public void setFourofakind(int fourofakind) {
this.fourofakind = fourofakind;
}
public int getFullhouse() {
return fullhouse;
}
public void setFullhouse(int fullhouse) {
this.fullhouse = fullhouse;
}
public int getSmallstraight() {
return smallstraight;
}
public void setSmallstraight(int smallstraight) {
this.smallstraight = smallstraight;
}
public int getLargestraight() {
return largestraight;
}
public void setLargestraight(int largestraight) {
this.largestraight = largestraight;
}
public int getChance() {
return chance;
}
public void setChance(int chance) {
this.chance = chance;
}
public int getYahtzee() {
return yahtzee;
}
public void setYahtzee(int yahtzee) {
this.yahtzee = yahtzee;
}
public int getTotalscore() {
return totalscore;
}
public void setTotalscore(int totalscore) {
this.totalscore = totalscore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I'm implementing MVC structure (to the best of my ability) which means that I have a View class with a method to display the main console column scoreboard. (Method unfinished)
public void displayMainScoreBoard(ArrayList<Player> playerList) {
Columns col = new Columns(); //Instance of column class.
ArrayList<String> Name = new ArrayList<>();
ArrayList<Integer> Ones = new ArrayList<>();
ArrayList<Integer> Twos = new ArrayList<>();
ArrayList<Integer> Threes = new ArrayList<>();
ArrayList<Integer> Fours = new ArrayList<>();
ArrayList<Integer> Fives = new ArrayList<>();
ArrayList<Integer> Sixes = new ArrayList<>();
ArrayList<Integer> Threeofakind = new ArrayList<>();
ArrayList<Integer> Fourofakind = new ArrayList<>();
ArrayList<Integer> Fullhouse = new ArrayList<>();
ArrayList<Integer> Smallstraight = new ArrayList<>();
ArrayList<Integer> Largestraight = new ArrayList<>();
ArrayList<Integer> Chance = new ArrayList<>();
ArrayList<Integer> Yahtzee = new ArrayList<>();
ArrayList<Integer> Totalscore = new ArrayList<>();
for (Player p : playerList) { //For every player, append their category data.
Name.add(p.getName());
Ones.add(p.getOnes());
Twos.add(p.getTwos());
Threes.add(p.getThrees());
Fours.add(p.getFours());
Fives.add(p.getFives());
Sixes.add(p.getSixes());
Threeofakind.add(p.getThreeofakind());
Fourofakind.add(p.getFourofakind());
Fullhouse.add(p.getFullhouse());
Smallstraight.add(p.getSmallstraight());
Largestraight.add(p.getLargestraight());
Chance.add(p.getChance());
Yahtzee.add(p.getYahtzee());
Totalscore.add(p.getTotalscore());
}
}
And heres CandiedOrange's full Column class. (Again, I claim no rights to his code.)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Columns {
List<List<String>> lines = new ArrayList<>();
List<Integer> maxLengths = new ArrayList<>();
int numColumns = -1;
public Columns addLine(String... line) {
if (numColumns == -1){
numColumns = line.length;
for(int i = 0; i < numColumns; i++) {
maxLengths.add(0);
}
}
if (numColumns != line.length) {
throw new IllegalArgumentException();
}
for(int i = 0; i < numColumns; i++) {
maxLengths.set( i, Math.max( maxLengths.get(i), line[i].length() ) );
}
lines.add( Arrays.asList(line) );
return this;
}
public void print(){
System.out.println( toString() );
}
public String toString(){
String result = "";
for(List<String> line : lines) {
for(int i = 0; i < numColumns; i++) {
result += pad( line.get(i), maxLengths.get(i) + 1 );
}
result += System.lineSeparator();
}
return result;
}
private String pad(String word, int newLength){
while (word.length() < newLength) {
word += " ";
}
return word;
}
}
How can I pass the Strings of my ArrayLists in my view to the addLine() Method?
I believe you should not be using that Columns class at all.
Most of your lists are numbers rather than strings. Numbers are best displayed right-justified. And the only string you have in each of the rows you want to display is the player name.
So instead of copying all the data to various lists, and assuming that for most of the numbers you have a reasonable width that they will not pass (4 digits? 6 digits?), then your task becomes:
Find the longest name in the list
Display each player such that the name is padded to accomodate the longest name found.
You could add these as methods to the Player class, so finding the maximal name length of a given list of players:
public static int maxNameLength( List<? extends Player> players ) {
int maxLength = 0;
for ( Player player : players ) {
int currLength = player.getName().length();
if ( currLength > maxLength ) {
maxLength = currLength;
}
}
return maxLength;
}
Now, displaying the current player in a properly padded way can be done using String.format, which uses a Formatter.
For the sake of brevity, suppose I just want to display the name, Yahtzee and total score. You'll have a method like this in Player:
public String getScoreLine( int maxLength ) {
String format = "%-" + maxLength + "s %6d %6d";
return String.format( format, getName(), getYahtzee(), getTotalscore() );
}
What the first part does is create a left-justified field for the string. So if maxLength is, say, 20, the format will be %-20s %6d %6d. The numbers will be displayed right-justified in fields 6 characters wide, the name, left-justified and padded to 20 characters.
Now you can loop on your list and display it like:
int maxNameLength = Player.maxNameLength( playerList );
for ( Player p : playerList ) {
System.out.println( p.getScoreLine( maxNameLength ) );
}
Note: if you want to put the getScoreLine method in your View rather than in the Player class (since you are trying to do MVC), you will need to give it the player as a parameter.
...that takes strings separated by commas as input.
Technically, it takes an array (more in this Java tutorial on varargs). But Java lets you create that array automatically when calling it with discrete arguments.
Since it accepts an array, and you have an ArrayList, you can easily get an array to pass to it, using toArray(T[]):
List<List<String>> linesToAdd = /*...*/;
// ...
for (List<String> line : linesToAdd) {
addLine(line.toArray(new String[line.size()]));
}
That said, it would be trivial (and a good coding exercise) to modify addLine to accept List<String> directly.
I followed the advice not to use the column class, even though I'd like to have tried using it. I semi-hardcoded the solution.
playerList is the list of players present in the game. and categories is obtained from another class to check which categories are pickable when scoring. (Displayed as X when unavailable and O when pickable.)
public void displayMainScoreBoard(ArrayList<Player> playerList, ArrayList<Boolean> categories) {
List<String> Name = new ArrayList<>();
List<String> Ones = new ArrayList<>();
List<String> Twos = new ArrayList<>();
List<String> Threes = new ArrayList<>();
List<String> Fours = new ArrayList<>();
List<String> Fives = new ArrayList<>();
List<String> Sixes = new ArrayList<>();
List<String> Threeofakind = new ArrayList<>();
List<String> Fourofakind = new ArrayList<>();
List<String> Fullhouse = new ArrayList<>();
List<String> Smallstraight = new ArrayList<>();
List<String> Largestraight = new ArrayList<>();
List<String> Chance = new ArrayList<>();
List<String> Yahtzee = new ArrayList<>();
List<String> Totalscore = new ArrayList<>();
for (Player p : playerList) { //For every player, append their category data.
Name.add(p.getName());
Ones.add(String.valueOf(p.getOnes()));
Twos.add(String.valueOf(p.getTwos()));
Threes.add(String.valueOf(p.getThrees()));
Fours.add(String.valueOf(p.getFours()));
Fives.add(String.valueOf(p.getFives()));
Sixes.add(String.valueOf(p.getSixes()));
Threeofakind.add(String.valueOf(p.getThreeofakind()));
Fourofakind.add(String.valueOf(p.getFourofakind()));
Fullhouse.add(String.valueOf(p.getFullhouse()));
Smallstraight.add(String.valueOf(p.getSmallstraight()));
Largestraight.add(String.valueOf(p.getLargestraight()));
Chance.add(String.valueOf(p.getChance()));
Yahtzee.add(String.valueOf(p.getYahtzee()));
Totalscore.add(String.valueOf(p.getTotalscore()));
}
boolean checkones = categories.get(0); //Checkers for which categories are available to score in.
boolean checktwos = categories.get(1);
boolean checkthrees = categories.get(2);
boolean checkfours = categories.get(3);
boolean checkfives = categories.get(4);
boolean checksixes = categories.get(5);
boolean checkthreeofkind = categories.get(6);
boolean checkfourofkind = categories.get(7);
boolean checkfullhouse = categories.get(8);
boolean checksmallstraight = categories.get(9);
boolean checklargestraight = categories.get(10);
boolean checkchance = categories.get(11);
boolean checkyahtzee = categories.get(12);
System.out.println("| "+ "| | Name " + stringBuilder(Name));
System.out.println("|" + isPickable(checkones) + "|1. | Ones " + stringBuilder(Ones));
System.out.println("|" + isPickable(checktwos) + "|2. | Twos " + stringBuilder(Twos));
System.out.println("|" + isPickable(checkthrees) + "|3. | Threes " + stringBuilder(Threes));
System.out.println("|" + isPickable(checkfours) + "|4. | Fours " + stringBuilder(Fours));
System.out.println("|" + isPickable(checkfives) + "|5. | Fives " + stringBuilder(Fives));
System.out.println("|" + isPickable(checksixes) + "|6. | Sixes " + stringBuilder(Sixes));
System.out.println("|" + isPickable(checkthreeofkind) + "|7. | Three of a kind " + stringBuilder(Threeofakind));
System.out.println("|" + isPickable(checkfourofkind) + "|8. | Four of a kind " + stringBuilder(Fourofakind));
System.out.println("|" + isPickable(checkfullhouse) + "|9. | Full House " + stringBuilder(Fullhouse));
System.out.println("|" + isPickable(checksmallstraight) + "|1. | Small Straight " + stringBuilder(Smallstraight));
System.out.println("|" + isPickable(checklargestraight) + "|11.| Large Straight " + stringBuilder(Largestraight));
System.out.println("|" + isPickable(checkchance) + "|12.| Chance " + stringBuilder(Chance));
System.out.println("|" + isPickable(checkyahtzee) + "|13.| Yahtzee " + stringBuilder(Yahtzee));
System.out.println("| "+ "| | Total Score " + stringBuilder(Totalscore));
}
/*
* Method for creating the lines for the scoreboard.
*/
public String stringBuilder(List<String> arrIn) {
StringBuilder sb = new StringBuilder();
for (String s : arrIn) {
sb.append("|");
sb.append(s);
sb.append(pad(s));
}
return sb.toString();
}
/*
* Method for padding the spaces between columns.
*/
public String pad(String s) {
int space = 15;
int sLength = s.length();
String retPad = "";
int temp = space - sLength;
for (int i = 0; i <= temp ; i++) {
retPad += " ";
}
return retPad;
}
public String isPickable(boolean b) {
if (b == true) {
return "O";
}
else {
return "X";
}
}
Gives this print out:
| | | Name |one |two |three
|X|1. | Ones |0 |0 |0
|X|2. | Twos |0 |0 |0
|X|3. | Threes |0 |0 |0
|X|4. | Fours |0 |0 |0
|X|5. | Fives |0 |0 |0
|X|6. | Sixes |0 |0 |0
|X|7. | Three of a kind |0 |0 |0
|X|8. | Four of a kind |0 |0 |0
|X|9. | Full House |0 |0 |0
|X|1. | Small Straight |0 |0 |0
|X|11.| Large Straight |0 |0 |0
|X|12.| Chance |0 |0 |0
|X|13.| Yahtzee |0 |0 |0
| | | Total Score |0 |0 |0
This way looks nice as long as a user doesn't enter a ridiculously long name. This can be fixed by asking the user to enter a shorter name (nick name).
Anyway, thanks for your help!
Related
ListTopVisitedSites(sites, 5) is supposed to return the following output:
www.google.com | 4
www.aol.com | 3
www.microsoft.com | 3
www.amazon.com | 3
www.facebook.com | 3
I am trying to print the top 5 elements. If multiple elements have the same quantity, they should be ordered by recency - (recently added). Also, I need to print an empty array of type string for no value.
Which part am I missing, or have coded incorrectly? All the methods and their parameters should remain the same, as I am supposed to keep the time complexity as N2 and space complexity as 1.
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
class SiteStats {
private String url;
private int numVisits;
public SiteStats(String url, int numVisits) {
this.url = url;
this.numVisits = numVisits;
}
public int getNumVisits() {
return this.numVisits;
}
public String getUrl() {
return this.url;
}
public void setNumVisits(int updatedNumVisits) {
this.numVisits = updatedNumVisits;
}
public String toString() {
return this.url + " | " + this.numVisits;
}
}
public class PartBSolution {
private static Queue<SiteStats> sites = new LinkedList<SiteStats>();
public static void listTopVisitedSites(Queue<SiteStats> sites, int n) {
sortQueue(sites);
while(sites.isEmpty()== false)
{
System.out.println(sites.peek() + " ");
sites.poll();
}
}
public static void insertMaxToRear(Queue<SiteStats> sites,
int max_index)
{
SiteStats max_value = null;
int s = sites.size();
for (int i = 0; i < s; i++)
{
SiteStats current = sites.peek();
sites.poll();
if (i != max_index)
sites.add(current);
else
max_value = current;
}
sites.add(max_value);
}
public static void sortQueue(Queue<SiteStats> sites)
{
for(int i = 1; i <= sites.size(); i++)
{
int max_index = maxIndex(sites,sites.size() - i);
insertMaxToRear(sites, max_index);
}
}
public static int maxIndex(Queue<SiteStats> sites,
int sortIndex)
{
int max_index = -1;
int max_value = 0;
int s = sites.size();
for (int i = 0; i < s; i++)
{
SiteStats current = sites.peek();
sites.poll();
if (current.getNumVisits() >= max_value && i <= sortIndex)
{
max_index = i;
max_value = current.getNumVisits();
}
sites.add(current);
}
return max_index;
}
public static void updateCount(String url) {
boolean flag=false;
int size2=sites.size();
for(int i = 0; i < size2 ; i++)
{
SiteStats temp=sites.peek();
sites.poll();
if(temp.getUrl().equals(url))
{
temp.setNumVisits(temp.getNumVisits()+1);
flag=true;
sites.add(temp);
break;
}
sites.add(temp);
}
if(!flag)
sites.add(new SiteStats(url,1));
}
public static void main(String[] args) {
String[] visitedSites = { "www.google.com", "www.google.com", "www.facebook.com", "www.aol.com", "www.google.com", "www.youtube.com",
"www.facebook.com", "www.aol.com", "www.facebook.com", "www.google.com", "www.microsoft.com", "www.9gag.com", "www.netflix.com",
"www.netflix.com", "www.9gag.com", "www.microsoft.com", "www.amazon.com", "www.amazon.com", "www.uber.com", "www.amazon.com",
"www.microsoft.com", "www.aol.com" };
for (String url : visitedSites) {
updateCount(url);
}
listTopVisitedSites(sites, 5);
}
}
/**
www.google.com | 4
www.aol.com | 3
www.microsoft.com | 3
www.amazon.com | 3
www.facebook.com | 3
*/
The parameter n that you pass into listTopVisitedSites(sites, 5); is never used again, so you can not expect it to only list the 5
You did not write the logic for parameter n of listTopVisitedSites. Please find the updated one.
public static void listTopVisitedSites(Queue<SiteStats> sites, int n) {
sortQueue(sites);
int iterate = 1;
while (sites.isEmpty() == false && iterate <= n) {
System.out.println(sites.peek() + " ");
sites.poll();
iterate++;
}
}
I have an ArrayList(called filmes) in which one of the elements is another ArrayList(called actores), this actores is made out of names of actors that have the same movie id as the movie in filmes.
But every time it adds an actor to the actores ArrayList it overwrites the previous one there.
So when there's more than one actor for the same movie it just shows the last one on the file.
For example the expected output should be 6978 | Big Trouble in Little China | 30-05-1986 [Kurt Russel,Kim Cattrall] [Comedy] but instead it's printing 6978 | Big Trouble in Little China | 30-05-1986 [Kim Cattrall] [Comedy]
/*Actorsfile.txt (the last element is the movie id)
11701,Angelina Jolie,false,1995
6384,Keanu Reeves,true,603
7382,Carrie-Anne Moss,false,603
11701,Angelina Jolie,false,10428
6856,Kurt Russell,true,6978
2109,Kim Cattrall,false,6978*/
try{
File ficheiroA = new File(Actorsfile);
Scanner leitorFicheiroA = new Scanner(ficheiroA);
while (leitorFicheiroA.hasNextLine()) {
ArrayList<Actor> actores = new ArrayList<>();
Actor actor = new Actor("");
String linha = leitorFicheiroA.nextLine();
String dadosA[] = linha.split(",");
if (dadosA.length == 4) {
int idFilmeA = Integer.parseInt(dadosA[3]);
int pos = index(idFilmeA, ids);
if (idFilmeA == ids[pos]) {
actor.nome = (dadosA[1]);
actores.add(actor);
filmes.get(pos).mudarActores(actores);
}
}
}
}
catch(FileNotFoundException e) {
String mensagem = "Erro: o ficheiro " + ficheiroActores + " nao foi encontrado.";
System.out.println(mensagem);
}
Actor Class:
public class Actor {
String nome;
String genero;
public Actor(String nome) {
this.nome = nome;
}
public String toString () {
return nome;
}
}
Filme Class:
public class Filme {
int id;
String titulo;
ArrayList<Actor> actores= new ArrayList<>();
ArrayList<GeneroCinematografico> generos= new ArrayList<>();
String dia,mes,ano;
public Filme(int id, String titulo,ArrayList<Actor> actores, ArrayList<GeneroCinematografico> generos,String ano,String mes,String dia) {
this.id = id;
this.titulo = titulo;
this.actores = actores;
this.generos = generos;
this.ano=ano;
this.mes=mes;
this.dia=dia;
}
public void mudarId(int id) {
this.id = id;
}
public void mudarTitulo(String titulo) {
this.titulo = titulo;
}
public void mudarActores(ArrayList<Actor> actores) {
this.actores =actores;
}
public void mudarGeneros(ArrayList<GeneroCinematografico> generos) {
this.generos = generos;
}
public String toString() {
return id + " | " + titulo + " | " + dia + "-" + mes + "-" + ano +" "+ actores +" "+ generos;
}
}
Edit:
I've done it a different way and now it's working well in the first filme, but the next are as a null.
Recent output it's 603 | The Matrix | 30-03-1999 [Keanu Reeves, Carrie-Anne Moss] [Science Fiction], 10428 | Hackers | 14-09-1995 null [Action] but the expected is 603 | The Matrix | 30-03-1999 [Keanu Reeves, Carrie-Anne Moss] [Science Fiction], 10428 | Hackers | 14-09-1995 [Angelina Jolie] [Action]. I would be greatful if I could do it this way, without using maps.
try{
File ficheiroA = new File(ficheiroActores);
Scanner leitorFicheiroA = new Scanner(ficheiroA);
i=0;
while (i<ids.length-1) {
int idFilme=ids[i];
ArrayList<Actor> actores = new ArrayList<>();
while (leitorFicheiroA.hasNextLine()) {
Actor actor;
String linha = leitorFicheiroA.nextLine();
String dadosA[] = linha.split(",");
int idFilmeA = Integer.parseInt(dadosA[3]);
//int pos = index(idFilmeA, ids);
if (dadosA.length == 4) {
if (idFilmeA == idFilme) {
actor =new Actor (dadosA[1]);
actores.add(actor);
}
}
filmes.get(i).mudarActores(actores);
}
i++;
}
You are declaring a new ArrayList inside the while, so it is resetting each iteration. What you want to do is to take the creation of the ArrayList outside the while. Instead of:
while (leitorFicheiroA.hasNextLine()) {
ArrayList<Actor> actores = new ArrayList<>();
You want:
ArrayList<Actor> actores = new ArrayList<>();
while (leitorFicheiroA.hasNextLine()) {
And then you call filmes.get(pos).mudarActores(actores); when the while finishes.
Edit:
To solve the problem you are commenting, I would remove filmes.get(pos).mudarActores(actores); from where it is now. Note that you have all the information you need in each Actor. So,I would leave the logic of the current while as is now, maybe put it in a function readActoresFromFile(), returning the List of Actores. Then I would iterate over each element of the List and put them on a Map which has the filmId as Key and the list of Actors of that film as values. Tell me if you need help with that.
I have a scenario, in which every timeslot has a profit and muliple jobs to choose from. I need to select the jobs at each time slot such that overall maximum profit is obtained. I require the maximum profit obtained and the schedule.
The only thing I can think of is to try for every comibnation using bruteforce. How can I solve this problem effectively.Is there any way I can do it better by using specific algorithm or data structure?
In the below example , any of the jobs J1,J2,J4 can be selected for timeslot1. Similarly for other time slots any one or none of the jobs can be selected. Only one job can be selected for a particular timeslot. If a job is done in one time slot, it cannot be done again.
Eg. If j1 is done in TS1, it cannot be picked again in TS2
+----------+--------+----------------------+
| TimeSlot | Profit | Possible Job |
+----------+--------+----------------------+
| 1 | 50 | J1 or J2 or J4 |
| 2 | 100 | J1 |
| 3 | 20 | J2 |
| 4 | 60 | J5 or J4 |
| 5 | 15 | J1 or J2 or J3 or J6 |
+----------+--------+----------------------+
This can be solved optimally by weighted maximum matching in bipartite graph.
In here, your graph is G=(U,V,E), where:
U = {1, 2, ...., n} // time slots
V = {J1, J2, ..., J_m} // jobs
E = { (i,J) | if job J can be done in time i }
w(i,J) = profit(i)
A maxmum matching in the above graph is translated directly to an optimal solution, by performing task J in timeslot i iff the maximum matching matched node J with node i.
public class JobProfitMaximizer {
private int numberOfJobs;
private Job[] jobs;
private int maxProfit;
public class JobComparator implements Comparator<Job> {
#Override
public int compare(Job arg0, Job arg1) {
if (arg0.end <= arg1.end)
return -1;
else
return 1;
}
}
public JobProfitMaximizer() {
numberOfJobs = 0;
maxProfit = 0;
}
private void printJobProfiles() {
for (Job j : jobs) {
System.out.println(j.start + " " + j.end + " " + j.profit);
}
}
private void createJobProfiles() {
jobs = new Job[numberOfJobs];
File inputFile = new File("***Filepath***********");
Scanner sc = null;
int jobCounter = 0;
try {
sc = new Scanner(inputFile);
while (sc.hasNextLine()) {
String s = sc.nextLine();
String[] profileOfJob = s.split(" ");
int start = Integer.parseInt(profileOfJob[1]);
int end = Integer.parseInt(profileOfJob[2]);
int profit = Integer.parseInt(profileOfJob[3]);
jobs[jobCounter] = new Job(start, end, profit);
jobCounter = jobCounter + 1;
}
} catch (FileNotFoundException e) {
System.out.println("The file is not present");
} finally {
try {
if (sc != null)
sc.close();
} catch (Exception f) {
System.out.println(f.getMessage());
}
}
}
private void setNumberOfJobs() {
File inputFile = new File("***Filepath***********");
Scanner sc = null;
int countOfJobs = 0;
try {
sc = new Scanner(inputFile);
while (sc.hasNextLine()) {
countOfJobs = countOfJobs + 1;
sc.nextLine();
}
numberOfJobs = countOfJobs;
System.out.println(numberOfJobs);
} catch (FileNotFoundException e) {
System.out.println("The file is not present");
} finally {
try {
if (sc != null)
sc.close();
} catch (Exception f) {
System.out.println(f.getMessage());
}
}
}
private void sortJobsOnFinishTimes() {
JobComparator jc = new JobComparator();
Arrays.sort(jobs, jc);
}
private void calculateMaximumProfit() {
int[] T = new int[numberOfJobs];
T[0] = jobs[0].profit;
for (int i = 1; i < numberOfJobs; i++) {
T[i] = Math.max(T[i - 1], jobs[i].profit);
for (int j = i - 1; j >= 0; j--) {
if (jobs[j].end <= jobs[i].start) {
T[i] = Math.max(T[i], T[j] + jobs[i].profit);
break;
}
}
}
int currentMaxProfitValue = T[0];
for (int m : T) {
if (m > currentMaxProfitValue) {
currentMaxProfitValue = m;
}
}
maxProfit = currentMaxProfitValue;
}
public static void main(String args[]) {
JobProfitMaximizer j = new JobProfitMaximizer();
j.setNumberOfJobs();
j.createJobProfiles();
j.sortJobsOnFinishTimes();
j.calculateMaximumProfit();
System.out.println("The maximum profit is " + j.maxProfit);
}
}
need some help with a maze solving program in java.
The program has to read a maze from a file, store it into an array, solve it, and display the solution in a drawing panel. I'm struggling storing it into an array, and I'm really unsure of how to move into solving it and displaying it. But if i could get some help on the array part to get into a groove, I'd really appreciate it.
Here is an example of an input file. I want it to work for any maze of this structure, (with +, -, S, E, and |). The first two numbers, (8, 10) represent the height and width, the # of rows and # of columns.
8 10
+-+-+-+-+-+-+-+-+-+
| |
+ +-+-+-+ +-+-+-+ +
| | | |
+ + +-+-+-+-+-+ + +
| | | | | |
+ + + +-+-+-+ + + +-+
| | | | | | | S|
+ + + + +-+ + + + +-+
| | | |E| | | |
+ + + +-+ +-+ + + +
| | | | | |
+ + +-+-+-+-+-+ + +
| | | |
+ +-+-+-+-+-+-+-+ +
| |
+-+-+-+-+-+-+-+-+-+
Here is my code so far:
import java.util.Arrays;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class MazeSolver {
// The name of the file describing the maze
static String mazefile;
static int width;
static int height;
public static void main(String[] args) throws FileNotFoundException {
if (handleArguments(args)) {
readMazeFile(mazefile);
DrawMaze.draw();
if (solveMaze())
System.out.println("Solved!");
else
System.out.println("Maze has no solution.");
}
else {
System.out.println("The arguments are invalid.");
}
}
// Handle the input arguments
static boolean handleArguments(String[] args) {
if (args.length > 4 || args.length < 1) {
System.out.println("There are too many or too few command line arguments");
return false;
}
if (args.length == 1) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
return true;
}
if (args.length == 2) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
int cellsize = Integer.parseInt(args[1]);
if (cellsize < 10) {
return false;
}
return true;
}
if (args.length == 3) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
int cellsize = Integer.parseInt(args[1]);
int borderwidth = Integer.parseInt(args[2]);
if (borderwidth < 5) {
return false;
}
return true;
}
if (args.length == 4) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
int cellsize = Integer.parseInt(args[1]);
int borderwidth = Integer.parseInt(args[2]);
int sleeptime = Integer.parseInt(args[3]);
if (sleeptime < 0 || sleeptime > 10000) {
return false;
}
return true;
}
return false;
}
// Read the file describing the maze.
static char[][] readMazeFile(String mazefile) throws FileNotFoundException {
Scanner scanner = new Scanner(new File(mazefile));
height = scanner.nextInt();
width = scanner.nextInt();
int arrayHeight = 2 * height + 1;
int arrayWidth = 2 * width + 1;
char[][] mazeArrays = new char[arrayHeight][arrayWidth];
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
for (int row = 0; row < arrayHeight; row++) {
for (int col = 0; col < arrayWidth; col++) {
mazeArrays[row][col] = line.charAt(col);
}
}
}
return mazeArrays;
}
// Solve the maze.
static boolean solveMaze() {
return true;
}
}
I think I have the handling of command line arguments down. The readMazeFile method is where I'm currently struggling. I just can't wrap my head around storing the maze in an array and solving it.
Thanks!
The first thing to do is to work out a data structure for you to store the maze in. I suggest using a structure that makes the solving as easy as possible, even if printing is more complicated. Here is a simple example:
class Node {
private final int row;
private final int col;
private final List<Node> paths;
}
class Maze {
private final int rowCount;
private final int colCount;
private final List<Node> nodes;
private Node start;
private Node end;
}
This, in my view, is going to be more useful than something like an array. An array would make it easy to print the maze but that's not the most difficult part of the operation. A path finding algorithm needs to be able to easily get the paths from any position which this data structure allows.
You asked for some help on reading the maze. I suggest making the reading method a static 'builder' method inside Maze. In general the structure will be something like:
class Maze {
public static Maze buildMaze(String mazeFile) {
// read row & col size from file
Maze maze = new Maze(rows, cols);
// skip first line (invariant)
for (int row = 0; row < rows; row++) {
// get next 2 lines (for horizontal & vertical paths)
for (int col = 0; col < cols; col++) {
// get corresponding horizontal wall or space
if (isHorizontalPath) {
maze.getNode(row,col).addHorizontalPath();
}
if (hasVerticalPath) {
maze.getNode(row, col).addVerticalPath();
}
// check for S and E
if (isStart) {
maze.setStart(row, col);
} else if (isEnd) {
maze.setEnd(row, col);
}
}
}
return maze;
}
}
It seems that 20 regiments were in a continuous process of formation. The first had 1000 men, the second had 950, the third 900, and so on down to the twentieth regiment, which garrisoned only 50. During each week, 100 men were added to each regiment, and at week's end, the largest regiment was sent off to the front.This lasted for a total of 20 weeks.
For this program I have already managed to print out the original number of men for each regiment. But I am having difficult adding 100 men to each regiment.The adding men must be a method in the army class. I am getting the regiment objects using a .txt file. All this files contains is the names of regiments numbered 1-20.
I currently have no errors my only problem is that I do not know how to add men to my regiment. I have to use the addMen method in the army class which I currently have blank.
public class Regiment {
private String name; //name of regiment
private int regNumber; //regiment number
private int men; // regiment men
public Regiment(int regNumber, String name, int men) {
this.name = name;
this.regNumber = regNumber;
this.men = men;
}
public String getName() {
return name;
}
public int getregNumber() {
return regNumber;
}
public int getMen() {
return men;
}
public int addMen2(int RegNumber) {
int men = 1050 - (regNumber * 50);
return men;
}
}
ArmyDataList:
class ArmyDataList {
public ArrayList<Regiment> list;
public ArmyDataList() {
list = new ArrayList<Regiment>();
}
public void AddToList(Regiment current) {
list.add(current);
}
public void RemoveFromList(Regiment current) {
list.remove(current);
}
public Regiment getLargest() {
if (list.isEmpty()) {
return null;
}
Regiment Reg1 = list.get(0);
for (int i = 1; i < list.size(); i++) {
Regiment current = list.get(i); // get next regiment
// is current regiment > largest
if (current.getMen() > Reg1.getMen()) {
Reg1 = current;
}
}
return Reg1;
}
public void addMen() {
}
public String toString() {
String out
= String.format("%28s%12s%n", "Regiments", " Men")
+ String.format("%12s%n", "Number")
+ String.format("%12s%16s%14s%n", "=======", "===============",
"=========");
for (int i = 0; i < list.size(); i++) {
Regiment regim = list.get(i);
int regNumber = regim.getregNumber();
String name = regim.getName();
int men = regim.addMen2(regNumber);
out = out + String.format("%12s", regNumber)
+ String.format("%16s", name)
+ String.format("%10s", men)
+ "\n";
}
return out + "\n";
}
}
RegimentTest:
public class RegimentTest {
public static void main(String[] args) throws IOException
{
ArmyDataList army = new ArmyDataList();
Scanner fileScan = new Scanner(new File("regiments.txt"));
System.out.println("Report Summary:\n");
while (fileScan.hasNext()) {
String line = fileScan.nextLine();
System.out.println(line);
Scanner in = new Scanner(line) ;
int regNumber = in.nextInt();
String name = in.next();
int men = 0 ; //men is set to 0 only because I havent add the men yet
Regiment adder = new Regiment(regNumber, name, men );
army.AddToList(adder) ;
}
System.out.println(army.toString());
}
Add a setMen(int numberOfMen) method to your Regiment class. Then in your addMen() method, you can do something like this:
public void addMen(){
for(Regiment r : list){ //iterate through the list of regiments
r.setMen(r.getMen() + 100); //add 100 men to each regiment
}
}
The setMen method would look like this:
public void setMen(int numberOfMen){
men = numberOfMen;
}
There is another issue with your toString method, where the regiment's addMen2 method is called - right now you're just printing the number, not initializing the number of men. In the constructor for your Regiment class, replace the line
this.men = men;
with
this.men = addMen2(regNumber);
Then in your toString method, replace
int men = regim.addMen2(regNumber);
with
int men = regim.getMen();
Here is what your main should look like:
public static void main(String[] args) throws IOException{
ArmyDataList army = new ArmyDataList();
Scanner fileScan = new Scanner(new File("regiments.txt"));
System.out.println("Report Summary:\n");
while (fileScan.hasNext()) {
String line = fileScan.nextLine();
System.out.println(line);
Scanner in = new Scanner(line);
int regNumber = in.nextInt();
String name = in.next();
int men = 0 ; //men is set to 0 only because I havent add the men yet
Regiment adder = new Regiment(regNumber, name, men );
army.AddToList(adder);
}
System.out.println(army.toString()); //print out the initial # of men
for(int i = 0; i < 20; i++)
army.addMen();
System.out.println(army.toString()); //print the final # of men
}
in Regiment get rid of method addMen2, and replace it with
public void addMen(int men) {
this.men +=men;
}
then in your army you could have method
public void addMen(int men) {
for(Regiment regiment : list){
regiment.addMen(men);
}
}
that will be simplest solution to add 100 men to each regiment,
other thing is, your toString is bit nasty, regiment should know how meny soldiers it ghas, you shouldnt need additional method to calculate it (reason why i recommend you to trash addMen2 method)
to initiate your Regiment, use constructor. You want to have regiments in sizes 1000, 1950, 1900 etc, do it when you are creating them
while (fileScan.hasNext()) {
String line = fileScan.nextLine();
System.out.println(line);
Scanner in = new Scanner(line) ;
int regNumber = in.nextInt();
String name = in.next();
int men = 1050 - (regNumber * 50);
Regiment adder = new Regiment(regNumber, name, men );
army.AddToList(adder) ;
}