Maximize digits in 24 hour format. - java

Came across this question in a Glassdoor review and thought it was interesting.
Given an integer consisting of 4 digits, we need to maximize it in 24
hour format. For example, 4372 should return a String of the form
23:47, which is the maximum 24 hour value that can be obtained from
the given integer. Assume the given integer always contains exactly 4 digits.
Here's an incomplete method I wrote trying to solve it:
private static String maximize24Hour(int digits) {
if (digits == 0)
return "00:00";
if (digits < 0)
return null;
ArrayList<Integer> list = new ArrayList<>();
do {
list.add(digits % 10);
digits /= 10;
} while (digits != 0);
// Extra processing needs to be done here. Haven't figured it out.
StringBuilder buf = new StringBuilder();
for (Integer d : list) {
buf.append(d);
}
String result = buf.toString();
String hours = result.substring(0, 2);
String minutes = result.substring(2, result.length());
if (Integer.parseInt(result) > 2359
|| Integer.parseInt(hours) > 23
|| Integer.parseInt(minutes) > 59
|| result.length() != 4)
return null;
return hours.concat(":").concat(minutes);
}
Am I even approaching it correctly? If this was just any number, it would be trivial. But it's asking for it to be in 24 hour format which is what I find tricky.
I'd be interested to see if anyone has solutions/ideas for this challenge.

Separate the integer into 4 digits.
If you don't have a 0, 1, or 2 then there is no answer.
Put the largest number that is <= 2 in the first spot in the time.
If the first digit was a 2, then put the largest remaining number that is <=3 in the second place. (If there isn't one, then there is no answer.) If the first digit was 1 or 0, then place the largest remaining number in the second place.
Put the largest remaining number that is <= 5 in the third place.
Put the only remaining number in the fourth place.
I think you don't need to back-track at any point because the bounds in steps 3, 4, and 5 are strictly increasing. You certainly don't need to consider all possible permutations of the numbers since we know that certain places are bounded.

Here is my method. May not be the most efficient one, but it does the job.
Break input into individual digits
Get all permutations of all digits
Check each output is valid, and keep track of the biggest.
High level looks like this:
import java.util.List;
import java.util.ArrayList;
public class MaxDigit {
// ... helper functions here
// maximize function
private static String maximize24Hour(int digits) {
if (digits < 1000 || digits >= 10000) {
return "invalid input";
}
// get all possibles and find the biggest
int max = -1;
List<String> singleDigits = getDigits(digits);
List<String> allPossibles = getPermutations(singleDigits);
for (String timeStr : allPossibles) {
int timeInt = Integer.parseInt(timeStr);
if (isValidTime(timeInt) && timeInt > max) {
max = timeInt;
}
}
// If none is valid
if (max < 0) {
return "cannot find any valid time";
}
// Convert int to time
return max/100 + ":" + max%100;
}
public static void main(String[] args) {
System.out.println(maximize24Hour(4372));
}
}
And here are the helpers:
/**
* Check specified time is valid
* #param time Time in hhmm format
* #return true if input time is valid
*/
private static boolean isValidTime(int time) {
int hour = time / 100;
int min = time % 100;
return hour <= 23 && min <= 59;
}
/**
* Generate all possible numbers from input
*
* For example: inputs {1, 2} gives {12, 21}
* For example: inputs {1, 2, 3} gives {123, 132, 213, 231, 312, 321}
*
* #param inputs Input digits
* #return all possibles
*/
private static List<String> getPermutations(List<String> inputs) {
if (inputs.size() <= 1) {
return inputs;
}
List<String> ret = new ArrayList<>();
for (int i = 0; i < inputs.size(); ++i) {
List<String> copy = new ArrayList<>(inputs);
copy.remove(i);
List<String> recusive = getPermutations(copy);
for (String values : recusive) {
ret.add(inputs.get(i) + values);
}
}
return ret;
}
private static List<String> getDigits(int digits) {
List<String> singleDigits = new ArrayList<>();
while (digits > 0) {
singleDigits.add(Integer.toString(digits%10));
digits /= 10;
}
return singleDigits;
}

Related

How do I swap all the digits of input number(From first to last, from second to last second and so on, Pseudocode would be good) [duplicate]

I have numbers like 1100, 1002, 1022 etc. I would like to have the individual digits, for example for the first number 1100 I want to have 1, 1, 0, 0.
How can I get it in Java?
To do this, you will use the % (mod) operator.
int number; // = some int
while (number > 0) {
print( number % 10);
number = number / 10;
}
The mod operator will give you the remainder of doing int division on a number.
So,
10012 % 10 = 2
Because:
10012 / 10 = 1001, remainder 2
Note: As Paul noted, this will give you the numbers in reverse order. You will need to push them onto a stack and pop them off in reverse order.
Code to print the numbers in the correct order:
int number; // = and int
LinkedList<Integer> stack = new LinkedList<Integer>();
while (number > 0) {
stack.push( number % 10 );
number = number / 10;
}
while (!stack.isEmpty()) {
print(stack.pop());
}
Convert it to String and use String#toCharArray() or String#split().
String number = String.valueOf(someInt);
char[] digits1 = number.toCharArray();
// or:
String[] digits2 = number.split("(?<=.)");
In case you're already on Java 8 and you happen to want to do some aggregate operations on it afterwards, consider using String#chars() to get an IntStream out of it.
IntStream chars = number.chars();
How about this?
public static void printDigits(int num) {
if(num / 10 > 0) {
printDigits(num / 10);
}
System.out.printf("%d ", num % 10);
}
or instead of printing to the console, we can collect it in an array of integers and then print the array:
public static void main(String[] args) {
Integer[] digits = getDigits(12345);
System.out.println(Arrays.toString(digits));
}
public static Integer[] getDigits(int num) {
List<Integer> digits = new ArrayList<Integer>();
collectDigits(num, digits);
return digits.toArray(new Integer[]{});
}
private static void collectDigits(int num, List<Integer> digits) {
if(num / 10 > 0) {
collectDigits(num / 10, digits);
}
digits.add(num % 10);
}
If you would like to maintain the order of the digits from least significant (index[0]) to most significant (index[n]), the following updated getDigits() is what you need:
/**
* split an integer into its individual digits
* NOTE: digits order is maintained - i.e. Least significant digit is at index[0]
* #param num positive integer
* #return array of digits
*/
public static Integer[] getDigits(int num) {
if (num < 0) { return new Integer[0]; }
List<Integer> digits = new ArrayList<Integer>();
collectDigits(num, digits);
Collections.reverse(digits);
return digits.toArray(new Integer[]{});
}
I haven't seen anybody use this method, but it worked for me and is short and sweet:
int num = 5542;
String number = String.valueOf(num);
for(int i = 0; i < number.length(); i++) {
int j = Character.digit(number.charAt(i), 10);
System.out.println("digit: " + j);
}
This will output:
digit: 5
digit: 5
digit: 4
digit: 2
I noticed that there are few example of using Java 8 stream to solve your problem but I think that this is the simplest one:
int[] intTab = String.valueOf(number).chars().map(Character::getNumericValue).toArray();
To be clear:
You use String.valueOf(number) to convert int to String, then chars() method to get an IntStream (each char from your string is now an Ascii number), then you need to run map() method to get a numeric values of the Ascii number. At the end you use toArray() method to change your stream into an int[] array.
I see all the answer are ugly and not very clean.
I suggest you use a little bit of recursion to solve your problem. This post is very old, but it might be helpful to future coders.
public static void recursion(int number) {
if(number > 0) {
recursion(number/10);
System.out.printf("%d ", (number%10));
}
}
Output:
Input: 12345
Output: 1 2 3 4 5
simple solution
public static void main(String[] args) {
int v = 12345;
while (v > 0){
System.out.println(v % 10);
v /= 10;
}
}
// could be any num this is a randomly generated one
int num = (int) (Math.random() * 1000);
// this will return each number to a int variable
int num1 = num % 10;
int num2 = num / 10 % 10;
int num3 = num /100 % 10;
// you could continue this pattern for 4,5,6 digit numbers
// dont need to print you could then use the new int values man other ways
System.out.print(num1);
System.out.print("\n" + num2);
System.out.print("\n" + num3);
Since I don't see a method on this question which uses Java 8, I'll throw this in. Assuming that you're starting with a String and want to get a List<Integer>, then you can stream the elements like so.
List<Integer> digits = digitsInString.chars()
.map(Character::getNumericValue)
.boxed()
.collect(Collectors.toList());
This gets the characters in the String as a IntStream, maps those integer representations of characters to a numeric value, boxes them, and then collects them into a list.
Java 9 introduced a new Stream.iterate method which can be used to generate a stream and stop at a certain condition. This can be used to get all the digits in the number, using the modulo approach.
int[] a = IntStream.iterate(123400, i -> i > 0, i -> i / 10).map(i -> i % 10).toArray();
Note that this will get the digits in reverse order, but that can be solved either by looping through the array backwards (sadly reversing an array is not that simple), or by creating another stream:
int[] b = IntStream.iterate(a.length - 1, i -> i >= 0, i -> i - 1).map(i -> a[i]).toArray();
or
int[] b = IntStream.rangeClosed(1, a.length).map(i -> a[a.length - i]).toArray();
As an example, this code:
int[] a = IntStream.iterate(123400, i -> i > 0, i -> i / 10).map(i -> i % 10).toArray();
int[] b = IntStream.iterate(a.length - 1, i -> i >= 0, i -> i - 1).map(i -> a[i]).toArray();
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
Will print:
[0, 0, 4, 3, 2, 1]
[1, 2, 3, 4, 0, 0]
Easier way I think is to convert the number to string and use substring to extract and then convert to integer.
Something like this:
int digits1 =Integer.parseInt( String.valueOf(201432014).substring(0,4));
System.out.println("digits are: "+digits1);
ouput is
2014
I wrote a program that demonstrates how to separate the digits of an integer using a more simple and understandable approach that does not involve arrays, recursions, and all that fancy schmancy. Here is my code:
int year = sc.nextInt(), temp = year, count = 0;
while (temp>0)
{
count++;
temp = temp / 10;
}
double num = Math.pow(10, count-1);
int i = (int)num;
for (;i>0;i/=10)
{
System.out.println(year/i%10);
}
Suppose your input is the integer 123, the resulting output will be as follows:
1
2
3
Here is my answer, I did it for myself and I hope it's simple enough for those who don't want to use the String approach or need a more math-y solution:
public static void reverseNumber2(int number) {
int residual=0;
residual=number%10;
System.out.println(residual);
while (residual!=number) {
number=(number-residual)/10;
residual=number%10;
System.out.println(residual);
}
}
So I just get the units, print them out, substract them from the number, then divide that number by 10 - which is always without any floating stuff, since units are gone, repeat.
Java 8 solution to get digits as int[] from an integer that you have as a String:
int[] digits = intAsString.chars().map(i -> i - '0').toArray();
neither chars() nor codePoints() — the other lambda
String number = Integer.toString( 1100 );
IntStream.range( 0, number.length() ).map( i -> Character.digit( number.codePointAt( i ), 10 ) ).toArray(); // [1, 1, 0, 0]
Why don't you do:
String number = String.valueOf(input);
char[] digits = number.toCharArray();
Try this one.
const check = (num) => {
let temp = num
let result = []
while(temp > 0){
let a = temp%10;
result.push(a);
temp = (temp-a)/10;
}
return result;
}
check(98) //[ 8, 9 ]
public int[] getDigitsOfANumber(int number) {
String numStr = String.valueOf(number);
int retArr[] = new int[numStr.length()];
for (int i = 0; i < numStr.length(); i++) {
char c = numStr.charAt(i);
int digit = c;
int zero = (char) '0';
retArr[i] = digit - zero;
}
return retArr;
}
Integer.toString(1100) gives you the integer as a string. Integer.toString(1100).getBytes() to get an array of bytes of the individual digits.
Edit:
You can convert the character digits into numeric digits, thus:
String string = Integer.toString(1234);
int[] digits = new int[string.length()];
for(int i = 0; i<string.length(); ++i){
digits[i] = Integer.parseInt(string.substring(i, i+1));
}
System.out.println("digits:" + Arrays.toString(digits));
This uses the modulo 10 method to figure out each digit in a number greater than 0, then this will reverse the order of the array. This is assuming you are not using "0" as a starting digit.
This is modified to take in user input.
This array is originally inserted backwards, so I had to use the Collections.reverse() call to put it back into the user's order.
Scanner scanNumber = new Scanner(System.in);
int userNum = scanNumber.nextInt(); // user's number
// divides each digit into its own element within an array
List<Integer> checkUserNum = new ArrayList<Integer>();
while(userNum > 0) {
checkUserNum.add(userNum % 10);
userNum /= 10;
}
Collections.reverse(checkUserNum); // reverses the order of the array
System.out.print(checkUserNum);
Just to build on the subject, here's how to confirm that the number is a palindromic integer in Java:
public static boolean isPalindrome(int input) {
List<Integer> intArr = new ArrayList();
int procInt = input;
int i = 0;
while(procInt > 0) {
intArr.add(procInt%10);
procInt = procInt/10;
i++;
}
int y = 0;
int tmp = 0;
int count = 0;
for(int j:intArr) {
if(j == 0 && count == 0) {
break;
}
tmp = j + (tmp*10);
count++;
}
if(input != tmp)
return false;
return true;
}
I'm sure I can simplify this algo further. Yet, this is where I am. And it has worked under all of my test cases.
I hope this helps someone.
int number = 12344444; // or it Could be any valid number
int temp = 0;
int divider = 1;
for(int i =1; i< String.valueOf(number).length();i++)
{
divider = divider * 10;
}
while (divider >0) {
temp = number / divider;
number = number % divider;
System.out.print(temp +" ");
divider = divider/10;
}
Try this:
int num= 4321
int first = num % 10;
int second = ( num - first ) % 100 / 10;
int third = ( num - first - second ) % 1000 / 100;
int fourth = ( num - first - second - third ) % 10000 / 1000;
You will get first = 1, second = 2, third = 3 and fourth = 4 ....
Something like this will return the char[]:
public static char[] getTheDigits(int value){
String str = "";
int number = value;
int digit = 0;
while(number>0){
digit = number%10;
str = str + digit;
System.out.println("Digit:" + digit);
number = number/10;
}
return str.toCharArray();
}
As a noob, my answer would be:
String number = String.valueOf(ScannerObjectName.nextInt());
int[] digits = new int[number.length()];
for (int i = 0 ; i < number.length() ; i++)
int[i] = Integer.parseInt(digits.substring(i,i+1))
Now all the digits are contained in the "digits" array.
if digit is meant to be a Character
String numstr = Integer.toString( 123 );
Pattern.compile( "" ).splitAsStream( numstr ).map(
s -> s.charAt( 0 ) ).toArray( Character[]::new ); // [1, 2, 3]
and the following works correctly
numstr = "000123" gets [0, 0, 0, 1, 2, 3]
numstr = "-123"    gets [-, 1, 2, 3]
A .NET solution using LINQ.
List<int> numbers = number.ToString().Select(x => x - 48).ToList();
I think this will be the most useful way to get digits:
public int[] getDigitsOf(int num)
{
int digitCount = Integer.toString(num).length();
if (num < 0)
digitCount--;
int[] result = new int[digitCount];
while (digitCount-- >0) {
result[digitCount] = num % 10;
num /= 10;
}
return result;
}
Then you can get digits in a simple way:
int number = 12345;
int[] digits = getDigitsOf(number);
for (int i = 0; i < digits.length; i++) {
System.out.println(digits[i]);
}
or more simply:
int number = 12345;
for (int i = 0; i < getDigitsOf(number).length; i++) {
System.out.println( getDigitsOf(number)[i] );
}
Notice the last method calls getDigitsOf method too much time. So it will be slower. You should create an int array and then call the getDigitsOf method once, just like in second code block.
In the following code, you can reverse to process. This code puts all digits together to make the number:
public int digitsToInt(int[] digits)
{
int digitCount = digits.length;
int result = 0;
for (int i = 0; i < digitCount; i++) {
result = result * 10;
result += digits[i];
}
return result;
}
Both methods I have provided works for negative numbers too.
see bellow my proposal with comments
int size=i.toString().length(); // the length of the integer (i) we need to split;
ArrayList<Integer> li = new ArrayList<Integer>(); // an ArrayList in whcih to store the resulting digits
Boolean b=true; // control variable for the loop in which we will reatrive step by step the digits
String number="1"; // here we will add the leading zero depending on the size of i
int temp; // the resulting digit will be kept by this temp variable
for (int j=0; j<size; j++){
number=number.concat("0");
}
Integer multi = Integer.valueOf(number); // the variable used for dividing step by step the number we received
while(b){
multi=multi/10;
temp=i/(multi);
li.add(temp);
i=i%(multi);
if(i==0){
b=false;
}
}
for(Integer in: li){
System.out.print(in.intValue()+ " ");
}
import java.util.Scanner;
class Test
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int num=sc.nextInt();
System.out.println("Enter a number (-1 to end):"+num);
int result=0;
int i=0;
while(true)
{
int n=num%10;
if(n==-1){
break;
}
i++;
System.out.println("Digit"+i+" = "+n);
result=result*10+n;
num=num/10;
if(num==0)
{
break;
}
}
}
}

java - a weird counter - invalid disconnected digits

I would like to know if there is any way to count like this:
base of each position:
4 2 3
counter values:
000--invalid - exception, always a non zero digit must be there
001
002
010
011
012
100
101--invalid : disconnected digits
102--invalid : disconnected digits
110
111
112
200
201--invalid : disconnected digits
202--invalid : disconnected digits
210
211
212
300
301--invalid : disconnected digits
302--invalid : disconnected digits
310
311
312
The idea is if non-zero digits are separated by zero, then leave that formation out. That means values like 101, 201 are invalid.
talking about decimal counting system for example (max: 9999), numbers like 1001, or 9010 will not be produced.
I came up with counting and then converting to each base, (in my first example, the bases would be 4.2.3 and for the 9999 example it would be 10.10.10.10) however, there are certain numbers of all numbers that they will be valid.
for example:
4.2.3: 17 out of 4*2*3 (or 24) will be valid
4.2.2.4: 30 out of 4*2*2*4 (or 64) will be valid
10.10.10.10: 8298 out of 10*10*10*10 (or 10000) will be valid.
as positions goes up, the more computation I need to perform.
What is your idea about a fast counter that can produce such numbers?
a simple solution as I mentioned would be count and convert, and then do a post process on generated numbers, but what is the optimized solution for this?
here is my code:
/**
* Author: Soleyman Pasban
* Date: Apr 6, 2016
*/
package PC;
public class DigitTest {
public static void main(String[] test) {
//int[] base = new int[]{4, 2, 3};
int[] base = new int[]{4, 2, 2, 4};
//int[] base = new int[]{10,10,10,10};
int valid = 0;
int total = 1;
for (int i = 0; i < base.length; i++) {
total *= base[i];
}
for (int i = 1; i < total; i++) {
int number = i;
int bi = base.length - 1;
String str = "";
while (bi >= 0) {
str = number % base[bi] + str;
number = number / base[bi];
bi--;
}
boolean pass = true;
boolean allowNonZero = true;
for (int j = 1; j < base.length; j++) {
if (str.charAt(j - 1) == '0' && str.charAt(j) != '0') {
//for the first case ...0* it should filter the cases
//I bypass it once by this, else the number must mark invalid
if (allowNonZero == false) {
pass = false;
}
allowNonZero = false;
}
//once see a zero, no none-zero must be appear
if (str.charAt(j - 1) != '0') {
allowNonZero = false;
}
}
if (pass) {
valid++;
} else {
str += " - invalid";
}
System.out.println(str);
}
System.out.println();
System.out.println("Valid: " + valid);
System.out.println("Total: " + total);
}
}
My question is if there is a way to keep the above algorithm simple. for a 16 digits like 4.8.7.2.2.3.2.2.4.2.7.4.2.3.2.2 (this is an example to show that it must work with any base) the amount of calculation, creating string variables and other stuff I think will be inefficient!
for an example if a number start with like 9010*********1 then this number is wrong from the beginning and counting the rest will be meaningless.
Is there any other solution for this problem? I would like to see if I can just produce the valid numbers by this.
Thanks
It's actually fairly simple. You start by creating a char[] of '0' characters for the appropriate length.
You then increment the last digit, and rollover when necessary. The updated array is then the next value, and you create the result using new String(buf).
Now, the trick is that when you roll over, you set the digit back to 0, and move one position to the left, and increment that. But, you remember how far you had to go left during chained rollovers, because you must increment the left-most zero on the next iteration, in order to prevent "disconnected digits".
Example:
1999
2000 <-- rollover, remember that second digit must be incremented next
2100 <-- now remember that third digit must be incremented next
2110 <-- now remember that forth digit must be incremented next
2111 <-- normal increment
2112 <-- normal increment
Since a weird counter like this is best if reusable, here is a class implementing this logic, including validation:
public final class WeirdCounter {
private int[] bases;
private char[] buf;
private int idx;
public WeirdCounter(int ... bases) {
if (bases.length == 0)
throw new IllegalArgumentException("No bases");
for (int base : bases)
if (base < 1 || base > 10)
throw new IllegalArgumentException("Invalid base:" + base);
this.bases = bases.clone();
this.buf = new char[bases.length];
Arrays.fill(this.buf, '0');
this.idx = this.buf.length - 1;
}
public String next() {
while (this.idx >= 0) {
char digit = this.buf[this.idx];
if (++digit < '0' + this.bases[this.idx]) {
this.buf[this.idx] = digit;
if (this.idx < this.buf.length - 1)
this.idx++;
return new String(this.buf);
}
this.buf[this.idx--] = '0';
}
return null;
}
}
This is very fast and easy to use:
WeirdCounter counter = new WeirdCounter(4,2,3);
for (String val; (val = counter.next()) != null; )
System.out.println(val);
OUTPUT
001
002
010
011
012
100
110
111
112
200
210
211
212
300
310
311
312
Note that the 16-digit example you gave (4.8.7.2.1.3...4.6.7.9.10...3.1.1) makes no sense. What does ... mean? Also, a base of 1 means that the digit can only ever be 0.
So, assuming that . means 1, the code will work. When a rollover crosses any such base-1 value, all digit to the right must stay 0.
Partial output using new WeirdCounter(4,8,7,2,1,3,1,4,6,7,9,10,1,3,1,1):
...
0000000356870000
0000000356880000
0000000356890000
0000010000000000
0000020000000000
0001000000000000
0010000000000000
0011000000000000
0020000000000000
0021000000000000
0030000000000000
0031000000000000
0040000000000000
0041000000000000
0050000000000000
0051000000000000
0060000000000000
0061000000000000
0100000000000000
0110000000000000
0111000000000000
...
Still, code is very, very fast, because when it tries to increment 0001000000000000, it knows to increment the first zero after the 1, so it immediate rolls over the base-1 digit and then increments the 1 digit to 2 instead, without even looking at the those other 0 digits.
public class Digits {
// make constructor or something
int[] base = new int[]{4, 2, 3};
int[] cur = new int[]{0, 0, 0};
public void find(int i, boolean hasNonZero) {
if (i == base.length) {
if (!hasNonZero) {
return; // all zeroes corner case
}
// output
for (int j = 0; j < base.length; j++) {
System.out.print(cur[j]);
}
System.out.println();
return;
}
for (int v = 0; v < base[i]; v++) { // each digit at position
if (hasNonZero && v != 0 && cur[i - 1] == 0) { // disconnected non zeroes
continue;
}
cur[i] = v;
find(i + 1, hasNonZero || v != 0); // next position
}
}
public static void main(String[] args) {
(new Digits()).find(0, false);
}
}
Simple recursion like this.
You can calculate the count without generating any numbers. Here's a simple O(n^3) solution to demonstrate the idea. It can probably be improved further.
public class DigitTest {
public static void main(String[] args) {
countWeirdNumbers(4, 2, 3);
countWeirdNumbers(4, 2, 2, 4);
countWeirdNumbers(10, 10, 10, 10);
}
public static void countWeirdNumbers(int... bases) {
long count = 0;
for (int start = 0; start < bases.length; start++) {
for (int end = start; end < bases.length; end++) {
int thisCount = 1;
for (int i = start; i <= end; i++) {
thisCount *= bases[i] - 1;
}
count += thisCount;
}
}
System.out.println(count);
}
}
The idea is that you're simply counting how many numbers don't have any zeroes in between the first and last nonzero digits. So iterate over all the possible positions of those two digits and count the possibilities for the digits in that range. Each digit has b-1 possibilities where b is the base at that position because 0 isn't allowed.
Here's a super-fast way that doesn't generate any invalid numbers. Just change the initializers for maxdigits and current for different base sequences.
It works by directly incrementing the previous number, so you can make an iterator out of it if you like.
This is good pattern to remember for generating a wide variety of different kinds of sequences in lexical order:
Given the "current item", you can always make the next item with these 2 steps:
Increment the rightmost character that can be greater than the corresponding character in the current item. This works because the next item must be greater, and given that must share the longest possible prefix in common with the current item. Then
Set the remaining characters to the lowest possible value, because otherwise you'd be skipping some.
These steps make it pretty easy to generate your sequence, and indeed a whole lot of other lexically ordered sequences.
public static void main (String[] args) throws java.lang.Exception
{
char[] maxdigits = "312".toCharArray();
char[] current = "001".toCharArray();
for (;;)
{
System.out.println(new String(current));
//each time we add 1, one digit is incremented by one,
//and all the lower-place digits are set to the least possible
//value
//Step 1 - find the position of digit to increment
boolean sawNonZero=false;
int incpos;
for(incpos = current.length-1; incpos>=0; --incpos)
{
if (current[incpos]=='0')
{
if (sawNonZero || current[incpos-1]!='0')
{
//can increment a leading zero or the first trailing zero
break;
}
//incrementing this one would create a zero gap
}
else
{
sawNonZero = true;
if (current[incpos]<maxdigits[incpos])
{
//can increment a digit that is less than max
break;
}
}
}
if (incpos<0)
{
break; //done
}
current[incpos]++;
//Step 2 - set the remaining digits to 0
for (incpos+=1; incpos<current.length; ++incpos)
{
current[incpos]='0';
}
}
}

How can I count if a specific set of digits are present in an array

Suppose I have a number 123. I need to see if I get all digits 1 through 9, including 0. The number 123 has three digits: 1,2, and 3. Then I multiply it by 2 and get 246 (I get digits 2, 4, 6). Then I multiply it by 3 and I get 369. I keep doing incremental multiplication until I get all digits.
My approach is the following:
public int digitProcessSystem(int N) {
String number = Integer.toString(N);
String [] arr = number.split("");
// List <Integer> arr2 = new ArrayList<>();
for (Integer i = 0; i < arr.length; i++) {
try {
arr2[i] = Integer.parseInt(arr[i]);
} catch (NumberFormatException e) {
}
}
count =0;
boolean contains = IntStream.of(arr2).anyMatch(x -> x == 1|| x==2 ||x == 3|| x==4|| x == 5|| x==6 ||x == 7|| x==8||x == 9|| x==0);
}
I really don't know how can I keep doing the boolean for digits that did not match in the first trail above because I will definitely get any one of the all digits in the above boolean search. How can I get that if some specific digits are present and some are not so that I can multiply the actual number to do the search for the digits that were not found in the first trial; just like the way I defined in the beginning.
You could wrap that into a while loop and include the numbers into a Set. Once the set has the size 10 all digits are present in the number. I´d also suggest to use a long instead of an int or you´ll be getting wrong results or run into an excpetion. Here´s some example code for this:
private static long digitProcessSystem(long N) {
long numberN = N;
String number = Long.toString(N);
// calculate 10 digits number here yet
if (number.length() < 10) {
// using the smallest possible number with each digit
// By using this number we are most likely allmost at the result
// This will increase the performance for small digits heavily.
long divider = 1023456789L / numberN;
numberN *= divider;
}
number = Long.toString(numberN);
String[] arr = number.split("");
Set<String> input = new HashSet<>(Arrays.asList(arr));
while(input.size() != 10){
// add N to number
numberN += N;
// Parse the new number
number = Long.toString(numberN);
// split
arr = number.split("");
// clear set
input.clear();
// Add the new numbers to the set. If it has the size 10 now the loop will stop and return the number.
input.addAll(Arrays.asList(arr));
};
return numberN;
}
public static void main(String[] args) {
System.out.println(digitProcessSystem(123));
}
output:
1023458769
I'm not sure what is your end goal. But you can use a HashSet and do something like this in order to achieve what you are trying to achieve:
public static void main (String[] args) throws Exception {
long number = 123L, counter = 1000000000L / number;
while(digitProcessSystem(number * counter++));
System.out.println("Number: " + number * (counter - 1));
}
public static boolean digitProcessSystem(long input) {
char[] arr = Long.toString(input).toCharArray();
Set<Character> set = new HashSet<>();
for (int i = 0; i < arr.length; i++) {
set.add(arr[i]);
}
return set.size() != 10;
}
Output:
Number: 1023458769
without using java language Facilities and hashset:
private static long digitProcessSystem(long N) {
long numberN = N;
String number = Long.toString(N);
String[] arr = number.split("");;
int arr2=new int[10];
int sum=0;
while(sum != 10){
sum=0;
// add N to number
numberN += N;
// Parse the new number
number = Long.toString(numberN);
// If it doesn´t have 10 digitis continue here yet
if(number.length() < 10) continue;
// split
arr = number.split("");
for(int i=0;i<arr.length;i++){
arr2[arr]=1;
}
for(int i=0;i<10;i++){
sum+=arr2[i];
}
};
return numberN;
}
Generally, if you want to process the characters of a String, don’t do it by splitting the string into substrings. Note that every CharSequence, including String, has the methods chars() and codepoints() allowing to process all characters as IntStream.
To check whether all digits from '0' to '9' are present, we can use chars() (don’t have to think about surrogate pairs) and do it straight-forward, map them to their actual number by subtracting '0', filter out all non-digits (just to be sure), then, map them to an int where the nth bit is set, so we can binary or them all together and check whether all of the lowest ten bits are set:
public static boolean hasAllDigits(String s) {
return s.length()>9 &&
s.chars().map(c -> c-'0').filter(c -> c>=0 && c<=9)
.map(c -> 1 << c).reduce(0, (a,b)->a|b) == 0b1111111111;
}
As a bonus, a length-check is prepended as a String must have at least ten characters to contain all ten digits, so we can short-cut if it hasn’t.
Now, I’m not sure about your actual task. If you just want to iterate until encountering a number having all digits, it’s quite simple:
long number=123;
for(long l = 1, end = Long.MAX_VALUE/number; l < end; l++) {
long candidate = number * l;
if(hasAllDigits(String.valueOf(candidate))) {
System.out.println("found: "+candidate);
return;
}
}
System.out.println("not found within the long range");
But if you want to know when you encountered all digits within the sequence of numbers, we have to adapt the test method and keep the bitset between the iterations:
public static int getDigits(String s) {
return s.chars().map(c -> c-'0').filter(c -> c>=0 && c<=9)
.map(c -> 1 << c).reduce(0, (a,b)->a|b);
}
 
long number=123;
int digits=0;
for(long l = 1, end = Long.MAX_VALUE/number; l < end; l++) {
long candidate=number * l;
int newDigits=digits | getDigits(String.valueOf(candidate));
if(newDigits != digits) {
System.out.printf("pos %10d: %10d%n", l, candidate);
digits=newDigits;
if(digits == 0b1111111111) {
System.out.println("encountered all digits");
break;
}
}
}
if(digits != 0b1111111111) {
System.out.println("did not encounter all digits within the long range");
}
This method will only print numbers of the sequence which have at least one digit not encountered before, so you can easily see which one contributed to the complete set and will see at most ten numbers of the sequence.

Changing numbers places in java

Can anyone please learn me how to change this number 5486 to 4568 ? I need to change two pairs of numbers places. Any ideas please?
My code :
public Number shiftRight(int n) {
int length = (getNumOfDigits()+MINUSONE);
length = (int) Math.pow(TEN, length);
for (int i=0; i<n; i++){
int m=num%TEN;
num=(m*length) + (num/TEN);
}
return new Number(num);
}
public int shiftRightDistance(Number other){
int max = getNumOfDigits();
for (int i=0;i<max;i++)
{
if(compareTo(shiftRight(i))==ZERO)
{
return i;
}
}
return MINUSONE;
}
public Number swapPairs() {
}
}
The simplest (and least confusing) thing might be to convert the number to a char array, swap pairs of characters, and then convert back to a number. You can use String.valueOf(int), String.toCharArray(), new String(char[]) and Integer.valueOf(String) to put that together.
Alternatively, you can build on the following method that swaps the digits of a non-negative number less than 100:
private int swapDigitsLessThan100(int n) {
return 10 * (n % 10) + n / 10;
}
The way to build on that would be to extract every pair of digits from the original number, working recursively. The following deals with numbers that are an even number of digits long:
public int swapDigits(int n) {
if (n == 0) {
return 0;
return 100 * swapDigits(n / 100) + swapDigitsLessThan100(n % 100);
}
With this code, if n is an odd number of digits, the result will be to use a leading 0 as an additional digit.

generating Variations without repetitions / Permutations in java

I have to generate all variations without repetitions made of digits 0 - 9.
Length of them could be from 1 to 10. I really don't know how to solve it, especially how to avoid repetitions.
Example:
length of variations: 4
random variations: 9856, 8753, 1243, 1234 etc. (but not 9985 - contains repetition)
Can you please help me? Or can you give me the code?
The keyword to look for is permutation. There is an abundance of source code freely available that performs them.
As for keeping it repetition free I suggest a simple recursive approach: for each digit you have a choice of taking it into your variation or not, so your recursion counts through the digits and forks into two recursive calls, one in which the digit is included, one in which it is excluded. Then, after you reached the last digit each recursion essentially gives you a (unique, sorted) list of repetition-free digits. You can then create all possible permutations of this list and combine all of those permutations to achieve your final result.
(Same as duffymo said: I won't supply code for that)
Advanced note: the recursion is based on 0/1 (exclusion, inclusion) which can directly be translated to bits, hence, integer numbers. Therefore, in order to get all possible digit combinations without actually performing the recursion itself you could simply use all 10-bit integer numbers and iterate through them. Then interpret the numbers such that a set bit corresponds to including the digit in the list that needs to be permuted.
Here is my Java code. Feel free to ask if you don't understand. The main point here is:
sort again character array. for example: a1 a2 a3 b1 b2 b3 .... (a1 = a2 = a3)
generate permutation and always keep condition: index of a1 < index of a2 < index of a3 ...
import java.util.Arrays;
public class PermutationDup {
public void permutation(String s) {
char[] original = s.toCharArray();
Arrays.sort(original);
char[] clone = new char[s.length()];
boolean[] mark = new boolean[s.length()];
Arrays.fill(mark, false);
permute(original, clone, mark, 0, s.length());
}
private void permute(char[] original, char[] clone, boolean[] mark, int length, int n) {
if (length == n) {
System.out.println(clone);
return;
}
for (int i = 0; i < n; i++) {
if (mark[i] == true) continue;
// dont use this state. to keep order of duplicate character
if (i > 0 && original[i] == original[i-1] && mark[i-1] == false) continue;
mark[i] = true;
clone[length] = original[i];
permute(original, clone, mark, length+1, n);
mark[i] = false;
}
}
public static void main(String[] args) {
PermutationDup p = new PermutationDup();
p.permutation("abcab");
}
}
I have created the following code for generating permutations where ordering is important and with no repetition. It makes use of generics for permuting any type of object:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Permutations {
public static <T> Collection<List<T>> generatePermutationsNoRepetition(Set<T> availableNumbers) {
Collection<List<T>> permutations = new HashSet<>();
for (T number : availableNumbers) {
Set<T> numbers = new HashSet<>(availableNumbers);
numbers.remove(number);
if (!numbers.isEmpty()) {
Collection<List<T>> childPermutations = generatePermutationsNoRepetition(numbers);
for (List<T> childPermutation : childPermutations) {
List<T> permutation = new ArrayList<>();
permutation.add(number);
permutation.addAll(childPermutation);
permutations.add(permutation);
}
} else {
List<T> permutation = new ArrayList<>();
permutation.add(number);
permutations.add(permutation);
}
}
return permutations;
}
}
Imagine you had a magical function - given an array of digits, it will return you the correct permutations.
How can you use that function to produce a new list of permutations with just one extra digit?
e.g.,
if i gave you a function called permute_three(char[3] digits), and i tell you that it only works for digits 0, 1, 2, how can you write a function that can permute 0, 1, 2, 3, using the given permute_three function?
...
once you solved that, what do you notice? can you generalize it?
using Dollar it is simple:
#Test
public void generatePermutations() {
// digits is the string "0123456789"
String digits = $('0', '9').join();
// then generate 10 permutations
for (int i : $(10)) {
// shuffle, the cut (0, 4) in order to get a 4-char permutation
System.out.println($(digits).shuffle().slice(4));
}
}
The code for this is similar to the one without duplicates, with the addition of an if-else statement.Check this code
In the above code,Edit the for loop as follows
for (j = i; j <= n; j++)
{
if(a[i]!=a[j] && !is_duplicate(a,i,j))
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
else if(i!=j) {} // if no duplicate is present , do nothing
else permute(a,i+1,n); // skip the ith character
}
bool is_duplicate(int *a,int i,int j)
{
if a[i] is present between a[j]...a[i]
return 1;
otherwise
return 0;
}
worked for me
Permutation without repetition is based on theorem, that amount of results is factorial of count of elements (in this case numbers). In your case 10! is 10*9*8*7*6*5*4*3*2*1 = 3628800. The proof why it is exactly right is right solution for generation also.
Well so how. On first position i.e. from left you can have 10 numbers, on the second position you can have only 9 numbers, because one number is on the position on the left and we cannot repeat the same number etc. (the proof is done by mathematical induction).
So how to generate first ten results? According my knowledges, he simplest way is to use cyclic shift. It means the order of number shift to the left on one position (or right if you want) and the number which overflow to put on the empty place.
It means for first ten results:
10 9 8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1 10
8 7 6 5 4 3 2 1 10 9
7 6 5 4 3 2 1 10 9 8
6 5 4 3 2 1 10 9 8 7
5 4 3 2 1 10 9 8 7 6
...
The first line is basic sample, so it is the good idea to put it into set before generation. Advantage is, that in the next step you will have to solve the same problem to avoid undesirable duplicities.
In next step recursively rotate only 10-1 numbers 10-1 times etc.
It means for first 9 results in step two:
10 9 8 7 6 5 4 3 2 1
10 8 7 6 5 4 3 2 1 9
10 7 6 5 4 3 2 1 9 8
10 6 5 4 3 2 1 9 8 7
10 5 4 3 2 1 9 8 7 6
...
etc, notice, that first line is present from previous step, so it must not be added to generated set again.
Algorithm recursively doing exactly that, what is explained above. It is possible to generate all the 3628800 combinations for 10!, because number of nesting is the same as number of elements in array (it means in your case for 10 numbers it lingers about 5min. on my computer) and you need have enough memory if you want to keep all combinations in array.
There is solution.
package permutation;
/** Class for generation amount of combinations (factorial)
* !!! this is generate proper permutations without repeating and proper amount (počet) of rows !!!
*
* #author hariprasad
*/
public class TestForPermutationII {
private static final String BUMPER = "*";
private static int counter = 0;
private static int sumsum = 0;
// definitoin of array for generation
//int[] testsimple = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] testsimple = {1, 2, 3, 4, 5};
private int ELEMNUM = testsimple.length;
int[][] shuff;
private String gaps(int len) {
String addGap = "";
for(int i=0; i <len; i++)
addGap += " ";
return addGap;
}
/** Factorial computing */
private int fact(int num) {
if (num > 1) {
return num * fact(num - 1);
} else {
return 1;
}
}
/** Cyclic shift position to the left */
private int[] lShiftPos(int[] arr, int pos) {
int[] work = new int[ELEMNUM];
int offset = -1;
for (int jj = 0; jj < arr.length; jj++) {
if (jj < pos) {
work[jj] = arr[jj];
} else if (jj <= arr.length - 1) {
if (jj == pos) {
offset = arr[pos]; // last element
}
if (jj != (arr.length - 1)) {
work[jj] = arr[jj + 1];
} else {
work[jj] = offset;
}
}
}
return work;
}
private String printBuff(int[] buffer) {
String res = "";
for (int i= 0; i < buffer.length; i++) {
if (i == 0)
res += buffer[i];
else
res += ", " + buffer[i];
}
return res;
};
/** Recursive generator for arbitrary length of array */
private String permutationGenerator(int pos, int level) {
String ret = BUMPER;
int templen = counter;
int[] work = new int[ELEMNUM];
int locsumread = 0;
int locsumnew = 0;
//System.out.println("\nCalled level: " + level);
for (int i = 0; i <= templen; i++) {
work = shuff[i];
sumsum++;
locsumread++;
for (int ii = 0; ii < pos; ii++) {
counter++;
sumsum++;
locsumnew++;
work = lShiftPos(work, level); // deep copy
shuff[counter] = work;
}
}
System.out.println("locsumread, locsumnew: " + locsumread + ", " + locsumnew);
// if level == ELEMNUM-2, it means no another shift
if (level < ELEMNUM-2) {
ret = permutationGenerator(pos-1, level+1);
ret = "Level " + level + " end.";
//System.out.println(ret);
}
return ret;
}
public static void main(String[] argv) {
TestForPermutationII test = new TestForPermutationII();
counter = 0;
int len = test.testsimple.length;
int[] work = new int[len];
test.shuff = new int[test.fact(len)][];
//initial
test.shuff[counter] = test.testsimple;
work = test.testsimple; // shalow copy
test.shuff = new int[test.fact(len)][];
counter = 0;
test.shuff[counter] = test.testsimple;
test.permutationGenerator(len-1, 0);
for (int i = 0; i <= counter; i++) {
System.out.println(test.printBuff(test.shuff[i]));
}
System.out.println("Counter, cycles: " + counter + ", " + sumsum);
}
}
Intensity (number of cycles) of algorithm is sum of incomplete factorials of number of members. So there is overhang when partial set is again read to generate next subset, so intensity is:
n! + n!/2! + n!/3! + ... + n!/(n-2)! + n!(n-1)!
There is one solution which is not from mine, but it is very nice and sophisticated.
package permutations;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* #author Vladimir Hajek
*
*/
public class PermutationSimple {
private static final int MAX_NUMBER = 3;
Set<String> results = new HashSet<>(0);
/**
*
*/
public PermutationSimple() {
// TODO Auto-generated constructor stub
}
/**
* #param availableNumbers
* #return
*/
public static List<String> generatePermutations(Set<Integer> availableNumbers) {
List<String> permutations = new LinkedList<>();
for (Integer number : availableNumbers) {
Set<Integer> numbers = new HashSet<>(availableNumbers);
numbers.remove(number);
if (!numbers.isEmpty()) {
List<String> childPermutations = generatePermutations(numbers);
for (String childPermutation : childPermutations) {
String permutation = number + childPermutation;
permutations.add(permutation);
}
} else {
permutations.add(number.toString());
}
}
return permutations;
}
/**
* #param args
*/
public static void main(String[] args) {
Set<Integer> availableNumbers = new HashSet<>(0);
for (int i = 1; i <= MAX_NUMBER; i++) {
availableNumbers.add(i);
}
List<String> permutations = generatePermutations(availableNumbers);
for (String permutation : permutations) {
System.out.println(permutation);
}
}
}
I think, this is the excellent solution.
Brief helpful permutation indexing Knowledge
Create a method that generates the correct permutation, given an index value between {0 and N! -1} for "zero indexed" or {1 and N!} for "one indexed".
Create a second method containing a "for loop" where the lower bound is 1 and the upper bound is N!. eg.. "for (i; i <= N!; i++)" for every instance of the loop call the first method, passing i as the argument.
def find(alphabet, alpha_current, str, str_current, max_length, acc):
if (str_current == max_length):
acc.append(''.join(str))
return
for i in range(alpha_current, len(alphabet)):
str[str_current] = alphabet[i]
alphabet[i], alphabet[alpha_current] = alphabet[alpha_current], alphabet[i]
find(alphabet, alpha_current+1, str, str_current+1, max_length, acc)
alphabet[i], alphabet[alpha_current] = alphabet[alpha_current], alphabet[i]
return
max_length = 4
str = [' ' for i in range(max_length)]
acc = list()
find(list('absdef'), 0, str, 0, max_length, acc)
for i in range(len(acc)):
print(acc[i])
print(len(acc))

Categories

Resources