Turn ArrayList<Integer> into one number? - java

I am trying to figure out another way other than using String.valueOf() and then using Integer.parseInt()to turn an array of numbers into one type long number, not adding the values up, just like appending a String.
Example: Let's say you have an ArrayList<Integer> of 5 elements and
the numbers are (e = element) ->
e0(1), e1(4), e2(3), e3(6), e4(7)
So I want to turn this into one type long number -> 14367.
I need this to find a so called Miraculous number in java. I am to use lists, and print a miraculous number. (also any tips about that miraculous number?)

Think about this mathematically. What's the relationship between a series of digits and the number they collectively represent?
Each digit represents a power of ten. The last digit is the 100 place, the next is the 101 place, etc.
long number = 0;
for (int digit: digits) {
number *= 10;
number += digit;
}

I suggest understanding doing this by hand. When we write 12345, what does each digit represent? For example, what does the 4 mean?

This gets clever with the toString() representation of an array, but here goes:
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
String theNum = nums.toString().replaceAll("\\D","");
Long.parseLong(theNum);

Related

How can I add a placeholder to a random Int then pull a single digit from that Int in Java?

I am new to Java and programming all together.. I am trying to make a program that ciphers a number for the user. The user inputs 5 digits separately so I add them together to get a total. I need to pull the first digit and second digit of the total and enter it into (firstDigit+key)%10 and (secondDigit+key)%10. Then need to combine the answer to each equation together.
My total needs to be two digits, so even if the user enters all 1's which would total to be 5, I need it to be displayed and seen as 05 so that both equations have a digit to use. It needs to be two digits. I cant seem to figure how to enter a place holder. I was thinking about trying to use:
if (total < 10)
but then what?
Secondly, the method I used below seems like a terrible way to pull a single digit from a number. I think I changed the int total into a string so I can use .substring to pull the digits, then converted back to an int. Surprisingly it works. Is there a better way to do this knowing that the number is random?
String totalString = Integer.toString(total);
String stringDigit1 = totalString.substring(0,1);
String stringDigit2 = totalString.substring(1,2);
int firstDigitInt1 = Integer.parseInt(stringDigit1);
int firstDigitInt2 = Integer.parseInt(stringDigit2);
int encodedDigit1 = (firstDigitInt1+key)%10;
int encodedDigit2 = (firstDigitInt2+key)%10;
System.out.println("Your encoded Number is: " + encodedDigit1 + encodedDigit2);
Your method for obtaining the individual digits is good, and if you want to maintain it I believe your intuition is correct, it should suffice to say:
if (total < 10) {
firstDigitInt1 = 0
}
This will work out with your following math.
Your method with substrings is far from terrible, but in case you wanted something more sleek you can instead say:
int Digit1 = total / 10;
int Digit2 = total % 10;
Here, you can take advantage of integer truncation (where an integer won't remember decimal places) to get the first digit, which also solves the first problem: 5 / 10 = 0 (in terms of ints). For the second digit, it suffices to say modulo 10, as it is the remainder once the total is divided by 10.

How to generate quasi random numbers that don't immediately repeat (and more)?

I want to generate an endless series of quasi random numbers to the following specification:-
Source of numbers is uniformly distributed and random, ranging 0 through 255 inclusive. It's an existing hardware device.
Required output range is 1 through 8 inclusive.
Two consecutive output numbers are never the same. For example 5 will never follow 5, but you can have 5,2,5.
Exactly one output number is required for every single source number. Rejection sampling therefore cannot be used. And while() loops, shuffles etc. can't be used.
It's this last stipulation that's vexing me. The source generator can only supply random bytes at a constant 1 /s and I want output at a constant 1 /s. Typically you'd simply reject a generated number if it was equal to the previous one, and generate another. In my case you only get one shot at each output. I think that it's some sort of random selection process, but this requirement has me going around in circles as I'm a bad programmer. An algorithm, flowchart or picture will do, but I'll be implementing in Java.
Apologies for the semi generic title, but I couldn't really think of anything more accurate yet concise.
If I understand the problem correctly, the first random number will be chosen randomly from among 8 different numbers (1 to 8), while every successive random number will be chosen from 7 different possibilities (1 to 8 excluding the previous one). Thus, your range of 256 values will need to be divided into 7 possibilities. It won't come out even, but that's the best you can do. So you need something like
public class RandomClass {
public RandomClass(HardwareSource source) {
this.source = source;
first = true;
}
pubic int nextRandom() {
int sourceValue = source.read();
int value;
if (first) {
value = sourceValue % 8 + 1;
prev = value;
} else {
value = sourceValue % 7 + 1;
if (value >= prev) {
value++;
}
prev = value;
first = false;
return value;
}
}
Suppose the first call generates 5. The second time you call it, value is first computed to be a number from 1 to 7; by incrementing it if the value is >= 5, the range of possible outputs becomes 1, 2, 3, 4, 6, 7, 8. The output will be almost evenly distributed between those two values. Since 256 is not divisible by 7, the distribution isn't quite even, and there will be a slight bias toward the lower numbers. You could fix it so that the bias will shift on each call and even out over the entire sequence; I believe one way is
value = (sourceValue + countGenerated) % 7 + 1;
where you keep track of how many numbers you've generated.
I think this is better than solutions that take the input modulo 8 and add 1 if the number equals the previous one. Those solutions will generate prev + 1 with twice the probability of generating other numbers, so it's more skewed than necessary.
int sum=0;
int prev=-1;
int next(int input){
sum=(sum+input)%8;
if(sum==prev)sum=(sum+1)%8;
prev=sum;
return sum+1;
}
(As I interpret even with the new bold emphasis, it is not required to always generate the same output value for the same input value - that would make the task impossible to solve)

Randomly break up array into chunks of at least 3 with even distribution

I have an array of size n, and would like to break it up into m chunks of size at least 3. For example,
given the array
[1,2,3,4,5,6,7,8,9,10]
and m=3, we could break the it up into
a=[1,2,3,4][5,6,7][8,9,10]
b=[1,2,3][4,5,6,7][8,9,10]
c=[1,2,3][4,5,6][7,8,9,10]
We could think of these solutions as being represented by the pairs (4,3,3) (3,4,3) and (3,3,4).
I would like a function that given an array, n, and m, returns a random solution AND returns these solutions with an even distribution (so that you are no more likely to get one particular solution than any other). (This function needs to work for n=50, so for performance reasons we cannot do this by calculating all possible solutions.)
So, in the case above, this method would return [4,3,3] a third of the time, [3,4,3] a third of the time, and [3,3,4] a third of the time.
Just a thought:
Let's say m=3, n=20. What we can do is to do this:
Choose a number between m and n - 2*m (between 3 and 14)
Let's say we random 6. This will be the first set and let's call it p1
Choose a number between our new subset of [m, [n - m - p1]] i.e. the subset of [3, 20 - 6 - 3] or [3, 11]
Let's say we roll 10. This is p2
Size of the remainder (or p3) will be 20 -p1 -p2 = 4
Final set will be [6, 10, 4]
Would this work? It wouldn't need any sort of iteration over the original list either. Your only iteration will be over m and not dependent on n.
I can try to make this more generic for variable m (step 1will need to change slightly and steps 3 and 5 will be in a loop) but I'm sure you can work it out if this solution is acceptable to you.
Example rewrite for step 1 would be:
Choose a number between m and n - [m - 1] * m
Would this work?
def randomCollate(item, chunk) {
def collated = item.collate( chunk )
def remainder = collated.reverse().takeWhile { it.size() != chunk }.flatten()
def randomIdx = new Random().nextInt( ( collated - remainder ).size() )
collated[randomIdx] += remainder
collated - [ remainder ]
}
randomCollate( 1..50, 3 )
Another idea I just had
Calculate how many array you are going to have with size m and how many with size m+1 (or a different sice). Let's call these values x and y.
Calculate the amount of possible permutations [3,3,4],[3,4,3],[4,3,3] -> 3 permutations (x+y)Py (binomial coefficient)
Chose a random permutation from 0 - possible permutations. Lets call this Z.
From now on I don't exactly know how this could be done, but I would try this:
Imagine you got a binary number with n digits and y of those are zeros. Get the Zst possible binary number with exactly y zeros and x ones.
Example binary: 100101101
Your result would be [x,y,y,x,y,x,x,y,x]
I hope you understand what I mean.
for each step allow a random range of n-m*min (min is 3 in your example); then pick a number from that range, add min, as r. if m is 2 return a list of r and n-r. otherwise return r and the result of the recursive call with n-r, m-1. shuffle this and you have the random sizes of the chunks.
rnd = new Random()
// build the chunk size list to randomly split `n` elements in `m` parts,
// where each part is at least of size `min`
// needs a shuffle afterwards
def s(n,m,min=3) {
def l = n-m*min // the range where we can pick a random offset
def r = min + (l?rnd.nextInt(l):0) // result for this step with optional random part
m==2 ? [r,n-r] : [r]+s(n-r,m-1) // only two remaining? pick result and remainder, or recurse
}
def tests = [[9,3,3],[10,3,3],[27,9,3],[4,2,2]]
1000.times{
tests.each{ n,m,min ->
def r = s(n,m,min)
assert r.sum()==n
assert r.size()==m
assert r.every{ it>= min }
}
}
def items = (0..9).collect() // test list
def slices = s(items.size(),3) // get the chunk sizes
Collections.shuffle(slices) // shuffle the result
// create ranges and use them to get the slices; should be another one or two methods
println slices.inject([sum:0,result:[]]) { r,s -> r.result<<items[((r.sum)..(r.sum+s-1))]; r.sum+=s; r }.result
//=> e.g. [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]

Printing PowerSet with help of bit position

Googling around for a while to find subsets of a String, i read wikipedia and it mentions that
.....For the whole power set of S we get:
{ } = 000 (Binary) = 0 (Decimal)
{x} = 100 = 4
{y} = 010 = 2
{z} = 001 = 1
{x, y} = 110 = 6
{x, z} = 101 = 5
{y, z} = 011 = 3
{x, y, z} = 111 = 7
Is there a possible way to implement this through program and avoid recursive algorithm which uses string length?
What i understood so far is that, for a String of length n, we can run from 0 to 2^n - 1 and print characters for on bits.
What i couldn't get is how to map those on bits with the corresponding characters in the most optimized manner
PS : checked thread but couldnt understood this and c++ : Power set generated by bits
The idea is that a power set of a set of size n has exactly 2^n elements, exactly the same number as there are different binary numbers of length at most n.
Now all you have to do is create a mapping between the two and you don't need a recursive algorithm. Fortunately with binary numbers you have a real intuitive and natural mapping in that you just add a character at position j in the string to a subset if your loop variable has bit j set which you can easily do with getBit() I wrote there (you can inline it but for you I made a separate function for better readability).
P.S. As requested, more detailed explanation on the mapping:
If you have a recursive algorithm, your flow is given by how you traverse your data structure in the recursive calls. It is as such a very intuitive and natural way of solving many problems.
If you want to solve such a problem without recursion for whatever reason, for instance to use less time and memory, you have the difficult task of making this traversal explicit.
As we use a loop with a loop variable which assumes a certain set of values, we need to make sure to map each value of the loop variable, e.g. 42, to one element, in our case a subset of s, in a way that we have a bijective mapping, that is, we map to each subset exactly once. Because we have a set the order does not matter, so we just need whatever mapping that satisfies these requirements.
Now we look at a binary number, e.g. 42 = 32+8+2 and as such in binary with the position above:
543210
101010
We can thus map 42 to a subset as follows using the positions:
order the elements of the set s in any way you like but consistently (always the same in one program execution), we can in our case use the order in the string
add an element e_j if and only if the bit at position j is set (equal to 1).
As each number has at least one digit different from any other, we always get different subsets, and thus our mapping is injective (different input -> different output).
Our mapping is also valid, as the binary numbers we chose have at most the length equal to the size of our set so the bit positions can always be assigned to an element in the set. Combined with the fact that our set of inputs is chosen to have the same size (2^n) as the size of a power set, we can follow that it is in fact bijective.
import java.util.HashSet;
import java.util.Set;
public class PowerSet
{
static boolean getBit(int i, int pos) {return (i&1<<pos)>0;}
static Set<Set<Character>> powerSet(String s)
{
Set<Set<Character>> pow = new HashSet<>();
for(int i=0;i<(2<<s.length());i++)
{
Set<Character> subSet = new HashSet<>();
for(int j=0;j<s.length();j++)
{
if(getBit(i,j)) {subSet.add(s.charAt(j));}
}
pow.add(subSet);
}
return pow;
}
public static void main(String[] args)
{System.out.println(powerSet("xyz"));}
}
Here is easy way to do it (pseudo code) :-
for(int i=0;i<2^n;i++) {
char subset[];
int k = i;
int c = 0;
while(k>0) {
if(k%2==1) {
subset.add(string[c]);
}
k = k/2;
c++;
}
print subset;
}
Explanation :- The code divides number by 2 and calculates remainder which is used to convert number to binary form. Then as you know only selects index in string which has 1 at that bit number.

permutations of certain digits in Java

I realize permutations in programming language is a very frequently asked question, however I feel like my question is sort of unique.
I have received input of a certain length integer N and stored each digit in an array where the index of the array stores the number of times that digit occurs in N.
now I want to test if some function holds true with all permutations of N's original length with no leading zeroes. Ex:
int[] digits = new int[10];
String n = "12345675533789025";
for (char c : n.toCharArray())
digits[c-'0']++;
for (Long f : allPermutationsOf(digits))
if (someCondition(f))
System.out.println(f);
a precondition to the following code is that N must be less than 2^64-1, (long's maximum value.)
The question is, how would I take all permutations of the digits array and return a Long[] or long[] without using some kind of String concatenation? Is there a way to return a long[] with all permutations of digits[] in the "Integer scope of things" or rather using only integer arithmetic?
To elaborate on one of the above comments, putting a digit d in a given place in the resulting long is easy: d*1 puts it in the 1s place, d*1000 puts it in the thousands place, and in general d * (10^k) puts d into the k+1th digit. You have N total digits to fill, so you need to do permutations on the powers of 10 from 1 to 10^(N-1).
If you are expecting the permutations to be Longs anyway, instead of representing n as an array of counts, it might be easier to represent it as a Long too.
Here are a couple of ways you can generate the permutations.
Think of generating permutations as finding the next largest number with the same set of digits, starting from the number consisting of the sorted digits of n. In this case, the answers to this StackOverflow question is helpful. You can use arithmetic operations and modding instead of string concatenation to implement the algorithm there (I can provide more details if you like). A benefit of this is that the permutations you generate will automatically be in order.
If you don't care about the order of the permutations and you expect the number of digit duplicates to be small, you can use the Steinhaus-Johnson-Trotter algorithm, which (according to Robert Sedgewick) is the fastest algorithm for generating permutations of unique elements. To make sure duplicate permutations are not generated, you would have to distinguish every duplicate digit and only emit the permutations where they appear in order (i.e., if 2 appears three times, then create the elements 2_1, 2_2, 2_3 and make sure those three elements always appear in that order in an emitted permutation).
For the requirement, assuming that the length of N is n, we can generate all permutations by going from digit to digit, starting from 0 and end at n - 1. With 0 is the leading digit.
For each digit, we only go through each possibility (0 to 9) once , which will avoid duplicate permutation.
From digit x to digit x + 1, we can easily generate the current value by passing a number called current
For example: at digit 3, we have current = 1234, so at digit 4, if we choose 5 to be at digit 4, the current will be 1234*10 + 5 = 12345
Sample code in Java:
public void generate(int index, int length, int[] digits, long current, ArrayList<Long> result) {
//All the permutation will be stored in result ArrayList
for (int i = 0; i < 10; i++) {
if (digits[i] > 0 && (i != 0 || index != 0)) {
digits[i]--;
if (index + 1 == length) {//If this is the last digit, add its value into result
result.add(current * 10 + i);
} else {//else, go to next digit
generate(index + 1, length, digits, current * 10 + i, result);
}
digits[i]++;
}
}
}

Categories

Resources