Check if an IP is contained in a set of ranges? - java

Does anyone know of a clean way to check if an IP is contained in a set of ranges?
I'm getting a response that looks like this:
"ipRange": "10.12.0.0/16,10.80.0.0/15,10.83.0.0/16,10.101.0.0-10.103.255.255,10.108.0.0/16,10.121.0.0/16,10.123.0.0/16,10.127.0.0/16,10.129.0.0/16,10.131.0.0/16,10.133.0.0/16,10.135.0.0-10.139.255.255,10.208.0.0/14,10.215.0.0/16,10.218.0.0/15,10.233.0.0/16,172.17.128.0-172.19.255.255,172.24.0.0/15,192.168.0.0/16"
And I need to see if an IP is in any of those works. The ones with "slash" notation should be straight forward, but what about the ranges where they have "-"?

I've commented the code below. Basically, I split the "ipRanges" into distinct ipAddresses or ipAddressRanges by looking for ",". Then test the given ip to each of those to see if it is good.
String ipRange = "10.12.0.0/16,10.80.0.0/15,10.83.0.0/16,10.101.0.0-10.103.255.255,10.108.0.0/16,10.121.0.0/16,10.123.0.0/16,10.127.0.0/16,10.129.0.0/16,10.131.0.0/16,10.133.0.0/16,10.135.0.0-10.139.255.255,10.208.0.0/14,10.215.0.0/16,10.218.0.0/15,10.233.0.0/16,172.17.128.0-172.19.255.255,172.24.0.0/15,192.168.0.0/16";
public IPAddressTest() {
String ipToTest = "10.101.0.0";
System.out.println(String.format("[%s] is in range (%b)", ipToTest, isInRange(ipToTest)));
}
private Boolean isInRange(String ipToTest) {
String[] ranges = ipRange.split(",");
for (String _range : ranges) {
String range = _range.indexOf("/") > -1 ? _range.substring(0, _range.indexOf("/")) : _range; // cut off the /xx if it exists
boolean test = test(ipToTest, range);
if (test) {
return true;
}
}
return false;
}
private Boolean test(String ipToTest, String ipRange) {
String[] ranges = ipRange.split("-"); // Do we have a range or just a single ip
String loRange = ranges[0]; // grab the first
String hiRange = ranges.length > 1 ? ranges[1] : null; // If there a range grab the top end, else nothing
if (hiRange == null) { // if a single ip, just do a string compare
return ipToTest.equals(loRange);
} else { // if a range then make sure each part is between the min and max
String[] partsToTest = ipToTest.split("\\."); // get each part of the ip
String[] partsLoRange = loRange.split("\\."); // get each part of the ip
String[] partsHiRange = hiRange.split("\\."); // get each part of the ip
int test = 0; // this will be our litmus test. if it = 15 when we are done, then each part is good, 63 of ipv6
for (int i = 0; i < 4; i++) { // change 4 to 6 for ipv6
int value = Integer.parseInt(partsToTest[i]); //get the int
int lo = Integer.parseInt(partsLoRange[i]); //get the int
int hi = Integer.parseInt(partsHiRange[i]); //get the int
if (value >= lo && value <= hi) { // if we have a good value, set the bit on 'test'
test += Math.pow(2, i);
}
}
if (test == 15) {
return true;
}
}
return false;
}
public static void main(String[] args) {
new IPAddressTest();
}

Related

Count Occurence in 2d array java

I have this 2d array
**Client| Status**
FAI | deferred
SDE | Bounced
FAI | Bounced
SDE | Bounced
SDE | deferred
FAI | deferred
What i want to do i s to create a function, that make some kind of statistical output:
EX:
FAI --> Deferred 66 % , Bounced 34 %
SDE --> Deferred 34 % , Bounced 66%
N.B.
For the first column there is a lot of possible clients, but for the second i have only those two states.
The function that i want to create is a function that count the occurrence of the first column elements, then for each client see the state in each occurrence if it is Bounced or referred, an d make a statistics for the client.
Here i don't really how to start my function,So any idea, any suggestion is welcome, and will help me.
Thank you!
Use HashMap(or any other implementation of Map interface) to efficient solve your problem(#kai solution is ok, but it is O(N^2)). This example is not generic, it only works if in second column of grid(data matrix) you have two possible values(deffered and bounced). Solution works in this way: we iterate over rows in data matrix and check if current entity(represent by name - first column of grid) is already in hashmap. If it is, just increment that entity percents(inc method of Entity class), otherwise we must first create new instance of entity, add it to hashmap and than increment percents. Printing is done similar(because we need to print names in same order they appear in matrix): we iterate again over data and print entity object(this is why toString method is overridden). isVisitedMember attr in Entity class is used because we want to print every entity just once.
import java.util.HashMap;
public class HelloWorld{
static class Entity {
private String name;
private int countFirst;
private int countSecond;
private boolean isVisitedMember; // because we want to print in same order as in original matrix
public Entity(String name) {
this.name = name;
countFirst = 0;
countSecond = 0;
isVisitedMember = false;
}
public void inc(String status) {
if (status.toLowerCase().equals("deferred")) {
++countFirst;
}
else {
++countSecond;
}
}
public boolean isVisited() {
return isVisitedMember;
}
public void setIsVisited(boolean value) {
isVisitedMember = value;
}
public float getFirstPercent() {
return (float)countFirst / (countFirst + countSecond) * 100;
}
public float getSecondPercent() {
return (float)countSecond / (countFirst + countSecond) * 100;
}
#Override
public String toString() {
if (countFirst <= countSecond) {
int first = (int)Math.ceil(getFirstPercent());
return String.format("%s --> Deferred %d %% , Bounced %d %%", name, first, 100 - first);
}
int second = (int)Math.ceil(getSecondPercent());
return String.format("%s --> Deferred %d %% , Bounced %d %%", name, 100 - second, second);
}
}
public static void main(String []args){
String[][] data = {
{ "FAI", "deferred" },
{ "SDE", "Bounced" },
{ "FAI", "Bounced" },
{ "SDE", "Bounced" },
{ "SDE", "deferred" },
{ "FAI", "deferred" },
};
HashMap<String, Entity> map = new HashMap<String, Entity>();
for (int i = 0; i < data.length; ++i) {
String name = data[i][0];
String value = data[i][1];
Entity entity = map.get(name);
if (entity == null) {
entity = new HelloWorld.Entity(name);
map.put(name, entity);
}
entity.inc(value);
}
// print in same order as in original matrix
for (int i = 0; i < data.length; ++i) {
String name = data[i][0];
Entity entity = map.get(name);
if (entity.isVisited()) {
continue;
}
entity.setIsVisited(true);
System.out.println(entity);
}
}
}
You have to make a List of all clients. Then you can count the number of deffered and bounced which every client have.
Here is my solution. Its not the best way to do this, but it works! The output is:
FAI --> Deffered 67 % , Bounced 33%
SDE --> Deffered 33 % , Bounced 67%
public static void main(String[] args) throws InterruptedException {
String[][] client_status = new String[6][2];
client_status[0][0] = "FAI";
client_status[0][1] = "deffered";
client_status[1][0] = "SDE";
client_status[1][1] = "Bounced";
client_status[2][0] = "FAI";
client_status[2][1] = "Bounced";
client_status[3][0] = "SDE";
client_status[3][1] = "Bounced";
client_status[4][0] = "SDE";
client_status[4][1] = "deffered";
client_status[5][0] = "FAI";
client_status[5][1] = "deffered";
List<String> clients = new ArrayList<String>();
int allDeffered = 0;
int allBounced = 0;
for(int i = 0; i < client_status.length; i++) {
if(!clients.contains(client_status[i][0])) {
clients.add(client_status[i][0]);
}
}
Integer[] clientDeffered = new Integer[clients.size()];
Integer[] clientBounced = new Integer[clients.size()];
int k = 0;
for(String client : clients) {
for(int j = 0; j<client_status.length; j++) {
if(client_status[j][0].equals(client)&&client_status[j][1].equals("deffered")) {
if(clientDeffered[k]==null) {
clientDeffered[k]=1;
}
else {
clientDeffered[k]++;
}
allDeffered ++;
}
if(client_status[j][0].equals(client)&&client_status[j][1].equals("Bounced")) {
if(clientBounced[k]==null) {
clientBounced[k]=1;
}
else {
clientBounced[k]++;
}
allBounced ++;
}
}
k++;
}
for(int l = 0; l<clients.size(); l++) {
double a = clientDeffered[l];
double b = allDeffered;
double c = clientBounced[l];
double d = allBounced;
System.out.println(clients.get(l) +" --> Deffered " +Math.round((a/b)*100) + " % , Bounced " +Math.round((c/d)*100) + "%");
}
}

Line indentor - Trying to pass the length of javaline in each line between classes however it keeps being set to 0

I have the task of making an indentor for some javaline. The idea is that first I have to split the java from the comment. I then have to find the longest line of just javacode excluding the comment from the input file and use that for the max length of java. However I have run into the issue of that its returning with 0 every time and not the longest line in an array.
The first piece of code is the class that holds the method for working out the longest length of javaline. The method is called findMaxJavaLineLength():
import java.util.*;
class Program
{
private ArrayList<JavaLine> stored = new ArrayList<>();
/**
* Constructor
*/
public Program()
{
stored.clear();
}
/**
* Add the next line of Java code to the stored program
* #param line A line of Java code
*/
public void addLine( String line )
{
stored.add( new JavaLine( line) );
}
public String indentProgram()
{
String res = "";
for ( JavaLine line: stored )
{
res += line.returnLineWithCommentAt() + "\n";
}
return res;
}
public int findMaxJavaLineLength()
{
int max = 0;
for ( JavaLine line: stored )
{
int lineLength = line.getJavaLineLength();
if ( lineLength > max) max = lineLength;
}
return max;
}
}
and the second piece of code is the JavaLine class which splits the code into parts and returns the length of java:
class JavaLine
{
private String java = ""; // Java code on line
private String comment = ""; // The single line comment
private String javaSpace = "";
private int lenJava = 0; // The line length of just the java cod
public JavaLine( String line )
{
String[] splitted = line.split("// ");
java = splitted[0];
int slashCount = line.length() - line.replaceAll("//","").length();
if (slashCount >= 1) {
comment = "// " + splitted[1];
}
}
public int getJavaLineLength()
{
lenJava = java.length();
return lenJava;
}
public String returnLineWithCommentAt( )
{
String output = "";
Program t = new Program();
int maxLenJavaLine = t.findMaxJavaLineLength();
int number = maxLenJavaLine - getJavaLineLength();
String javaSpace = "";
for (int n = 0; n < number; n++){
javaSpace = javaSpace + " ";
}
String commentOutput = comment;
if ( java.contains("}")){
output = java;
}else if ( java.contains("{")){
output = java;
} else {
output = java + javaSpace + commentOutput + "test: " + t.findMaxJavaLineLength();
}
return output;
}
}
I have tested it and it seems like the lenJava bit in the getjavalength is working out the length of the javaline correctly when I grab it from the same class. However it sets to 0 when I grab it from the other class when trying to work out the longest line. It seems as if the length just doesn't get passed to the other class from the javaline class.
Below is the output that I am currently receiving.
import java.lang.Thread;// Use External classtest: 0
class Countdowntest: 0
{
public static void main( String args[] )test: 0
{
// Start from 10test: 0
while ( countdown > 0 )// While greater than 0test: 0
{
System.out.println(countdown);// Write contents of countdowntest: 0
if ( countdown == 3 )// If equal to 3test: 0
{
System.out.println("Ignition");// Write Ignitiontest: 0
}
countdown--;// Decrement countdown by 1test: 0
try {
Thread.sleep( 100 );// 1000 milliseconds delaytest: 0
}
catch( InterruptedException e ) {}
}
System.out.println( "Blast Off");// Write Blast offtest: 0
}
}
The bit of the output where it says "test: 0" is where I am expecting the length of the javaline which is the longest. so it should be "test: 50" or whatever instead of "test: 0".
Thank you
You create a new Program called t in the second line of JavaLine.returnLineWithCommentAt() but you don't add any lines to it with addLine() before calling findMaxJavaLineLength() on it, so of course it contains no lines and findMaxJavaLineLength() returns 0.
Perhaps you intended to call findMaxJavaLineLength() from Program.indentProgram() and then pass that value into returnLineWithCommentAt()?
Just change the signature of returnLineWithCommentAt() to
public String returnLineWithCommentAt(int maxLineLength)
And then you can call it in Program.indentProgram() thus:
int maxLineLength = findMaxJavaLineLength();
for (JavaLine line: stored)
{
res += line.returnLineWithCommentAt(maxLineLength) + "\n";
}
Don't forget to remove t from JavaLine.returnLineWithCommentAt().

How to generate 10 random numbers in java and assign them to fields?

I have one project in school where i need to make a simulation of keeping records for vehicles.
And Vehicle is abstract class which extends two classes (Automobile class and Motor class). There is also one Interface (NewRegistration) which contains one method register() and these two classes implements that interface. It should register a new registration for automobile and motor, but i should previously check if registration which i have insert is correct in one method checkNumber().
All in all, i have solved every task i have gotten, but only one i can't solve and it is to generate 10 random numbers..
Registration should have 15 characters, for first and second character UpperCase letter, for third character symbol "-", and for the the last two characters lowerCase letters.. other characters should be numbers and those numbers should be randomly generated.
Here is what i have done so far:
Automobile.java:
public class Automobil extends Vozilo implements NovaRegistracija{
private int brojVrata, brojSedista;
public Automobil(String marka, String model, String registracija, int kubikaza, int brojVrata, int brojSedista) {
super(marka, model, registracija, kubikaza);
this.brojVrata = brojVrata;
this.brojSedista = brojSedista;
}
public Automobil() {
}
// checkNumber() method
#Override
public void proveriBroj() {
boolean provera = true;
boolean proveraKubikaze = true;
String parsedInteger = String.valueOf(getKubikaza());
for (int j = 0; j < parsedInteger.length(); j++) {
if (Character.isLetter(parsedInteger.charAt(j))) {
proveraKubikaze = false;
}
}
// Checking registration
if (this.getRegistracija().length() == 15) {
if (Character.isUpperCase(getRegistracija().charAt(0)) && Character.isUpperCase(getRegistracija().charAt(1))) {
if (getRegistracija().charAt(2) == '-') {
if (Character.isLowerCase(getRegistracija().charAt(getRegistracija().length()-1)) && Character.isLowerCase(getRegistracija().charAt(getRegistracija().length()-2))) {
for (int i = 3; i < getRegistracija().length()-2; i++ ) {
if (!Character.isDigit(getRegistracija().charAt(i))) {
provera = false;
System.out.println("11111111111111111");
break;
}
}
} else {
System.out.println("222222222222");
provera = false;
}
} else {
System.out.println("333333333333");
provera = false;
}
} else {
System.out.println("44444444444444444");
provera = false;
}
} else {
System.out.println("555555555555555");
provera = false;
}
if (proveraKubikaze) {
System.out.println("Kubikaza je dobra!");
} else {
System.out.println("Kubikaza nije dobra!");
}
if (provera) {
System.out.println("Broj registracije je ispravan!");
} else {
System.out.println("Broj registracije je neispravan!");
}
}
// register() method from interface NewRegistration
#Override
public void registruj() {
this.setRegistracija("AA-" + "aa");
proveriBroj();
System.out.println("- - - - - - - - - - - - - - - - - - - -");
}
public int getBrojVrata() {
return brojVrata;
}
public void setBrojVrata(int brojVrata) {
this.brojVrata = brojVrata;
}
public int getBrojSedista() {
return brojSedista;
}
public void setBrojSedista(int brojSedista) {
this.brojSedista = brojSedista;
}
}
So how would i now assign randomly 10 generate numbers for the whole registration of vehicle?
Thank you in advance.
Here is a function I wrote:
import java.util.Random
private String generateRegistration() {
String selectFrom1 = "ABCDEFGHIJKLMNOPRSTUVWXYZ";
String selectFrom2 = "0123456789";
String selectFrom3 = selectFrom1.toLowerCase();
return randomFromSelection(selectFrom1,2)+"-"+randomFromSelection(selectFrom2,10)+randomFromSelection(selectFrom3,2)
}
private String randomFromSelection(String selection, int times) {
Random random = new Random();
String toReturn = "";
for (int useless = 0; useless < times; useless++) {
toReturn += selection.charAt(random.nextInt(selection.length()));
}
return toReturn;
}
This function is very flexible and can be used with any input for selection or times.
Use org.apache.commons.lang.RandomStringUtils.
System.out.println(RandomStringUtils.randomNumeric(10));
Math.random() so this is the method i would go for, you can simply generate simple numbers by for ex. multiplying 10 and (or without) rounding.
public static double random()
Returns a double value with a positive sign, greater than or equal to
0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.

I need someone to tell me what is wrong with logic in my code

I am a beginner in Java. I am trying to write code according to the following text:
You are to write an application to pre­sell a limited number of movie
tickets. The simple user interface will be contained in Main.java and
the object to implement this is referred to as TicketSeller and
consists of only the following public methods:
public TicketSeller(int initialTicketAllotment) - Specify the number
of tickets you want to sell.
public int requestTickets(int ticketRequest) - Requests
ticketRequest number of tickets. Returns
TicketSeller.TOO_MANY_TICKETS_REQUESTED if there are more than
TicketSeller.MAXIMUM_TICKETS_ALLOWED. Note that one of these
constants is private and one is public. Which one needs to be exposed
to the user?
public int getNumberOfBuyers() - Tracks number of ticket buyers. You
only count buyers who have fulfilled a request. Errors don't count.
Here is what I have so far. However, there is an error in my code but I cannot find it:
public class TicketSeller {
private final static int MAXIMUM_TICKETS_ALLOWED = 4;
public static final int TOO_MANY_TICKETS_REQUESTED = -1;
private int buyers = 0;
private int initialTicketAllotment;
int placeHolder;
public TicketSeller(int initialTicketAllotment) {
this.initialTicketAllotment = initialTicketAllotment;
}
public int requestTickets(int ticketRequest) {
if (placeHolder > 0) {
int value = 0;
value = placeHolder - ticketRequest;
placeHolder = value;
buyers += 1;
}
if (ticketRequest > MAXIMUM_TICKETS_ALLOWED
|| ticketRequest > initialTicketAllotment) {
return TOO_MANY_TICKETS_REQUESTED;
}
if (ticketRequest >= 0 && ticketRequest <= MAXIMUM_TICKETS_ALLOWED
&& placeHolder == 0) {
int value = 0;
value = initialTicketAllotment - ticketRequest;
placeHolder = value;
buyers += 1;
}
return placeHolder;
}
public int getNumberOfBuyers() {
return buyers;
}
}
Incorrect output located in the code comments below:
public class Main {
public static void main(String[] args) {
TicketSeller ts = new TicketSeller(8);
System.out.println(ts.requestTickets(1)); //outputs 7
System.out.println(ts.requestTickets(2)); //outputs 5
System.out.println(ts.requestTickets(3)); //outputs 2
System.out.println(ts.requestTickets(1)); //outputs 1
System.out.println(ts.requestTickets(1)); //outputs 7, instead of 0
}
}
Your logical errors lie in your constuctor and your requestTickets(int) method:
public TicketSeller(int initialTicketAllotment) {
this.initialTicketAllotment = initialTicketAllotment;
// you need to initialize 'placeholder' to the initial
// amount of tickets available
this.placeholder = initialTicketAllotment;
}
public int requestTickets(int ticketRequest) {
// you should check if there are no more tickets to request
// or more than MAXIMUM_TICKETS_ALLOWED (4 tickets) have been
// requested, before checking if placeholder > 0. Also, you
// want to check if 'ticketRequest > placeholder' not the
// initial amount of tickets.
if (ticketRequest > MAXIMUM_TICKETS_ALLOWED
|| ticketRequest > placeholder) {
return TOO_MANY_TICKETS_REQUESTED;
}
// remove the local 'value' variable, it just confuses your
// code to other readers, thinking you need a temporary variable
// for some reason
if (placeHolder > 0) {
placeholder -= ticketRequest;
buyers += 1;
}
// if placeholder equals 0, that means there are no more tickets
// left... not sure why you would set it back to
// 'initialTicketAllotment - ticketRequest'. I would get rid of this
// method.
/*
if (ticketRequest >= 0 && ticketRequest <= MAXIMUM_TICKETS_ALLOWED
&& placeHolder == 0) {
int value = 0;
value = initialTicketAllotment - ticketRequest;
placeHolder = value;
buyers += 1;
}
*/
return placeHolder;
}

Calling Zip Code — Android

I have both the phone number and address (including the zipcode) in the same TextView. I want the phone number to be clickable to call; however, this is making the zip code also clickable to make a phone call. How do I make it no longer clickable without creating another TextView? Thanks!
tvInfo.setText(Html.fromHtml("John Smith<br>123 Fake Street<br>Faketown, FK 12345<br><b>(804) 932-3300</b><br>"));
Linkify.addLinks(tvInfo, Linkify.PHONE_NUMBERS);
android will regard digits with count >=5 as phone numbers. so I think there will be at least 2 solutions:
1)a simple work around : if you are sure the length of phone numbers is more than 5, for example, at least 6 digits, you could make some work around:
private final static int MY_PHONE_NUMBER_MINIMUM_DIGITS = 6;
Linkify.addLinks(main, Patterns.PHONE, "tel:", new Linkify.MatchFilter() {
public final boolean acceptMatch(CharSequence s, int start, int end) {
int digitCount = 0;
for (int i = start; i < end; i++) {
if (Character.isDigit(s.charAt(i))) {
digitCount++;
if (digitCount >= MY_PHONE_NUMBER_MINIMUM_DIGITS ) {
return true;
}
}
}
return false;
}
}, Linkify.sPhoneNumberTransformFilter);
this workaround is based on android source code of Linkify, in Linkify, the method:
gatherLinks(links, text, Patterns.PHONE,
new String[] { "tel:" },
sPhoneNumberMatchFilter, sPhoneNumberTransformFilter);
will be called, while sPhoneNumberMatchFilter will filter the digits less than 5:
public static final MatchFilter sPhoneNumberMatchFilter = new MatchFilter() {
public final boolean acceptMatch(CharSequence s, int start, int end) {
int digitCount = 0;
for (int i = start; i < end; i++) {
if (Character.isDigit(s.charAt(i))) {
digitCount++;
if (digitCount >= PHONE_NUMBER_MINIMUM_DIGITS/*=5*/) {
return true;
}
}
}
return false;
}
};
so we just replace the "PHONE_NUMBER_MINIMUM_DIGITS" with 6
2)a more complicated solution is, if your phone numbers are in a more specific format for example, must be something like "(xxx)xxx-xxxx", you could use your own pattern to replace the Patterns.PHONE, to extract and apply links of phone numbers more accurately

Resources