Generating random strings, missing one letter - java

I have a small problem when trying to generate a random string with random size (between 3 and 20). I have an array arr with all characters from a (lowercase) to Z (uppercase). I then generate a random length arrLength for a second array arr2, which will be containing some randomly selected chars.
My issue is that the letter 'a' (lowercase) never appears in my randomly generated strings. I think that the mistake might be inside the for loop, but I have failed to see it so far. Maybe it has something to do with (int) casting or Math.floor rounding?
char[] arr = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
int arrLength = (int) (Math.floor((Math.random() * ((17 - 3) + 1)) + 3));
char[] arr2 = new char[arrLength];
String str = "";
for(int i=0;i<arrLength;i++) {
char num = arr[(int) (Math.floor(Math.random() * (50) + 1))];
arr2[i] = num;
}

Instead of the magic constant 50 use arr.length (note there are more than 50 characters in the array) and leave out the +1 as it makes the lowest number you can get to 1 and array indices start at 0 in Java.

Related

Adding Values to a List and Converting to BigInteger - Java [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm writing a code that determines the smallest integer that is a sequence of sevens followed by some number of zeros (possibly none) that is divisible by int n. Since this number can be massive, the return value should be a BigInteger.
My code so far has an if-else ladder that covers the case that if any int n is not divisible by two or five is guaranteed to only contain sevens (no zeros). In the case where int n is not divisible by two or five, my thought process was to continue adding sevens to a LinkedList in a while loop, until that list (converted to a BigInteger) is divisible by int n. The same logic goes for the case where int n is divisible by two or five, except a two for-loops would add seven and zero to the list.
My code is getting a runtime error when converting the list to a string and then to a BigInteger, specifically on the line BigInteger numBig = new BigInteger(str);. The error is: "java.lang.NumberFormatException: Zero length BigInteger (in java.math.BigInteger)" Also, I'm not quite sure the logic is sound for the case where int n is divisible by two or five.
You don't need BigInteger for this task. The idea is the following:
First you determine the number of required zeros. Since number composed of only sevens cannot be divided by 2 or 5, the number of zeros is equal to the maximum power of 2 or 5 in number n.
Now we have a number n which is not divisible by 2 or 5. Suppose that a remainder of the division of a number composed of m sevens by n is equal to r:
777...m-times..777 mod n = r
Then number composed of (m+1) sevens will have a remainder 10*r + 7, because
777..(m+1)-times...777 = 777...m-times...7 * 10 + 7
So you can just recalculate the remainder until it becomes zero.
public static BigInteger method(int n) {
int two;
for (two = 0; n % 2 == 0; two++) n /= 2;
int five;
for (five = 0; n % 5 == 0; five++) n /= 5;
int zeros = Math.max(two, five);
int sevens = 1;
int r = 7 % n;
while (r != 0) {
r = (r * 10 + 7) % n;
sevens++;
}
// Now just make a number of 'sevens' sevens and 'zeros' zeros:
StringBuilder result = new StringBuilder();
for (int i = 0; i < sevens; i++) {
result.append("7");
}
for (int i = 0; i < zeros; i++) {
result.append("0");
}
return new BigInteger(result.toString());
}
"Zero length BigInteger" means you're trying to create a BigInteger from something that has length of 0. The stack trace would tell you on which line exactly.
I would guess the bug is in your convert method. If you pass in an empty list, it tries to convert an empty string into BigInteger with new BigInteger("")
I don't know what your algorithm is supposed to do in this case. If for example you want to convert an empty list into the number zero, you can do:
if (res.isEmpty()) return BigInteger.ZERO;

Unable to pass all test cases in online judge

My solution is not accepted by the online judge. Any help would be appreciated.
JP and Strings
A 1-character string is which consists of only one letter 'a',
2-character string consists of only letters 'a' and 'b'. Similarly
26-character string consists of all the small letters in alphabet i.e
from 'a' to 'z'. A string is valid if there is no character in the
string which has the same position as in the alphabetical sequence.
For example, string "bac" is not valid because the character 'c' is at
the position 3 in the string(Consider string and alphabets both as
1-indexed) which is same as in the alphabetical sequence. Whereas
string "cab" is valid. Now there is a function F(N , L) such that,
F(N , L) = Number of valid N-Character strings of length L.
Input: The first line will contain the number of queries Q. Next Q
lines will contain two space separated integers containing N and L.
Output: For every query print a single line containing the value of
the function F(N , L). Answer may be too large so print it modulo
1000000007.
Constraints: 1 <= Q <= 10^3 1 <= N <= 26 1 <= L <= 10^9
Statement: Given two integers N and L where N represents the number of
characters and L represents the length of string.
My solution approach is:
There will be two possible use cases:
1.) L <= N If length of string L is less or equal to N then at each position we can choose N-1 characters so total number of strings will be (N-1)^L
2.) L > N If length of string L is grater than N then number of possible strings will be: (N-1)^N * N^(L-N) For rest N position we can choose N-1 characters but after Nth position all N characters can be used.
Code: http://ideone.com/fzGLKH
public static void main(String[] args) throws IOException {
FastScanner in = new FastScanner();
int q = in.nextInt();
int n,l;
while(q>0){
n = in.nextInt();
l = in.nextInt();
if(n<l){
System.out.println((int)((Math.pow(n-1, n)*Math.pow(n, l-n))% 1000000007));
}
else{
System.out.println((int)(Math.pow(n-1, l)% 1000000007));
}
q--;
}
}
What's the bug?
You are doing Math.pow(n - 1, l) % 1000000007.
The problem's constraints is 1 <= l <= 1000000000, so it may be a huge value like 10^9-digit number. It will cause overflow and you cannot get correct answer.
The solution for the bug
What do you do if you want to calculate a^b mod m (a^b is the bth power of a).
You can use Exponentation by squaring algorithm for calculating a^b mod m.
The algorithm in java is following:
public static long modpow(long a, long b, long m) {
long ret = 1;
while(b > 0) {
if((b & 1) == 1) ret = ret * a % m;
a = a * a % m;
b >>= 1;
}
return ret;
}
The time complexity is O(log b), so you can solve this problem!

Reversing a modulus operator for decrypting

For school, i've got an assignment to encrypt a four-digit Integer by the following requirements.
A company wants to transmit data over the telephone, but they are
concerned that their phones may be tapped. All of their data is
transmitted as four-digit integers. They have asked you to write a
method that will encrypt their data so that it may be transmitted more
securely. Your method should read a four-digit integer and encrypt it
as follows: Replace each digit by (the sum of that digit plus 7)
modulus 10. Then, swap the second digit with the fourth. Then print
the encrypted integer. Write a separate method that inputs an
en-crypted four-digit integer, and decrypts it to form the original
number.
The encrypting of the four-digit wasn't such of a problem, I've converted it to a string, then to a char array and then seperately encrypted the numbers by its needs.
The method I made looks like this:
public int encrypt4DigitNumber(int number) throws Exception {
String numberAsString = String.valueOf(number);
if (numberAsString.length() != 4) {
throw new Exception("The digit has to be 4 digits long");
}
int[] numbers = new int[4];
char[] numbersAsChars = numberAsString.toCharArray();
for (int index = 0; index < numbersAsChars.length; index++) {
int currentNumber = Character.getNumericValue(numbersAsChars[index]);
int numberToReplace = (currentNumber + 7) % 10;
numbers[index] = numberToReplace;
}
int second = numbers[1];
int fourth = numbers[3];
numbers[1] = fourth;
numbers[3] = second;
StringBuilder encryptedNumberStringBuilder = new StringBuilder();
for (int encryptedNumber : numbers) {
encryptedNumberStringBuilder.append(encryptedNumber);
}
String encryptedNumberString = encryptedNumberStringBuilder.toString();
return Integer.parseInt(encryptedNumberString);
}
The problem came when I had to de-crypt the encrypted four-digit code.
I know I had to swap the 2 array elements, and add 7 to each number in the array.
The thing I didn't know how to do was reverse the modulus operator, the only thing I can come up with is multiply the current number by 10, but that won't work.
After doing some research, I have to search the left-overs from the modulus somewhere, but I have absolutely no idea how to do that. Do I need to return those in the encrypt function aswell and pass them into the decrypt function?
Can someone explain the process of reversing the modulus operator?
If you encrypt a number from 0 to 9 (= mod 10) with an offset 7, you can of course subtract the offset from every digit during decryption and wrap around if the number is negative, but that is not very nice:
int numberToReplace = currentNumber - 7;
if (numberToReplace < 0) {
numberToReplace += 10;
}
If the encryption offset is 7, then the decryption offset would be 3 (10 - 7). You could just add 3 to each digit and apply mod 10 in order to decrypt them.
int numberToReplace = (currentNumber + 3) % 10;
Let's see what actually (i + 7) % 10 do:
0 = 7
1 = 8
2 = 9
3 = 0
4 = 1
5 = 2
6 = 3
7 = 4
8 = 5
9 = 6
As you can see there's definitely quite obvious pattern. So in order to decode our original digit back we have to do
(i + 3) % 10

Create random String of numbers with specific requirements

I want to create a random String of numbers.
From 0-9.
10 digits long.
First digit cannot be a 0.
One of the digits has to be in the String 2 times and one has to not be there at all.
Or one digit has to be there 3 times, and 2 other digits can not be there at all.
To make this a little bit clearer here are some examples:
1223456789 - 10 digits, no starting zero, one digit (2) is there 2 times and one digit (0) is not there at all
1000345678 - 10 digits, no starting zero, one digit (0) is there 3 times and two digits (2,9) are not there at all
The starting zero is pretty easy caught with startsWith - method, but I have not found a way to check for the rest and I am not particularly good at regex while I am also not entirely sure you can even do this using regex.
For generating the random String itself, I have worked with the Random class as well as RandomStringUtils, both of which don't have restrictions on creating numbers.
Has anyone of you an idea how to achieve this?
Imagine you have 10 sacks, each one of them has its corresponding number embroided on it, from 0 to 9, like this:
.---.._
{------';
}====={
.´ '.
/ .´| \ inside there are
| | | <--- stones with '1' engraved
\: _|_ /
-__ =.´
You also have a coin to flip heads or tails on your hand.
.------..-
´ . /___ `.`.
; / / ´} ; ; ______________________________
: "|'__' // : : / |
' .|/__\. } \ ' ' /_ HEAD! You shall pick 3 |
' /"../ ' ' | stones from the 1st sack! |
; / \/ ͷ ; ; \____________________________/
`_/ ´ ´
" -------´-´
First, we will decide if we will have 3 repeating numbers or 2 repeating numbers. Flip the coin to decide! Tail is 3, Head is 2. We will call this result ͷ.
Remove the sack embroided with 0 (Zero) for a moment.
Now pick ͷ (2 or 3) stones from a random sack of the 9 sacks you have in front of you. Remember, you cannot start with 0, that is why we removed it for a moment! Remove the sack you just picked from the line of sacks, forever. You cannot pick from this one anymore. Put back the 0 (Zero) sack on the line.
Place one of the stones you just picked in front of yourself. Hold ͷ-1 in your hand.
Now repeat this until you have 9 stones in your hand:
Select a random sack, pick ONE stone from it and hold it in your hand. Remove the sack from the
line.
By the end of this process, you will have 9 stones in your hand, one in front of yourself. Shuffle up the ones in your hand. Place them in a straight line in front of yourself, next to the stone that was already in front of you.
You will end with 10 numbers, ͷ repetitions of the same number, won't start with zero, and the remaining sack(s) in front of you are just a side-effect of removing the sacks along the way.
What about trying to make what you want first using the rules then construct the rest.
Here is a possible idea
Using the first rule
One of the digits has to be in the String 2 times and one has to not be there at all.
Create a LinkedList then add the numbers 1 to 9 to it.
Generate a random number between 0-8 (range of the indexes of the list), use the index to retrieve a value out of the list (as in delete it) then add that to the String so the first number isn't 0.
Add 0 back to the list so it can be used somewhere else.
There are now 9 numbers left in the LinkedList with the first number being non zero and already in the String variable as per step 2. From here, generate another random number in the range of the LinkedList indexes. Whatever this number is, remove it from the LinkedList add it twice to the ArrayList.
There are now 8 numbers left in the LinkedList, 1 non zero number in the String. and 3 numbers in the ArrayList for a total of 4 numbers in your sequence that are confirmed to be correct. You have to get another 6 numbers to complete it. So far it would look something like this.
String sequence => "4"
ArrayList beingBuilt => [2, 6, 6]
LinkedList available => [1, 3, 4, 5, 7, 8, 9, 0]
Seems you only can have 10 numbers, loop 6 more times through the LinkedList using a random number to pluck at a random index, delete it from LinkedList add it to ArrayList.
After this the ArrayList should have 9 numbers, you could shuffle it to make it more random then convert it to a String and append to on the end of the sequence. Your rule should be satisfied now.
To make it more random you could manipulate how you pluck out numbers from the LinkedList and also the last rule you had you could change it for that too fairly simply. I used a LinkedList due to faster deletes, I did think about using a set but perhaps more work to handle the random number index being mapped to a number that actually exists in the set.
Just an idea though
The idea is: first generate a random string with 0-9 each once and not starts with 0, then: 1. replace one of the digital will another or 2.replace two digitals with another.
import java.util.Random;
public class Main {
public static void main(String[] args) {
System.out.println(generateRandomString());
System.out.println(generateRandomString());
}
public static String generateRandomString() {
String alphabet = "0123456789";
String result = "";
Random random = new Random();
// build a random string construct will 0-9 and each digital appear once
for (int i = 0; i < 10; i++) {
int index = random.nextInt(alphabet.length());
if (i == 0) { // first cannot be 0
index = random.nextInt(alphabet.length() - 1) + 1;
}
String c = alphabet.substring(index, index + 1);
result += c;
alphabet = alphabet.replace(c, "");
}
return random.nextInt(2) == 0 ? shuffle1(random, result) : shuffle2(random, result);
}
// One of the digits has to be in the String 2 times and one has to not be there at all.
private static String shuffle1(Random random, String result) {
int from = random.nextInt(10);
int to = random.nextInt(9) + 1;
while (from == to) {
to = random.nextInt(9) + 1;
}
result = result.replace(result.substring(to, to + 1), result.substring(from, from + 1));
return result;
}
// One digit has to be there 3 times, and 2 other digits can not be there at all
private static String shuffle2(Random random, String result) {
int from = random.nextInt(10);
int to1 = random.nextInt(9) + 1;
int to2 = random.nextInt(9) + 1;
while (from == to1) {
to1 = random.nextInt(9) + 1;
}
while (from == to2 || to2 == to1) {
to2 = random.nextInt(9) + 1;
}
result = result.replace(result.substring(to1, to1 + 1), result.substring(from, from + 1));
result = result.replace(result.substring(to2, to2 + 1), result.substring(from, from + 1));
return result;
}
}
If you're not too concerned about performance then the simplest thing would be to just generate random lists of numbers and check them against your conditions until you get one that works. Best to do the filtering as numbers and then convert to a string at the end rather than using regular expressions.
public String getRandomInts() {
Random random = new Random();
int[] ints;
do {
ints = random.ints(10, 0, 10).toArray();
} while (!meetsCriteria(ints));
return Arrays.stream(ints).mapToObj(String::valueOf).collect(Collectors.joining(""));
}
private boolean meetsCriteria(int[] ints) {
if (ints[0] == 0) {
return false;
}
if (frequency(ints, 0) == 1
&& frequency(ints, 1) == 8
&& frequency(ints, 2) == 1) {
return true;
}
if (frequency(ints, 0) == 2
&& frequency(ints, 1) == 7
&& frequency(ints, 3) == 1) {
return true;
}
return false;
}
private int frequency(int[] ints, int count) {
return (int) IntStream.range(0, 10)
.filter(n1 -> Arrays.stream(ints).filter(n2 -> n1 == n2).count() == count)
.count();
}

How does this code add commas before every three digits?

Help me to understand how this code works. It essentially adds commas into a string of numbers. So if the user types a 1 to 3 digit number it is unchanged. For a four digit number ,it adds a comma so
1111 becomes 1,111
11111 becomes 11,111
111111111 becomes 11,111,111
and so on. Here's the code:
private String addCommasToNumericString (String digits)
{
String result = "";
int len = digits.length();
int nDigits = 0;
for (int i = len - 1; i >= 0; i--)
{
result = digits.charAt(i) + result;
nDigits++;
if (((nDigits % 3) == 0) && (i > 0))
{
result = "," + result;
}
}
return (result);
}
I´ll explain what I do understand of it
The for loop basically counts the length of the number the user has written to avoid putting a comma before the first number (e.g. ,1111). And while i is less than the length of the string it subtracts 1.
result returns the char at position i, since it counts downwards it returns the chars "opposite" from right towards left.
nDigits adds 1 from to the initial value of 0 on each iteration through the loop.
I guess now is where I am having trouble seeing exactly what is going on: if ("nDigits % 3) == 0.
So for the two first iteration through loop it will not execute the if loop because:
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
nDigits starts out as 1 because of the nDigits++ code inside the for loop, so how does it put the comma after three digits and not two? And how does it know when there is only 4 or 5 digits to place the comma corretly at position 1 and two (1,111 - 11,111)?
I think the easiest way to explain this is to slow it down to each pass.
The loop starts at the end of the string so if you have the string 12345, then after the first time through the loop result will be "5" and nDigits will be 1.
The next time through, '4' will be added to the front of the result giving you "45" and nDigits will be 2.
The third time through, it adds '3' to the front of result making that "345" and then the if-then triggers and adds a comma to the front. Result is now ",345".
More passes will give you "12,345".
I think what is confusing you is that loop starts at the '5' and not at the '1'. Everything is added to the front of result and not to the end as you would normally expect.
Hope this helps!
The key thing in this method is to count the digits from right to left. If you don't do it that way it won't work.
You can also do the same with String Manipulation instead of char manipulation. Maybe it makes it easier to understand so I'll provide an example.
My solution involves the use of the subString Method and operates in a similar manner to yours. Starting FROM RIGHT TO LEFT, it divides the original String in two substrings and adds a comma in between them every time there is a 3 digits group.
private String addCommas (String digits) {
String result = digits;
if (digits.length() <= 3) return digits; // If the original value has 3 digits or less it returns that value
for (int i = 0; i < (digits.length() – 1) / 3; i++) {
int commaPos = digits.length() – 3 – (3 * i); // comma position in each cicle
result = result.substring(0, commaPos) + "," + result.substring(commaPos);
}
return result;
}
The variable result is used for incremental build of the final output, in each iteration one or two chars are concatenated from left (i.e. the string is build from right to left).
One char is concatenated everytime by running
result = digits.charAt(i) + result;
it is the actual digit
the second char is concatenated in each third iteration by running
result = "," + result;
it is the order separator
The implementation is not optimal at all, because in Java the string are immutable and result = "," + result; ends up in creating a new object. The StringBuffer or StringBuilder are far more effective for this purpose.
Essentially what this does is start at the last digit of the number and iterate through from right to left, prepending them to the result String and putting a comma in every 3 characters.
In this particular code, len holds the total length of the number and nDigits is a count of how many of those digits have been evaluated already. Starting at position len-1 (so the index of the last digit of the number), the for-loop iterates through position 0 (the first digit of the number). It takes the digit at position i, puts it at the front of the result String, and then evaluates if there should be a comma in front of it. nDigits % 3 will return 0 every 3rd digit, so the if statement evaluates if there should be a comma by checking that if there have been 3 digits written and the one you just wrote was not 0.
for (int i = len - 1; i >= 0; i--)
i starts with len - 1, to start from the last digit. i > 0 in if (((nDigits % 3) == 0) && (i > 0)) is the one that avoid a comma before the first number (e.g. ,1111).
I modified answer of #Antonio Ricardo Diegues Silva for my purposes.
/**
* Get number in {#link String} with divider after 'n' number of digits
* #param number number for processing
* #param n amount after which will be inserted divider
* #return {#link String} number with dividers
*/
public static <T extends Number> String insertDividerBetweenEveryNDigits(T number, int n, String divider) {
StringBuilder builder = new StringBuilder().append(number);
int digitsNumber = builder.length();
if (digitsNumber > n) { // If the original value has n digits or less it just returns that value
for (int i = 1; i <= (digitsNumber - 1) / n; i++) {
int dividerPos = digitsNumber - (n * i); // divider position in each cycle
builder.insert(dividerPos, divider);
}
}
return builder.toString();
}

Categories