corresponding permutation number - java

I have a given word, for wich I need to find its number of permutation on its corresponding sorted word .
Say I have word BABA , its corresponding sorted word would be, AABB, if I start permuting this sorted word, would come to AABB as a second "word", regardless of letter repetition, then ABAB, ABBA , BABA .. so the permute number for word BABA is 5 .
The easy way would be start doing all possible combinations, and then compared with the initial word .
so far , ive done..
import java.util.Arrays;
public class Permutation {
int location =1;
public static char[] warray;
void printArray(char []a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
System.out.println("location " + location );
}
void permute(char []a,int k ) {
if(k==a.length) {
location++;
// Check if the permuted word is the one looking for.
if (Arrays.equals(a, warray))
{ System.out.println("final iteration k" + k);
printArray(a);
System.exit(0);}
}
else
for (int i = k; i < a.length; i++) {
char temp=a[k];
a[k]=a[i];
a[i]=temp;
permute(a,k+1);
}
}
public static void main(String[] args) {
if (args[0].length() > 25 ) {
System.out.println(" Word not in permited range " );
System.exit(0);
}
else {
Permutation p=new Permutation();
warray = new char[args[0].length()];
char [] wpermute = new char[args[0].length()];
for (int i = 0; i < args[0].length(); i++) {
warray[i] = new Character(args[0].charAt(i));
wpermute[i] = new Character(args[0].charAt(i));
}
Arrays.sort(wpermute);
System.out.print("sorted word : " );
for (int i = 0; i < wpermute.length; i++) {
System.out.print(wpermute[i]);
}
p.permute(wpermute,0);
}
}
But this could be very slow performance.
My second guess, would be , starting like a binary search startting with first letter of unsorted word, calculate possibble permutations to have this letter as the first letter on permutations, and then second letter..and so ... would that sound good ?

If you only have 2 letters and if the length of the word is N and the number of A's is n then the number of permutations is N choose n.
If you have N letters total and n_a, n_b, ..., n_z describe the number of each letter then the total number of permutations is
N!/(n_a! n_b! n_c! ... n_z!)
Check out Multinomials, scroll down to the bit on permutations.

Another word would be QUESTION , its sorted word is EINOQSTU .
for question , q is in position 1 , and in postion 5 in the new word, how many permutations need to do to put is in postion 1 = 20161 .
Now I take second letter in question, is U, which is in position 8 in sorted word , how many permutations need to do, is 24481
I think, I could calculate , not perform, the number permutations needed to put a letter in y position, to be in X position. and then , the sum of all , would be the permutations needed for the whold word.
Now, how to calculate those numbers, I know has to be with factorial plus something else ..is not ?

So I finally completed the code, and yes, needed to check the multinomials.
also got part of the idea from a related post here.
But here my code.
package WordPuzzle;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/** Rafael G. */
public class WordPuzzle {
static String sortWord (String[] wordinput){
char [] wsorted = new char[wordinput[0].length()];
wsorted = wordinput[0].toCharArray();
Arrays.sort(wsorted);
String aux="";
for (int i = 0; i < wsorted.length; i++) {
aux = aux + wsorted[i];
}
return aux;
}
static void calculatePerm(String wordtofind,String wordsorted)
{
int sum = 0;
int numberpermutations;
char nextchar;
int charlocremainder =0;
String lowerLetters;
String greaterLetters;
Map<Character, Integer> characterCounts = new HashMap<Character, Integer> ();
int count ;
char letter;
int factorial;
int [] factorials = new int [wordsorted.length()+1];
factorial =1;
numberpermutations = 1;
int nMinusI;
int nextcharcount;
// set a mapping of repeated letters and its number
// and store factorial calculation.
for (int i = 0; i < wordsorted.length(); i++) {
letter = wordsorted.charAt(i);
factorial = factorial * (i+1);
factorials[i+1]= factorial;
count = characterCounts.containsKey(letter) ? characterCounts.get(letter) + 1 : 1;
characterCounts.put(letter, count);
}
String trimWord = new String(wordsorted);
for (int i = 0; i < wordtofind.length() ; i++){
nMinusI = wordtofind.length()-(i+1);
nextchar = wordtofind.charAt(i);
charlocremainder = trimWord.indexOf(nextchar);
lowerLetters = trimWord.substring(0, charlocremainder);
// Calculate the denominator which is the number of repeated letters
// of the formula (N-i)! * (Na+Nb) /Na!Nb!..
nextcharcount = characterCounts.get(nextchar);
characterCounts.put(nextchar, nextcharcount-1);
int denomfact = factorials[nextcharcount];
if (lowerLetters.length() > 1){
char x = lowerLetters.charAt(0);
char y = x;
for (int k = 1 ; k < lowerLetters.length(); k++){
y = lowerLetters.charAt(k);
if (x != y) {
denomfact = denomfact * factorials[characterCounts.get(x)];
x = y;
}
}
denomfact = denomfact * factorials[characterCounts.get(y)];
}
numberpermutations = factorials[nMinusI] * lowerLetters.length() / denomfact;
sum = sum + numberpermutations;
greaterLetters= trimWord.substring(charlocremainder+1);
trimWord = lowerLetters.concat(greaterLetters);
}
System.out.println(" Rank of permutation " + (sum+1));
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
long startTime = System.nanoTime();
String wordsorted;
String wordentered;
if (args[0].length() > 25 ) {
System.out.println("Word not in permited range " );
System.exit(0);
}
else {
wordentered = args[0].toUpperCase();
wordsorted = sortWord(args).toUpperCase();
calculatePerm(wordentered,wordsorted);
}
long endTime = System.nanoTime();
System.out.println("Took "+(endTime - startTime)/1000000000.0 + " seconds");
System.out.println("Took "+(endTime - startTime)* 0.000001 + " milliseconds");
}
}

Related

I need a Java method that returns a diamond pattern of numbers

I am new to programming and decided to join an online Java course for beginners.
I am asked to do 2 things:
Print a sequence of digits with preceding and trailing white spaces on a single line. It is assumed that the method parameter centerDigit can only take values from 0 to 9. For example: printSequenceDigits( 2, 7 ) results in: " 01210 "
Print a diamond pattern of numbers on the terminal window, With the help of the printSequenceDigits() method. For example: printDigitDiamond(2) results in:
" 0 "
" 010 "
" 01210 "
" 010 "
" 0 "
So far I have been able to complete task 1, but I am unsure how I can implement the 2nd task using the "for" loop in the 1st task to display the diamond.
I would be grateful if anyone can get me on the way
Here is my code so far:
/**
* Method which prints a sequence of digits with preceding and trailing white spaces on a single line
* of the terminal window.
*
* #author
* #version
*/
public class PrintSequenceDigits
{
/**
* Constructor which prints a sequence of digits with preceding and trailing white spaces on a single
* line of the terminal window
*/
public static void printSequenceDigits(int centerDigit, int length) {
// declare variables
int integerCenterDigit, integerLength, integerStringLength, integerNetLength;
String stringResults = "";
// calculate length of stringResults
integerStringLength = centerDigit * 2 + 1; // for printNumberLine( 2, 7 ) --> 2*2+1=5
// calculate length of int length
integerNetLength = (length - integerStringLength) / 2; // for printNumberLine( 2, 7 ) --> (7-5)/2=1
for(integerCenterDigit = 0;
integerCenterDigit < integerNetLength;
integerCenterDigit++){
stringResults = stringResults + ' '; // print blank space before
}
for(integerCenterDigit = 0; // print 0
integerCenterDigit <= centerDigit; // print 1
// print length +1 etc depending on input length
integerCenterDigit++){
stringResults = stringResults + integerCenterDigit; // for printNumberLine( 2, 7 ) print 012
}
for(integerCenterDigit = centerDigit -1; // print length -1 (=1)
integerCenterDigit >= 0;
// print length -1 etc depending on input length
integerCenterDigit--){
stringResults = stringResults + integerCenterDigit; // for printNumberLine( 2, 7 ) print 10
}
for(integerCenterDigit = 0;
integerCenterDigit < integerNetLength;
integerCenterDigit++){
stringResults = stringResults + ' '; // print blank space after
}
System.out.println(stringResults); // prints total of the above = " 01210 "
}
/**
* Method which prints a diamond pattern of numbers on the terminal window
*
* #param
* #return
*/
public static void printDigitDiamond(int diamondCenter) {
int integerDiamondCenter;
}
}
Am I on the right track here or do I have to revise my for loop in task 1?
Can this loop be constructed differently to make it easier to pass the results from task1 to task 2?
You're on the right track. Your first method does its task, right? Check that off the list. Now you need to print out a diamond digit using the first method, right? You can accomplish two ways:
Let the first method do the printing. Your 2nd task calls the first with the proper parameters to make the entire digit diamond be printed as you wish.
Remove "printing" from the equation by returning a String.
This 2nd solution is just as good as the first in your case, however in general the 2nd solution is better overall. If you think about it, generating the string AND printing it are two separate tasks. You may not always want to do both, so logically you should separate them.
The actual printing is somewhat trivial, but if it weren't, then I would recommend creating a separate method to do that and if anything, create a method that calls both in order to both generate and print the string. In this way you have full functionality and your code is not repeated.
In addition to this, there is a small optimization that I would recommend if you're having to append more than 3 Strings together. There is a class called StringBuilder that has the silly task of optimizing construction of the string and that's all.
So that said, your method would become:
public static void generateSequenceDigits(int centerDigit, int length) {
int integerCenterDigit, integerLength, integerStringLength, integerNetLength;
StringBuilder stringResults = new StringBuilder();
integerStringLength = centerDigit * 2 + 1;
integerNetLength = (length - integerStringLength) / 2;
for(integerCenterDigit = 0;
integerCenterDigit < integerNetLength;
integerCenterDigit++){
stringResults.append(' ');
}
for(integerCenterDigit = 0;
integerCenterDigit <= centerDigit;
// print length +1 etc depending on input length
integerCenterDigit++){
stringResults.append(integerCenterDigit);
}
for(integerCenterDigit = centerDigit -1;
integerCenterDigit >= 0;
integerCenterDigit--){
stringResults.append(integerCenterDigit);
}
// Not strictly necessary
/*
for(integerCenterDigit = 0;
integerCenterDigit < integerNetLength;
integerCenterDigit++){
stringResults.append(' ');
}
*/
return stringResults.toString(); // <-- Build final string
}
Then to print it out, you'd do System.out.println(generateSequenceDigits(2, 7));.
In this way, you can reuse generateSequenceDigits in your 2nd method. Like I did in the first, you could use StringBuilder to append lines and then return them in a gigantic String. In your main you would then simply print it out, though you could potentially write it to a file or save it to a database whereas if you simply printed it, you would have to first adapt your method. I leave the other method to you to do.
PS - Also please note that the last loop appending spaces is not visible and so I commented it out. There may be strange situations in which you may need it, so I would simply leave it commented out. Good luck!
Here's "The Java Way" to do it for Boris...
dtest.java:
import edu.iastate.its.niads.demo.Diamond;
public class dtest {
public static void main(String[] args) {
Diamond d = new Diamond(4);
System.out.println(d);
}
}
Diamond.java:
package edu.iastate.its.niads.demo;
public class Diamond {
private static final int DEF_SIZE = 4;
private int size;
public Diamond ( ) { this(DEF_SIZE); }
public Diamond ( int size ) { setSize(size); }
public void setSize ( int size ) { this.size = size; }
public int getSize ( ) { return size; }
#Override
public int hashCode ( ) { return size; }
#Override
public boolean equals ( Object obj ) {
if (!(obj instanceof Diamond)) return false;
return (((Diamond)obj).size == this.size);
}
/* called printSequenceDigits() in the assignment */
private String line ( int mx, int wid ) {
StringBuilder sb = new StringBuilder(wid + 1);
for (int s = 0; s < (wid/2) - mx; ++s) sb.append(' ');
for (int u = 0; u < mx; ++u) sb.append(u);
for (int d = mx; d >= 0; --d) sb.append(d);
for (int s = 0; s < (wid/2) - mx; ++s) sb.append(' ');
sb.append('\n');
return sb.toString();
}
/* replaces printDigitDiamond() in the assignment */
#Override
public String toString () {
int dim = (2 * size) + 3;
StringBuilder sb = new StringBuilder(dim * (dim+1));
for (int u = 0; u < size; ++u) sb.append(line(u, dim));
for (int d = size; d >= 0; --d) sb.append(line(d, dim));
return sb.toString();
}
}
Sample run:
john% java dtest
0
010
01210
0123210
012343210
0123210
01210
010
0
You are using too many loops in your solution. Your code is good as a beginner but if you want to explore more as you learn, here is a better implementation for printDiamond() and printSequenceDigits() functions.
I have also added comments to make you understand the program better. Feel free to comment if you want to understand any specif part.
Here is the code snippet:
public static void main (String[] args)
{
/* Print Diamond */
printDiamond(4);
}
/**
* Print Diamond
* Arguments: Length of the diamond
**/
private static void printDiamond(int num) {
/* Check Input Number */
if(num < 0 || num > 9) {
System.out.println("Invalid Input!");
return;
}
/* Length = num*2 + 1 */
for(int i = 0; i < num*2 + 1; i++) {
/* Print Sequence Digits */
printSequenceDigits(i <= num ? i : num*2 - i, num*2 + 1);
}
}
/**
* Print Sequence Digits
* Arguments: Row Index, Total Length of Row
**/
private static void printSequenceDigits(int x, int length) {
/* Crate Row Sequence */
char[] ptr = new char[x*2+1];
/* Fill The Values */
for(int i = 0; i < ptr.length/2 + 1; i++) {
/* First Half = Other Half (Reversed) */
ptr[i] = ptr[ptr.length - 1 - i] = (char) (i + '0');
}
/* Pad Extra Spaces */
char[] padding = new char[(length - ptr.length)/2];
Arrays.fill(padding,' ');
/* Print Sequence */
System.out.println("\" " + new String(padding) + new String(ptr)
+ new String(padding) + " \"");
}
Output:
" 0 "
" 010 "
" 01210 "
" 0123210 "
" 012343210 "
" 0123210 "
" 01210 "
" 010 "
" 0 "
You can use below logic for print diamond.
int number = 3;
int space = number -1;
for (int i = 1; i < number; i++) {
for(int s = 1; s <= space; s++) {
System.out.print(" ");
}
space--;
for (int j = 0; j < i; j++) {
System.out.print(j);
}
for (int p = i - 2 ; p >= 0; p--) {
System.out.print(p);
}
System.out.print("\n");
}
space = 0;
for (int i = number; i > 0; i--) {
for(int s = 0; s < space; s++) {
System.out.print(" ");
}
space++;
for (int j = 0; j < i; j++) {
System.out.print(j);
}
for (int p = i - 2 ; p >= 0; p--) {
System.out.print(p);
}
System.out.print("\n");
}

Decrease run time of this java program

I have made a program to input an array, and find the product of 3 largest numbers of the array such that:
The array constitutes of sub-arrays consisting of index increased one at a time.
That is, for an array of 10 elements, find the product considering the first 3 elements, then first 4 elements, then first 5 elements and so on.
Here's my code:
import java.io.*;
import java.util.Arrays;
public class monkmulti {
public static void main(String args[] ) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine()); // no. of elements
String xs = br.readLine(); //accepting those elements in a string
xs=xs+" ";
if(n<1||n>100000) //constraint
System.exit(0);
int i,temp,count=0;
for(i=0;i<xs.length();i++)
{
if(xs.charAt(i)==' ')
{
count++;
}
}
if(count!=n) //checks if no. of elements are equal to n
System.exit(0);
int[] x=new int[count];
int k=0;
temp=0;
for(i=0;i<xs.length();i++)
{
if(xs.charAt(i)==' ')
{
x[k++]=Integer.parseInt(xs.substring(temp, i));
temp=i+1;
}
}
count=0;
int len=x.length,j;
int[] x1=new int[len];
System.arraycopy(x, 0, x1, 0, len);
for(i=0;i<len;i++)
{
if(x[i]<1||x[i]>100000) //constraint for each element
System.exit(0);
}
int m1=0,m2=0,m3=0;
int max1=x[0],max2=x[0],max3=x[0];
/*code to be improved below from here*/
for(i=2;i<len;i++)
{
for(j=0;j<=i;j++)
{
for(k=0;k<i;k++)
{
if(x1[k]>x1[k+1])
{
temp=x1[k];
x1[k]=x1[k+1];
x1[k+1]=temp;
}
}
}
System.out.println(x1[i]*x1[i-1]*x1[i-2]);
}
}
}
Input:
n=user inputs no. of elements in array
xs= string accepting n elements separated by a space
Output:
product considering first 3 elements
product considering first 4 elements
so on..
Example:
Input:
5
6 2 9 3 8
Output:
-1
-1
108
162
432
Explanation
There are 5 integers 6,2,9,3,8
For the third index, the top 3 numbers are 6,2 and 9 whose product is 108.
For the fourth index, the top 3 numbers are 6,9 and 3 whose product is 162.
For the fifth index, the top 3 numbers are 6,9 and 8 whose product is 432.
If I understand, You need something like this:
The order is O(items * log(subgroups)) -> O(items * log(3)) -> O(items)
public static void product(int[] items, int subGroup) {
if (subGroup > 0 && items.length >= subGroup) {
// this save the largest numbers:
PriorityQueue<Integer> maxElements = new PriorityQueue<>(subGroup);
int product = 1;
for (int i = 0; i < items.length; i++) {
// the queue of largest numbers is full:
if (maxElements.size() == subGroup) {
// the minimum of previous largest number is lower than the new number
if (maxElements.peek() < items[i]) {
// swapping
product /= maxElements.poll();
product *= items[i];
maxElements.add(items[i]);
}
System.out.println(product);
} else {
product *= items[i];
maxElements.add(items[i]);
if (maxElements.size() < subGroup) {
//the queue of largest numbers isn't full
System.out.println("-1");
} else {
// the queue of largest numbers is full now
System.out.println(product);
}
}
}
}
}
public static void main(String[] args) {
int[] input = {6, 2, 9, 3, 8};
product(input, 3);
}
Output:
-1
-1
108
162
432
EDIT:
A little bit faster:
private static void heap(int[] maxElements) {
int candidate = 1;
if (maxElements[1] > maxElements[2]) {
candidate = 2;
}
if (maxElements[0] > maxElements[candidate]) {
int temp = maxElements[0];
maxElements[0] = maxElements[candidate];
maxElements[candidate] = temp;
}
}
private static int addElement(int k, int[] maxElements, int item) {
if (k < 3) {
maxElements[k++] = item;
if (k < 3) {
System.out.println("-1");
} else {
heap(maxElements);
System.out.println(maxElements[0] * maxElements[1] * maxElements[2]);
}
} else {
if (maxElements[0] < item) {
maxElements[0] = item;
heap(maxElements);
}
System.out.println(maxElements[0] * maxElements[1] * maxElements[2]);
}
return k;
}
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine()); // no. of elements
String line = br.readLine(); //accepting those elements in a string
int[] maxElements = new int[3];
int k = 0;
int item = 0;
char c;
for (int i = 0; i < line.length(); i++) {
c = line.charAt(i);
if (c == ' ') {
k = addElement(k, maxElements, item);
item = 0;
} else {
item = item * 10 + (c - '0');
}
}
addElement(k, maxElements, item);
}
The following solution removed all "number of elements" check code as it's not really necessary for the solution.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;
public class MonkMulti
{
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Input a list of numbers separated by space");
String xs = br.readLine(); // accepting those elements in a string
// split input values by space
String[] numbers = xs.split("\\ ");
// create int array
int[] x = new int[numbers.length];
// convert all strings to int
for (int i = 0; i < numbers.length; i++)
{
x[i] = Integer.valueOf(numbers[i]);
}
for (int arraySize = 3; arraySize <= x.length; arraySize++)
{
calculateMonkMulti(x, arraySize);
}
}
/**
* Calculate the product for different sizes
*
* #param values
* #param arraySize
*/
private static void calculateMonkMulti(int[] values, int arraySize)
{
// new target sub array
int[] sorted = new int[arraySize];
// copy values of the sub array
System.arraycopy(values, 0, sorted, 0, arraySize);
// sort the sub array
Arrays.sort(sorted);
// calculate start index of top 3 elements
int startIndex = sorted.length - 3;
// get top three elements
System.err.println(startIndex + "/" + arraySize + "/" + sorted.length);
int int1 = sorted[startIndex];
int int2 = sorted[++startIndex];
int int3 = sorted[++startIndex];
// calculate
long result = int1 * int2 * int3;
// output (or return)
System.out.println(int1 + " * " + int2 + " * " + int3 + " = " + result);
}
}
Solution using JDK classes and functions.
I get the following runtime values:
For the total array with 100.000 values from the link: Runtime: 47 ms for all sub arrays 100000 elements
For a runtime over all sub array of x elements, starting the following (updated after finished):
Total runtime: 66 ms after 1000 elements with 100000 elements total
Total runtime: 195 ms after 2000 elements with 100000 elements total
Total runtime: 317 ms after 3000 elements with 100000 elements total
...
Total runtime: 295667 ms after 98000 elements with 100000 elements total
Total runtime: 301906 ms after 99000 elements with 100000 elements total
Total runtime: 308266 ms after 100000 elements with 100000 elements total
Runtime: 308266 ms for all sub arrays 100000 elements
I do not know what the web site measures. The compilation time?
Version 2:
A new optimized version can solve the problem in total Runtime: 26900 ms for all sub arrays 100000 elements
And now Version 3:
...
Total runtime: 54 ms after 98000 elements with 100000 elements total
Total runtime: 54 ms after 99000 elements with 100000 elements total
Total runtime: 54 ms after 100000 elements with 100000 elements total
Runtime: 55 ms for all sub arrays 100000 elements
My fastest solution:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
public class MonkMulti
{
static int[] sortedFast;
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new FileReader(new File(
"u:/temp/numbers.txt")));
String xs = br.readLine(); // accepting those elements in a string
// split input values by space
long startTime = System.currentTimeMillis();
String[] numbers = xs.split("\\ ");
// create int array
int[] sourceValues = new int[numbers.length];
// convert all strings to int
for (int i = 0; i < numbers.length; i++)
{
sourceValues[i] = Integer.valueOf(numbers[i]);
}
// create memory array for top 3 values
sortedFast = new int[3];
// copy first to elements from source to memory by one position up
System.arraycopy(sourceValues, 0, sortedFast, 1, 2);
// and set the lowest element to -1
sortedFast[0] = -1;
long result = 0;
// start with 3 elements in sub array
int startIndex = 3;
// loop all sub arrays from 3 .. sourceValues.leength
for (int arraySize = startIndex; arraySize <= sourceValues.length; arraySize++)
{
// calculate the value
result += calculateMonkMegaFast(sourceValues, arraySize);
}
long endTime = System.currentTimeMillis();
System.out
.println("Runtime: " + (endTime - startTime)
+ " ms for all sub arrays " + sourceValues.length
+ " elements (some value to ignore to prevent optimization: " + result + ")");
}
private final static long calculateMonkMegaFast(int[] values, int arraySize)
{
// check if the next element if greater as the lowest element in memory
// sort the sub array
if (values[arraySize - 1] > sortedFast[0])
{
// yes, replace lowest element with the bigger element from source
sortedFast[0] = values[arraySize - 1];
// sort the 3 element memory array
Arrays.sort(sortedFast);
}
// get new top 3 elements
int int1 = sortedFast[0];
int int2 = sortedFast[1];
int int3 = sortedFast[2];
// calculate result
long result = int1 * int2 * int3;
// output (or return)
// System.out.println(int1 + " * " + int2 + " * " + int3 + " = " +
// result);
return result;
}
}
Result calculation should use double to prevent value overflow. The complexity is almost O(n).

How to add numbers(integers) that are stored inside a string

I have to create a program that uses Luhn's algorithm to check to see if a credit card is valid.
The algorithm is this:
Form a sum of every other digit, including the right-most digit; so
5490123456789128 sums to 8+1+8+6+4+2+0+4 = 33
Form double each remaining digit, then sum all the digits that creates it; the remaining digits in our example (5 9 1 3 5 7 9 2) double to 10 18 2 6 10 14 18 4, which sums to 1+0+1+8+2+6+1+0+1+4+1+8+4 = 37
Add the two sums above (33+37 = 70)
If the result is a multiple of 10 (i.e., its last digit is 0) then it was a valid credit card number.
I made a Scanner and saved the credit card number into String card number
Then I created a while loop to save every other character starting from the right into a string. So now, I have a string filled with every other digit of the credit card number, starting from the right. However, I need to add up all of the digits within that string, which I can't figure out.
For example, if the user entered 1234 as the card number, the string everyotherdigit = 42. How can I add up 4 and 2 within the string?
There are numerous ways to do that. You can actually find your own solution by doing a bit of googling.
Anyway, this is what you can do:
Get individual characters from your string, and convert them to int.
String cardNumber = "5490123456789128";
int value = cardNumber.charAt(0) - '0';
Using a for loop and changing 0 to x(loop counter) will solve everything.
Get single String and convert to int.
String cardNumber = "5490123456789128";
int value = Integer.parseInt(cardNumber.substring(0,1));
I'd treat the string as an array of chars, and use Character.digit(int, int) to convert each character to the corresponsing int:
public static boolean isValidCreditCard (String s);
char[] arr = s.toCharArray();
int everyOtherSum = 0;
for (int i = arr.length - 1; i >= 0; i -= 2) {
everyOtherSum += Character.digit(arr[i], 10);
}
int doubleSum = 0;
for (for (int i = arr.length - 2; i >= 0; i -= 2) {
int currDigit = Character.digit(arr[i], 10);
int doubleDigit = currDigit * 2;
while (doubleDigit > 0) {
doubleSum += (doubleDigit % 10);
doubleDigit /= 10;
}
}
int total = everyOtherSum + doubleSum;
return total % 10 == 0;
}
So something like this would work for you:
public static void main(String[] args)
{
String cardNum = "5490123456789128";
String others = null;
int evenDigitSum = 0;
int oddDigitTransformSum = 0;
for (int pos = 0; pos < cardNum.length(); pos++)
{
if ((pos%2) != 0)
{
evenDigitSum += (cardNum.charAt(pos) - '0');
}
else
{
others = Integer.toString((cardNum.charAt(pos)-'0')*2);
for (char c : others.toCharArray())
{
oddDigitTransformSum += (c-'0');
}
}
}
System.out.println("Odds: " + oddDigitTransformSum);
System.out.println("Evens: " + evenDigitSum);
System.out.println("Total: " + (evenDigitSum+oddDigitTransformSum));
System.out.println("Valid Card: " + ((evenDigitSum+oddDigitTransformSum)%10==0));
}
public int cardCount(String numbers){
Stack<Integer> stack = new Stack<>();
int count = 0;
for(char c : numbers.toCharArray()){
stack.push(Character.getNumericValue(c));
}
int size = stack.size();
for(int i=1;i <= size; i++){
if(i%2 != 0){
count = count + stack.pop();
}else{
stack.pop();
}
}
return count;
}
This just does what you asked, not the entire algorithm

Mix multiple strings into all the possible combinations

I have some strings.
1
2
3
How do I combine them into all their unique combinations?
123
132
213
231
312
321
Here is the code I have, but I would like to work without the Random class because I understand that this is not the best way to do it.
import java.util.Random;
public class Solution
{
public static void main(String[] args)
{
String[] names = new String[]{"string1", "string2", "string3"};
for (int i = 0; i < 9; i++) {
Random rand = new Random();
int rand1 = rand.nextInt(3);
System.out.println(names[rand.nextInt(3)] +
names[rand1] +
names[rand.nextInt(3)]);
}
}
}
You can loop over the array by creating another nested loop for each repetition.
for (String word1 : words) {
for (String word2 : words) {
for (String word3 : words) {
System.out.println(word1 + word2 + word3);
}
}
}
Here is how to avoid having the same word in one combination.
for (String word1 : words) {
for (String word2 : words) {
if ( !word1.equals(word2)) {
for (String word3 : words) {
if ( !word3.equals(word2) && !word3.equals(word1)) {
System.out.println(word1 + word2 + word3);
}
}
}
}
}
Here is a class version that is capable of multiple lengths, using backtracking.
import java.util.ArrayList;
import java.util.List;
public class PrintAllCombinations {
public void printAllCombinations() {
for (String combination : allCombinations(new String[] { "A", "B", "C" })) {
System.out.println(combination);
}
}
private List<String> allCombinations(final String[] values) {
return allCombinationsRecursive(values, 0, values.length - 1);
}
private List<String> allCombinationsRecursive(String[] values, final int i, final int n) {
List<String> result = new ArrayList<String>();
if (i == n) {
StringBuilder combinedString = new StringBuilder();
for (String value : values) {
combinedString.append(value);
}
result.add(combinedString.toString());
}
for (int j = i; j <= n; j++) {
values = swap(values, i, j);
result.addAll(allCombinationsRecursive(values, i + 1, n));
values = swap(values, i, j); // backtrack
}
return result;
}
private String[] swap(final String[] values, final int i, final int j) {
String tmp = values[i];
values[i] = values[j];
values[j] = tmp;
return values;
}
}
Please note that using the random method, it is never guaranteed that all combinations are being get. Therefore, it should always loop over all values.
You could use the Google Guava library to get all string permutations.
Collection<List<String>> permutations = Collections2.permutations(Lists.newArrayList("string1", "string2", "string3"));
for (List<String> permutation : permutations) {
String permutationString = Joiner.on("").join(permutation);
System.out.println(permutationString);
}
Output:
string1string2string3
string1string3string2
string3string1string2
string3string2string1
string2string3string1
string2string1string3
Firstly, there is nothing random in the result you are after - and Random.nextInt() will not give you unique permutations, or necessarily all permutations.
For N elements, there are N! (N-factorial) unique sequences - which I believe is what you are after. Therefore your three elements give six unique sequences (3! = 3 * 2 * 1).
This is because you have a choice of three elements for the first position (N), then a choice of the two remaining elements for the second position (N-1), leaving one unchosen element for the last position (N-2).
So, this means that you should be able to iterate over all permutations of the sequence; and the following code should do this for a sequence of 3 elements:
// Select element for first position in sequence...
for (int i = 0 ; i < 3 ; ++i)
{
// Select element for second position in sequence...
for (int j = 0 ; j < 3 ; ++j)
{
// step over indices already used - which means we
// must test the boundary condition again...
if (j >= i) ++j;
if (j >= 3) continue;
// Select element for third position in sequence...
// (there is only one choice!)
for (int k = 0 ; k < 3 ; ++k)
{
// step over indices already used, recheck boundary
// condition...
if (k >= i) ++k;
if (k >= j) ++k;
if (k >= 3) continue;
// Finally, i,j,k should be the next unique permutation...
doSomethingWith (i, j, k);
}
}
}
Now, big caveat that I have just written this OTH, so no guarentees. However, hopefully you can see what you need to do. Of course, this could and should be generalised to support arbitary set sizes, in which case you could populate an int[] with the indices for the sequence.
However, I guess that if you look around there will be some better algorithms for generating permutations of a sequence.

Permutation - Need help desining a better block that won't need unused values

I need help making my permutation's (order important, repeatable) size smaller by discarding the unneeded permutations before hand.
The current permutation takes a global minimum and maximum from the values provided. However, some of the permutations are discarded afterward as they don't fall within the range needed.
The idea is there are for example 3 numbers which need a permutation. For example: 1-3, 8-10 and 5-15. The current code will create a permutation of 1-15 even though values from 4-7 will be discarded later on.
Unfortunately in some instances its not possible to create an array large enough in Java to contain the permutation results.
Any help would be appreciated on changing this permutation to only include necessary values prior to computing the permutation.
PermutationCore:
public class PermutationCore {
private String[] a;
private int n;
public PermutationCore(String[] arrayOfPossibilities, int lengthOfPermutation) {
this.a = arrayOfPossibilities;
this.n = lengthOfPermutation;
}
public String[][] getVariations() {
int l = a.length;
int permutations = (int) Math.pow(l, n);
Co.println("Permutation array size: " + permutations);
String[][] table = new String[permutations][n];
for (int x = 0; x < n; x++) {
int t2 = (int) Math.pow(l, x);
for (int p1 = 0; p1 < permutations;) {
for (int al = 0; al < l; al++) {
for (int p2 = 0; p2 < t2; p2++) {
table[p1][x] = a[al];
p1++;
}
}
}
}
return table;
}
}
Permutation
public class Permutation {
private ArrayList<Iteration> listOfIteration = new ArrayList<Iteration>();
private boolean prepared;
private PermutationCore permutationCore;
private int min = Integer.MAX_VALUE;
private int max = Integer.MIN_VALUE;
private int count = 0;
private String[][] arrayOfStringResults;
public void addIteration(Iteration iteration){
if (prepared){throw new IllegalStateException("Permuation is already prepared. Create a new instance to add new items");}
this.listOfIteration.add(iteration);
}
public void prepare(){
String[] arrayOfString;
for (Iteration iteration : listOfIteration){
if (iteration.end > max){max = iteration.end;}
if (iteration.start < min){min = iteration.start;}
}
arrayOfString = new String[max-min+1];
for (int i=0; i<arrayOfString.length; i++){
arrayOfString[i] = String.valueOf(min+i);
}
permutationCore = new PermutationCore(arrayOfString, listOfIteration.size());
prepared = true;
// Co.println("Min/max: " + min + "," + max);
arrayOfStringResults = permutationCore.getVariations();
// ArrayTools.sort2DStringArray(arrayOfStringResults);
}
public boolean iterate(){
LABEL_ITERATE_LOOP: {
int i=0;
if (count == arrayOfStringResults.length){
return false;
}
for (Iteration iteration : listOfIteration){
int currentValue = Integer.valueOf(arrayOfStringResults[count][i]);
if (currentValue > iteration.end || currentValue < iteration.start){
//Co.println("Failed at: " + iteration.start + "," + iteration.end + " / " + currentValue);
count++;
break LABEL_ITERATE_LOOP;
}
iteration.current = currentValue;
i++;
}
count++;
}
return true;
}
public Iteration getIteration(Object request) {
for (Iteration iteration : listOfIteration){
if (iteration.request == request){
return iteration;
}
}
return null;
}
public ArrayList<Iteration> getListOfIterations(){
return listOfIteration;
}
public static class Iteration{
private int start;
private int end;
private int current;
private Object request;
public Iteration(int start, int end, Object request){
this.start = start;
this.end = end;
this.request = request;
}
public double getCurrentValue(){
return this.current;
}
public Object getRequest(){
return this.request;
}
}
}
This of your problem as permuting k numbers from 0 to (n-1), and printing a[n] instead of n. :) That is what you can do, to reduce iterations.
The other way to do it, is to use a number between 0 to n!-1 and figure out what the current permutation is, and print it. Although it is a slower method, it's faster to resume operations in this format - and we can quickly print the kth permutation.
Let us say the numbers are: 1, 2, 3, 4. There are a total of 4! permutation = 24, possible. To print the 15th (counting from zero) permutation, here's what we do:
n = 4
a = 1 2 3 4
divide 15 by (n-1)!
we get 15/6 = 2, reminder = 3.
So the permutation starts with a[2] = 3.
a = 1 2 4
take the reminder, divide by (n-2)!
we get 3/2 = 1, reminder = 1.
so the permutation is now permutation, a[1] = 3, 2
a = 1 4
take the reminder, divide by (n-1)!
we get 1/1 = 1, reminder = 0
so the permutation is now permutation, a[1] = 3, 2, 4.
do until reminder is zero. print a[0]= 3, 2, 4, 1.
^ this is the most efficient way to generate the kth permutation of any series.
You can use BigInteger math to perform this method very efficiently.

Categories

Resources