Simple Number to Array with Individual Digits - java

I am exceptionally new to programming, but I am working on improving my skills as a programmer. Currently, I am working on a problem I gave myself where I am trying to take a variable number and make each of its digits a separate number in an array. I don't care about the order of the digits, so if they are reversed, then it doesn't matter to me. I know people have asked this question numerous times, but they always seem to use a lot of things that I don't understand. Since my school doesn't offer any Java courses, I only know what I have learned on my own, so if you could explain any terms you use in the code that aren't extremely trivial, that would be wonderful. Right now, I have written:
int number = 1234567890;
while (number > 0) {
System.out.println(number%10);
number = number/10;
This works fine for printing the digits individually, but I can't figure out how to add them to the array. I greatly appreciate any help you can give, and please keep in mind that I much prefer simplicity over small size. Thank you in advance!
P.S. Some responses I've seen for similar questions include what I think are arrays of strings. In order for the part of the program that I have working to still work, I think that I need to use an array of integers. If you're curious, the rest of the code is used to determine if the numbers in the array are all different, in order to achieve the final result of determining if a number's digits are all distinct. It looks like this:
int repeats=0;
int[] digitArray;
digitArray = new int[10];
for (int i = 0; i < digitArray.length; i++)
for (int j = 0; j < digitArray.length; j++)
if ((i != j) && (digitArray[i]==digitArray[j])) unique = unique+1;
System.out.println(unique==0);

Method number.toString().length() will return the number of digits. That is the same as the length of your needed array. Then you use your code as before, yet instead of printing you add the digit to the array.
int number = 1234567890;
int len = Integer.toString(number).length();
int[] iarray = new int[len];
for (int index = 0; index < len; index++) {
iarray[index] = number % 10;
number /= 10;
}

I would rather suggest you to use an ArrayList, since to use an array, you would have to allocate the size in advance, for which you need to know the number of digits in your number, which you don't know.
So, either work with an array, and do the iteration over the number twice - once for finding size, and next for doing actual work. Else, move ahead with an ArrayList.
Adding an element to an ArrayList is quite simple. You just need to call - List#add(E) method with appropriate parameter.
So, here's an extension of your solution: -
// Declare a List<Integer>, since it will store integers only.
List<Integer> digits = new ArrayList<Integer>():
int number = 1234567890;
while (number > 0) {
int digit = number % 10; // Store digit in a variable
number = number/10;
// Add digit to the list
digits.add(digit);
}
Alternatively, if you want to have only unique digits in your List, then you should use a HashSet, which automatically removes the duplicates.

With Java 8:
Integer.toString(n).chars().map(a->a-'0').toArray()

char [] arr = scan.next().toCharArray();
This code will read a number from scan.next() and then it is going to give it as an input to char array which will have the number at its indices as single digit by digit.
Hope this will help.

Related

How do I make this have a space complexity of O(1) instead of O(n)?

I'm trying to convert a decimal into binary number using iterative process. How can I make this have a space complexity of O(1) instead of O(n)?
int i = 0;
int j;
int bin[] = new int[n]; //n here is my paramater int n
while(n > 0) {
bin[i] = n % 2;
n /= 2;
i++;
}
//I'm reversing the order of index i with variable j to get right order (e.g. 26 has 11010, instead of 01011)
for(j = i -1; j >= 0; j--) {
System.out.print(bin[j]);
}
First, you don't need place for n bits if the value itself is n. You just need log2(n)+1. It won't give you wrong results to use n bits, but for big values of n, the memory available to your Java process might be not enough.
And, about O(1)... maybe not really what you were thinking, but:
Javas int has a specific fixed value range, which leads to the guarantee that a (positive) int value needs max 31 bit (if you have negative numbers too, storing the sign somewhere is necessary, that's bit 32).
With that information, strictly speaking, you can get O(1) just by rewriting your loops so that they loop exactly 31 times. Then, for each value of n, your code has exactly the same amount of steps, and that is O(1) per definition.
Going the bit fiddling route won't help here. There are some useful shortcuts if your values fulfil certain conditions, but if you want your code to work with any int value, the normal loop as you have here is likely the best you can get.
(Of yourse, CPU intrinsics may help, but not for Java...)

Array Duplicate Efficiency Riddle

Recently in AP Computer Science A, our class recently learned about arrays. Our teacher posed to us a riddle.
Say you have 20 numbers, 10 through 100 inclusive, right? (these numbers are gathered from another file using Scanners)
As each number is read, we must print the number if and only if it is not a duplicate of a number already read. Now, here's the catch. We must use the smallest array possible to solve the problem.
That's the real problem I'm having. All of my solutions require a pretty big array that has 20 slots in it.
I am required to use an array. What would be the smallest array that we could use to solve the problem efficiently?
If anyone could explain the method with pseudocode (or in words) that would be awesome.
In the worst case we have to use an array of length 19.
Why 19? Each unique number has to be remembered in order to sort out duplicates from the following numbers. Since you know that there are 20 numbers incoming, but not more, you don't have to store the last number. Either the 20th number already appeared (then don't do anything), or the 20th number is unique (then print it and exit – no need to save it).
By the way: I wouldn't call an array of length 20 big :)
If your numbers are integers: You have a range from 10 to 100. So you need 91 Bits to store which values have already been read. A Java Long has 64 Bits. So you will need an array of two Longs. Let every Bit (except for the superfluous ones) stand for a number from 10 to 100. Initialize both longs with 0. When a number is read, check if the corresponding bit mapped to the read value is set to 1. If yes, the read number is a duplicate, if no set the bit to 1.
This is the idea behind the BitSet class.
Agree with Socowi. If number of numbers is known and it is equal to N , it is always possible to use N-1 array to store duplicates. Once the last element from the input is received and it is already known that this is the last element, it is not really needed to store this last value in the duplicates array.
Another idea. If your numbers are small and really located in [10:100] diapason, you can use 1 Long number for storing at least 2 small Integers and extract them from Long number using binary AND to extract small integers values back. In this case it is possible to use N/2 array. But it will make searching in this array more complicated and does not save much memory, only number of items in the array will be decreased.
You technically don't need an array, since the input size is fixed, you can just declare 20 variables. But let's say it wasn't fixed.
As other answer says, worst case is indeed 19 slots in the array. But, assuming we are talking about integers here, there is a better case scenario where some numbers form a contiguous interval. In that case, you only have to remember the highest and lowest number, since anything in between is also a duplicate. You can use an array of intervals.
With the range of 10 to 100, the numbers can be spaced apart and you still need an array of 19 intervals, in the worst case. But let's say, that the best case occurs, and all numbers form a contiguous interval, then you only need 1 array slot.
The problem you'd still have to solve is to create an abstraction over an array, that expands itself by 1 when an element is added, so it will use the minimal size necessary. (Similar to ArrayList, but it doubles in size when capacity is reached).
Since an array cannot change size at run time You need a companion variable to count the numbers that are not duplicates and fill the array partially with only those numbers.
Here is a simple code that use companion variable currentsize and fill the array partially.
Alternative you can use arrayList which change size during run time
final int LENGTH = 20;
double[] numbers = new double[LENGTH];
int currentSize = 0;
Scanner in = new Scanner(System.in);
while (in.hasNextDouble()){
if (currentSize < numbers.length){
numbers[currentSize] = in.nextDouble();
currentSize++;
}
}
Edit
Now the currentSize contains those actual numbers that are not duplicates and you did not fill all 20 elements in case you had some duplicates. Of course you need some code to determine whither a numbers is duplicate or not.
My last answer misunderstood what you were needing, but I turned this thing up that does it an int array of 5 elements using bit shifting. Since we know the max number is 100 we can store (Quite messily) four numbers into each index.
Random rand = new Random();
int[] numbers = new int[5];
int curNum;
for (int i = 0; i < 20; i++) {
curNum = rand.nextInt(100);
System.out.println(curNum);
boolean print = true;
for (int x = 0; x < i; x++) {
byte numberToCheck = ((byte) (numbers[(x - (x % 4)) / 4] >>> ((x%4) * 8)));
if (numberToCheck == curNum) {
print = false;
}
}
if (print) {
System.out.println("No Match: " + curNum);
}
int index = ((i - (i % 4)) / 4);
numbers[index] = numbers[index] | (curNum << (((i % 4)) * 8));
}
I use rand to get my ints but you could easily change this to a scanner.

Find groups of 3 consecutive numbers or more in Java ArrayList

I know there are similar questions out there and I've tried really hard to implement them but I can't quite seem to make them work for my needs. I don't need to find just consecutive numbers. I need to find consecutive numbers of 3 or more and replace the middle numbers with a hyphen.
For example :
arraylist contains 1,3,4,6,7,8,9. The output should be 1,3,4,6-9.
or say the arraylist contains 1,3,4,5,7,8,9. The output should be 1,3-5,7-9.
The problem I'm having is writing the logic to differentiate between 1 digit, 2 digits, 3 or more digits, and groups of consecutive digits that are 3 or more. Thanks in advance for whatever help you can provide! :-)
Here's a pretty verbose way. This creates a new array list to which you will either add the number from the original or the range. It finds ranges by testing if the next entry is one greater than the current, and how long that trend continues. If there are at least 3 in a row, it adds the range and starts looking after the range. Otherwise, it just adds each number.
List<String> altered = new ArrayList<>();
for(int i=0; i<list.size(); i++){
int start = i;
int size = 1;
int end = start;
if(i<list.size()-2){
end = start+1;
while(list.get(end) == list.get(end-1)+1){
size++;
end++;
if(end >= list.size())
break;
}
}
if(size >=3){
altered.add(list.get(start)+"-"+list.get(end-1));
i = end-1;
}
else
altered.add(""+list.get(i));
}
System.out.println(altered);

Generating Random integers within a range to meet a percentile in java

I am trying to generate random integers within a range to sample a percentile of that range. For example: for range 1 to 100 I would like to select a random sample of 20%. This would result in 20 integers randomly selected for 100.
This is to solve an extremely complex issue and I will post solutions once I get this and a few bugs worked out. I have not used many math packages in java so I appreciate your assistance.
Thanks!
Put all numbers in a arraylist, then shuffle it. Take only the 20 first element of the arraylist:
ArrayList<Integer> randomNumbers = new ArrayList<Integer>();
for(int i = 0; i < 100; i++){
randomNumbers.add((int)(Math.random() * 100 + 1));
}
Collections.shuffle(randomNumbers);
//Then the first 20 elements are your sample
If you want 20 random integers between 1 and one hundred, use Math.random() to generate a value between 0 and 0.999... Then, manipulate this value to fit your range.
int[] random = new int[20];
for(int i =0; i< random.length;i++)
{
random[i] = (int)(Math.random()*100+1);
}
When you multiply Math.random() by 100, you get a value between 0 and 99.999... To this number you add 1, yielding a value between 1.0 and 100.0. Then, I typecasted the number to an integer by using the (int) typecast. This gives a number between 1 and 100 inclusive. Then, store the values into an array.
If you are willing to go with Java 8, you could use some features of lambdas. Presuming that you aren't keeping 20% of petabytes of data, you could do something like this (number is the number of integers in the range to get) it isn't efficient in the slightest, but it works, and is fun if you'd like to do some Java 8. But if this is performance critical, I wouldn't recommend it:
public ArrayList<Integer> sampler(int min, int max, int number){
Random random = new Random();
ArrayList<Integer> generated = new ArrayList<Integer>();
IntStream ints = random.ints(min,max);
Iterator<Integer> it = ints.iterator();
for(int i = 0; i < number; i++){
int k = it.next();
while(generated.contains(k)){
k = it.next();
}
generated.add(k);
}
ints.close();
return generated;
}
If you really need to scale to petabytes of data, you're going to need a solution that doesn't require keeping all your numbers in memory. Even a bit-set, which would compress your numbers to 1 byte per 8 integers, wouldn't fit in memory.
Since you didn't mention the numbers had to be shuffled (just random), you can start counting and randomly decide whether to keep each number or not. Then stream your result to a file or wherever you need it.
Start with this:
long range = 100;
float percentile = 0.20f;
Random rnd = new Random();
for (long i=1; i < range; i++) {
if (rnd.nextFloat() < percentile) {
System.out.println(i);
}
}
You will get about 20 percent of the numbers from 1 to 100, with no duplicates.
As the range goes up, the accuracy will too, so you really wouldn't need any special logic for large data sets.
If an exact number is needed, you would need special logic for smaller data sets, but that's pretty easy to solve using other methods posted here (although I'd still recommend a bit set).

Randomly generated numbers in a basic array

I simply need to know what i should do to make so that a basic array is filled with randomly generated numbers. now i know how to do that, what i don't know how to to do is to make it so that the randomly generated numbers are bigger than the last number generated all the way through to the end of the array.
Just generate for the list, and then sort them smallest to largest.
for(int i = 0; i < arr.length; ++i) {
arr[i] = Random.nextInt(100);
}
Arrays.sort(arr);
Generate random numbers, and then sort the array.
You can sort the array using Arrays.sort()
It doesn't make sure that each number is strictly bigger then the previous numbers [it only gurantees <=], so if it is an issue - you will have to make sure you have no dupes in the generated numbers.
You can generate an array of random numbers, and then sort it using Array sort.
There was a comment on the question, I lost the author's name, that recommended adding the randomly generated number to the previous number, which I thought was an interesting approach.
arr[0] = Random.nextInt(100);
for(int i = 1; i < arr.length; ++i) {
arr[i] = arr[i-1] + Random.nextInt(100);
}
This removes the need to sort your result array.
You can have your own algorithm of generating incremental...
For example...
Random each time and add that number to the last one :)
Random class in java does not allow you to have a minim limit where to start.. only one...
For example:
myArray[0] = Random.nextInt(10000);
for(int i=1; i<myArray.length; i++)
{
myArray[i] = myArray[i-1]+Random.nextInt(10000);
}
So.. it's random and you don't have to sort it.. try keeping everything simple...
I'm surprised no one mentioned that we can use SecureRandom API to easily generate random arrays without manually populating it.
For ex. generating a random array of size 100:
SecureRandom random = new SecureRandom();
int arr[] = random.ints(100).toArray();
BTW this should be possible from java 8 onwards.

Categories