Issue with hold function in Yatzy bot - java

I'm stuck with a 'hold' function when developing a Yatzy bot. Everything else works, but the logic for this function seems to fail in some instances. Basically, the idea is to hold all the numbers given, and then roll the dice that don't match the numbers given.
[00:04] #Dessimat0r: .roll
[00:04] YatzyBot: #1: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
[00:04] #Dessimat0r: .hold 2 1
[00:04] YatzyBot: #2: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
[00:04] #Dessimat0r: .hold 2 1
[00:04] YatzyBot: #3: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
As can be seen, all numbers are being held instead of just the selected few (This is not coincidence from the dice rolls). The code is below:
} else if (event.getMessage().startsWith(".hold")) {
if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) {
String[] tokens = event.getMessage().split(" ");
if (tokens[0].equals(".hold")) {
boolean failed = false;
try {
if (tokens.length == 1) {
bot.sendMessage(CHANNEL, "Must choose some dice to hold!");
return;
}
ArrayList<Integer> dice = new ArrayList<Integer>();
ArrayList<Integer> holdnums = new ArrayList<Integer>();
ArrayList<Integer> rollnums = new ArrayList<Integer>();
for (Die d : y.getDice()) {
dice.add(d.getFaceValue());
}
// parse other numbers
for (int i = 1; i < tokens.length; i++) {
int num = Integer.parseInt(tokens[i]);
holdnums.add(num);
}
ListIterator<Integer> diter = dice.listIterator();
dice: while (diter.hasNext()) {
Integer d = diter.next();
if (holdnums.isEmpty()) {
rollnums.add(d);
diter.remove();
continue;
}
ListIterator<Integer> iter = holdnums.listIterator();
while (iter.hasNext()) {
int holdnum = iter.next().intValue();
if (holdnum == d) {
iter.remove();
diter.remove();
continue dice;
}
}
}
if (!holdnums.isEmpty()) {
bot.sendMessage(CHANNEL, "Hold nums not found: " + holdnums);
failed = true;
}
if (!failed) {
y.getTurn().rollNumbers(convertIntegers(rollnums));
Map<Scoring, Integer> scores = y.getRollScores();
Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class);
Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class);
for (Entry<Scoring, Integer> entry : scores.entrySet()) {
if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) {
unchosen.put(entry.getKey(), entry.getValue());
} else {
chosen.put(entry.getKey(), entry.getValue());
}
}
bot.sendMessage(CHANNEL, "#" + y.getTurn().getRolls() + ": dice: " + y.getDiceStr() + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores));
}
} catch (TurnException e1) {
bot.sendMessage(CHANNEL, e1.getMessage());
} catch (RollException e2) {
bot.sendMessage(CHANNEL, e2.getMessage());
} catch (YahtzyException e3) {
bot.sendMessage(CHANNEL, e3.getMessage());
} catch (NumberFormatException e4) {
bot.sendMessage(CHANNEL, e4.getMessage());
}
}
}
}
Edit: Fixed it all. Updated code:
} else if (event.getMessage().startsWith(".hold")) {
if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) {
String[] tokens = event.getMessage().split(" ");
if (tokens[0].equals(".hold")) {
boolean failed = false;
try {
if (tokens.length == 1) {
bot.sendMessage(channel, "Must choose some dice to hold!");
return;
}
ArrayList<Integer> holdnums = new ArrayList<Integer>();
ArrayList<Integer> rollnums = new ArrayList<Integer>();
// parse other numbers
for (int i = 1; i < tokens.length; i++) {
int num = Integer.parseInt(tokens[i]);
holdnums.add(num);
}
for (int i = 0; i < y.getDice().length; i++) {
int d = y.getDice()[i].getFaceValue();
if (holdnums.isEmpty()) {
rollnums.add(d);
continue;
}
ListIterator<Integer> iter = holdnums.listIterator();
boolean found = false;
while (iter.hasNext()) {
int holdnum = iter.next().intValue();
if (holdnum == d) {
iter.remove();
found = true;
break;
}
}
if (!found) {
rollnums.add(d);
}
}
if (!holdnums.isEmpty()) {
bot.sendMessage(channel, "Hold nums not found: " + holdnums);
failed = true;
}
if (!failed) {
boolean[] rolled = y.getTurn().rollNumbers(convertIntegers(rollnums));
Map<Scoring, Integer> scores = y.getRollScores();
Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class);
Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class);
for (Entry<Scoring, Integer> entry : scores.entrySet()) {
if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) {
unchosen.put(entry.getKey(), entry.getValue());
} else {
chosen.put(entry.getKey(), entry.getValue());
}
}
bot.sendMessage(channel, "#" + y.getTurn().getRolls() + ": dice: " + diceToString(rolled) + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores));
}
} catch (TurnException e1) {
bot.sendMessage(channel, e1.getMessage());
} catch (RollException e2) {
bot.sendMessage(channel, e2.getMessage());
} catch (YahtzyException e3) {
bot.sendMessage(channel, e3.getMessage());
} catch (NumberFormatException e4) {
bot.sendMessage(channel, e4.getMessage());
}
}
}
}

Everything looks OK, but this check for holdnum is not in the right place:
if (absent) {
bot.sendMessage(CHANNEL, "Hold num not found: " + holdnum);
failed = true;
break dice;
}
It is too early to say here if given hold number is right or wrong, so it is better to remove this piece of code. To check validity of holdnums you could look at this list after the "dice" loop finishes: if holdnums is not empty, it contains some items, that were not found.
For updated question:
I see one problem: rollnums.add(d) should not be called in nested while to avoid adding the same value several times. Instead, it should be called once, after this loop is completed.

Related

Runtime Error(Non Zero Exit Code) in CodeChef Program (JAVA)

Here's the question -
https://www.codechef.com/DEC17/problems/CPLAY
And here's my solution -
import java.util.Scanner;
class Penalty_Shoot_Out
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
//System.out.println("T: ");
int T = sc.nextInt();
sc.nextLine();
while(T-->0)
{
String s = sc.nextLine();
int l = s.length();
s = " " + s;
int A_score = 0, B_score = 0, A_shots = 0, B_shots = 0, flag = 0, A_shots_left = 5, B_shots_left = 5, shots_left = 0;
Outer:for(int i=1; i<=20; i++)
{
char c = s.charAt(i);
if(i%2==1)
{
flag = 0;
A_shots++;
A_shots_left--;
if(c=='1')
A_score++;
}
else
{
flag = 1;
B_shots++;
B_shots_left--;
if(c=='1')
B_score++;
}
if(i<=10)
{
if(A_score<B_score)
{
if(B_score-A_score>A_shots_left)
{
System.out.println("TEAM-B " + i);
break Outer;
}
}
else
{
if(A_score-B_score>B_shots_left)
{
System.out.println("TEAM-A " + i);
break Outer;
}
}
}
else if(i>10 && i<=20)
{
if(i%2==0)
{
if(A_score>B_score)
System.out.println("TEAM-A " + i);
else if(B_score>A_score)
System.out.println("TEAM-B " + i);
else
System.out.println("TIE");
break Outer;
}
}
}
}
}
}
These are the exceptions -
Exception
in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at Penalty_Shoot_Out.main(Main.java:8)
I'm getting the correct answer on my computer, but when I submit it online, I get the NZEC Runtime Error.
I tried Googling for solutions and most people said the error might have to do with the main function returning a wrong number or not returning a number. Some said it may be due to the use of a particular function or due to an exception that i am not handling during I/O. However, I haven't been able to figure it out.
I'd really appreciate it if someone could fix my code.
You should put your solution in a try catch.
public static void main(String args[])
{
try {
Scanner sc = new Scanner(System.in);
//System.out.println("T: ");
int T = sc.nextInt();
sc.nextLine();
while(T-->0)
{
String s = sc.nextLine();
int l = s.length();
s = " " + s;
int A_score = 0, B_score = 0, A_shots = 0, B_shots = 0, flag = 0,
A_shots_left = 5, B_shots_left = 5, shots_left = 0;
Outer:for(int i=1; i<=20; i++)
{
char c = s.charAt(i);
if(i%2==1)
{
flag = 0;
A_shots++;
A_shots_left--;
if(c=='1')
A_score++;
}
else
{
flag = 1;
B_shots++;
B_shots_left--;
if(c=='1')
B_score++;
}
if(i<=10)
{
if(A_score<B_score)
{
if(B_score-A_score>A_shots_left)
{
System.out.println("TEAM-B " + i);
break Outer;
}
}
else
{
if(A_score-B_score>B_shots_left)
{
System.out.println("TEAM-A " + i);
break Outer;
}
}
}
else if(i>10 && i<=20)
{
if(i%2==0)
{
if(A_score>B_score)
System.out.println("TEAM-A " + i);
else if(B_score>A_score)
System.out.println("TEAM-B " + i);
else
System.out.println("TIE");
break Outer;
}
}
}
}
} catch(Exception e) {
return;
}
}
}

Some elements are just magically not removed from ArrayList

ok here's the block of code i wrote :
public ArrayList<Location> possibleMoves() {
ArrayList<Location> a1 = new ArrayList<Location>(); // an array to contain all possible locations
Board testB = new Board(); // a test board to test if locations are valid or not
// locations have x & y coordinates
a1.add(new Location(getCurrentLocation().getx() - 1, getCurrentLocation().gety() + 1));
a1.add(new Location(getCurrentLocation().getx() + 1, getCurrentLocation().gety() - 1));
a1.add(new Location(getCurrentLocation().getx() - 1, getCurrentLocation().gety() - 1));
a1.add(new Location(getCurrentLocation().getx() + 1, getCurrentLocation().gety() + 1));
for (int i = 0; i < a1.size(); i++) {
try {
Tower testTower = testB.getGrid()[a1.get(i).getx()][a1.get(i).gety()];
}catch(ArrayIndexOutOfBoundsException e) {
a1.remove(a1.get(i));
}
}
return a1;
}
When you remove the element, the position of the following ones is decreased. Do this also to i. And, you can just use remove(int).
for (int i = 0; i < a1.size(); i++) {
try {
Tower testTower = testB.getGrid()[a1.get(i).getx()][a1.get(i).gety()];
} catch(ArrayIndexOutOfBoundsException e) {
a1.remove(i--);
}
}
If you want to remove elements from a List while visiting its elements I suggest to used the following pattern:
Iterator<Location> locationsIt = a1.iterator();
while (locationsIt.hasNext()) {
Location location = locationsIt.next();
try {
Tower testTower = testB.getGrid()[location.getx()][location.gety()];
} catch(ArrayIndexOutOfBoundsException e) {
locationsIt.remove();
}
}
It's easy to use and it's not error prone.

File Writing Issues w/ ArrayList

EDIT: Program now writes the first existing score only, and as follows:
File size(in lines)-
0- Writes as normal.
1- Prompts for initials, output shows user score was added to myscores, but the first score is the one added to the file.
2+- Similar to second, no prompt for initials, first score is written twice to file.
import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.text.*;
/* Notes:
* High Scores Class:
* Used to read/write high scores text file
* */
/*
* To do:
* Fix reading/writing file
* Fix sort as needed
* FILTER OUT WHITESPACE WHEN READING
*/
public class HighScores
{
//user will input their 3 initials, must be 3
public ArrayList<String> filearr;//hold file contents
public BufferedReader hsds;//read initials in
public ArrayList<Score> myscores;//hold all existing scores
public ArrayList<String> vals;//hold filearr contents to be split and parsed
public HighScores() //constructor
{
myscores = new ArrayList<Score>();
vals = new ArrayList<String>();
hsds = new BufferedReader(new InputStreamReader(System.in));//for user input
filearr = new ArrayList<String>();//holds values to be written to file
System.out.println("File created.");
}
public void populate(Score uscore)
//argument is score generated by user
//this is called after game finishes
//handles score(write or no?
{
Integer thescore = uscore.myscore;
switch (filearr.size())
{
case 2://doesnt prompt for initials, writes first score twice each on a new line
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
String strpos = "" + ((vals.get(0)).charAt(3));//remember strings are arrays!
for (int i = 0; i < vals.size(); i++)
{
Score temp = new Score();
String tempstr = vals.get(i);
temp.initials = (tempstr.split(strpos)[0]);
temp.myscore = Integer.parseInt((tempstr.split(strpos)[2]));
myscores.add(temp);
}
int ssize = myscores.size();
BubbleSort bsort = new BubbleSort();
bsort.bubbleSort(myscores, ssize);//ssize is current size of scores
System.out.println("Unsorted scores");
for(int i = 0; i < myscores.size(); i++)
{
System.out.println("Score " + i + " : ");
System.out.println("inits: " + (myscores.get(i).initials));
System.out.println("myscore: " + ("" +(myscores.get(i).myscore)));
}
int max = myscores.size();
int y = 0;
Score sscore = new Score();
sscore.myscore = thescore;
if(sscore.myscore > (myscores.get(y)).myscore)//sorting algorithm
{
try
{
System.out.println("Please enter 3 initials to identify your high score.");
String tinitials = "" + ((hsds.readLine()).toUpperCase());
//initials are always formatted as upper case
if (tinitials.length() > 3)
{
String temp = tinitials.split(strpos)[0];
sscore.initials = temp;
}
else
{
sscore.initials = tinitials;
}
hsds.close();
}
catch (Exception e)
{
e.printStackTrace();
}
if(sscore.myscore < (myscores.get(max - 1)).myscore)//smaller than largest
{
System.out.println("bigger, sm max");
myscores.set(y, sscore);//in at 0
y++;//now 1
while ((myscores.get(y)).myscore < sscore.myscore)
{
myscores.set(y-1, myscores.get(y));//shift this one down
myscores.set(y, sscore);//fill the hole
y++;//ends up at 5
}
}
else if(sscore.myscore > (myscores.get(max-1)).myscore)//bigger than largest
{
System.out.println("bigger, gr max");
Score temp = (myscores.get(max-1));
myscores.set(max-1, sscore);//in at end
y++;
while(y < (max-1))
{
myscores.set(y-1, myscores.get(y));//shift this one down
myscores.set(y, myscores.get(y+1));//fill the hole
y++;//ends up at 5
}
myscores.set(max-2, temp);
}
else if((sscore.myscore).equals((myscores.get(max-1)).myscore))//equal to largest
{
System.out.println("bigger, eq max");
y++;//now 1
while ((myscores.get(y)).myscore < sscore.myscore)
{
myscores.set(y-1, myscores.get(y));
myscores.set(y, sscore);
y++;
}
myscores.set(y-1, sscore);
}
else
{
System.out.println("Oops.");
}
}
else//smaller than first element
{
System.out.println("too small");
}//end sort
System.out.println("Sorted scores");
for(int i = 0; i < myscores.size(); i++)
{
System.out.println("Score " + i + " : ");
System.out.println("inits: " + (myscores.get(i).initials));
System.out.println("myscore: " + ("" +(myscores.get(i).myscore)));
}
break;
case 0://writes first score once
Score newscore = new Score();
newscore.myscore = thescore;
try
{
System.out.println("Please enter 3 initials to identify your high score.");
String tinitials = "" + ((hsds.readLine()).toUpperCase());
//initials are always formatted as upper case
if (tinitials.length() > 3)
{
strpos = "" + (tinitials.charAt(3));
String temp = tinitials.split(strpos)[0];
newscore.initials = temp;
}
else
{
newscore.initials = tinitials;
}
}
catch (Exception e)
{
e.printStackTrace();
}
myscores.add(newscore);
break;
case 1://writes first score again on separate line
newscore = new Score();
newscore.myscore = thescore;
strpos = "" + ((vals.get(0)).charAt(3));//remember strings are arrays!
try
{
System.out.println("Please enter 3 initials to identify your high score.");
String tinitials = "" + ((hsds.readLine()).toUpperCase());
//initials are always formatted as upper case
if (tinitials.length() > 3)
{
strpos = "" + (tinitials.charAt(3));
String temp = tinitials.split(strpos)[0];
newscore.initials = temp;
}
else
{
newscore.initials = tinitials;
}
}
catch (Exception e)
{
e.printStackTrace();
}
for (int i = 0; i < vals.size(); i++)
{
Score temp = new Score();
String tempstr = vals.get(i);
temp.initials = (tempstr.split(strpos)[0]);
temp.myscore = Integer.parseInt((tempstr.split(strpos)[2]));//works, idk why
myscores.add(temp);
}
bsort = new BubbleSort();
if (newscore.myscore > (myscores.get(0)).myscore)
{
myscores.add(newscore);
}
else
{
bsort.bubbleSort(myscores, myscores.size());
}
break;
default:
System.out.println("Invalid file supplied.");
break;
}
}
public void Save(PrintWriter writeme)//write everything to a file, filearr should be
//the same size as it was upon object construction
{
for (int i = 0; i < myscores.size(); i++)
{
filearr.add(myscores.get(i).initials + " " + ("" + (myscores.get(i).myscore))); //copy the finished list over
writeme.println(filearr.get(i)); //write the list to the high scores file
//writeme is myout in dsapp.java
}
}
}
The classes not shown are Score(score object template), Encrypter(array generation and difficulty selection), BubbleSort(bubble sort algorithm), and DSApp(application file, draws GUI and performs file operations). Comments should explain everything; I can supply more code as needed. Any and all help would be greatly appreciated.
IndexOutOfBoundsExceptions on:
temp.myscore = Integer.parseInt((tempstr.split(strpos)[1]));
means that the array returned by tempstr.split(strpos) has less than 2 items (0 or 1). It should be fairly easy to add a print statement there or debug the program step by step to figure out why.
inability to write properly to a file
that's a bit vague (do you get an exception? the file is created but invalid? etc.)

How to sort ip address in ascending order

Is there any method to sort this? Or do I just need to split it and use a loop to compare?
Input
123.4.245.23
104.244.253.29
1.198.3.93
32.183.93.40
104.30.244.2
104.244.4.1
Output
1.198.3.93
32.183.93.40
104.30.244.2
104.244.4.1
104.244.253.29
123.4.245.23
So far I use HashMap to stored my data. I want sort the value by the Ip address in ascending order. Seems TreeMap is better choice?
TLDR
Don't rewrite the wheel like I tried too, use the InetAddress class in a Comparator.
Edit
A more efficient and accurate way to do it is with the InetAddress class mentioned above. Credits to 200_success for code.
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;
public class IPSort {
private static String[] TESTS = {"0:0:0:0:0:0:fff:ffff","::FFFF:222.1.41.90",":8:","::::5:6::8","::::5:6::7","::::5:6::8","123..245.23","1...","..1.","123...23",".1..","123..245.23", "123..245.23", "104.244.253.29", "1.198.3.93", "32.183.93.40", "32.183.93.40", "104.30.244.2", "104.244.4.1","0.0.0.1",":a:","::5:3:4:5:6:78","1::2:3","1::2:3:4","1::5:256.2.3.4","1:1:3000.30.30.30","ae80::217:f2ff:254:7:237:98","::2:3:4:5:6:7","2:3:4:5:6:7","::5:3:4:5:6:7:8","::5:3:4:5:6:7:8:9:0","1::8","1::2:3","1::2:3:4","1::5:256.2.3.4","1:1:3000.30.30.30","ae80::217:f2ff:254.7.237.98","1:2:3:4::5:1.2.3.4","2001:0000:1234:0000:0000:C1C0:ABCD:0876","12345::6:7:8","1::1.2.900.4","fe80::","::ffff:0:0"};
public static class InetAddressComparator implements Comparator<InetAddress> {
#Override
public int compare(InetAddress a, InetAddress b) {
byte[] aOctets = a.getAddress(),
bOctets = b.getAddress();
int len = Math.max(aOctets.length, bOctets.length);
for (int i = 0; i < len; i++) {
byte aOctet = (i >= len - aOctets.length) ?
aOctets[i - (len - aOctets.length)] : 0;
byte bOctet = (i >= len - bOctets.length) ?
bOctets[i - (len - bOctets.length)] : 0;
if (aOctet != bOctet) return (0xff & aOctet) - (0xff & bOctet);
}
return 0;
}
}
public static Optional<InetAddress> toInetAddress(String s) {
try {
return Optional.of(InetAddress.getByName(s));
} catch (UnknownHostException badAddress) {
return Optional.empty();
}
}
public static void main(String[] args) throws Exception {
System.out.println("Valid 32-bit addresses");
Arrays.stream(TESTS)
.map(IPSort::toInetAddress)
.filter(Optional::isPresent)
.map(Optional::get)
.filter((addr) -> addr instanceof Inet4Address)
.map(InetAddress::getHostAddress)
.forEach(System.out::println);
System.out.println("\nValid 128-bit addresses");
Arrays.stream(TESTS)
.map(IPSort::toInetAddress)
.filter(Optional::isPresent)
.map(Optional::get)
.filter((addr) -> addr instanceof Inet6Address)
.map(InetAddress::getHostAddress)
.forEach(System.out::println);
System.out.println("\nInvalid addresses");
Arrays.stream(TESTS)
.filter((s) -> !toInetAddress(s).isPresent())
.forEach(System.out::println);
System.out.println("\nSorted addresses");
Arrays.stream(TESTS)
.map(IPSort::toInetAddress)
.filter(Optional::isPresent)
.map(Optional::get)
.sorted(new InetAddressComparator())
.map(InetAddress::getHostAddress)
.forEach(System.out::println);
}
}
Original Answer
In order to sort IPs you first need to know a bit about them. There are two types of IPs; 32 Bit and 128 Bit.
32 Bit Source
The 32 bit IP is split into 4 groups of numbers between 0 and 255. These groups are seperated via a .
A single group, as shown above, is 8 bits of data. This is the reason the numbers in a group are limited between 0 and 255.
For a 32 bit IP to be formatted correctly it should be int.int.int.int. Even if the int is a 0 it must be shown in the IP address. This is different to a 128 bit IP which may omit 0s. For example ::5: which is the same as 0:0:5:0:0:0:0:0.
128 Bit Source
The 128 bit IP is split into 8 groups of numbers between 0 and FFFF (which is equivalent to 65535). Unlike a 32 bit IPs group, these groups are separated buy a :.
A single group, as show above, is 16 bits of data. This is the reason the numbers in the groups are limited between 0 and FFFF.
To format a 128 bit IP properly there are several rules you have to follow. 0s may be omitted from groups and if the remaining groups all are 0 then the groups may also be omitted. The groups have to be separated by a :. If you are omitting groups the last group which isn't a 0 has to be followed by a :. These rules leave us with a format int:int:int:int:int:int:int:int. An example of 0s and groups being omitted would be 58f:::fff:2:. This is the same as 58f:0:0:fff:2:0:0:0.
Sorting
Once the IPs have been sorted into their respective groups they can be sorted. To sort an IP you need to use a method called weighting. This is because simply adding or multiplying different groups together wouldn't work. For example take the these two IPs; 192.5.48.198 and 198.48.5.192. If you add or multiply the values of the groups together you get the same answer. So there is no way to accurately compare them using addition and multiplication. If you use weighting you get something like this.
32 Bit Weighting
Value of IP = (Group one value * 256^4) + (Group two value * 256^3) +
(Group three value * 256^2) + (Group four value * 256)
128 Bit Weighting
Value of IP = (Group one value * 65536^8) + (Group two value * 65536^7) +
(Group three value * 65536^6) + (Group four value * 65536^5) +
(Group five value * 65536^4) + (Group six value * 65536^3) +
(Group seven value * 65536^2) + (Group eight value * 65536)
The Code in Java
As long as the IP is formatted reasonably correctly this code will separate the two kinds of IP and then sort them.
import java.util.*;
import java.math.*; //For BigInteger
import java.util.regex.*;
import java.lang.*;
public class IPSort
{
String[] tests = {":8:","::::5:6::8","::::5:6::7","::::5:6::8","123..245.23","1...","..1.","123...23",".1..","123..245.23", "123..245.23", "104.244.253.29", "1.198.3.93", "32.183.93.40", "32.183.93.40", "104.30.244.2", "104.244.4.1","0.0.0.1",":a:","::5:3:4:5:6:78","1::2:3","1::2:3:4","1::5:256.2.3.4","1:1:3000.30.30.30","ae80::217:f2ff:254:7:237:98"};
ArrayList<String> bit32 = new ArrayList<String>();
ArrayList<String> bit128 = new ArrayList<String>();
ArrayList<String> cleanBit32 = new ArrayList<String>();
ArrayList<String> cleanBit128 = new ArrayList<String>();
boolean myMatcher32Bit(String s)
{
Pattern patter32Bit = Pattern.compile("^(?=(?:[^.]*\\.){3}[^.]*$)(?=(?:[^:]*:){0}[^:]*$)(?=(?:[^a-zA-Z]*[^a-zA-Z])*$)");
Matcher matcher32Bit = patter32Bit.matcher(s);
return matcher32Bit.find();
}
boolean myMatcher128Bit(String s)
{
Pattern patter128Bit = Pattern.compile("^(?=(?:[^.]*\\.){0}[^.]*$)(?=(?:[^:]*:){1,7}[^:]*$)");
Matcher matcher128Bit = patter128Bit.matcher(s);
return matcher128Bit.find();
}
public void sortIntoRespectiveIPTypes()
{
for(String s: tests)
{
if(myMatcher32Bit(s))
{
bit32.add(s);
}
else if(myMatcher128Bit(s))
{
bit128.add(s);
}
}
System.out.println("32 bit IPs");
for(String ip: bit32)
{
System.out.println(" "+ip);
}
System.out.println("\n128 bit IPs");
for(String ip: bit128)
{
System.out.println(" "+ip);
}
int count = 0;
for(String ip: tests)
{
if(myMatcher32Bit(ip)==false && myMatcher128Bit(ip)==false)
{
count++;
}
}
if(count != 0)
{
System.out.println("\nDidn't match an IP format");
for(String ip: tests)
{
if(myMatcher32Bit(ip)==false && myMatcher128Bit(ip)==false)
{
System.out.println(" "+ip);
}
}
}
}
public void sort32BitIPs(ArrayList<String> bit32, ArrayList<String> newBit32)
{
ArrayList<BigInteger> bigInt32Bit = new ArrayList<BigInteger>();
for(String ip:bit32)
{
String[] tempArray = ip.split("\\.");
int i=0;
for(String s:tempArray)
{
if(s.equals(""))
{
tempArray[i]="0";
}
i++;
}
bigInt32Bit.add(convert32Bit(tempArray));
}
Collections.sort(bigInt32Bit);
ArrayList<String> fixFormat = new ArrayList<String>();
for(String ip:bit32)
{
String[] fixArray = ip.split("\\.");
int i=0;
for(String s:fixArray)
{
if(s.equals(""))
{
fixArray[i]="0";
}
i++;
}
StringBuilder strBuilder = new StringBuilder();
for(int i2 = 0; i2 < 4; i2++)
{
if(i2<3)
{
try
{
if(!fixArray[i2].equals(""))
{
strBuilder.append(fixArray[i2]+".");
}
else
{
strBuilder.append(".");
}
}
catch(Exception e)
{
strBuilder.append("0.");
}
}
else
{
try
{
strBuilder.append(fixArray[i2]);
}
catch(Exception e)
{
strBuilder.append("0");
}
}
}
String newString = strBuilder.toString();
fixFormat.add(newString);
bit32=fixFormat;
}
for(BigInteger finalValue:bigInt32Bit)
{
for(String ip:bit32)
{
String[] tempArray = ip.split("\\.");
int i=0;
for(String s:tempArray)
{
if(s.equals(""))
{
tempArray[i]="0";
}
i++;
}
if(finalValue.equals(convert32Bit(tempArray)))
{
if(!newBit32.contains(ip))
{
String str = bit32.toString();
String findStr = ip;
int lastIndex = 0;
int count = 0;
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if(lastIndex != -1){
count++;
lastIndex += findStr.length();
}
}
for(int k = 0; k<count;k++)
{
newBit32.add(ip);
}
}
}
}
}
}
BigInteger convert32Bit(String[] array)
{
int[] tempArray = new int[array.length];
ArrayList<BigInteger> tempBigIntList = new ArrayList<BigInteger>();
int i = 0;
for(String s:array)
{
int power = 4-i;
tempArray[i]= Integer.parseInt(s);
String string = Integer.toString(tempArray[i]);
BigInteger myBigInt = new BigInteger(string);
BigInteger num2 = myBigInt.multiply(new BigInteger("256").pow(power));
tempBigIntList.add(num2);
i++;
}
BigInteger bigInt32Bit = new BigInteger("0");
for(BigInteger bI:tempBigIntList)
{
bigInt32Bit = bigInt32Bit.add(bI);
}
return bigInt32Bit;
}
public void sort128BitIPs(ArrayList<String> bit128,ArrayList<String> newBit128)
{
ArrayList<BigInteger> bigInt128Bit = new ArrayList<BigInteger>();
for(String ip:bit128)
{
String[] tempArray = ip.split(":");
int i=0;
for(String s:tempArray)
{
if(s.equals(""))
{
tempArray[i]="0";
}
i++;
}
bigInt128Bit.add(convert128Bit(tempArray));
}
Collections.sort(bigInt128Bit);
for(BigInteger finalValue:bigInt128Bit)
{
for(String ip:bit128)
{
String[] tempArray = ip.split(":");
int i=0;
for(String s:tempArray)
{
if(s.equals(""))
{
tempArray[i]="0";
}
i++;
}
if(finalValue.equals(convert128Bit(tempArray)))
{
if(!newBit128.contains(ip))
{
String str = bit128.toString();
String findStr = ip;
int lastIndex = 0;
int count = 0;
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if(lastIndex != -1){
count++;
lastIndex += findStr.length();
}
}
for(int k = 0; k<count;k++)
{
newBit128.add(ip);
}
}
}
}
}
}
BigInteger convert128Bit(String[] array)
{
int[] tempArray = new int[array.length];
ArrayList<BigInteger> tempBigIntList = new ArrayList<BigInteger>();
int i = 0;
for(String s:array)
{
int power = 8-i;
tempArray[i]= Integer.parseInt(s,16);
String string = Integer.toString(tempArray[i]);
BigInteger myBigInt = new BigInteger(string);
BigInteger num2 = myBigInt.multiply(new BigInteger("65536").pow(power));
tempBigIntList.add(num2);
i++;
}
BigInteger bigInt128Bit = new BigInteger("0");
for(BigInteger bI:tempBigIntList)
{
bigInt128Bit = bigInt128Bit.add(bI);
}
return bigInt128Bit;
}
public void printInOrder(ArrayList<String> bit32,ArrayList<String> bit128)
{
System.out.println("\nSorted IPs");
System.out.println("Sorted 32 bit IPs - Ascending");
for(String ip: bit32)
{
System.out.println(" "+ip);
}
Collections.reverse(bit32);
System.out.println("\nSorted 32 bit IPs - Descending");
for(String ip: bit32)
{
System.out.println(" "+ip);
}
System.out.println("\nSorted 128 bit IPs - Ascending");
for(String ip: bit128)
{
System.out.println(" "+ip);
}
Collections.reverse(bit128);
System.out.println("\nSorted 128 bit IPs - Descending");
for(String ip: bit128)
{
System.out.println(" "+ip);
}
}
public void run(ArrayList<String> bit32,ArrayList<String> bit128,ArrayList<String> newBit32,ArrayList<String> newBit128)
{
sortIntoRespectiveIPTypes();
sort32BitIPs(bit32,newBit32);
sort128BitIPs(bit128,newBit128);
printInOrder(newBit32,newBit128);
}
public static void main(String[] args)
{
IPSort ipS = new IPSort();
ipS.run(ipS.bit32,ipS.bit128,ipS.cleanBit32,ipS.cleanBit128);
}
}
As a note it is possible to use this class to sort IPs but my code does not use it
This code also sorts the list into an ascending order, then into a descending order. This is printed out in the command console when the code is run
Output
I would suggest to implement your own Comparator. See this post: Sorting IP addresses in Java
Copy paste only for you:
/**
* LGPL
*/
public class InetAddressComparator implements Comparator {
#Override
public int compare(InetAddress adr1, InetAddress adr2) {
byte[] ba1 = adr1.getAddress();
byte[] ba2 = adr2.getAddress();
// general ordering: ipv4 before ipv6
if(ba1.length < ba2.length) return -1;
if(ba1.length > ba2.length) return 1;
// we have 2 ips of the same type, so we have to compare each byte
for(int i = 0; i < ba1.length; i++) {
int b1 = unsignedByteToInt(ba1[i]);
int b2 = unsignedByteToInt(ba2[i]);
if(b1 == b2)
continue;
if(b1 < b2)
return -1;
else
return 1;
}
return 0;
}
private int unsignedByteToInt(byte b) {
return (int) b & 0xFF;
}
}
For the ip4 adresses you showed you just
need to split it up. then i would convert it to a long value, and sort by that.
long value = f3 + f2*256 + f1 * 256^2 + f0 * 256^3
where f0 - f3 are the splitted values.
Pad each fragment in IP to length 3 and then sort e.g. below:
List<String> ipList = new ArrayList<String>();
ipList.add("123.4.245.23");
ipList.add("104.244.253.29");
ipList.add("1.198.3.93");
ipList.add("32.183.93.40");
ipList.add("104.30.244.2");
ipList.add("104.244.4.1");
Collections.sort(ipList, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
String[] ips1 = o1.split("\\.");
String updatedIp1 = String.format("%3s.%3s.%3s.%3s",
ips1[0],ips1[1],ips1[2],ips1[3]);
String[] ips2 = o2.split("\\.");
String updatedIp2 = String.format("%3s.%3s.%3s.%3s",
ips2[0],ips2[1],ips2[2],ips2[3]);
return updatedIp1.compareTo(updatedIp2);
}
});
//print the sorted IP
for(String ip: ipList){
System.out.println(ip);
}
It prints:
1.198.3.93
32.183.93.40
104.30.244.2
104.244.4.1
104.244.253.29
123.4.245.23
public class IpSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] arr = {"192.168.1.1",
"191.122.123.112",
"192.161.1.1",
"191.122.123.1",
"123.24.5.78",
"121.24.5.78",
"123.24.4.78",
"123.2.5.78",
"192.1.1.1",
"125.45.67.89",
"1.1.1.1",
"3.4.5.6",
"2.2.2.2",
"6.6.6.7",
"155.155.23.0"};
String tmp;
for(int i=0;i<arr.length;i++)
{
for(int j=1;j<arr.length-i;j++)
{
String[] instr1 = arr[j-1].split("\\.");
String[] instr2 = arr[j].split("\\.");
if(Integer.parseInt(instr1[0]) > Integer.parseInt(instr2[0]))
{
tmp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=tmp;
}else if(Integer.parseInt(instr1[0]) == Integer.parseInt(instr2[0])
&& Integer.parseInt(instr1[1]) > Integer.parseInt(instr2[1]) )
{
tmp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=tmp;
} else if(Integer.parseInt(instr1[0]) == Integer.parseInt(instr2[0])
&& Integer.parseInt(instr1[1]) == Integer.parseInt(instr2[1])
&& Integer.parseInt(instr1[2]) > Integer.parseInt(instr2[2]) )
{
tmp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=tmp;
} else if(Integer.parseInt(instr1[0]) == Integer.parseInt(instr2[0])
&& Integer.parseInt(instr1[1]) == Integer.parseInt(instr2[1])
&& Integer.parseInt(instr1[2]) == Integer.parseInt(instr2[2])
&& Integer.parseInt(instr1[3]) > Integer.parseInt(instr2[3]) )
{
tmp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=tmp;
}
}
}
System.out.println("final sorted list of ips :\n");
for(int k=0;k<arr.length;k++){
System.out.println(arr[k]);
}
}
}
In Java8
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
class Test {
private static final Comparator<InetAddress> COMPARATOR = Comparator
.comparing(InetAddress::getAddress,
Comparator.comparingInt((byte[] b) -> b.length)
.thenComparing(b -> new BigInteger(1, b)));
public static void main(String[] args) {
final String[] addresses = {
"123.4.245.23",
"104.244.253.29",
"1.198.3.93",
"32.183.93.40",
"104.30.244.2",
"104.244.4.1"
};
for (final String address : sort(addresses)) {
System.out.println(address);
}
}
public static String[] sort(final String[] addresses) {
return Arrays.stream(addresses)
.map(s -> new AbstractMap.SimpleImmutableEntry<>(toInetAddress(s), s))
.sorted(Comparator.comparing(Map.Entry::getKey, Comparator.nullsLast(COMPARATOR)))
.map(Map.Entry::getValue)
.toArray(String[]::new);
}
private static InetAddress toInetAddress(final String address) {
try {
return InetAddress.getByName(address);
} catch (final UnknownHostException | SecurityException e) {
e.printStackTrace();
return null;
}
}
}
Output:
1.198.3.93
32.183.93.40
104.30.244.2
104.244.4.1
104.244.253.29
123.4.245.23
How about this plain logic:
Ip Address:
[10.1.1.2, 10.22.33.11, 10.12.23.12]
1) Fill in the IP to complete 12 digits format with prefix 0:
like
[010.001.001.002, 010.022.033.011, 010.012.023,012]
2) Remove "."s to make it complete string of digits:
[010001001002, 010022033011, 010012023012]
3) Apply Sort
[010001001002, 010012023012, 010022033011]
4) Retain dots after every 3 digits:
[010.001.001.002, 010.012.023.012, 010.022.033.011]
5) Remove prefix 0's
[10.1.1.2, 10.12.23.12, 10.22.33.11]
6) Sorted!
public class SortIP
{
public static String getFormattedIP(String ip)
{
String arg[] = new String[4];
arg = (ip).split("\\.");
int i=0;
while(i<=3)
{
if(arg[i].length()==1)
{
arg[i]="00"+arg[i];
}
else if(arg[i].length()==2)
{
arg[i]="0"+arg[i];
}
i++;
}
return arg[0]+arg[1]+arg[2]+arg[3];
}
public static ArrayList<Integer> sortedList(Object[] obj,String order)
{
if(order.equalsIgnoreCase("Ascending"))
{
Arrays.sort(obj, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Map.Entry<Integer, Long>) o1).getValue()
.compareTo(((Map.Entry<Integer, Long>) o2).getValue());
}
});
}
else
{
Arrays.sort(obj, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Map.Entry<Integer, Long>) o2).getValue()
.compareTo(((Map.Entry<Integer, Long>) o1).getValue());
}
});
}
int counter=0;
ArrayList<Integer> key = new ArrayList<Integer>();
//int key[] = new int[ipRange.size()];
for (Object e : obj) {
key.add(((Map.Entry<Integer, Long>) e).getKey());
//key[counter++]=((Map.Entry<Integer, Long>) e).getKey();
System.out.println(((Map.Entry<Integer, Long>) e).getKey() + " : " + ((Map.Entry<Integer, Long>) e).getValue());
}
return key;
}
public static void main(String[] args)
{
Map<Integer,String> ipRange= new TreeMap<Integer,String>();
Map<Integer,Long> formatedIpRange= new TreeMap<Integer,Long>();
ipRange.put(1, "10.1.4.100");
ipRange.put(2, "1.10.400.10");
ipRange.put(3, "196.0.14.15");
ipRange.put(4, "196.70.5.1");
ipRange.put(5, "196.70.7.3");
ipRange.put(6, "153.70.7.0");
for(int j=1;j<=ipRange.size();j++)
{
formatedIpRange.put(j, Long.parseLong(getFormattedIP(ipRange.get(j))));
}
Object[] a = formatedIpRange.entrySet().toArray();
ArrayList<Integer> key = sortedList(a,"descending");
System.out.println("ordered list ");
for (Integer integer : key)
{
System.out.println(ipRange.get(integer));
}
}
}
Try this one
#Override
public int compare(Object adr1, Object adr2) {
try
{
if(adr1 == null || adr1.toString().isEmpty()) return -1;
if(adr2 == null || adr2.toString().isEmpty()) return 1;
String[] ba1 = adr1.toString().split( "\\." );
String[] ba2 = adr2.toString().split( "\\." );
for ( int i = 0; i < ba1.length; i++ )
{
int b1 = Integer.parseInt( ba1[ i ] );
int b2 = Integer.parseInt( ba2[ i ] );
if (b1 == b2)
continue;
if (b1 < b2)
return -1;
else
return 1;
}
return 0;
}
catch ( Exception ex )
{
return 0;
}
}
This is an implementation in Perl, but it demonstrates the need to precompute the splits or factorings instead of computing them again and again for each comparison. I haven't tested it on mixed ipv4 & ipv6 but I think it should work. I just used the example. It seems like precomputing split values is the winner, then comparing the quads separately, instead of exponentiating and adding them all up.
2022-11-02 11:58:42 Wed $ cat | /tmp/foo.pl
123.4.245.23
104.244.253.29
1.198.3.93
32.183.93.40
104.30.244.2
104.244.4.1
Benchmark: timing 10000 iterations of factor_each_time, factor_precompute, split_each_time, split_precompute...
factor_each_time: 3 wallclock secs ( 2.94 usr + 0.00 sys = 2.94 CPU) # 3401.36/s (n=10000)
factor_precompute: 1 wallclock secs ( 1.03 usr + 0.00 sys = 1.03 CPU) # 9708.74/s (n=10000)
split_each_time: 3 wallclock secs ( 3.01 usr + 0.00 sys = 3.01 CPU) # 3322.26/s (n=10000)
split_precompute: 1 wallclock secs ( 1.00 usr + 0.00 sys = 1.00 CPU) # 10000.00/s (n=10000)
Code:
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
use English '-no_match_vars';
use Regexp::Common;
use Benchmark qw(:all);
#use YAML;
my #lines = <STDIN>;
chomp $_ for #lines;
timethese( 10000, {
split_each_time => sub {
my #sorted = sort ip_each_time_split_sorter #lines;
#warn "split_each_time:\n".Dump(\#sorted);
},
split_precompute => sub {
my #sorted =
map $_->{num},
sort ip_precompute_split_sorter
map split_vals($_),
#lines
;
#warn "split_precompute:\n".Dump(\#sorted);
},
factor_each_time => sub {
my #sorted = sort ip_each_time_factor_sorter #lines;
#warn "factor_each_time:\n".Dump(\#sorted);
},
factor_precompute => sub {
my #sorted =
map $_->{num},
sort ip_precompute_factor_sorter
map factor_vals($_),
#lines
;
#warn "factor_precompute:\n".Dump(\#sorted);
},
} );
sub ip_each_time_factor_sorter {
our ($a, $b);
my $a_factor = factor_vals($a);
my $b_factor = factor_vals($b);
return -1 if exists $a_factor->{ipv4} && exists $b_factor->{ipv6};
return 1 if exists $a_factor->{ipv6} && exists $b_factor->{ipv4};
return $a_factor->{val} <=> $b_factor->{val};
}
sub ip_precompute_factor_sorter {
our ($a, $b);
return -1 if exists $a->{ipv4} && exists $b->{ipv6};
return 1 if exists $a->{ipv6} && exists $b->{ipv4};
return $a->{val} <=> $b->{val};
}
sub factor_vals {
my ($ip) = #_;
my $xform;
if ($ip =~ m{ \A $RE{net}{IPv4}{-keep} \z }mxs) {
$xform = {
ipv4 => 1,
num => $1,
val => (
($2 || 0) * 256 ** 4
+ ($3 || 0) * 256 ** 3
+ ($4 || 0) * 256 ** 2
+ ($5 || 0) * 256 ** 1
),
};
}
elsif ($ip =~ m{ \A $RE{net}{IPv6}{-keep} \z }mxs) {
$xform = {
ipv6 => 1,
num => $1,
val => (
($2 || 0) * 65536 ** 8
+ ($3 || 0) * 65536 ** 7
+ ($4 || 0) * 65536 ** 6
+ ($5 || 0) * 65536 ** 5
+ ($6 || 0) * 65536 ** 4
+ ($7 || 0) * 65536 ** 3
+ ($8 || 0) * 65536 ** 2
+ ($9 || 0) * 65536 ** 1
),
};
}
else {
warn "skipping bad entry: $_\n";
}
return $xform;
}
sub split_vals {
my ($ip) = #_;
my $xform;
if ($ip =~ m{ \A $RE{net}{IPv4}{-keep} \z }mxs) {
$xform = {
ipv4 => 1,
num => $1,
vals => [
$2 || 0,
$3 || 0,
$4 || 0,
$5 || 0,
],
};
}
elsif ($ip =~ m{ \A $RE{net}{IPv6}{-keep} \z }mxs) {
$xform = {
ipv6 => 1,
num => $1,
vals => [
$2 || 0,
$3 || 0,
$4 || 0,
$5 || 0,
$6 || 0,
$7 || 0,
$8 || 0,
$9 || 0,
],
};
}
else {
warn "skipping bad entry: $_\n";
}
return $xform;
}
sub ip_precompute_split_sorter {
our ($a, $b);
return -1 if exists $a->{ipv4} && exists $b->{ipv6};
return 1 if exists $a->{ipv6} && exists $b->{ipv4};
my $a_vals = $a->{vals};
my $b_vals = $b->{vals};
for my $i (0..$#{$a_vals}) {
my $sortval = $a_vals->[$i] <=> $b_vals->[$i];
return $sortval if $sortval != 0;
}
return 0;
}
sub ip_each_time_split_sorter {
our ($a, $b);
my $a_split = split_vals($a);
my $b_split = split_vals($b);
return -1 if exists $a_split->{ipv4} && exists $b_split->{ipv6};
return 1 if exists $a_split->{ipv6} && exists $b_split->{ipv4};
my $a_vals = $a_split->{vals};
my $b_vals = $b_split->{vals};
for my $i (0..$#{$a_vals}) {
my $sortval = $a_vals->[$i] <=> $b_vals->[$i];
return $sortval if $sortval != 0;
}
return 0;
}

Topological graph sorting java

I've got some problems with the topological sorting. It can find lops, but it counts some of the tasks (or "nodes" if you want to call it) several times. I think the problem is something with how I read or the Edge class, but I just can't see where it goes wrong. Any help would be really appreciated :)
enter code here
import java.util.*;
import java.io.*;
import java.lang.*;
class Task {
int id, time, staff;
int depA, depB;
String name;
int eStart, lStart;
Edge outEdge;
int cntPredecessors;
boolean visited;
Task(int id, String name, int time, int staff) {
this.id = id;
this.name = name;
this.time = time;
this.staff = staff;
visited = false;
}
public String getName() {
return name;
}
public String toString() {
return name;
}
}
class Edge {
Task id, name, time, staff;
Edge neste;
Task fra, til;
Edge(Task id) {
this.id = id;
}
}
class Input {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("enter a filename!");
System.exit(1);
} else if (args.length == 1) {
String fil = args[0]+".txt";
LesFraFil(fil);
// skrivUt();
topSort();
} else {
System.out.println("too many parameters, try again...");
}
}
static int antTask;
static Task[] ids;
static int tTid;
static void LesFraFil(String fil) {
int i = 0;
int j;
try {
String lest;
Scanner in = new Scanner(new FileReader(fil));
Edge til;
int counter = 0;
antTask = in.nextInt();
ids = new Task[antTask];
System.out.println(antTask);
while (in.hasNextLine()) {
lest = in.nextLine();
// hvis tom linje, så hopper den over
if(lest.trim().length() == 0) continue;
String split[] = lest.split("\\s+");
int id = Integer.parseInt(split[0]);
String act = split[1];
int tid = Integer.parseInt(split[2]);
int staff = Integer.parseInt(split[3]);
int depA = Integer.parseInt(split[4]);
tTid += tid;
ids[i] = new Task(id, act, tid, staff);
j = 4;
/*
* Lesingen av inputen skal avbrytes når den leser 0.
* j er den som holder på hvor langt vi er i split arrayet
* når den møter på 0
*/
while(split[j].compareTo("0") != 0) {
int tmp = Integer.parseInt(split[j])-1;
// System.out.println(tmp+1 + " Aktivitetens navn : " + act); //+ " tiden aktiviteten tar tid: " + tid + " avhengihet: " + split[j]);
j++;
if (ids[tmp] == null) {
ids[tmp] = new Task(id, act, tid, staff);
ids[tmp].visited = true;
}
ids[i].cntPredecessors++;
if(ids[tmp].outEdge == null) {
ids[tmp].outEdge = new Edge(ids[i]);
} else {
til = ids[tmp].outEdge;
while(til.neste != null) {
til = til.neste;
}
til.neste = new Edge(ids[i]);
}
}
counter++;
i++;
}
if (antTask == counter) {
System.out.println("Lesinga gikk som planlagt av fil: " + fil);
System.out.println("Total arbeidstid: " + tTid);// + antTask + " == " + counter );
} else {
System.out.println("Noe gikk galt avslutter!");
System.out.println(antTask + " || " + counter);
System.exit(2);
}
in.close();
} catch (Exception e) {
System.err.println("ERROR!" + e.getMessage());
}
}
static void skrivUt() {
for (Task sort : ids) {
System.out.print(sort.id + " " + sort.name);
Edge til = sort.outEdge;
while (til != null) {
System.out.print(" " + til.id.id);
til = til.neste;
}
System.out.println();
}
}
static void topSort() {
LinkedList<Task> list = new LinkedList<Task>();
ArrayList<Task> array = new ArrayList<Task>();
Task temp;
int count = 0;
int totalTime = 0;
// Legger taskene i lista
for (Task t : ids) {
if(t.cntPredecessors == 0) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
// går i evig løkke til lista er tom.
while (!list.isEmpty()) {
temp = list.pop(); // fjerner elementet fra lista
array.add(temp); // legger inn i arraylisten
count++;
// System.out.println(temp);
for(Edge til = temp.outEdge; til!=null;til=til.neste) {
til.id.cntPredecessors--;
if(til.id.cntPredecessors==0) {
list.add(til.id);
}
}
}
if(count < antTask) {
System.out.println("A loop has been found. Terminating...");
System.exit(0);
}
System.out.println("Topological sort: " + Arrays.toString(array.toArray()));// den sorterte "arraylisten"
System.out.println("Total time spend: " + totalTime);
}
} // End class Input
Here is an example of an input file
8
1 Build-walls 4 2 5 0
2 Build-roofs 6 4 1 0
3 Put-on-wallpapers 1 2 1 2 0
4 Put-on-tiles 1 3 2 0
5 Build-foundation 4 2 0
6 Make-floor 2 2 5 0
7 Put-carpet-floor 4 2 6 2 0
8 Move-in 4 4 3 7 0
The problem is with this loop (inside topSort()):
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
You just need to remove it.
Reason: this loop adds to list nodes that have 1 incoming edge. Later (in the while loop), it is possible that for these nodes the cntPredecessors field will be decreased to 0 which will make them being pushed back onto list, thus counted twice.
In the future, please try to narrow down your code to something that contains less "noise", that is: the smallset (or nearly smallest) code that illustrates the problem. This will ease the understanding on potential answerers (not to mention that it may help you see the problem yourself).

Categories

Resources